搞定了一个只在Windows系统下可以使用的字体

最近接手了一个很急的项目,但解决一个字体的坑就浪费了元旦后的这一个礼拜,不得不周日也过来搞这个,今天终于解决了,喜极而泣,对这种遭遇想到了那句话:

明明是个算法工程师,硬生生的搞成了个开发

废话不多说,简单介绍下背景吧。项目需要的字体叫“汉鼎简中黑”,大家可以上谷歌搜,基本出来的都是同一个文件,这里给出链接:汉鼎简中黑-站长字体

按理说是TrueType字体,那就是通用的啊。但是这种字体却用PIL打不开,调用的函数在Pillow (PIL Fork) 3.0.0 documentation,encoding的几种方法我都试了,全都没用,要么报错要么就直接显示一段空白,达不到显示字体的效果。

但奇怪的是,这个在Windows下却是能够打开的,还能加到字体库里,在Word里打出这种字体。。。


一、原因

这种怪事肯定要查的,但查了好久一点思路都没有,PIL源码都看了,依然感觉没有错误啊,调用没有问题啊。

然后感觉可能是这个字体文件有问题,别的网站上的字体文件应该没问题吧,就各种试了,大概把谷歌结果的前两页都试了一遍,依旧没有结果,查看文件属性,发现建立日期都在1970年,压缩包大小都是2.1MB,这些网站也是相互乱抄。

天无绝人之路,周五终于让我找到了一个查bug的工具了,FootTools,主要利用了里面的ttx命令,具体可参考原创 Font­Tools安装与使用简明指南 [论坛存档] - 极限社区Font­Tools 安装与使用简明指南

安装可参考fonttools,从 python 操作字体文件的库,下载fonttools的源码_GitHub_帮酷

pip install fonttools

比如这样可以打印出字体文件的表信息:

ttx -l 1.TTF

打印的结果是:

Listing table info for "1.TTF":
    tag     checksum    length    offset
    ----  ----------  --------  --------
    OS/2  0x00000000        78   3563724
    cmap  0x00000000      1748   3561896
    cvt   0xFF000000         8     34102
    fpgm  0x00000000        48   3563644
    glyf  0x00000000   3494038     34118
    head  0x00000000        54       236
    hhea  0x00000000        36       290
    hmtx  0x00000000     33740   3528156
    loca  0x00000000     33744       326
    maxp  0x00000000        32     34070
    mort  0x00000000       200   3559838
    name  0x00000000       639   3563802
    post  0xFF000000        32   3563692
    prep  0x00000000         8     34110

还可以这样将.TTF文件转为.ttx文件:

ttx 1.TTF

这是一个xml文件,可以用编辑器查看里面的内容,发现里面就是一个巨大的表,代表的意思可以参考刘枭扬:ttx 和字型檔 'name' 表|OpenType, etc. 創刊ttf文件结构解析 - blueangle17的专栏 - CSDN博客


二、解决

从name表可以知道这个是适用于Windows系统的,这也解决了开头的那个问题,为什么只有Windows系统能显示这个字体。

带来的一个问题是有些Windows的字符在Unix系统下使用不了,所以第一步就是删掉这些不合规的字体。

改好了之后就可以把.ttx文件转为.TTF文件了:

ttx 1.ttx

不过可以发现,这个依然是不成功的,说明还有些参数需要设置。

查看cmap表,platformID为"3",参考刘枭扬:ttx 和字型檔 'name' 表|OpenType, etc. 創刊,发现platEncID为"3"表示为"PRC",这里将其改为"1",即"Unicode 基本文平面 (UCS-2)"。

再次调用转码指令就可以成功了。

----------------------------------------此处是高兴过早的分界线----------------------------------------

然而的然而,我测试了这个字体,又是一个奇怪的现象,打印数字和字母结果是正确的,打印汉字却常常乱码或不显示,这委实又是一个大问题啊,让人头疼。

又开始了漫长的debug之路,我设置字符为"\ue7c7",发现打印出的字是"缜",参考【缜】字的含义,可知这个编码正是GBK编码。由于这个字体过于古老,里面的编码是GBK,而不是现在通用的Unicode编码。

接下来就是算法工程师搞开发的关键一步了,将cmap表里对应的GBK编码统一换成Unicode编码,得到新的.ttx文件后转码即可。


【已完结】

编辑于 2019-09-05

文章被以下专栏收录