YSLD¶
The gt-ysld module provides a YAML parser/encoder for GeoTools style objects:
human readable alternative to machine readable XML
compact representation
flexible syntax using indentation, rather than order
YAML parser provides variables for snippet reuse
Full access to GeoTools rendering engine not limited by SLD specification
References:
YSLD (GeoServer User Guide)
gt-main style layer descriptor (interfaces)
gt-api symbology encoding (interfaces)
style (tutorial)
gt-render style (code examples)
YSLD Syntax¶
Quick example (the FeatureTypeStyle, Rule and list of Symbolizers is auto-generated):
line:
stroke-color: '#3333cc'
Rules example (the FeatureTypeStyle is auto-generated):
rules:
- filter: ${type = 'road'}
symbolizers:
- line:
stroke-color: '#000000'
stroke-width: 2
- else: true
symbolizers:
- line:
stroke-color: '#666666'
stroke-width: 1
Complete example with names, titles and comments:
# Created on 2016-03-4
name: water
title: Lakes and Rivers
abstract: Water style using transparency to allow for hill
shade bathymetry effects.
feature-styles:
- rules:
- name: hydro
title: Hydro
symbolizers:
- polygon:
stroke-color: '#333089'
stroke-width: 1.25
fill-color: '#333089'
fill-opacity: 0.45
Yet another markup language (YAML) uses indentation to form a document structure of mappings and lists. The specification supports comments, multiline text and definition reuse.
Expressions¶
Expressions are specified as CQL/ECQL parse-able expression strings. See the CQL documentation and this CQL tutorial for more information about the CQL syntax.
Literal examples:
line:
stroke-width: 10
stroke-linecap: 'butt'
Note: Single quotes are needed for string literals to differentiate them from attribute references.
Attribute example:
text:
label: ${STATE_NAME}
Function example:
point:
rotation: ${sqrt([STATE_POP])}
Color examples:
polygon:
stroke-color: '#ff00ff'
fill-color: rgb(255,0,255)
Color literals can be specified either as a 6 digit hex string or a 3 argument
rgb
function call.
Filters¶
Rule filters are specified as CQL/ECQL parse-able filters. A simple example:
rules:
- filter: ${type = 'highway'}
symbolizers:
- line:
stroke-width: 5
See the CQL documentation and this CQL tutorial for more information about the CQL syntax.
Tuples¶
Some attributes are specified as pairs. For example:
rules:
- scale: [10000,20000]
point:
anchor: [0.5,0.5]
The literal strings min and max can also be used:
rules:
- scale: [min,10000]
symbolizers:
- line:
stroke-width: 3
- scale: [10000,max]
symbolizers:
- line:
stroke-width: 1
Arrays¶
Lists and arrays are specified as space delimited. For example:
stroke-dasharray: '5 2 1 2'
Anchors & References¶
With YAML it is possible to reference other parts of a document. With this it is possible to support variables and mix ins. An example of a color variable:
redish: &redish '#DD0000'
point:
fill-color: *redish
An named “anchor” is declared with the & character and then referenced with the * character. This same feature can be used to do “mix-ins” as well:
define: &highway_zoom10
scale: (10000,20000)
filter: type = 'highway'
rules:
- <<: *highway_zoom10
symbolizers:
- point
The syntax in this case is slightly different and is used when referencing an entire mapping object rather than just a simple scalar value.
YSLD Grammar¶
Document structure:
<YAML variable definition>
<grid definition>
<style definition>
Grid definition (predefined WGS84, WebMercator):
# grid definition
grid:
name: <text>
Style definition:
# style definition
name: <text>
title: <text>
abstract: <text>
feature-styles:
- <feature style>
Optional top-level sld and layer definition:
# sld definition
sld-name: <text>
sld-title: <text>
sld-abstract: <text>
# named layer definition
layer-name: <text>
# user layer definition
user-name: <text>
user-remote: <text>
user-service: <text>
Feature style definition:
feature-styles:
- name: <text>
title: <text>
abstract: <text>
transform:
<transform>
rules:
- <rules>
x-firstMatch: <boolean>
x-composite: <text>
x-composite-base: <boolean>
Rule definition:
# rules
rules:
- name: <text>
title: <text>
filter: <filter>
else: <boolean>
scale: [<min>,<max>]
zoom: [<min>,<max>]
symbolizers:
- <symbolizers>
x-inclusion: <text>
Line symbolizer definition:
symbolizers:
- line:
geometry: <expression>
uom: <text>
x-labelObstacle: <boolean>
x-composite-base: <boolean>
x-composite: <text>
stroke-color: <color>
stroke-width: <expression>
stroke-opacity: <expression>
stroke-linejoin: <expression>
stroke-linecap: <expression>
stroke-dasharray: <float list>
stroke-dashoffset: <expression>
stroke-graphic:
<graphic_options>
stroke-graphic-fill:
<graphic_options>
offset: <expression>
Polygon symbolizer definition:
symbolizers:
- polygon:
geometry: <expression>
uom: <text>
x-labelObstacle: <boolean>
x-composite-base: <boolean>
x-composite: <text>
fill-color: <color>
fill-opacity: <expression>
fill-graphic:
<graphic_options>
stroke-color: <color>
stroke-width: <expression>
stroke-opacity: <expression>
stroke-linejoin: <expression>
stroke-linecap: <expression>
stroke-dasharray: <float list>
stroke-dashoffset: <expression>
stroke-graphic:
<graphic_options>
stroke-graphic-fill:
<graphic_options>
offset: <expression>
displacement: <expression>
Point symbolizer definition:
symbolizers:
- point:
geometry: <expression>
uom: <text>
x-labelObstacle: <boolean>
x-composite-base: <boolean>
x-composite: <text>
symbols:
- external:
url: <text>
format: <text>
- mark:
shape: <shape>
fill-color: <color>
fill-opacity: <expression>
fill-graphic:
<graphic_options>
stroke-color: <color>
stroke-width: <expression>
stroke-opacity: <expression>
stroke-linejoin: <expression>
stroke-linecap: <expression>
stroke-dasharray: <float list>
stroke-dashoffset: <expression>
stroke-graphic:
<graphic_options>
stroke-graphic-fill:
<graphic_options>
size: <expression>
rotation: <expression>
anchor: <tuple>
displacement: <tuple>
opacity: <expression>
Raster symbolizer definition:
symbolizers:
- raster:
opacity: <expression>
channels:
gray:
<channel_options>
red:
<channel_options>
green:
<channel_options>
blue:
<channel_options>
color-map:
type: <ramp|interval|values>
entries:
- [color, entry_opacity, band_value, text_label]
contrast-enhancement:
mode: <normalize|histogram>
gamma: <expression>
Text symbolizer definition:
symbolizers:
- text:
geometry: <expression>
uom: <text>
x-composite-base: <boolean>
x-composite: <text>
label: <expression>
fill-color: <color>
fill-opacity: <expression>
fill-graphic:
<graphic_options>
stroke-graphic:
<graphic_options>
stroke-graphic-fill:
<graphic_options>
font-family: <expression>
font-size: <expression>
font-style: <expression>
font-weight: <expression>
placement: <point|line>
offset: <expression>
anchor: <tuple>
displacement: <tuple>
rotation: <expression>
halo:
radius: <expression>
fill-color: <color>
fill-opacity: <expression>
fill-graphic:
<graphic_options>
graphic:
symbols:
<graphic_options>
size: <expression>
opacity: <expression>
rotation: <expression>
x-allowOverruns: <boolean>
x-autoWrap: <expression>
x-conflictResolution: <boolean>
x-followLine: <boolean>
x-forceLeftToRight: <boolean>
x-goodnessOfFit: <expression>
x-graphic-margin: <expression>
x-graphic-resize: <none|proportional|stretch>
x-group: <boolean>
x-labelAllGroup: <boolean>
x-labelPriority: <expression>
x-repeat: <expression>
x-maxAngleDelta: <expression>
x-maxDisplacement: <expression>
x-minGroupDistance: <expression>
x-partials: <boolean>
x-polygonAlign: <boolean>
x-spaceAround: <expression>
Graphic options used above:
symbols:
- mark:
shape: <shape>
<<: *fill
<<: *stroke
- external:
url: <text>
format: <text>
anchor: <tuple>
displacement: <tuple>
opacity: <expression>
rotation: <expression>
size: <expression>
options: <options>
gap: <expression>
initial-gap: <expression>
Fill used above:
fill: &fill
fill-color: <color>
fill-opacity: <expression>
fill-graphic:
<<: *graphic
Stroke used above:
stroke: &stroke
stroke-color: <color>
stroke-width: <expression>
stroke-opacity: <expression>
stroke-linejoin: <expression>
stroke-linecap: <expression>
stroke-dasharray: <float[]>
stroke-dashoffset: <expression>
stroke-graphic-fill:
<<: *graphic
stroke-graphic-stroke:
<<: *graphic
Hints¶
Symbolizer hints are specified as normal mappings on a symbolizer object. Hints start with the prefix ‘x-’ and are limited to numeric, bool and text (no expressions).
If you are checking the GeoServer docs hints are called “vendor options”:
Hints can be used with any symbolizer:
point:
...
# No labels should overlap this feature, used to ensure point graphics are clearly visible
# and not obscured by text
x-labelObstacle: true
The majority of hints focus on controlling text:
text:
# When false does not allow labels on lines to get beyond the beginning/end of the line.
# By default a partial overrun is tolerated, set to false to disallow it.
x-allowOverruns: false
# Number of pixels are which a long label should be split into multiple lines. Works on all
# geometries, on lines it is mutually exclusive with the followLine option
x-autoWrap: 400
# Enables conflict resolution (default, true) meaning no two labels will be allowed to
# overlap. Symbolizers with conflict resolution off are considered outside of the
# conflict resolution game, they don't reserve area and can overlap with other labels.
x-conflictResolution: true
# When true activates curved labels on linear geometries. The label will follow the shape of
# the current line, as opposed to being drawn a tangent straight line
x-followLine: true
# When true forces labels to a readable orientation, when false they make follow the line
# orientation even if that means the label will look upside down (useful when using
# TTF symbol fonts to add direction markers along a line)
x-forceLeftToRight: true
# Sets the percentage of the label that must sit inside the geometry to allow drawing
# the label. Works only on polygons.
x-goodnessOfFit: 90
# Pixels between the stretched graphic and the text, applies when graphic stretching is in use
x-graphic-margin: 10
# Stretches the graphic below a label to fit the label size. Possible values are 'stretch',
# 'proportional'.
x-graphic-resize: true
# If true, geometries with the same labels are grouped and considered a single entity to be
# abeled. This allows to avoid or control repeated labels
x-group: false
# When false, only the biggest geometry in a group is labelled (the biggest is obtained by
# merging, when possible, the original geometries). When true, also the smaller items in the
# group are labeled. Works only on lines at the moment.
x-labelAllGroup: false
# When positive it's the desired distance between two subsequent labels on a "big" geometry.
# Works only on lines at the moment. If zero only one label is drawn no matter how big the
# geometry is
x-repeat: 0
# When drawing curved labels, max allowed angle between two subsequent characters. Higher
# angles may cause disconnected words or overlapping characters
x-maxAngleDelta: 90
# The distance, in pixel, a label can be displaced from its natural position in an attempt to
# find a position that does not conflict with already drawn labels.
x-maxDisplacement: 400
# Minimum distance between two labels in the same label group. To be used when both
# displacement and repeat are used to avoid having two labels too close to each other
x-minGroupDistance: 3
# Option to truncate labels placed on the border of the displayArea (display partial labels).
x-partials: true
# Option overriding manual rotation to align label rotation automatically for polygons.
x-polygonAlign: true
# The minimum distance between two labels, in pixels
x-spaceAround: 50
# When true enables text kerning (adjustment of space between characters to get a more compact and readable layout)
x-kerning: true
Additional hints for working with graphic fills:
# Used to specify top, right, bottom and left margins around the graphic used in the fill.
# Allowed values:
# top right bottom left (one explicit value per margin)
x-graphic-margin: 5 10 5 10
# top right-left bottom (three values, with right and left sharing the same value)
x-graphic-margin: 5 10 5
# top-bottom right-left (two values, top and bottom sharing the same value)
x-graphic-margin: 5 10
# top-right-bottom-left (single value for all four margins)
x-graphic-margin: 5
# Activates random distribution of symbol.
# none disables random distribution
x-random: none
# free generates a completely random distribution
x-random: free
# grid will generate a regular grid of positions, and only randomizes the position of the symbol
# around the cell centers, providing a more even distribution in space
x-random: grid
# Determines the size the the texture fill tile that will contain the randomly distributed symbols.
# A smaller tile size will create a more regular pattern
x-random-tile-size: 10
# Activates random symbol rotation. Possible values are none (no rotation) or free.
x-random-rotation: free
# Determines the number of symbols in the tile. Increasing this number will generate a more dense distribution of symbols
x-random-symbol-count: 5
# The “seed” used to generate the random distribution. Changing this value will result in a
# different symbol distribution.
x-random-seed property: 42
Using YSLD¶
YSLD relies on the gt-main style layer descriptor. Style files are parsed to a StyledLayerDescripter object, which can then be used by the GeoTools style renderer.
To read a YSLD style:
StyledLayerDescriptor style = Ysld.parse(ysld);
The value of ysld can be any of java.io.Reader, java.io.InputStream, @link java.io.File or java.lang.String containing a valid YSLD style.
To write a YSLD style, given a Styled Layer Descriptor:
Ysld.encode(sld, output);
The value of output can be any of java.io.Reader, java.io.InputStream, or java.io.File.
YSLD also provides a validator, which can be called using:
Ysld.validate(ysld);
This call accepts the everything that Ysld.parse(ysld) does, and returns a list of exceptions corresponding to syntax errors.