字体基础知识:分类、度量与编码
做字体渲染这些年,我最大的感受是:不懂字体分类和度量,写出来的渲染代码迟早要翻车。刚入行时我总觉得「不就是画几个字嘛」,直到被衬线体的 hinting 坑过一次,才老老实实回来补基础。
这一章咱们把三个核心概念讲透:字体的分类、度量体系、字符编码。别小看这些,它们是后面所有渲染算法的基础。
字体的分类
字体分类这事儿,说白了就是看笔画末端有没有「小爪子」。我习惯把字体分成三大类:
衬线体(Serif)
笔画末端有装饰性的「衬线」,像小爪子一样。典型代表:Times New Roman、宋体。
- 特点:横细竖粗,衬线引导视线横向流动
- 适用场景:印刷正文、长文阅读
- 渲染难点:小字号时衬线容易糊成一团,需要 hinting 干预
无衬线体(Sans-serif)
没有装饰性衬线,笔画粗细均匀。典型代表:Helvetica、微软雅黑、思源黑体。
- 特点:简洁现代,屏幕可读性好
- 适用场景:UI 界面、网页正文、小字号显示
- 渲染优势:笔画简单,抗锯齿效果好处理
等宽字体(Monospace)
每个字符占据相同宽度。典型代表:Consolas、Source Code Pro、Courier New。
- 特点:字符对齐整齐,适合代码和表格
- 适用场景:代码编辑器、终端、ASCII 艺术
- 渲染注意:等宽不代表所有字符视觉宽度一致,i 和 w 的留白差异需要微调
| 分类 | 典型字体 | 主要用途 | 渲染难度 |
|---|---|---|---|
| 衬线体 | Times New Roman、宋体 | 印刷、长文 | 高(小字号需 hinting) |
| 无衬线体 | Helvetica、微软雅黑 | 屏幕 UI、网页 | 中 |
| 等宽字体 | Consolas、Source Code Pro | 代码、终端 | 低(但对齐要求高) |
字体的度量
字体度量是渲染引擎的「坐标系」。你想想看,如果不知道基线在哪,字符就全飘在天上了。我画个图帮你理解:
核心度量术语
- 基线(Baseline):所有字符的「地面」,大部分字符底部对齐于此
- 上升部(Ascender):从基线到最高点的距离,包含大写字母和上伸部分
- 下降部(Descender):从基线到最低点的距离,如 g、j、p 的下伸部分
- x-高度(x-Height):小写字母 x 的高度,影响小字号可读性
- 大写高度(Cap Height):大写字母的高度
关键点:渲染时所有字符的位置都基于基线计算。上升和下降决定了行高,x-高度决定了小字号的清晰度。我见过有人把上升和下降设反了,结果文字上下颠倒——嗯,调试时还挺好笑的。
度量在渲染中的实际应用
举个例子,你要计算两行文字之间的行距:
// 伪代码:计算行高
lineHeight = ascender - descender + lineGap
// 下一行起始 Y 坐标
nextLineY = currentLineY + lineHeight
我曾经在某个项目中,直接用了字体的 emSize 作为行高,结果行间距大得离谱。后来才发现,emSize 是设计空间,不是实际行高。实际行高要用 ascender - descender 算。
字符编码
字符编码是计算机和字体之间的「翻译官」。没有编码,字体就不知道你要画哪个字。
ASCII
最基础的编码,128 个字符,包含英文字母、数字、标点和控制字符。一个字节存一个字符。
- 范围:0x00 - 0x7F
- 局限:只能表示英文,中文?不存在的
- 渲染意义:现代字体渲染基本不直接处理 ASCII,但它是所有编码的基础
Unicode
统一码,目标是给全世界所有字符一个唯一的编号。目前已经超过 14 万个字符。
- 编码方式:UTF-8、UTF-16、UTF-32
- UTF-8:变长编码,1-4 字节,兼容 ASCII,Web 和文件系统最常用
- UTF-16:2 或 4 字节,Windows 和 Java 内部使用
- UTF-32:固定 4 字节,处理简单但浪费空间
| 编码 | 字节数 | 兼容 ASCII | 常见场景 |
|---|---|---|---|
| UTF-8 | 1-4 | 是 | Web、Linux、JSON |
| UTF-16 | 2 或 4 | 否 | Windows、Java、.NET |
| UTF-32 | 4 | 否 | 内部处理、ICU 库 |
编码与字体渲染的关系
渲染引擎拿到 Unicode 码点后,需要做两件事:
- 查表:通过 cmap 表(字符映射表)找到对应的字形索引
- 取形:根据字形索引从 glyf 表(字形数据表)中取出轮廓数据
说白了,Unicode 是「门牌号」,cmap 表是「地图」,glyf 表是「房子」。没有门牌号,你就找不到房子。
本章小结
字体分类决定了渲染策略,度量体系决定了排版布局,字符编码决定了字符映射。这三者构成了字体渲染的「三角基石」。后面讲 TrueType 和 OpenType 时,你会发现所有技术细节都绕不开这些基础概念。