480 lines
21 KiB
Markdown
480 lines
21 KiB
Markdown
Title: The Node file format
|
||
|
||
GSK render nodes can be serialized and deserialized using APIs such as `gsk_render_node_serialize()` and `gsk_render_node_deserialize()`. The intended use for this is development - primarily the development of GTK - by allowing things such as creating testsuites and benchmarks, exchanging nodes in bug reports. GTK includes the `gtk4-node-editor` application for creating such test files.
|
||
|
||
The format is a text format that follows the [CSS syntax rules](https://drafts.csswg.org/css-syntax-3/). In particular, this means that every array of bytes will produce a render node when parsed, as there is a defined error recovery method. For more details on error handling, please refer to the documentation of the parsing APIs.
|
||
|
||
The grammar of a node text representation using [the CSS value definition syntax](https://drafts.csswg.org/css-values-3/#value-defs) looks like this:
|
||
|
||
document: <@-rule>*<node>
|
||
@-rule: @cicp "name" { <property>* }
|
||
node: container [ "name" ] { <document> } | <node-type> [ "name" ] { <property>* } | "name"
|
||
property: <property-name>: <node> | <value> ;
|
||
|
||
Each node has its own `<node-type>` and supports a custom set of properties, each with their own `<property-name>` and syntax. The following paragraphs document each of the nodes and their properties.
|
||
|
||
When serializing and the value of a property equals the default value, this value will not be serialized. Serialization aims to produce an output as small as possible.
|
||
|
||
To embed newlines in strings, use \A. To break a long string into multiple lines, escape the newline with a \.
|
||
|
||
# Names
|
||
|
||
### Nodes
|
||
|
||
Nodes can be given a name by adding a string after the `<node-type>` in their definition. That same node can then be used further down in the document by specifying just the name identifying the node.
|
||
|
||
### Textures
|
||
|
||
Just like nodes, textures can be referenced by name. When defining a named texture, the name has to be placed in front of the URL.
|
||
|
||
# Color states
|
||
|
||
Color states are represented either by an ident (for builtin ones) or a string
|
||
(for custom ones):
|
||
|
||
color-state: <ident> | <string>
|
||
|
||
Custom color states can be defined at the beginning of the document, with an @cicp rule.
|
||
|
||
The format for @cicp rules is
|
||
|
||
@cicp "name" {
|
||
...
|
||
}
|
||
|
||
The following properties can be set for custom color states:
|
||
|
||
| property | syntax | default | printed |
|
||
| --------- | ---------------- | -------- | ----------- |
|
||
| primaries | `<integer>` | 2 | always |
|
||
| transfer | `<integer>` | 2 | always |
|
||
| matrix | `<integer>` | 2 | always |
|
||
| range | `<range>` | full | non-default |
|
||
|
||
Note that the primaries, transfer and matrix properties always need
|
||
to be specified, since GTK does not allow creating color state objects
|
||
with these being set to 2 (== unspecified).
|
||
|
||
Range can have the following values:
|
||
|
||
range: narrow | full
|
||
|
||
# Colors
|
||
|
||
Colors can be specified with a variation of the modern CSS color syntax:
|
||
|
||
color(<color-state> <number> <number> <number> ["/" <number>])
|
||
|
||
The traditional syntax for sRGB colors still works as well:
|
||
|
||
rgba(<number>, <number>, <number>, <number)
|
||
rgb(<number, <number>, <number>)
|
||
|
||
# Rectangles
|
||
|
||
Rectangles can be specified just as four integers for x, y, width and height:
|
||
|
||
rect: <number> <number> <number> <number>
|
||
|
||
Rounded rectangles use a CSS-like syntax:
|
||
|
||
rounded-rect: <rect> [ "/" <number>{1,4} [ "/" <number>{1,4} ] ]
|
||
|
||
# Nodes
|
||
|
||
### container
|
||
|
||
The **container** node is a special node that allows specifying a list of child nodes. Its contents follow the same rules as an empty document.
|
||
|
||
### blend
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bottom | `<node>` | color { } | always |
|
||
| mode | `<blend-mode>` | normal | non-default |
|
||
| top | `<node>` | color { } | always |
|
||
|
||
Creates a node like `gsk_blend_node_new()` with the given properties.
|
||
|
||
Possible values for the mode property are:
|
||
|
||
blend-mode: normal | multiply | screen | overlay | darken |
|
||
lighten | color-dodge | color-burn | hard-light |
|
||
soft-light | difference | exclusion | color |
|
||
hue | saturation | luminosity
|
||
|
||
### blur
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| blur | `<number>` | 1 | non-default |
|
||
| child | `<node>` | color { } | always |
|
||
|
||
Creates a node like `gsk_blur_node_new()` with the given properties.
|
||
|
||
### border
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| colors | `<color>{1,4}` | black | non-default |
|
||
| outline | `<rounded-rect>` | 50 | always |
|
||
| widths | `<number>{1,4}` | 1 | non-default |
|
||
|
||
Creates a node like `gsk_border_node_new()` with the given properties.
|
||
|
||
For the color and width properties, the values follow the typical CSS order
|
||
of top, right, bottom, left. If the last/left value isn't given, the 2nd/right
|
||
value is used. If the 3rd/bottom value isn't given, the 1st/top value is used.
|
||
And if the 2nd/right value also isn't given, the 1st/top value is used for
|
||
every 4 values.
|
||
|
||
### cairo
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | none | always |
|
||
| pixels | `<url>` | none | non-default |
|
||
| script | `<url>` | none | non-default |
|
||
|
||
The pixels are a base64-encoded data url of png data. The script is
|
||
a base64-encoded data url of a cairo script.
|
||
|
||
### clip
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| clip | `<rounded-rect>` | 50 | always |
|
||
|
||
Creates a node like `gsk_clip_node_new()` with the given properties.
|
||
|
||
As an extension, this node allows specifying a rounded rectangle for the
|
||
clip property. If that rectangle is indeed rounded, a node like
|
||
`gsk_rounded_clip_node_new()` will be created instead.
|
||
|
||
### color
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| color | `<color>` | #FF00CC | always |
|
||
|
||
Creates a node like `gsk_color_node_new()` with the given properties.
|
||
|
||
The color is chosen as an error pink so it is visible while also reminding
|
||
people to change it.
|
||
|
||
### color-matrix
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| matrix | `<transform>` | none | non-default |
|
||
| offset | `<number>{4}` | 0 0 0 0 | non-default |
|
||
|
||
Creates a node like `gsk_color_matrix_node_new()` with the given properties.
|
||
|
||
The matrix property accepts a <transform> for compatibility purposes, but you
|
||
should be aware that the allowed values are meant to be used on 3D transformations,
|
||
so their naming might appear awkward. However, it is always possible to use the
|
||
matrix3d() production to specify all 16 values individually.
|
||
|
||
### conic-gradient
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| center | `<point>` | 25, 25 | always |
|
||
| rotation | `<number>` | 0 | always |
|
||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||
|
||
Creates a node like `gsk_conic_gradient_node_new()` with the given properties.
|
||
|
||
### cross-fade
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| end | `<node>` | color { } | always |
|
||
| progress | `<number>` | 0.5 | non-default |
|
||
| start | `<node>` | color { } | always |
|
||
|
||
Creates a node like `gsk_cross_fade_node_new()` with the given properties.
|
||
|
||
### debug
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| message | `<string>` | "" | non-default |
|
||
|
||
Creates a node like `gsk_debug_node_new()` with the given properties.
|
||
|
||
### fill
|
||
|
||
| property | syntax | default | printed |
|
||
| --------- | --------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | *see below* | always |
|
||
| path | `<string>` | "" | always |
|
||
| fill-rule | `<fill-rule>` | winding | always |
|
||
|
||
Creates a node like `gsk_fill_node_new()` with the given properties.
|
||
|
||
The default child node is the default color node, but created with the
|
||
bounds of the path.
|
||
|
||
Possible values for the fill-rule property are:
|
||
|
||
fill-rule: winding | even-odd
|
||
|
||
### glshader
|
||
|
||
| property | syntax | default | printed |
|
||
| ---------- | ------------------ | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| sourcecode | `<string>` | "" | always |
|
||
| args | `<uniform values>` | none | non-default |
|
||
| child1 | `<node>` | none | non-default |
|
||
| child2 | `<node>` | none | non-default |
|
||
| child3 | `<node>` | none | non-default |
|
||
| child4 | `<node>` | none | non-default |
|
||
|
||
Creates a GLShader node. The `sourcecode` must be a GLSL fragment shader.
|
||
The `args` must match the uniforms of simple types declared in that shader,
|
||
in order and comma-separated. The `child` properties must match the sampler
|
||
uniforms in the shader.
|
||
|
||
### inset-shadow
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| blur | `<number>` | 0 | non-default |
|
||
| color | `<color>` | black | non-default |
|
||
| dx | `<number>` | 1 | non-default |
|
||
| dy | `<number>` | 1 | non-default |
|
||
| outline | `<rounded-rect>` | 50 | always |
|
||
| spread | `<number>` | 0 | non-default |
|
||
|
||
Creates a node like `gsk_inset_shadow_node_new()` with the given properties.
|
||
|
||
### linear-gradient
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| start | `<point>` | 0 0 | always |
|
||
| end | `<point>` | 0 50 | always |
|
||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||
|
||
Creates a node like `gsk_linear_gradient_node_new()` with the given properties.
|
||
|
||
### mask
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| source | `<node>` | color { } | always |
|
||
| mode | `<mask-mode>` | alpha | non-default |
|
||
| mask | `<node>` | color { } | always |
|
||
|
||
Creates a node like `gsk_mask_node_new()` with the given properties.
|
||
|
||
Possible values for the mode property are:
|
||
|
||
mask-mode: alpha | inverted-alpha | luminance | inverted-luminance
|
||
|
||
### opacity
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| opacity | `<number>` | 0.5 | non-default |
|
||
|
||
Creates a node like `gsk_transform_node_new()` with the given properties.
|
||
|
||
### outset-shadow
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| blur | `<number>` | 0 | non-default |
|
||
| color | `<color>` | black | non-default |
|
||
| dx | `<number>` | 1 | non-default |
|
||
| dy | `<number>` | 1 | non-default |
|
||
| outline | `<rounded-rect>` | 50 | always |
|
||
| spread | `<number>` | 0 | non-default |
|
||
|
||
Creates a node like `gsk_outset_shadow_node_new()` with the given properties.
|
||
|
||
### radial-gradient
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| center | `<point>` | 25 25 | always |
|
||
| hradius | `<number>` | 25 | always |
|
||
| vradius | `<number>` | 25 | always |
|
||
| start | `<number>` | 0 | always |
|
||
| end | `<number>` | 1 | always |
|
||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||
|
||
Creates a node like `gsk_radial_gradient_node_new()` with the given properties.
|
||
|
||
### repeat
|
||
|
||
| property | syntax | default | printed |
|
||
| ------------ | ---------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | *bounds of child node* | non-default |
|
||
| child | `<node>` | color { } | always |
|
||
| child-bounds | `<rect>` | *bounds of child node* | non-default |
|
||
|
||
Creates a node like `gsk_repeat_node_new()` with the given properties.
|
||
|
||
### repeating-linear-gradient
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| start | `<point>` | 0 0 | always |
|
||
| end | `<point>` | 0 50 | always |
|
||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||
|
||
Creates a node like `gsk_repeating_linear_gradient_node_new()` with the given
|
||
properties.
|
||
|
||
### repeating radial-gradient
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| center | `<point>` | 25 25 | always |
|
||
| hradius | `<number>` | 25 | always |
|
||
| vradius | `<number>` | 25 | always |
|
||
| start | `<number>` | 0 | always |
|
||
| end | `<number>` | 1 | always |
|
||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||
|
||
Creates a node like `gsk_repeating_radial_gradient_node_new()` with the given
|
||
properties.
|
||
|
||
### rounded-clip
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| clip | `<rounded-rect>` | 50 | always |
|
||
|
||
Creates a node like `gsk_rounded_clip_node_new()` with the given properties.
|
||
|
||
### shadow
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| shadows | `<shadow>` | black 1 1 | always |
|
||
|
||
Creates a node like `gsk_shadow_node_new()` with the given properties.
|
||
|
||
### stroke
|
||
|
||
| property | syntax | default | printed |
|
||
| ----------- | ------------------ | ----------------- | ----------- |
|
||
| child | `<node>` | *see below* | always |
|
||
| path | `<string>` | "" | always |
|
||
| line-width | `<number>` | 0 | non-default |
|
||
| line-cap | `<line-cap>` | butt | always |
|
||
| line-join | `<line-join>` | miter | always |
|
||
| miter-limit | `<number>` | 4 | non-default |
|
||
| dash | `<number>{+}|none` | none | non-default |
|
||
| dash-offset | `<number>` | 0 | non-default |
|
||
|
||
Creates a node like `gsk_stroke_node_new()` with the given properties.
|
||
|
||
The default child node is the default color node, but created with the
|
||
stroke bounds of the path.
|
||
|
||
Possible values for the line-cap property are:
|
||
|
||
line-cap: butt | round | square
|
||
|
||
Possible values for the line-join property are:
|
||
|
||
line-join: miter | round | bevel
|
||
|
||
### text
|
||
|
||
| property | syntax | default | printed |
|
||
| ------------ | ------------------- | ------------------- | ----------- |
|
||
| color | `<color>` | black | non-default |
|
||
| font | `<string>` `<url>`? | "Cantarell 15px" | always |
|
||
| glyphs | `<glyphs>` | "Hello" | always |
|
||
| offset | `<point>` | 0 0 | non-default |
|
||
| hint-style | `<hint-style>` | slight | non-default |
|
||
| antialias | `<antialias>` | gray | non-default |
|
||
| hint-metrics | `<hint-metrics>` | off | non-default |
|
||
|
||
Creates a node like `gsk_text_node_new()` with the given properties.
|
||
|
||
If a url is specified for the font, it must point to a font file for the
|
||
font that is specified in the string. It can be either a data url containing
|
||
a base64-encoded font file, or a regular url that points to a font file.
|
||
|
||
Glyphs can be specified as an ASCII string, or as a comma-separated list of
|
||
their glyph IDs. Optionally, the advance width, x and y offsets and flags can
|
||
be specified as well, like this: 40 10 0 0 color.
|
||
|
||
If the given font does not exist or the given glyphs are invalid for the given
|
||
font, an error node will be returned.
|
||
|
||
Possible values for the hint-style property are:
|
||
|
||
hint-style: none | slight | full
|
||
|
||
Possible value for the antialias property are:
|
||
|
||
antialias: none | gray
|
||
|
||
Possible value for hint-metrics are:
|
||
|
||
hint-metrics: on | off
|
||
|
||
### texture
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ------------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| texture | `<string>`?`<url>`? | *see below* | always |
|
||
|
||
Creates a node like `gsk_texture_node_new()` with the given properties.
|
||
|
||
If a string is specified for the texture, it will be used as a name for the text.
|
||
Textures can be reused by specifying the name of a previously used texture. In
|
||
that case, the url can be omitted.
|
||
|
||
The default texture is a 10x10 checkerboard with the top left and bottom right
|
||
5x5 being in the color #FF00CC and the other part being transparent. A possible
|
||
representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQXY0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=")
|
||
`.
|
||
|
||
### texture-scale
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| bounds | `<rect>` | 50 | always |
|
||
| texture | `<url>` | *see below* | always |
|
||
| filter | `filter` | linear | non-default |
|
||
|
||
Creates a node like `gsk_texture_scale_node_new()` with the given properties.
|
||
|
||
The default texture is a 10x10 checkerboard, just like for texture.
|
||
|
||
Possible values for the filter property are:
|
||
|
||
filter: linear | nearest | trilinear
|
||
|
||
### transform
|
||
|
||
| property | syntax | default | printed |
|
||
| -------- | ---------------- | ---------------------- | ----------- |
|
||
| child | `<node>` | color { } | always |
|
||
| transform| `<transform>` | none | non-default |
|
||
|
||
Creates a node like `gsk_transform_node_new()` with the given properties.
|