字的研究(2)fontTools-字体文件的解析

【自取】最近整理的,有需要可以领取学习:

前言

本文主要介绍了使用第三方库FontTools对OpenType字体文件(包括TrueType Outline和PostScript Outline)的解析操作。

[En]

This article mainly introduces the parsing operation of OpenType font files (including TrueType outline and Postscript outline) by using Python third-party library fontTools.

fontTools简介

fontTools是由一组操作字体的库和组件组成的Python第三方库,要求 Python3.6以及更高的版本。其中包括merge(字体合并)、subset(取字体子集)以及ttx(将OpenType转化为XML)等。

安装

pip install fontTools

本文使用的版本是4.28.5

[En]

The version used in this article is 4.28.5

字体文件的解析

读取

如前文所述,OpenType字体文件标准是有sfnt结构封装的,基于sfnt的表结构,OpenType格式的字体文件可以分为多个表结构。

创建TTFont实例,通过keys()可以查看字体文件的所有表名:

from fontTools.ttLib.ttFont import TTFont
font = TTFont("Resources/simsun.ttf")
print(font.keys())

运行结果如下:

[En]

The running results are as follows:

['GlyphOrder', 'head', 'hhea', 'maxp', 'OS/2', 'hmtx', 'cmap', 'fpgm', 'prep', 'cvt ', 'loca', 'glyf', 'name', 'post', 'gasp', 'EBDT', 'EBLC', 'GDEF', 'GPOS', 'GSUB', 'MERG', 'meta', 'vhea', 'vmtx']

表名中包含’glyf’,所以simsun.ttf是一个使用TrueType轮廓的字体文件。

换成使用Postscript轮廓的字体文件:

font = TTFont("Resources/AdobeSongStd-Light.otf")
print(font.keys())

运行结果如下:

[En]

The running results are as follows:

['GlyphOrder', 'head', 'hhea', 'maxp', 'OS/2', 'name', 'cmap', 'post', 'CFF ', 'BASE', 'GPOS', 'GSUB', 'VORG', 'hmtx', 'vhea', 'vmtx', 'DSIG']

表名中没有’glyf’而存在’CFF ‘,后者是存储Postscript信息的表格。

对于TrueType Collection文件则可以使用如下方法读取,返回一个TTFont实例的列表

from fontTools.ttLib.ttCollection import TTCollection
collection = TTCollection("Resources/simsun.ttc")
print(list(collection))

运行结果如下:

[En]

The running results are as follows:

[, ]

直接从这些表中提取特定信息很复杂,但TTFont提供了一些轻松获取信息的方法:

[En]

Extracting specific information directly from these tables is complex, but TTFont provides some ways to get the information easily:

font.getGlyphOrder() # 返回一个字形名称列表,以其在文件中的顺序排序
font.getGlyphNames() # 返回一个字形名称列表,以字母顺序排序
font.getBestCmap() # 返回一个字形ID为键、字形名称为值的字典
font.getReverseGlyphMap() # 返回一个字形名称为键、字形ID为值的字典
font.getGlyphName(10000) # 输入字形ID返回字形名称
font.getGlyphID("uni70E0") # 输入字形名称返回字形ID
font.getGlyphSet() # 返回一个_TTGlyphSet对象,包含字形轮廓数据

在上述方法中,最后一种与等高线数据相关的方法是最重要的。遗憾的是,官方文件似乎没有对这个对象做出任何进一步的解释,所以以下是我在阅读源代码及其评论后的分析。如果有任何错误或遗漏,请让我知道。

[En]

Of the above methods, the last one related to contour data is the most important. Unfortunately, the official document does not seem to give any further explanation to this object, so the following is my analysis after reading the source code and its comments. If there are any mistakes or omissions, please let me know.

Pen与_TTGlyphset

我认为,作者设计这一部分时的难点在于OpenType字体文件标准存在两种不同轮廓描述方式。Pen和_TTGlyphset的存在使得两种不同的轮廓描述方式可以用同一套方法解析和显示。

The Pen Protocol

