sbitgraft:把点阵表搬进轮廓字体

星霞宋体分成两份发布:轮廓一份,点阵一份,另附一个把两者拼起来的小工具。

分开交付由许可决定。轮廓那半来自 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。

评论

点击下面的按钮加载评论框。评论提交后需经确认,不会立即显示。