OpenType字体规范解析(一)综述
我们在设计中经常需要使用字体文件,有时候会想一窥究竟字体文件到底是以怎样的格式存储的,OpenType就是定义字体文件存储格式的规范。
OpenType 是 Microsoft 和 Adobe 于 1996 年共同开发的字体标准,旨在统一 TrueType 和 PostScript 技术,其文件扩展名可以是 .ttf 或 .otf,取决于内部使用的字形数据格式。
OpenType字体文件规范综述见https://learn.microsoft.com/en-us/typography/opentype/spec/otff
文件结构
OpenType文件由一系列表(table)构成。
表目录
文件开头需要包含表目录。
表目录用于定义字体中所包含的所有顶级表格的信息。这些表格存储了字体渲染、布局和元数据等功能所需的数据。
表目录格式如下:
类型 | 名称 | 描述 |
---|---|---|
uint32 | sfntVersion | 0x00010000 或 0x4F54544F(即 ‘OTTO’) |
uint16 | numTables | 表格数量 |
uint16 | searchRange | 小于或等于 numTables 的最大 2 的幂,乘以 16。公式:(2floor(log2(numTables))) * 16,其中“”为指数运算符。 |
uint16 | entrySelector | 小于或等于 numTables 的最大 2 的幂的对数。公式:log2(searchRange / 16),等价于 floor(log2(numTables))。 |
uint16 | rangeShift | 表格数量乘以 16,减去 searchRange。公式:(numTables * 16) - searchRange。 |
TableRecord | tableRecords[numTables] | 表格记录数组——每个顶级表格(即字体文件中的主要表格)对应一个记录。 |
TableRecord
表目录中需要包含每个表对应的TableRecord,其中记录了每个表的概要信息。
TableRecord格式如下:
类型 | 名称 | 描述 |
---|---|---|
Tag | tableTag | 表格标识符。 |
uint32 | checksum | 此表格的校验和。 |
Offser32 | offset | 从字体文件开始的偏移量。 |
uint32 | length | 此表格的长度。 |
核心表
在表目录之后,文件需要包含每个表的具体数据。每个表由不同字段组成,字段的数据格式见下一节。
核心表及其简介:
必须表
这些表是 OpenType 字体文件中必不可少的,它们包含最基本的信息,支持字体的基础功能。
-
cmap (Character to Glyph Index Mapping Table)
描述字符编码与字形索引之间的映射,确保输入的文本字符能被正确转换为字形。 -
head (Font Header Table)
提供字体的全局信息,如版本号、字体边界框、时间戳等。 -
hhea (Horizontal Header Table)
定义水平布局的信息,包括行距、最大字形宽度等。 -
hmtx (Horizontal Metrics Table)
存储每个字形的水平指标(如宽度和左边距)。 -
maxp (Maximum Profile Table)
指定字体中的各种限制和最大值,例如最大字形数、最大堆栈深度等。 -
name (Naming Table)
包含字体的元信息,例如字体名称、版权信息、版本等。 -
OS/2 (OS/2 and Windows Metrics Table)
提供与字体相关的详细元数据,例如字重、字体类别、字符范围等。 -
post (PostScript Table)
定义字体中字形名称及 PostScript 相关信息。
描述字形的表
这些表包含字形的轮廓或图形描述数据。
-
glyf (Glyph Data Table)
定义字形的 TrueType 描述数据(仅适用于 TrueType 字体)。 -
CFF (Compact Font Format Table)
提供字形的 CFF 描述数据(适用于 CFF 字体)。 -
SVG (Scalable Vector Graphics Table)
用于存储 SVG 格式的矢量图形,用作替代字形。 -
COLR 和 CPAL (Color Tables)
用于多色字体(如 Emoji 字体),描述彩色字形和配色。
排版相关的表
这些表提供高级排版功能,支持复杂文本布局。
-
GSUB (Glyph Substitution Table)
描述字形替换规则,例如连字或字符形式的替换。 -
GPOS (Glyph Positioning Table)
描述字形定位规则,例如调整间距或添加标点符号。 -
GDEF (Glyph Definition Table)
定义字形分类及其属性。 -
BASE (Baseline Table)
提供基线的对齐信息,用于多种脚本和书写方向。 -
JSTF (Justification Table)
定义字体在文本调整中的行为,例如字符间距调整。
图像和位图表
这些表存储位图或其他替代描述的字形数据。
-
EBDT, EBLC, EBSC
描述嵌入式位图字形的数据。 -
sbix (Standard Bitmap Graphics Table)
提供与字形关联的彩色位图。 -
CBDT, CBLC
描述彩色位图字体的数据。
全局辅助表
这些表提供字体文件的全局支持信息。
-
kern (Kerning Table)
定义字对的字距调整信息(通常被 GPOS 表取代)。 -
vhea 和 vmtx
提供垂直排版的相关信息(适用于垂直书写的字体)。
数据格式
在OpenType字体文件中使用以下数据类型,也就是每个表中所包含的字段,使用以下数据类型存储。另外,所有OpenType字体均使用大端(网络)字节顺序。
数据类型 | 描述 |
---|---|
uint8 | 8位无符号整数。 |
int8 | 8位有符号整数。 |
uint16 | 16位无符号整数。 |
int16 | 16位有符号整数。 |
uint24 | 24位无符号整数。 |
uint32 | 32位无符号整数。 |
int32 | 32位有符号整数。 |
Fixed | 32位有符号定点数(16.16格式)。 |
FWORD | 描述字体设计单位中数量的int16值。 |
UFWORD | 描述字体设计单位中数量的uint16值。 |
F2DOT14 | 16位有符号定点数,低14位为小数部分(2.14格式)。 |
LONGDATETIME | 日期和时间,从UTC时间1904年1月1日午夜12点起计算的秒数,表示为64位有符号整数。 |
Tag | 由四个uint8组成的数组(长度=32位),用于标识表、设计变量轴、脚本、语言系统、特性或基线。 |
Offset8 | 指向表的8位偏移量,与uint8相同,NULL偏移=0x00。 |
Offset16 | 指向表的短偏移量,与uint16相同,NULL偏移=0x0000。 |
Offset24 | 指向表的24位偏移量,与uint24相同,NULL偏移=0x000000。 |
Offset32 | 指向表的长偏移量,与uint32相同,NULL偏移=0x00000000。 |
Version16Dot16 | 打包的32位值,包含主版本号和次版本号。(参见表版本号的格式说明)。 |
校验和(checksum)计算
校验和用于确定字体文件的数据完整性,在head表通过checksumAdjustment字段定义。
校验和通过以下方式计算:
uint32
CalcTableChecksum(uint32 *Table, uint32 Length)
{
uint32 Sum = 0L;
uint32 *Endptr = Table+((Length+3) & ~3) / sizeof(uint32);
while (Table < EndPtr)
Sum += *Table++;
return Sum;
}
值得注意的是,checksumAdjustment并不直接存储校验和,而是存储一个固定数值减去校验和的值。
其设置流程如下:
- 将 checksumAdjustment 字段设置为 0。
- 计算所有表格(包括 ‘head’ 表格)的校验和,并将每个表格的校验和值填写到表目录中的相应记录。
- 计算整个字体的校验和。
- 从 0xB1B0AFBA 中减去该值。
- 将结果存储在 ‘head’ 表格的 checksumAdjustment 字段中。
这样,可以保证最后,计算整个文件校验和时,其值等于0xB1B0AFBA就说明校验正确。
注:文章包含AI辅助生成内容,如无意中使用了您的数据,请联系笔者进行处理。
小广告
笔者开源了一款字体设计工具,可以设计字体轮廓并生成otf字体文件,欢迎来玩。源码地址:
github: https://github.com/HiToysMaker/fontplayer
gitee: https://gitee.com/toysmaker/fontplayer