Documentation is work in progress and not completeEditor
FlashCC/The canvas/Section 6 of 29

Text measurement and fitting

The per-character advance table, greedy wrapping with pre-wrap semantics, and the size ladder that fits text to its box without ever clamping.

text.ts replaced ceil(len / 18) * size, which overflowed the artboard on long hooks. Canvas measureText was rejected deliberately: "a layout that differs between test and production is worse than one that is slightly conservative in both."

Advance table (em)

ClassCharactersAdvance
space" "0.26
thiniljI|!.,;:' ` ``0.28
narrowft()[]{}/\-r0.36
widemwMW@0.86
uppercaseA–Z0.68
digits0–90.56
everything else0.53

FAMILY_SCALE = { sans: 1, display: 1, serif: 0.97, mono: 1.15 }, MONO_ADVANCE = 0.6, SAFETY = 1.02 — a deliberate 2% over-estimate, because predicting one line too many costs a slightly smaller font and predicting one too few puts text off the slide.

Wrapping

Greedy, with pre-wrap semantics. Split on \n (hard breaks), then on /(\s+)/ keeping whitespace runs as tokens. If a word does not fit, flush the line; if the token was whitespace, drop it (browsers drop leading whitespace on a wrapped line); an over-wide single word is broken mid-word by scanning for the longest prefix that fits.

lineCount is Math.max(1, lines) — never zero.

Fitting

fitToBox sorts the ladder descending regardless of input order and returns the first size where lines × fontSize × lineHeight <= maxHeight. If none fit it returns the smallest with overflows: true and its real height. It never clamps; callers must.

ladder(max, min, steps = 12) produces evenly spaced integers, deduped. ladder(104, 40) → 104, 98, 92, 87, 81, 75, 69, 63, 57, 52, 46, 40.

clampY pins an oversized block to the top of its region rather than centring it, so the start stays readable.

This guarantee currently holds for sans and serif only. See defect D1 — it is the most consequential defect in the reference.