星霞宋体分成两份发布:轮廓一份,点阵一份,另附一个把两者拼起来的小工具。
分开交付由许可决定。轮廓那半来自 SIL 开放字体许可 1.1 的字体,点阵那半来自 GNU 通用公共许可证第 2 版、附字体嵌入例外的 BDF 源码。两套许可不能合成一个文件再分发,只能在本地拼。
拼合因此是产品的一部分,工具需要可靠,也需要在输入不合格时拒绝写出文件。
移植的是表结构
工具叫 sbitgraft,一个 C 文件,无外部依赖,随两个字体仓库的发行版一起发布(sbitgraft-<版本>.tar.xz)。它把点阵那侧的 EBDT、EBLC、EBSC 三张表搬到轮廓那侧,随后重算各表校验和与 head.checkSumAdjustment。
接着按 tag 排序重建表目录,改写 name 表的变长字符串池,写出 1.0 版的字体集合头。
这种移植按表结构做,不依赖写死的字节偏移,对任意一对满足前提的字体都成立。
前提不合格就不写文件
内嵌点阵按 glyph ID 索引,两个输入必须对同一个码点指向同一个 glyph ID。
工具会先逐码点比对两侧的字符映射表。不一致时打印出前几个冲突的码点并退出,不写任何文件。拼接的产物会被装进系统,损坏的字体往往要到某个具体页面才现形,因此校验必须在写出文件之前完成。
hinting 相关的三处处理
移除 hinting 时,fpgm、prep、cvt 三张表与每个字形的指令块都要删。maxp 里为解释器保留的字段也必须一并清零,maxZones 置 1,其余置 0。光栅器按那些数字分配栈与存储空间;若它们仍描述一个已不存在的解释器,校验工具会报错。
gasp 不在删除之列。它描述渲染方式,与网格对齐无关,没有 hinting 的字体同样需要它。
复合字形也要处理。它的指令块位于最后一个组件之后,必须逐个跨过组件才能定位到。
打包成字体集合
同一个家族的几个 face 只在 name、post、OS/2 这几张小表上有差别。逐字节相同的表只存一份,字体集合的体积因此接近单个 face,而不是各 face 体积之和。
head 不参与共享,每个 face 需要自己的 checkSumAdjustment。
工具的能力边界
会做:
- 解析 SFNT 表目录
- 按 tag 读写表
- 重算校验和
- 重建表目录
- 改写
name表 - 写字体集合头
不做:
- 重映射字符映射表
- 子集化
- 增删字形
glyf 只在移除 hinting 时解析,只读到定位指令块所需的深度,不解析坐标。
分开交付是许可要求的;工具在输入不一致时不写文件。
工具与它拼接的两份字体在 https://github.com/lunzima/GlowSong 与 https://github.com/lunzima/GlowHei。
评论
点击下面的按钮加载评论框。评论提交后需经确认,不会立即显示。
已提交,确认后会显示。