What a shape's fill or stroke is painted with (§58).
§58 lists seven kinds of paint. Five are members here — solid colour,
linear, radial and conic gradients, and patterns, the last covering both of
§58's texture rows (PatternPaint) — and each member carries a
discriminant so widening stays additive and typechecked (R-6's
ScreenEffect staging mechanism, kept from R-16's one-member era). The
remaining §58 row, honestly:
procedural shader — is not a paint object and does not need to be:
a procedural paint is a §60 NodeMaterial, authored directly and worn as
the shape's material. Wrapping a shader graph in a Paint would add a
second spelling for the same object with §79 obligations §60 already
declined (a material is a catalog reference, not a document).
How each tier reaches the screen (R-16, extended 2026-08-29)
A solid paint travels as §53 per-vertex colour through the material the
author supplied — R-16's tier, unchanged to the byte: no new item kind, no
pipeline, no frame-path edit, and per-vertex colour is exact for a flat
colour.
An object paint cannot ride that path exactly (a radial gradient is not
affine; a pattern is a texture read), so it takes the pipeline RFC 0001
built: the shape derives its own material — a §60 NodeMaterial whose
graph evaluates the paint per fragment, exactly — and is an ordinary
"node" item to the render list. That is why an object-painted shape is
constructed without a material (§85 refuses the pair loudly): the paint
is the material, and R-16's two objections to a shape inventing one
dissolve at this tier — the derived material owns no GPU resource the
application must dispose, and §79 writes the paint itself, not a key.
The tier is opt-in: call registerShapePaints() once (it installs the
paint-to-graph lowering, the same move as registerNodeMaterialPipeline()
and the §37/§62 registries), or authoring an object paint throws naming the
call. A bundle that never registers carries none of the lowering.
N shapes naming the same paint values lower to the same graph bytes, so the
backend's source-keyed program cache compiles one program for all of
them (RFC 0001 §2; the lowering is a pure function, §33). The paint values
are baked into the graph as constants — re-authoring a paint every frame
therefore compiles per distinct value and is the wrong tool for animation;
animate the node, the material's §57 state, or a pattern's texture instead.
What a shape's fill or stroke is painted with (§58).
§58 lists seven kinds of paint. Five are members here — solid colour, linear, radial and conic gradients, and patterns, the last covering both of §58's texture rows (PatternPaint) — and each member carries a discriminant so widening stays additive and typechecked (
R-6'sScreenEffectstaging mechanism, kept from R-16's one-member era). The remaining §58 row, honestly:NodeMaterial, authored directly and worn as the shape's material. Wrapping a shader graph in aPaintwould add a second spelling for the same object with §79 obligations §60 already declined (a material is a catalog reference, not a document).How each tier reaches the screen (R-16, extended 2026-08-29)
A solid paint travels as §53 per-vertex colour through the material the author supplied — R-16's tier, unchanged to the byte: no new item kind, no pipeline, no frame-path edit, and per-vertex colour is exact for a flat colour.
An object paint cannot ride that path exactly (a radial gradient is not affine; a pattern is a texture read), so it takes the pipeline RFC 0001 built: the shape derives its own material — a §60
NodeMaterialwhose graph evaluates the paint per fragment, exactly — and is an ordinary"node"item to the render list. That is why an object-painted shape is constructed without amaterial(§85 refuses the pair loudly): the paint is the material, and R-16's two objections to a shape inventing one dissolve at this tier — the derived material owns no GPU resource the application must dispose, and §79 writes the paint itself, not a key.The tier is opt-in: call
registerShapePaints()once (it installs the paint-to-graph lowering, the same move asregisterNodeMaterialPipeline()and the §37/§62 registries), or authoring an object paint throws naming the call. A bundle that never registers carries none of the lowering.N shapes naming the same paint values lower to the same graph bytes, so the backend's source-keyed program cache compiles one program for all of them (RFC 0001 §2; the lowering is a pure function, §33). The paint values are baked into the graph as constants — re-authoring a paint every frame therefore compiles per distinct value and is the wrong tool for animation; animate the node, the material's §57 state, or a pattern's texture instead.