用 pyftsubset 裁中文字体,只保留用到的 800 个字,命令直接报 KeyError: 0x4e2d,输出的字体文件 0 字节。同样的命令裁英文字体没问题。日志里能对上时间点,这种反而好排。
字体是 CFF 轮廓的 OTF,字符映射和字形名对不上,子集化时按 glyph id 找不到对应项。pyftsubset 默认按 unicode 取字形,缺少 layout 特性时连替换表也一起丢。命令失败后还是生成了空文件。这一点先确认清楚,后面就不用反复试。
pyftsubset SourceHanSans.ttf --text-file=used.txt --output-file=sub.ttf --layout-features='*' --no-hinting --desubroutinize
python -c "from fontTools.ttLib import TTFont; f=TTFont('sub.ttf'); print(len(f.getBestCmap()))"
围绕「fonttools 子集化」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
报错里带路径的,先去看那个路径在不在、权限对不对。
处理上按这个顺序:先用 ttLib 打开字体 确认是 glyf 还是 CFF;加 --no-hinting 和 --desubroutinize 处理 CFF 轮廓;显式传 layout features 保留必需特性;子集化后重新加载 检查字数表和文件大小。
结果对不对很好判断,子集化命令退出码为 0,输出文件大于 20KB,浏览器加载后页面上的 800 个字全部正常显示。