基于TrueType轮廓的字体文件和基于Postscript轮廓是两种截然不同的数据格式。Pen是一个用于标准化的”画”出轮廓的对象,或者是数据和实际轮廓间的媒介。

具体来说,Pen对象的子类包含将上述两种轮廓数据转化为画线、移动等模拟实际轮廓的方法。在fontTools的pen库中包含将轮廓数据转化为qt、reportLab等第三方库中实例的Pen子类。

_TTGlpyhset

_TTGlyphset是一个类似字典的,以字形名称为键、_TTGlyph为值的对象。_TTGlyph中包含字形数据轮廓数据并可以通过draw方法”画”出。_TTGlyph的两个子类_TTGlyphGlyf和_TTGlyphCFF分别对应TrueType轮廓和Postscript轮廓。具体使用方法如下:

font = TTFont("Resources/simsun.ttf")
glyph = font.getGlyphSet()["uni70E0"]
glyph.draw(pen) # pen为实例化后的Pen子类

freetypePen

以freetype-py库为例,使用freetypePen首先需要安装freetype-py:

pip install freetype-py

下面的代码修改了FontTool官方文档中提供的示例程序:

[En]

The following code modifies the sample program provided from the official documentation of fontTools:

from fontTools.ttLib import TTFont
from fontTools.pens.freetypePen import FreeTypePen
from fontTools.misc.transform import Offset

pen = FreeTypePen(None) # 实例化Pen子类
font = TTFont("Resources/simsun.ttf") # 实例化TTFont
glyph = font.getGlyphSet()["uni70E0"] # 通过字形名称选择某一字形对象
glyph.draw(pen) # "画"出字形轮廓
width, ascender, descender = glyph.width, font['OS/2'].usWinAscent, -font['OS/2'].usWinDescent # 获取字形的宽度和上沿以及下沿
height = ascender - descender # 利用上沿和下沿计算字形高度
pen.show(width=width, height=height, transform=Offset(0, -descender)) # 显示以及矫正

运行结果如下:

[En]

The running results are as follows:

字的研究(2)fontTools-字体文件的解析

注意,可能由于fontTools==4.28.5版本问题,通过pip安装后freetypePen.py并没有包含在pens文件夹下,需要使用的可以从fontTools的GitHub仓库中下载,放到site-packages\fontTools\pens文件夹下,下载路径为https://github.com/fonttools/fonttools/blob/main/Lib/fontTools/pens/freetypePen.py。该问题可能在后续版本中修复。

ttx

最后,我个人认为FontTools中最有用的组件之一TTX是将TTFont实例转换为XML格式,并将XML文件转换为TTFont。基于这个组件,我们可以很容易地修改字体文件的内容。

[En]

Finally, I personally think that one of the most useful components in fontTools, ttx, is to convert TTFont instances to XML format and XML files to TTFont. Based on this component, we can easily modify the content of the font file.

from fontTools.ttLib import TTFont

font = TTFont("Resources/simsun.ttf") # 实例化TTFont
font.saveXML("simsun.xml") # TTFont实例转化为XML文件,参数为XML文件路径
font.importXML("simsun1.xml") # XML文件转化为TTFont实例,参数为XML文件路径

除了将整个字体文件转换为XML文件外,TTX还可以将文件中的单个表转换为XML文件,避免了不必要的存储和时间消耗:

[En]

In addition to converting the entire font file to a XML file, ttx can also convert a single table in the file to an XML file, avoiding unnecessary storage and time consumption:

from fontTools.ttLib.ttFont import TTFont

font = TTFont("Resources/simsun.ttf")
font.saveXML("temp2.xml",tables=["glyf"]) # tables为需要转化的表名组成列表

单个表的XML文件直接导入TTFont时,只会影响XML文件存在的表,而其他表不变:

font.importXML("temp2.xml")

参考

https://fonttools.readthedocs.io/en/latest/index.html

https://github.com/fonttools/fonttools

Original: https://www.cnblogs.com/yc0806/p/15842529.html
Author: 多事鬼间人
Title: 字的研究(2)fontTools-字体文件的解析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/7273/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

发表回复

登录后才能评论
免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部