The paint tree
Read what the renderer paints with takumi-paint, for PPTX, Canvas, and native drawing exporters.
takumi-paint lays out a document and returns what painting it would draw, instead of an image. Use it when the output is not pixels: an editable PPTX, a Canvas replay, a native drawing API.
import { } from "takumi-paint";
const = await (
`<style>.big { font: 700 40px Geist; color: #B3261E }</style>
<div style="width: 640px; padding: 32px; background: #F7F3EC">
<div class="big">4,2 %</div>
<p>hello <b>world</b></p>
</div>`,
{ : 640 },
);
const = .;
.?..; // [247, 243, 236, 255]
for (const of . ?? []) {
for (const of . ?? []) {
const = .[.];
.(., ?., ?., ., .);
}
}The package runs the same layout as takumi-js and walks the same stacking-context scene the image, SVG, and PDF backends paint. It records used values: a 50% width is a number, currentColor is a color, and <b>world</b> is its own run with its own face.
Coordinates
Every length is a device pixel, and so are the width and height options. A 20px font measures 40 under a devicePixelRatio of 2.
A node's transform is an absolute matrix placing its border box on the canvas. Everything inside a node, such as clip, boxDecoration, image, and runs, is relative to the node's border-box top-left.
Paint order
Nodes come in the order the renderer paints them, so zIndex does not appear: draw a node's boxDecoration, then its image, inlineBackgrounds, and runs, then its children, then its boxDecoration.outline.
Each node is a compositing group. Its opacity, clip, and blendMode apply to everything inside it, children included.
Fields
Prop
Type
Description
source?PaintSourceThe input node this box came from: its child-index path, id, tag name, and class name
boxDecoration?PaintBoxDecorationUsed background, border widths, colors, styles and radii, box shadows split inset and outer, and the outline
image?PaintImageThe content box an image sits in and where it draws after object-fit and object-position
runs?PaintTextRun[]Shaped text runs with their font instance, size, color, decorations, and glyph positions
inlineBackgrounds?PaintInlineBackground[]One rounded rectangle per line for each inline span with a background
unresolvedEffects?PaintUnresolvedEffectsfilter, backdrop-filter, mask-image, and clip-path as CSS text
Runs reference tree.fonts by index. A font instance names the registered family, the face index, the weight and style after variations, and any synthetic bold or skew the shaper applied.
What stays CSS
Gradients come resolved: stops in pixels along the axis, plus the tile geometry. filter, backdrop-filter, mask-image, and clip-path are carried as CSS text under unresolvedEffects, so an exporter can decide what to do with them.
Last updated on