1// Type metrics, which live in a font file rather than in a table anyone can2// write down. One context that exists only to measure, kept apart from the3// canvas that paints so a measurement never disturbs a transform mid-frame.45let ruler = null;67function context() {8 if (ruler) return ruler;9 if (typeof document === "undefined") return null;10 ruler = document.createElement("canvas").getContext("2d");11 return ruler;12}1314export function measure(text, size, face, track) {15 const ctx = context();16 // Before the faces load — and in any environment without a canvas at all,17 // which is what the headless checks are — the faces' own advance is the18 // honest estimate: both are cut on a fixed grid, Tiny5 at five-eighths of the19 // em and DM Mono at three-fifths.20 const advance = face === "Tiny5" ? 0.625 : 0.6;21 if (!ctx)22 return Math.max(0, text.length * size * advance + (text.length - 1) * track);23 ctx.font = `${size}px ${face}`;24 let width = -track;25 for (const ch of text) width += ctx.measureText(ch).width + track;26 return width;27}