Functions
Import these from @grafloria/renderer.
Functions
applyMatrix
tsfunction applyMatrix(m: Matrix, p: Point): Point
arcToCubics
SVG elliptical arc → cubic béziers (endpoint→centre parameterisation, SVG 1.1
appendix F.6). Used by A path commands — the actor shape's head, cylinder
caps, jump-point arcs.
tsfunction arcToCubics(
x1: number,
y1: number,
rx: number,
ry: number,
rotationDeg: number,
largeArc: boolean,
sweep: boolean,
x2: number,
y2: number
): PathCmd[]
boundsIntersect
tsfunction boundsIntersect(a: Bounds, b: Bounds): boolean
boundsUnion
tsfunction boundsUnion(a: Bounds | null, b: Bounds | null): Bounds | null
canvasSafety
What would canvas mode cost this diagram?
Note the asymmetry, and that it is the whole design: this question is only ever asked about stepping TO canvas. Going back to SVG can lose nothing — it only ever restores focusable, labelled, HTML-capable DOM — so it is never guarded, never refused, and always allowed.
tsfunction canvasSafety(input: CanvasSafetyInput): CanvasSafety
circlePath
tsfunction circlePath(cx: number, cy: number, r: number): PathCmd[]
classListOf
The class tokens on an element (className prop, space separated).
tsfunction classListOf(props: VNodeProps | undefined): string[]
collectDefinitions
Every id-bearing definition anywhere in the tree: paint servers and filters
from <defs>, and the per-node <clipPath>s the label engine emits INLINE
(as a sibling of the text it clips). A single recursive pre-pass, because
<defs> is appended LAST by the SVG renderer while the elements referencing
it are painted first.
tsfunction collectDefinitions(root: VNode): Map<string, VNode>
collectEntities
The top-level entities of a rendered tree: every keyed child of the links and nodes layers. These are the units of change — the granularity at which the SVG renderer caches, and therefore the granularity at which identity means "unchanged".
The connection-preview layer is deliberately NOT an entity: it exists only mid-drag, changes every frame, and is handled by {@link previewIsActive}.
tsfunction collectEntities(root: VNode): Map<string, VNode>
colorKeyFromPixel
#rrggbb from a picking-canvas pixel.
tsfunction colorKeyFromPixel(r: number, g: number, b: number, a: number): string | null
distanceToPath
Shortest distance from p to the path's outline (open OR closed).
tsfunction distanceToPath(cmds: PathCmd[], p: Point): number
distanceToSegment
tsfunction distanceToSegment(p: Point, a: Point, b: Point): number
ellipsePath
Ellipse centred at (cx, cy) as four cubic segments.
tsfunction ellipsePath(cx: number, cy: number, rx: number, ry: number): PathCmd[]
entityOf
node-n1 / link-l1 / port-p3 → the entity that owns the subtree.
tsfunction entityOf(vnode: VNode): EntityScope | null
explainHazards
A human-readable account of what a canvas switch would take away.
tsfunction explainHazards(hazards: readonly CanvasHazard[]): string
flattenPath
Flatten a command list into polylines. steps controls curve subdivision —
16 segments per curve keeps the deviation well under a pixel for the curve
sizes a diagram draws, and hit-testing only ever needs "within tolerance".
tsfunction flattenPath(cmds: PathCmd[], steps = 16): SubPath[]
fontString
Build the canvas font shorthand from a resolved style.
tsfunction fontString(style: ComputedStyle): string
geometryOf
VNode primitive → path commands, in the element's own local coordinates.
tsfunction geometryOf(vnode: VNode): PathCmd[]
linePath
tsfunction linePath(x1: number, y1: number, x2: number, y2: number): PathCmd[]
mergeRects
Merge rects that overlap or nearly touch, so we don't clip 40 slivers.
tsfunction mergeRects(rects: Bounds[], slack = 8): Bounds[]
multiply
m1 · m2 — apply m2 FIRST, then m1 (the SVG/canvas nesting convention).
tsfunction multiply(m1: Matrix, m2: Matrix): Matrix
nextColorKey
Colour keys for the offscreen picking canvas.
The index is spread across the 24-bit colour space with a stride so that adjacent records get FAR-APART colours. That matters: a browser antialiases even the picking pass, and a blended edge pixel between two adjacent keys must not land on a third VALID key. With a large stride, a blend of two keys is overwhelmingly likely to be a colour no record owns — which reads as "miss", not as "wrong entity". Exact-match lookup does the rest.
tsfunction nextColorKey(index: number): string
padBounds
tsfunction padBounds(b: Bounds, pad: number): Bounds
parseDashArray
"5,5" / "5 5" / [5,5] → [5, 5]. "none" → [].
tsfunction parseDashArray(value: unknown): number[] | undefined
parseInlineStyle
Parse an inline style — the renderer emits BOTH forms: a CSS string
("fill: red; stroke-width: 2", from the shape registry and the link style
computation) and an object ({ cursor: 'move' }, from the interaction
overlays). Both are normalised to kebab-case CSS declarations here.
tsfunction parseInlineStyle(style: unknown): Record<string, string>
parsePath
Parse an SVG path d string into {@link PathCmd}s.
Full command coverage (M m L l H h V v C c S s Q q T t A a Z z) including implicit repeated coordinate sets ("M 0 0 10 10" ⇒ moveto + lineto) and the smooth-curve reflection rules. Arcs are converted to cubics.
Written by hand rather than leaned on the DOM (SVGPathElement) so it works
headlessly — in Node, in a worker, in a test — which is exactly where the
canvas backend has to be provable.
tsfunction parsePath(d: string | undefined | null): PathCmd[]
parseTransform
Parse an SVG transform attribute into a matrix.
Supports the forms the renderer actually emits — translate / rotate / scale / matrix — composed left-to-right, exactly as SVG composes them. An unrecognised function is skipped rather than throwing: a transform we cannot read must not take the whole frame down.
tsfunction parseTransform(transform: string | undefined | null): Matrix
parseViewBox
"0 0 800 600" → a rectangle.
tsfunction parseViewBox(raw: unknown): Rectangle | null
pathBounds
Bounding box of the flattened path. null for an empty path.
tsfunction pathBounds(cmds: PathCmd[]): Bounds | null
pointInPath
Non-zero-winding point-in-path — the same fill rule a 2D context uses by default, so "is this point inside the filled shape?" answers identically to "did the fill put a pixel here?".
tsfunction pointInPath(cmds: PathCmd[], p: Point): boolean
polyPath
points="1,2 3,4" (or 1 2 3 4) → a polyline / polygon command list.
tsfunction polyPath(points: string | undefined, close: boolean): PathCmd[]
previewIsActive
True when the tree carries a live connection / reconnection preview. It has no stable identity and moves with the pointer, so any frame containing one is repainted whole — the honest, correct answer, and it only happens mid-drag.
tsfunction previewIsActive(root: VNode): boolean
readCssVarOverrides
Read the --grafloria-* values ACTUALLY COMPUTED on a host element.
This is what makes canvas mode honour a host that overrides the theme through
CSS (.dark-mode [data-grafloria-instance] { --grafloria-node-fill: #222 }) — the
variable is resolved by the browser's own cascade and handed to the canvas
resolver as a concrete value. Returns {} in a headless environment.
tsfunction readCssVarOverrides(element: Element | null | undefined): Record<string, string>
rectPath
Axis-aligned rectangle, with optional (possibly asymmetric) corner radii.
tsfunction rectPath(
x: number,
y: number,
width: number,
height: number,
rx = 0,
ry = rx
): PathCmd[]
rotation
tsfunction rotation(degrees: number, cx = 0, cy = 0): Matrix
scaling
tsfunction scaling(sx: number, sy: number = sx): Matrix
textAlignFor
SVG text-anchor → canvas textAlign.
tsfunction textAlignFor(anchor: ComputedStyle['textAnchor']): CanvasTextAlign
textBaselineFor
SVG dominant-baseline → canvas textBaseline.
The renderer only ever emits middle (centred labels), hanging (top-aligned
text blocks) and baseline; anything else falls back to the canvas default,
which is what an unset dominant-baseline means in SVG too.
tsfunction textBaselineFor(baseline: string | undefined): CanvasTextBaseline
textLines
The lines a <text> element draws.
Two shapes, both emitted by the shared text-block engine:
- single line →
textContenton the<text>itself, - multi line → one
<tspan>per line, each withxand adyoffset from the running baseline (the firstdycarries the block's vertical alignment). Canvas has no tspan, so the dy chain is accumulated here.
tsfunction textLines(vnode: VNode, x: number, y: number): TextLine[]
toNumber
"2px" / 2 / "2" → 2. Returns undefined for anything unparseable.
tsfunction toNumber(value: unknown): number | undefined
transformCmds
tsfunction transformCmds(cmds: PathCmd[], m: Matrix): PathCmd[]
translation
tsfunction translation(dx: number, dy: number): Matrix
Was this page helpful?