因为工作需要,我需要读取TTF字体文件里面的字节码点分区信息,以此对字进行分类筛选。

利用FontCreator软件打开TTF文件,我们可以看到分区如下图所示:

如上图所示,我们虽然可以查看分区信息,但是如果批量进行手动查询,工作量还是不少的。

所以我们利用FontTools插件对TTF文件进行解析。

流程总共分为4步:

  • 利用FontTools插件对TTF字体文件进行解析
  • 利用FontTools将TTF转换成我们能够读取的形式➡xml文件
  • 利用Lxml插件对xml文件进行信息节点读取
  • 将信息进行包装并存储

方法内容如下:

import re
from fontTools.ttLib import TTFont
import lxml.etree as ET
import csv


'''
    此函数用来读取TTF字体文件中的字节码点分区信息并将其存储进csv
'''

def unicodePartition(url, name):
    # 利用fontTolls读取TTF文件内容
    font = TTFont('{}\{}.TTF'.format(url, name))
    # 利用fontTolls将字体文件信息存储为xml文件
    font.saveXML('{}\{}.xml'.format(url, name))
    # 利用lxml读取xml文件(树)
    tree = ET.parse('{}\{}.xml'.format(url, name))
    # 获取其根节点
    root = tree.getroot()
    # 存储分区信息
    data = []
    # 存储字节码点
    unicode = []

    # camp标签下的部分内容如下,
    # <cmap>
    #     <cmap_format_4 platformID="3" platEncID="1" language="0">
    #         <map code="0x20" name="space"/>
    #         <!-- SPACE -->
    #         <map code="0x21" name="exclam"/>
    #         <!-- EXCLAMATION MARK -->
    #         <map code="0x22" name="quotedbl"/>
    #         <!-- QUOTATION MARK -->
    #         <map code="0x4e00" name="uni4E00"/>
    #         <!-- CJK UNIFIED IDEOGRAPH-4E00 -->
    #         <map code="0x4e01" name="uni4E01"/>
    #         <!-- CJK UNIFIED IDEOGRAPH-4E01 -->
    #         <map code="0x4e03" name="uni4E03"/>
    #         <!-- CJK UNIFIED IDEOGRAPH-4E03 -->
    #     </cmap_format_4>
    # </cmap>

    # 遍历cmap标签下的cmap_format_4标签内容
    for i in root.xpath('//cmap/cmap_format_4')[1]:
        # 此时的i相当于<map code="0x20" name="space"/>或者<!-- SPACE -->
        # 读取其text内容,只有<!-- SPACE -->这种注释才能读取出text信息
        if (i.text):
            # 按空格进行分割
            text = re.split(r'[ ]+', i.text)
            # 因为分割完有极个别的为[' ',spcae,' ']这种的,故按长度进行下识别.
            if len(text) == 3:
                data.append(text[1])
            else:
                data.append(text[1] + '-' + text[2])
        else:
            # 按0x进行分割
            result = re.split(r'0x', i.get('code'))
            if len(result) == 2:
                code = result[1]
            else:
                code = result[0]
            unicode.append(code)
    # 在字体文件下新建相应的csv文件用来存储结果
    csvFile = open('{}\{}.csv'.format(url, name), 'w', newline='')
    try:
        # 创建一个文件写入流
        writer = csv.writer(csvFile)
        # 写个表头
        writer.writerow(('unicode', 'partition'))
        # 分别将字节码点和分区信息写进csv
        for i, j in zip(unicode, data):
            writer.writerow((i, j))
    finally:
        # 关闭文件写入流
        csvFile.close()


if __name__ == '__main__':
    unicodePartition('E:\\fontunicode', 'STCAIYUN')

运行完效果如下: