字体瘦身

110 阅读2分钟

遇到的问题

通过react-pdf渲染报告,需要显示病人的信息,当渲染病人名字中的一个"卸"字时却得到如下结果: 上图中病人的姓名"不卸一"中的"卸"字没有正确显示。

报告使用的字体为 ttf 格式的思源字体(SourceHanSansSC),大小不到 5M,应该被瘦身过,但是已无法从前同事那得知这个字体从何而来。

在 mac 上通过glyph(可试用,windows 用 FontCreator),打开该思源字体,发现汉字近 7000 个,却没有"卸"字。

双击字体通过 glyph 打开: 搜索卸字,没有搜索到结果:

因此只能重新下载ttf 格式(react-pdf 只支持 ttf 格式,官方下载为 otf 格式)的思源字体。

清除不必要的字形

下载好的字体有 30M,用 glyph 打开发现有很多不需要的东西(不需要的图标、日语、符号等):

通过直接在 glyph 上删除字形,再重新导出 ttf 会有问题,尝试其他方案包括font-spiderFont-min等都有问题,最后找到sfnttool(需安装java 环境),它可以保留需要的字形。 fork sfnttool 项目到新的仓库并添加执行脚本,在项目根目录下运行 yarn start 就可以对字体进行瘦身了:

保留的字符包括一些中英文的标点符号、英文字母、常用汉字(6000 多个)等:

const chineseChars = require('./chinese-chars');

const BASE_CHARS = `!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_\abcdefghijklmnopqrstuvwxyz{|}~¥®·—…、。《》「」【】〔〕〜`;
const PUNCTUATION = `(),|≤≥!:;?‘’“”`;

module.exports = `/.notdef\u0001` + BASE_CHARS + PUNCTUATION + chineseChars;

瘦身后的思源字体 SourceHanSansSC 从原来的 30M 降到了 3M 多,进行测试发现字符 ≤ 和 ≥ 无法显示,最后通过 glyph 打开看到这俩字符的 unicode 码为空: 手动添加后(≤2264 和 ≥2265)重新导出 ttf 就能够正确显示了。

结果: