Skip to content

Build a custom renderer

docs/RENDERING-NGD.md in the repository contains the complete copy-and-paste-oriented consumer guide. This page is the shorter architectural view.

flowchart LR
  Host["host capabilities<br/>font metrics · minimum sizes · icons"] --> Contract["EngineContract"]
  Contract --> Engine["layoutDiagram()"]
  Program["SemanticProgram"] --> Engine
  Engine --> NGD["NGD"]
  Host --> Skin["renderer skin<br/>palette · artwork · strokes"]
  NGD --> Adapter["native adapter"]
  Skin --> Adapter --> Objects["whiteboard objects"]

If a setting changes bounds, wrapping, obstacle clearance, or connector space, provide it before layout. If it changes only paint inside resolved bounds, map it while rendering.

Before layout While rendering
exact font measurement semantic colour-role mapping
minimum node width/height native shape implementation
reserved icon size icon artwork lookup
icon hint → catalogue id manifest ordinary stroke colour/thickness
legibility floor dash rhythm, shadows, selection UI
  1. Wrap the host text API as deterministic measureText, or build a measurer from the exact regular and semibold font files. 2. Set native minimum shape and reserved icon dimensions in minSizes. 3. Run layoutDiagram() to obtain NGD.
  2. Create one root group matching coordinateSpace. 5. Traverse zLayers; switch exhaustively on group, edge, node, vector, label. 6. Map semantic colour and decoration roles to the product palette. 7. Resolve icon catalogueId values to product artwork with a visible fallback. 8. Preserve bounds, emitted text baselines, route points, caps, and vector layers.

Document, group, and vector text expose resolved baselines. Node labels expose pre-wrapped lines and use shape-specific placement rules; reproduce the reference renderer’s formulas or an equivalent native implementation without remeasuring or rewrapping them. Fully resolved node-line baselines are a useful future NGD improvement for an even thinner adapter.

The existing contract supports custom font metrics, minimum node/icon sizes, icon catalogues, colour-role agreement, and legibility floors. The renderer owns palette values, artwork, native shape primitives, ordinary stroke treatment, and viewport transforms.

NGD does not currently echo every contract input, notably iconPx, so retain the immutable render settings beside the document. The adapter can also retain NGD ids and group membership for hit-testing, selection, folding, connector handles, accessibility, and application metadata. Animation, dark mode, branded themes, selection chrome, and export formats are all natural renderer concerns as long as they preserve the solved geometry.

Typography sizes, internal shape padding, engine spacing, and most notation dimensions remain engine-owned. A product requiring a different type scale, large cap geometry, or thick layout-affecting strokes should extend the typed layout/style contract rather than overriding NGD after the fact.