PaintLayerModifier
Shared engine for paint layers (fill, stroke, shadow, glow, inner-shadow). Resolves a TextPaint from the parameter, precomputes gradient/texture mapping per styled range, and stamps coverage quads through CoverageQuadOps. Thin subclasses only pick a coverage mode and parse their geometry params — all paint/mapping logic lives here once.
Remarks
ParseExtra), then the shared projection overrides [,mapping][,shape][,fit][,angle][,scale][,offset][,corners][,miterLimit][,tint][,blend][,spread]. Projection values affect gradient/texture paints; tint multiplies every paint kind. The paint slot is optional-with-rewind: only a genuine paint token (colour literal or known swatch name) is consumed; anything else rewinds to the geometry slots, so <stroke=2px> reads as a width. Each projection value resolves through the override hierarchy, weakest → strongest: swatch → modifier field → default parameters → tag attribute (ApplyProjection).Derived Types(5)
Types that inherit from PaintLayerModifier.
Nested Types
public IPaintProvider Provider{ get; set }Source of named paint swatches this layer resolves (e.g. <fill=ember>, <stroke=gold>). disables swatch resolution, leaving only inline colour tokens. A gradient or texture paint is only reachable through a swatch, so set this to give the layer a gradient/texture from code.
public PaintMapping Mapping{ get; set }How a gradient/texture paint spreads over the text (whole block, per line, per glyph, or per range). Inherit (default) uses the swatch's value; a per-range value overrides both.
public Vector2 PaintOffset{ get; set }Pan of the paint's sample origin in normalized frame units. NaN per axis uses the swatch's offset; a per-range value overrides both.
public CornerStyle Corners{ get; set }Corner treatment of this layer's offset iso-lines (outline rim, shadow spread). Round is artifact-free at any width; Sharp keeps mitered corners up to MiterLimit. Single-channel SDF mode has no perpendicular field — Sharp renders as Round there.
public Color32 Tint{ get; set }Colour multiplied with the resolved solid, gradient, or texture paint.
protected PaintRef PaintField{ get }The subclass's own [Parameter] paint, used as the default when the markup carries no paint value.
Coverage mode written to TEXCOORD2.x (see CoverageMode).
protected Color32 DefaultPaintColor{ get }Solid colour applied when the paint token is omitted entirely. White for the face/fill; dark layers (stroke, shadow) override so a bare tag still renders sensibly without a paint provider. A present-but-unresolved name still falls back to white, not this.
Parses layer-specific tokens (after paint/mapping/shape/angle/scale) into coverage params and an optional quad offset. Read scalars with NextUnitFloat / vectors with NextUnitVector2 and set the matching *Px flag from the unit (Absolute = px), so the value resolves to em at emit.
Clears the range accumulator AND releases the emitter's held gradient ramp rows — the re-run OnApply re-acquires them immediately, so an animated parameter never leaks a row reference per frame (the atlas sweep's grace period protects the currently displayed mesh). The winner buffer is zeroed here too: a granular re-apply replays without the OnEnable-time PrepareAttribute clear, and stale winner indices would point into the freshly reset ranges list.
Resolves the range's paint and geometry, then stamps the per-codepoint winner-index buffer: overlapping ranges of one modifier resolve innermost-wins ONCE here (an IsInner compare against the current holder), so the per-glyph hook reads a single buffer slot instead of scanning ranges. The buffer indexes at most 255 applied ranges per layer instance; ranges beyond that keep the earlier winner.
