Takumi

Reference

Paint options, tree methods, and node, run, and drawable fields.

Entry points

APIResult
paint(node, options?)A Promise<PaintTree> from a shared painter
new Painter(options?)A painter with its own registered fonts
painter.paint(node, options?)A Promise<PaintTree> from that painter
painter.registerFont(font)Registers a font that stays until you remove it
painter.unregisterFont(family)Removes every face of a family
painter.clearFonts()Removes every registered font except the bundled fallback
painter.free()Releases the painter's WebAssembly memory

node accepts JSX, an HTML string, or a takumi node tree.

new Painter({ fontCacheMaxBytes }) caps the decoded fonts that fonts lists keep. Past the cap, the least recently used families are released and load again when a call lists them. Fonts from registerFont() are never released.

Paint options

OptionTypeEffect
width, heightnumberCanvas size in device pixels. An omitted dimension follows the content.
devicePixelRationumberDevice pixels per CSS pixel. Default 1.
fontsFontLoader[]Fonts registered before layout
imagesImagesInputImage bytes, keyed by the src that references them
cssCssInput | readonly CssInput[]Stylesheets applied before layout
fontFamiliesstring[]Fallback family chain for this call
langstringDefault BCP 47 language tag on the root

PaintTree

MemberValue
width, heightCanvas size in device pixels
fontsEvery Font the runs use
rootThe root BoxNode
nodesEvery node in document order, as an array
stepsSteps a renderer takes, in paint order, as an array
toJSON()The tree as plain JSON, without font files

Nodes

Every node has these fields.

FieldValue
typebox, text, or image
elementThe input element's id, tagName, className, and child path
transformMatrix from local space onto the canvas
width, heightSize of the local space
boundsThe node's rectangle on the canvas, after transform
parentThe enclosing BoxNode
drawablesWhat the node draws, in local space
NodeExtra fields
BoxNodecontentBox, outline, effects, overflowClip, children
TextNodetextAlign with start and end resolved, runs in visual order
ImageNodeimage: the decoded image's src, width, and height

TextRun

FieldValue
textFinal text, after text-transform and ellipsis
element?The inline element the run came from
x, yBaseline start in the text node's local space
widthAdvance
lineIndex of the line, from 0
ascent, descentTypographic distances from the baseline
fontThe Font the run was shaped with
fontSize, lineHeight, letterSpacingUsed text metrics in device pixels
glyphsGlyph id, x, y from the baseline start, and cluster?
outlines()Each glyph's outline as SVG path data
transform?The text-fit scale, applied before x, y

Font records family?, weight, style, stretch, variationSettings, and faceIndex. font.data() returns the font file.

Value formats

TypeFormat
Rgba[r, g, b, a], each byte from 0 to 255, in sRGB
Matrix[a, b, c, d, e, f], as setTransform takes it
Rect{ x, y, width, height }
CornerRadiitopLeft, topRight, bottomRight, bottomLeft, each an { x, y } radius
Shaperect, rounded-rect, or path (SVG path data, as new Path2D() takes it)
Paintcolor, linear-gradient, radial-gradient, conic-gradient, image, pattern
Strokewidth, dash?, cap, join
Drawablefill, stroke, shadow, glyphs, image, masked, group
Filterblur, color-matrix, drop-shadow, unsupported
Effectsopacity, blendMode, isolation, filters, backdropFilters, backdropClip?, clip?, mask?
Rolebackground, border, box-shadow, outline, image, text, text-shadow, text-stroke, text-decoration, inline-background

What stays unresolved

  • filter: url(#id) arrives as { type: "unsupported", css }.
  • backdrop-filter needs what is already drawn behind the node. Targets such as PPTX cannot read that.
  • run.outlines() holds null for glyphs the run's color does not fill. These are color font layers, which arrive as their own drawables, and bitmap glyphs such as some emoji.

Last updated on