3、字体文件格式:TrueType(TTF)、OpenType(OTF)、Web字体(WOFF/WOFF2)、位图字体
字体文件格式,说白了就是字形的「容器」。不同的容器,装东西的方式、压缩率、支持的特性天差地别。我刚开始做渲染时,以为字体就是一堆点阵图,后来被 TTF 的二次贝塞尔曲线狠狠教育了一顿。
今天咱们就把主流的几种格式掰开揉碎,看看它们到底怎么存字形,各自适合什么场景。
3.1 TrueType(TTF)—— 桌面时代的基石
TrueType 是苹果和微软在 90 年代联合推出的。它的核心是用二次贝塞尔曲线描述字形轮廓。为什么用二次?因为计算简单,渲染快,当时的 CPU 扛得住。
TTF 文件结构分几大块:
- 表目录(Table Directory):索引所有数据表的位置
- glyf 表:存储每个字形的轮廓点坐标
- cmap 表:字符编码到字形索引的映射
- head 表:全局信息,比如单位 per em、字体方向
- hmtx / vmtx 表:水平/垂直度量信息
我个人习惯用 ttx 工具把 TTF 转成 XML 来查看内部结构。你试试这个命令:
# 将 TTF 转成可读的 XML
ttx -o SourceHanSansSC.xml SourceHanSansSC-Regular.ttf
# 查看 cmap 表
ttx -t cmap -o cmap.xml SourceHanSansSC-Regular.ttf
打开 XML 你会看到一堆 <TTGlyph> 节点,里面是 on 和 off 曲线点。嗯,这里要注意:on 点表示曲线上的点,off 点是控制点。二次贝塞尔每两个 off 点之间隐含一个 on 点,这是 TTF 特有的隐式约定。
3.2 OpenType(OTF)—— 更强大的容器
OpenType 是 Adobe 和微软在 TTF 基础上扩展的格式。它支持两种轮廓描述方式:
- CFF(Compact Font Format):用三次贝塞尔曲线,由 Adobe 主导
- TrueType 轮廓:兼容 TTF 的二次贝塞尔
三次贝塞尔比二次多一个控制点,曲线更平滑,文件更小。你想想看,同样的字形,CFF 版本通常比 TTF 版本小 30%-50%。
OTF 最大的亮点是高级排版特性:
| 特性 | 说明 | 典型应用 |
|---|---|---|
| 连字(Ligature) | 将多个字符替换为单个字形 | fi → fi, fl → fl |
| 上下文替换 | 根据前后字符自动替换字形 | 阿拉伯语首/中/尾形 |
| 花体变体 | 同一字符提供多种风格 | 书法字体中的 swash |
| 旧式数字 | 数字的上伸/下伸风格 | 正文排版更自然 |
这些特性通过 GSUB 表和 GPOS 表实现。GSUB 管替换,GPOS 管位置微调。我建议你打开一个支持连字的 OTF 字体,用 hb-shape 工具看看替换过程:
# 查看 "fidelity" 的连字替换过程
hb-shape --font-file=MyFont.otf "fidelity"
# 输出类似:f_i.liga|d|e|l|i|t|y
看到 f_i.liga 了吗?那就是连字替换后的字形名。
otfinfo 查看 --format,如果返回 CFF 就是真 OTF。
3.3 Web 字体(WOFF / WOFF2)—— 为网络而生
WOFF 本质上是 TTF/OTF 的压缩包。它加了一个 40 字节的文件头,包含元数据(版权、版本等),然后用 zlib 压缩。WOFF2 更进一步,用 Brotli 压缩,并针对字形轮廓做了自定义预处理。
我记得第一次对比 WOFF 和 WOFF2 的压缩率时,结果让我很惊讶:
| 格式 | 压缩算法 | 典型压缩率(相对 TTF) | 解压速度 |
|---|---|---|---|
| WOFF | zlib (deflate) | 60%-70% | 快 |
| WOFF2 | Brotli + 字形预处理 | 40%-50% | 中等 |
WOFF2 的预处理包括:
- 轮廓点坐标变换:将绝对坐标转为差值,减少数值范围
- 重复指令合并:相同 hinting 指令只存一次
- 表级重排:按访问频率重新排序表,提升解压效率
实际项目中,我建议你:
- 中文网站优先用 WOFF2,因为中文字体动辄几 MB,压缩收益巨大
- WOFF 作为降级方案,兼容 IE11 等老浏览器
- 不要直接引用 TTF/OTF 做 Web 字体,加载慢且浪费带宽
3.4 位图字体—— 像素级的精确控制
位图字体就是把每个字形存成固定大小的像素矩阵。没有轮廓,没有曲线,只有 0 和 1。常见格式有 BDF、PCF、FNT。
为什么现在还有人用位图字体?三个场景:
- 嵌入式系统:LCD 屏幕、LED 点阵屏,不需要缩放
- 终端/控制台:等宽位图字体渲染快,无锯齿
- 极小字号:8px 以下,矢量字体的 hinting 很难做好,位图反而清晰
BDF(Bitmap Distribution Format)是纯文本格式,可读性最好。一个字符的定义长这样:
STARTCHAR A
ENCODING 65
SWIDTH 500 0
DWIDTH 8 0
BBX 8 10 0 -2
BITMAP
00
7C
82
82
82
FE
82
82
82
00
ENDCHAR
每行十六进制数代表一行的像素。比如 7C 展开成二进制是 01111100,正好 8 个像素。
PCF(Portable Compiled Format)是 BDF 的二进制编译版,加载更快。FNT 是 Windows 的老格式,现在基本只在内核驱动里见到。
3.5 格式对比与选型建议
为了让你一目了然,我把四种格式的核心差异整理成一张表:
| 维度 | TTF | OTF (CFF) | WOFF2 | 位图 |
|---|---|---|---|---|
| 轮廓类型 | 二次贝塞尔 | 三次贝塞尔 | 同源字体 | 无 |
| 文件大小 | 大 | 中 | 小 | 极小(单尺寸) |
| 缩放质量 | 依赖 hinting | 较好 | 同源字体 | 差(需多尺寸) |
| 高级排版 | 有限 | 丰富 | 同源字体 | 无 |
| 适用场景 | 桌面/文档 | 专业排版 | Web 加载 | 嵌入式/终端 |
选型时我的建议很简单:
- 做 Web 项目,无脑选 WOFF2,降级到 WOFF
- 做桌面软件,用 OTF(CFF),文件小且曲线平滑
- 做嵌入式,用位图字体,但要准备 3-5 个常用尺寸
- 做字体设计,从 TTF 开始,工具链最成熟
3.6 格式内部结构图
下面这张 SVG 图展示了四种字体格式的内部结构对比,帮你建立整体认知:
这张图把四种格式的核心组件和适用场景串起来了。你可以看到,TTF 和 OTF 是「母体」,WOFF2 是「压缩包」,位图字体是「独立分支」。理解了这个关系,后面学渲染管线时就不会迷路。