Takumi

Reference

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

Entry points

APIResult
paint(node, options?)A Promise<PaintTree> using a shared painter
new Painter()A painter with its own registered fonts
painter.paint(node, options?)A Promise<PaintTree> using that painter
painter.registerFont(font)Registers a font before painting
painter.free()Releases the painter's WebAssembly memory

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

Paint options

OptionTypeEffect
width, heightnumberCanvas size in device pixels; omitted dimensions follow content
devicePixelRationumberDevice pixels per CSS pixel; default 1
fontsFontLoader[]Fonts registered before layout
imagesImagesInputImages keyed by the referenced src
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
for (const node of tree)Every node in document order, produced one at a time
node(index)The node listed at index
Iterator.from(tree)The same nodes with find, filter, and the other ES2025 iterator helpers, which stop as soon as they have an answer
paintSteps()Steps a renderer takes, in paint order

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; iterable
TextNodetextAlign with start and end resolved, runs in visual order
ImageNodeimage: the decoded 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 IDs and offsets from the baseline start
outline()Glyph outlines 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
Filterblur, color-matrix, drop-shadow, unsupported
Effectsopacity, blendMode, isolation, filters, backdropFilters, clip, mask

What stays unresolved

  • filter: url(#id) arrives as { type: "unsupported", css }.
  • backdrop-filter needs what is already drawn behind the node, which targets such as PPTX cannot read.
  • A translucent layer inside a box, such as a span's opacity, is multiplied into each draw, so overlapping draws in it paint darker than the renderer's layer.
  • Bitmap glyphs, such as some emoji fonts, are left out of run.outline().

Last updated on

On this page