Paint
Lay out JSX or HTML and get the shapes, text runs, and images to draw.
takumi-paint is takumi's paint tree output, for drawing a layout with your own API. It shares one layout engine, a port of Chromium's layout, with image output and PDF output. Where those produce pixels or pages, it returns the paint tree: what to draw, where, and in which order, with every CSS value resolved.
Draw the tree on Canvas, write it into editable slides such as PPTX, or pass it to a native drawing API.
Install
npm i takumi-paintPaint JSX
paint() takes JSX, an HTML string, or a node tree, and returns a PaintTree. The demos on these pages paint this card when the site builds.
import { } from "takumi-paint";
export const = await (
< ={{ : "flex", : 24, : "#F7F3EC" }}>
<
={{
: "flex",
: "column",
: 10,
: 272,
: 20,
: "white",
: "2px solid #E7E0D4",
: 16,
: "0 8px 20px rgba(60, 40, 20, 0.16)",
}}
>
<
={{
: 48,
: 48,
: 24,
: "hidden",
: "linear-gradient(135deg, #8B5CF6, #F472B6)",
}}
/>
< ={{ : 22 }}>Hello, paint</>
< ={{ : 0.6, : 14 }}>Boxes, text, and steps</>
</>
</>,
{ : 368 },
);
Read the nodes
tree.nodes lists every node in document order.
import { } from "takumi-paint";
const = await (
< ="card" ={{ : 240, : 16, : "#F7F3EC" }}>
Hello <>world</>
</>,
{ : 320 },
);
const = ..(() => . === "box" && .?. === "card");
.(?.[0]); // { type: "fill", role: "background", shape: { type: "rect", … }, … }
for (const of .) {
if (. !== "text") continue;
for (const of .) .(., .?., ..);
}| Node | Holds |
|---|---|
box | A CSS box: its background, border, shadows, and children |
text | One paragraph, as shaped runs in visual order |
image | A replaced image, such as <img> or an SVG |
Lengths are in device pixels. devicePixelRatio scales CSS lengths during layout.
tree.toJSON() returns the tree as plain JSON, without font files, so you can hand it to another process.
Choose a guide
| Need | Read |
|---|---|
| Draw nodes in order | Drawing |
| Place text or lay it out again | Text |
| Check options and field types | Reference |
Reuse a painter
paint() uses one shared Painter. Create your own Painter to keep a separate font registry, and call free() to release its WebAssembly memory.
import { } from "takumi-paint";
const = new ();
try {
const = await .(<>Hello</>, { : 320 });
.(.);
} finally {
.();
}Painter also has registerFont(), unregisterFont(), and clearFonts(), and takes the same fontCacheMaxBytes option as PdfRenderer.
Runtimes
takumi-paint has the same entries as takumi-pdf, which are the default import, takumi-paint/next, and takumi-paint/no-init with takumi-paint/wasm-url. See Runtimes.
Last updated on