OS/2 表
最后更新 2026-11-02
本页目录
OS/2 原本是微软为了 Windows 排版给 TrueType 加的补充表(名字来自那个已经消失的操作系统)。今天它成了描述一款字体「有多重、多宽、多高」的主表,几乎所有排版软件都会读。
它也是一张典型的「兼容补丁合集」:不同版本往里加字段,旧字段的含义被新字段部分取代,所以同名概念往往有两套值。
字重与字宽
| 字段 | 取值 | 说明 |
|---|---|---|
usWeightClass |
1–1000 | 惯例是 100 的倍数:100 Thin、300 Light、400 Regular、500 Medium、700 Bold、900 Black |
usWidthClass |
1–9 | 1 Ultra-condensed … 5 Normal … 9 Ultra-expanded |
usWeightClass 是建议值,不是刻度尺:字体设计师可以把 Regular 写成 400,也可以写成 350。所以「同一款字体在不同系统里看起来粗细不一致」有时不是渲染问题,而是这个字段本来就填得不一样。
字宽是另一个维度:Condensed 版本通常 usWidthClass 更小,但家族名里也会写 Condensed。两个地方都要对得上,否则按字宽匹配的程序会挑错。
fsSelection:斜体与粗体的「开关」
fsSelection 是一个位字段,常用的几位:
| 位 | 含义 |
|---|---|
| 0 | ITALIC —— 这一款是斜体 |
| 5 | BOLD —— 这一款是粗体 |
| 6 | REGULAR —— 常规字款(与上面两位互斥) |
| 7 | USE_TYPO_METRICS —— 请用 sTypo* 那组度量,而不是 usWin* |
| 8 | WWS —— 名字符合 WWS 规则 |
第 7 位是理解「为什么同一个字体在 Mac 和 Windows 上行高不一样」的关键:它明确告诉渲染器该信哪一组上下伸。没设这一位时,不同引擎的默认选择不同。
两组上下伸
OS/2 里同时存在两套垂直度量,这是历史包袱:
| 字段 | 符号 | 来源 |
|---|---|---|
sTypoAscender / sTypoDescender / sTypoLineGap |
通常 ascender 正、descender 负 | 微软与苹果商定的「排版用」度量 |
usWinAscent / usWinDescent |
都是正数 | 早期 Windows 用来裁切与滚动的边界,按「最坏的拉丁字形」取 |
所以本站度量图里,winDescent 要先取负才能画到基线以下。反过来说,看到「下降部是正数」不要以为读错了——那是这张表的规定。
x 高度与大写高度
版本 2 之后才有:
sxHeight:小写x的高度;sCapHeight:大写字母的高度。
这两个值是声明,不是从轮廓量出来的。有的字体填得不准,有的干脆填 0。要让「不同字体在同一字号下看起来一样大」,正规做法是看真实的 x 高度,而不是信任这两个字段。
声明「我支持哪些字符」
ulUnicodeRange1..4 是 128 个位,用来大致声明「这个字体覆盖了哪些区段」(拉丁、希腊、CJK……)。ulCodePageRange1..2 类似,按代码页声明。
它们不能用来判断具体某个字符:位是区段级的,而且经常填得过宽。真要判断「有没有这个字」,只能读 cmap——本站的覆盖率就是这么算的。
其它零碎
achVendID:四字节厂商代码(如APPL、GOOG),不是商标声明;panose:十字节的「风格指纹」,用来做相似字体推荐,实践里常常全填 0;fsType:嵌入权限位(能否嵌入 PDF、是否只读嵌入),老字体里很常见「禁止嵌入」;usFirstCharIndex/usLastCharIndex:非符号字体的字符范围提示,同样只是提示。
本站怎么用它
- 字重:直接显示
usWeightClass,并且在界面上标明它可能只是近似值; - 斜体:看
fsSelection的第 0 位,而不是看家族名里有没有Italic; - 度量图的上下伸:同时画
hhea与OS/2两组,因为「哪一组算数」取决于渲染器。
延伸阅读
- OpenType 规范:
OS/2表(每个版本加了哪些字段写得很清楚) - OpenType 规范:
OS/2表的fsSelection位定义与USE_TYPO_METRICS