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
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>). null 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 PaintLayerModifier.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.
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.
protected virtual void ParseExtra(ref ParameterReader reader, in RangeApplyContext context, ref PaintLayerModifier.LayerGeometry g)Parses layer-specific tokens after the optional paint and before shared projection values into coverage parameters and an optional quad offset. Read scalars with ParameterReader.NextUnitFloat and vectors with ParameterReader.NextUnitVector2; set the matching *Px flag from the unit (UnitKind.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 clear a parse gives every attribute buffer, and stale winner indices would point into the freshly reset ranges list.
protected override void OnApply(in RangeApplyContext context)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.
