head / hhea / post:三张「小」表
最后更新 2026-11-02
EN中文
本页目录
head、hhea、post 各自只有十来个字段,名字也不像 OS/2 那样成体系,但它们决定了「一格有多细」「一行有多高」「斜体倾多少」「下划线画在哪」。三张表合起来讲,是因为它们经常被一起读。
head:全局参数
| 字段 | 说明 |
|---|---|
unitsPerEm |
字体单位的刻度。常见 1000(CFF)或 2048(TrueType),有效范围 16–16384 |
xMin / yMin / xMax / yMax |
所有字形轮廓的整体包围盒 |
macStyle |
位字段:0 粗体、1 斜体、2 下划线、3 描边、4 阴影、5 窄体、6 宽体 |
fontRevision |
数字版本号(与 name 里的版本字符串无关) |
indexToLocFormat |
loca 表用短格式还是长格式 |
magicNumber |
固定值 0x5F0F3CF5,用来确认「这确实是个字体文件」 |
created / modified |
时间戳,从 1904 年起算的秒数 |
unitsPerEm 是理解度量图的第一把钥匙:字体里所有坐标都是「每 em 分成多少格」的格数,和像素没有关系。字号 16px 时,一个 unitsPerEm = 2048 的字体里,1 格 = 16 / 2048 像素。
macStyle 与 OS/2 的 fsSelection 说的是同一件事的两套写法:前者是老 Mac 的做法,后者是 Windows 的做法。读的时候优先 fsSelection,把它当兜底。
hhea:水平排版的三条基准
| 字段 | 说明 |
|---|---|
ascender |
排版的升部(正数) |
descender |
排版的降部(通常是负数) |
lineGap |
建议的行间空隙 |
advanceWidthMax |
最宽那个字形的步进宽度 |
numberOfHMetrics |
hmtx 里有多少条完整记录(其余复用最后一条) |
caretSlopeRise / Run |
插入符的倾斜方向,斜体时用来画竖线 |
很多渲染器把 ascender + |descender| + lineGap 当作「这个字体自带的行高」。但 OS/2 里还有一组 sTypo* 与 usWin*——哪一组算数,取决于 fsSelection 的第 7 位。同一款字体在 Mac 和 Windows 上行高不同,多半就是这里的选择不同。
post:斜体与下划线
| 字段 | 说明 |
|---|---|
italicAngle |
斜体倾角,单位是度,逆时针为正;右倾的斜体是负值(常见 −12) |
underlinePosition |
下划线顶部到基线的距离,负数表示在基线以下 |
underlineThickness |
下划线粗细 |
isFixedPitch |
是否等宽字体 |
| Glyph names | 版本 2.0 才有,字形名字(A、uni4E2D 这类) |
italicAngle 常被当作「这是不是真斜体」的旁证:真斜体几乎都写了非零角度,而从正体直接倾斜的伪斜体会写 0 或者随便写一个值。它不能当唯一依据,但和 fsSelection 一起看比只看名字可靠。
三个符号方向别搞反
这是本站度量图里最容易画错的地方:
| 值 | 实际方向 |
|---|---|
hhea.descender |
负(基线以下) |
OS/2.sTypoDescender |
负 |
OS/2.usWinDescent |
正(这是「向下多少」,不是坐标) |
post.underlinePosition |
负(基线以下) |
post.italicAngle |
负 = 向右倾 |
本站在 shared/src/fonts/metrics.ts 一处把这些符号统一成「y 向上为负」的字体坐标,组件里不再翻第二次。两套方向混着用,图就会整体上下颠倒或者镜像。
三张表都不管的事
- 有没有某个字符:看
cmap; - 一共有多少字形:看
maxp; - 字重、x 高度:看
OS/2。
延伸阅读
- OpenType 规范:
head、hhea、post三节 - Apple TrueType Reference Manual:
head/post的原始定义