Takumi

Text

Draw shaped runs or collect values for a text exporter.

A paragraph's text is one TextNode. node.runs holds its runs in visual order. A run is text shaped with one font and size. A <b> starts a new run.

Read a run

Hover a run to see its fields. The dot marks run.x and run.y, where the baseline starts.

text
"Text arrives as "
element
none
line
0
x, y
24, 46
width
135.44
ascent
20.1
descent
5.9
fontSize
20
lineHeight
30
font
Geist 400
paragraph.tsx
import {  } from "takumi-paint";

export const  = await (
  < ={{ : 260, : 24, : 0, : 20, : "30px" }}>
    Text arrives as <>shaped runs</> with their baselines.
  </>,
  { : 308 },
);
FieldValue
x, yBaseline start, in the text node's local space
widthAdvance
ascent, descentTypographic distances from the baseline
lineIndex of the line, from 0
elementThe inline element the run came from, such as <b>

The text node comes before the inline boxes in its paragraph. Its runs can sit on both sides of those boxes.

run.transform is set when text-fit scales the line. Apply it before placing the run at x, y.

Draw glyphs

run.outline() returns the glyphs as SVG path data. The paths start at the baseline start. Drawing them needs no font engine.

DrawableDraw
glyphsFill the outline with paint, blurred by blur
glyphs with strokeStroke the outline, as -webkit-text-stroke does
masked under background-clip: textDraw the background layers, masked by the glyphs

A native text API reads run.glyphs instead. It holds glyph IDs in run.font and their offsets from the baseline start. run.font.data() returns the font file. Runs in the same face share one Font object.

Lay text out again

A slide writer can rebuild a text box from the paragraph box and the run fields.

slides.tsx
import {  } from "takumi-paint";

const  = await (
  < ={{ : 240, : 12, : "center", : "30px" }}>Title</>,
  { : 320 },
);

const  = ..(() =>
  . === "text"
    ? [
        {
          : .?., 
          : .,
          : .,
          : ..(() => ({
            : .,
            : .,
            : .,
            : .,
            : .,
            : [., .], 
          })),
        },
      ]
    : [],
);

.();
ValueField
Text boxnode.parent.contentBox
Alignmentnode.textAlign
Linerun.line
Text and facerun.text, run.font
Font sizerun.fontSize
Line heightrun.lineHeight
Letter spacingrun.letterSpacing
Baselinerun.x, run.y

run.letterSpacing is already in the glyph positions. Under line-height: normal, a fallback face can make run.lineHeight taller.

Last updated on

On this page