GSUB 与 GPOS

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 分类:告诉上面两张表这个字形是基字、连字还是标记

共同的结构

两张表都是同一套四层结构:

  1. ScriptList:按书写系统分组,标签如 latn(拉丁)、hani(汉字)、DFLT(默认);
  2. LangSys:同一书写系统下的语言变体,如 ZHS (简体中文)、ZHT (繁体)、JAN (日文);
  3. FeatureList:每个语言下有哪些特性,用四个字母标记;
  4. LookupList:特性真正指向的查找——替换规则或定位规则。

所以这个字体支不支持小型大写 = 在 GSUB 的某个语言系统里找得到 smcp 这个特性。

GSUB 能做的几件事

查找类型 做什么 例子
单替换 一个字形换成另一个 a → a.alt
多替换 一个字形拆成多个 连写的 æ 拆回 a e
替代替换 同一位置给几个候选 样式替代 salt
连字替换 多个字形合成一个 f + i → fi
上下文替换 看前后文决定换不换 数字在分数里换成分子字形
链式上下文 更复杂的前后文规则 印度文字的连写
f i fi → 两个字形 一个字形(liga)
GSUB 的连字替換:把相邻的两个字形换成一个。方框代表字形槽,不是设计稿上的间距。

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 里写了规则,还要满足三个条件才看得见:

  1. 渲染引擎去查了这张表(有些简化引擎直接忽略);
  2. 文本里真的出现了那个组合;
  3. 特性默认开启,或者用户/样式显式开启。

所以这个字体有连字和这段文字里有连字,是两个不同的判断。

本站为什么绕开它们

分析字体时,样例图需要取字形轮廓。有些老库在遇到 GSUB 时会直接抛错(因为字形数据是替换后的、与原始轮廓对不上),所以本站对这条路径做了兜底:撞上就退回逐字形取轮廓。

这也意味着样例图里不体现连字效果——它是这个字体的字长什么样,不是这段文字排出来什么样。

延伸阅读

  • OpenType 规范:GSUB、GPOS、GDEF
  • OpenType 规范:feature tags 的完整列表
  • 本站:cmap 表