python使用ttf文件_使用Python制作繁体显示的简体字体文件

最近几天发生了一些事情,导致《剑网3免费版》(台服)关服,于是昨天突发奇想,是不是想办法修改字体文件,就可以在简体客户端里面显示出繁体呢。

思绪

得到这个想法后,我便顺手拿出一个字体文件,阅读起了TTF文件的数据结构,随手谷歌了一篇文章,大致了解到TTF文件由矢量图形表(Glyphs)、字符到矢量图的映射表 (cmap)、矩阵样式等信息表 (hmtx、hdmx、OS/2 等)构成,与想象中设计基本一致。那么我们要做的事情,就是通过一份繁简转换表,从一个繁体字体文件中读取每一个繁体字符的矢量图、矩阵样式信息、字符映射表,并修改其映射关系到对应的简体字符,然后替换或者追加到简体字体文件对应的表中即可。

实现

翻阅一些现有库,发现有python项目 FontTools 可以快速将TTF字体转化为XML信息表,这样一来就不用花时间研究如何读写二进制的字体文件了,可以将时间集中在分析了XML文件中字体各个表的数据结构。经过一上午的数据结构分析,思路已然理清,通过调用ttx命令将源字体文件转化为XML文件,然后使用xml.etree.ElementTree读取转化后的文件,分别处理glyf、cmap、hmtx、vmtx、GlyphOrder表即可,其中glyf和GlyphOrder表长度必须严格相等。

经过一小时的编码,逻辑已经实现,结果在运行时报了错

ERROR: Unhandled exception has occurred

Traceback (most recent call last):

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\tables\_c_m_a_p.py", line 114, in compile

offset = seen[id(table.cmap)]

KeyError: 2602400102464

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttx.py", line 400, in main

process(jobs, options)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttx.py", line 374, in process

action(input, output, options)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\misc\loggingTools.py", line 367, in wrapper

return func(*args, **kwds)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttx.py", line 292, in ttCompile

ttf.save(output)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\ttFont.py", line 172, in save

writer_reordersTables = self._save(tmp)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\ttFont.py", line 211, in _save

self._writeTable(tag, writer, done, tableCache)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\ttFont.py", line 632, in _writeTable

tabledata = self.getTableData(tag)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\ttFont.py", line 650, in getTableData

return self.tables[tag].compile(self)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\tables\_c_m_a_p.py", line 116, in compile

chunk = table.compile(ttFont)

File "c:\users\root\appdata\local\programs\python\python38\lib\site-packages\fontTools\ttLib\tables\_c_m_a_p.py", line 838, in compile

header = struct.pack(cmap_format_4_format, self.format, length, self.language,

struct.error: 'H' format requires 0 <= number <= 65535

追源码看了一下,是cmap_format_4长度超过了限制,这个表使用了 USHORT 作为长度存储类型,所以最大值为 65535。回头看了下字体文件,发现其中有大量的字符没有绘制,但是映射表中却填写了映射到一个空白矢量图上。于是我新加了一段处理逻辑,移除掉空白矢量图以及其映射关系,再次运行,这次没有报错得到了新的字体。

将字体放入游戏中,很完美,虽然编码实际上是GBK但是字体矢量图都被替换成了繁体字符,除了有些繁简对应一对多关系的可能有些许瑕疵,整体效果不错,优化代码后提交到 GitHub仓库,收工睡觉。(:3▓▒

2924030083.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值