GSUB 与 GPOS
最后更新 2026-11-02
- GSUB
- GPOS
- GDEF
- 连字
- 字偶距
- kern
- 特性
- locl
- 小型大写
EN中文
本页目录
cmap 只回答这个码位用哪个字形。至于 f 和 i 要不要连成一个字形、A 和 V 之间要不要收紧、中文标点要不要变窄,全在另外三张表里。它们的结构比前面几张复杂得多,但概念只有三个。
三张表的分工
| 表 | 全名 | 管什么 |
|---|---|---|
GSUB |
Glyph Substitution | 替换:把哪个字形换成哪个 |
GPOS |
Glyph Positioning | 定位:把字形往哪挪 |
GDEF |
Glyph Definition | 分类:告诉上面两张表这个字形是基字、连字还是标记 |
共同的结构
两张表都是同一套四层结构:
- ScriptList:按书写系统分组,标签如
latn(拉丁)、hani(汉字)、DFLT(默认); - LangSys:同一书写系统下的语言变体,如
ZHS(简体中文)、ZHT(繁体)、JAN(日文); - FeatureList:每个语言下有哪些特性,用四个字母标记;
- LookupList:特性真正指向的查找——替换规则或定位规则。
所以这个字体支不支持小型大写 = 在 GSUB 的某个语言系统里找得到 smcp 这个特性。
GSUB 能做的几件事
| 查找类型 | 做什么 | 例子 |
|---|---|---|
| 单替换 | 一个字形换成另一个 | a → a.alt |
| 多替换 | 一个字形拆成多个 | 连写的 æ 拆回 a e |
| 替代替换 | 同一位置给几个候选 | 样式替代 salt |
| 连字替换 | 多个字形合成一个 | f + i → fi |
| 上下文替换 | 看前后文决定换不换 | 数字在分数里换成分子字形 |
| 链式上下文 | 更复杂的前后文规则 | 印度文字的连写 |
GPOS 能做的几件事
| 查找类型 | 做什么 | 例子 |
|---|---|---|
| 单调整 | 整个字形的位移 | 上标往上挪 |
| 成对调整 | 两个字形之间加/减距离 | 字偶距(kern) |
| 附着 | 把标记挂到基字上 | 重音、阿拉伯文的音符 |
| 连写附着 | 连着写的时候挂上去 | 阿拉伯文 |
| 标记到标记 | 标记挂在标记上 | 多重附加符号 |
常用的特性标签
| 标签 | 名字 | 默认 |
|---|---|---|
liga |
标准连字(fi、fl) |
开 |
clig |
上下文连字 | 开 |
dlig |
可选连字 | 关 |
smcp |
小型大写 | 关 |
onum / lnum |
旧式 / 等高数字 | 关 / 开 |
tnum / pnum |
等宽 / 比例数字 | 关 / 开 |
frac |
分数 | 关 |
subs / sups |
下标 / 上标 | 关 |
salt / ss01–ss20 |
样式替代 / 风格集 | 关 |
locl |
本地化字形(按语言换字形) | 按语言 |
kern |
字偶距(在 GPOS 里) | 开 |
palt |
中文标点比例宽度 | 关 |
默认那一列是排版引擎的通常行为,不是规范强制;不同引擎对 dlig 之类可能不同。
同一个字,不同语言
locl 特性让同一个码位在简体中文、繁体中文、日文环境下画出不同的字形。
典型的例子是骨、直、门这类字:中日的标准写法笔画不同,但码位相同。所以这个字体在中文里长这样、在日文里长那样不是 bug,是 locl 按语言系统换了字形。
这也解释了为什么做多语言排版时,lang 属性不只是给拼写检查用的。
有表 ≠ 生效
GSUB 里写了规则,还要满足三个条件才看得见:
- 渲染引擎去查了这张表(有些简化引擎直接忽略);
- 文本里真的出现了那个组合;
- 特性默认开启,或者用户/样式显式开启。
所以这个字体有连字和这段文字里有连字,是两个不同的判断。
本站为什么绕开它们
分析字体时,样例图需要取字形轮廓。有些老库在遇到 GSUB 时会直接抛错(因为字形数据是替换后的、与原始轮廓对不上),所以本站对这条路径做了兜底:撞上就退回逐字形取轮廓。
这也意味着样例图里不体现连字效果——它是这个字体的字长什么样,不是这段文字排出来什么样。
延伸阅读
- OpenType 规范:
GSUB、GPOS、GDEF - OpenType 规范:feature tags 的完整列表
- 本站:cmap 表