游戏人间
首发于游戏人间
FontPruner 字体精简工具

FontPruner 字体精简工具

需求

FontPruner 是我们 16 年底开发的一个小工具,可以通过白名单机制来消除字体文件 (.ttf) 中大量的冗余符号,减小字体文件的尺寸,从而降低其包体占用和内存开销。

我们知道,中文字体普遍个头比较大,小的 3-5 MB,大一些的 10-20 MB,有的甚至还更大一些。而通过 FontForge 这样的工具可以看出,汉字仅占字体文件的一半不到(其他为日韩等语言和特殊符号),而其中常用 3000 字又仅占汉字总量的5%,所以理论上这个开销能缩减到原尺寸的 1/10 以内。

(下图是我机器上已安装的字体列表)




思路

要精简这些字体的尺寸,一个简单的做法是,找到中文,英文,标点符号它们各自的起止点,把在范围之外的其他语言字符去掉。这样做逻辑上很简单,但是有几个问题,一是游戏文本中可能用到特殊字符没有在我们框定的范围内,二是汉字中有 80% 是实际上使用频率极低的冷僻字,而偏偏是这些冷僻字笔画特别多,用于描述字形的 glyph data 的数据量,比常用的简化字要大得多。

那么有没有更好的方法呢?

一个改进的方案是,扫描所有游戏中可能出现的文本信息,生成一个活跃字表 (Active Character Table, ACT),然后把这个表之外的字符全部剔除。

使用这种白名单的方式,我们可以更精确地释放那些冷僻字占用的空间,但需要注意的事情有两点:

  1. 当游戏内容改变时,要及时更新我们的 ACT 表。
  2. 聊天框的用户输入可能出现任意字符,建议直接使用系统已有的默认字体

这个白名单方案有一个额外的好处,就是能顺便帮我我们找出所有游戏内的可显示文本,有助于统一规范化游戏内所有文本的引用,便于之后可能的本地化工作。


原理

基于上面说的白名单方案,我们制作了工具 FontPruner,它的主要工作原理如下:



简单地解释一下,FontPruner 首先收集游戏内可能出现在屏幕上的各类文本,生成白名单(也就是曾经在游戏中出现过所有字符的集合),然后调用 sfntly 对字体文件做精简处理。


流程

具体的处理流程如下所示:



我们可以定期在 Build 机器上执行此工具,这样游戏内容变更时,可以自动更新对应的字体文件。


效果

接下来是精简的具体效果:



上图分别是 ttf 包含 1/4/100/200/500 个中文字体时,文件尺寸的变化情况。根据该测试数据可知,在包含 5000 常用字的情况下,对于一个 28MB 的字体文件,我们可以把字体的开销控制在 3-5MB 左右。


资源

关于此工具的更多信息,请访问下面的链接:

github.com/GameBuilding

如果基于此工具有好的想法,欢迎一起讨论~


Gu Lu

文章被以下专栏收录

    因为热爱游戏,所以不管玩游戏也好,做游戏也罢,能把人生当游戏,不断地探索新的乐趣,并以此为生,此之谓“游戏于人间”。 而立之后,时常感叹交流得太少。若能常漫步于游戏人之间,分享心得体会,不失为一趣,寓“行走于游戏人之间”之意。