Skip to content

measure · 文本度量 ​

量一行字占多大。缺省是纯估算器,不碰 canvas——这是整条管线能在 Node / CI 里跑起来的前提。

导出 ​

TextMeasurer、TextStyle、Typography、estimateTextMeasurer、createTableMeasurer、estimateCharWidth、labelLines、layoutLabelLines、labelAnchor、measureLabel、FALLBACK_FONT_SIZE、FALLBACK_LINE_HEIGHT。

签名 ​

ts
interface TextStyle { fontFamily: string; fontSize: number; lineHeight?: number }
interface Typography { fontFamily: string; fontSize: number; lineHeight: number; captionSize: number }
interface TextMeasurer {
  readonly fingerprint?: string;
  measure(text: string, style: TextStyle): Size;
}

const estimateTextMeasurer: TextMeasurer;   // 纯估算,不碰 canvas
function createTableMeasurer(table: FontWidthTable): TextMeasurer;
const FALLBACK_FONT_SIZE = 14;
const FALLBACK_LINE_HEIGHT = 1.35;

为什么单独成一个叶子模块 ​

registry(算尺寸 / 锚点)与 layout(度量阶段)都要用它。放进 layout 会造出 registry → layout 的类型环, 所以度量契约单独成一个零依赖叶子,两边都只依赖它。

Typography(就是 TextStyle 加一个 captionSize)也住在这里,theme 只是 re-export 它。 于是 registry 不必 import theme——「registry 不认识 theme」才是字面成立的。

默认度量器是纯估算器:同输入同输出、不碰 canvas、不碰字体系统——这是 headless 能成立的前提。 宿主有真实字体度量时可以注入 createTableMeasurer 或使用 @ggn/draw/measure-canvas 的 createCanvasMeasurer()。fingerprint 会进入 pipeline 布局缓存键。

导出用途
labelLines(label)Label → 行数组(字符串按 \n 切)
labelAnchor(label)取对齐(缺省 center)
measureLabel(label, style, measurer)多行尺寸:宽 = 最宽行,高 = 行数 × 行高
layoutLabelLines(label, style, measurer)按 maxWidth / overflow 折行或省略
estimateCharWidth(char, fontSize)字宽分类估算(CJK 1.0em / 窄字符 0.3em …)

MIT License