Paint
Lay out JSX or HTML with takumi-paint and get the shapes, text runs, and images to draw with your own renderer.
Use takumi-paint when you want the laid-out boxes, text runs, and images and plan to draw them with your own renderer. You can draw the tree on Canvas, write it into editable slides such as PPTX, or pass it to a native drawing API.
takumi-paint shares one layout engine, a port of Chromium's layout, with image output and PDF output. Those produce pixels or pages. takumi-paint returns a paint tree that says what to draw, where, and in which order, with every CSS value resolved.
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 runs |
| Check options and field types | Paint 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