ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

python fonttools字体多语言解析

python fonttools字体多语言解析
1.py
from fontTools.ttLib import TTFont # 语言ID映射表(部分常用) lang_map = { # Windows Language IDs (LCID) 0x0000: 'default', 0x0409: 'en', # English (US) 0x0809: 'en-GB', # English (UK) 0x0C09: 'en-AU', # English (Australia) 0x1009: 'en-CA', # English (Canada) 0x1409: 'en-NZ', # English (New Zealand) 0x0404: 'zh-Hant', # Chinese Traditional (Taiwan) 0x0021: 'zh-Hans', # Chinese Simplified 0x0804: 'zh-Hans', # Chinese Simplified (PRC) 0x0C04: 'zh-Hant-HK', # Chinese Traditional (Hong Kong) 0x1004: 'zh-Hant-MO', # Chinese Traditional (Macao) 0x1404: 'zh-Hans-SG', # Chinese Simplified (Singapore) 0x0411: 'ja', # Japanese (Japan) 0x0412: 'ko', # Korean (Korea) 0x040C: 'fr', # French (France) 0x080C: 'fr-BE', # French (Belgium) 0x0C0C: 'fr-CA', # French (Canada) 0x100C: 'fr-CH', # French (Switzerland) 0x0407: 'de', # German (Germany) 0x0C07: 'de-AT', # German (Austria) 0x1007: 'de-CH', # German (Switzerland) 0x040A: 'es', # Spanish (Spain, Modern Sort) 0x080A: 'es-MX', # Spanish (Mexico) 0x0C0A: 'es-ES', # Spanish (Spain, Traditional Sort) 0x0413: 'nl', # Dutch (Netherlands) 0x0813: 'nl-BE', # Dutch (Belgium) 0x0414: 'no', # Norwegian Bokmål (Norway) 0x0814: 'nn-NO', # Norwegian Nynorsk (Norway) 0x0415: 'pl', # Polish (Poland) 0x0416: 'pt-BR', # Portuguese (Brazil) 0x0816: 'pt', # Portuguese (Portugal) 0x0418: 'ro', # Romanian (Romania) 0x0419: 'ru', # Russian (Russia) 0x041B: 'sk', # Slovak (Slovakia) 0x0424: 'sl', # Slovenian (Slovenia) 0x040E: 'hu', # Hungarian (Hungary) 0x042E: 'hr', # Croatian (Croatia) 0x041F: 'tr', # Turkish (Turkey) 0x0441: 'ar-SA', # Arabic (Saudi Arabia) 0x0436: 'af', # Afrikaans (South Africa) 0x043E: 'ms', # Malay (Malaysia) 0x0439: 'hi', # Hindi (India) 0x043C: 'th', # Thai (Thailand) 0x0450: 'vi', # Vietnamese (Vietnam) 0x045A: 'hy', # Armenian (Armenia) 0x046B: 'bn', # Bengali (India) 0x0457: 'ml', # Malayalam (India) 0x0449: 'mr', # Marathi (India) 0x044C: 'ta', # Tamil (India) 0x044E: 'te', # Telugu (India) 0x047A: 'uz', # Uzbek (Latin) 0x042D: 'eu', # Basque (Basque) 0x042C: 'az', # Azerbaijani (Latin) 0x0423: 'be', # Belarusian (Belarus) 0x040D: 'he', # Hebrew (Israel) 0x041D: 'sv', # Swedish (Sweden) 0x041E: 'th', # Thai (Thailand) 0x0425: 'et', # Estonian (Estonia) 0x0426: 'fi', # Finnish (Finland) 0x042F: 'mk', # Macedonian (North Macedonia) 0x043F: 'kk', # Kazakh (Kazakhstan) 0x0443: 'mn', # Mongolian (Mongolia) 0x0444: 'ne', # Nepali (Nepal) 0x0445: 'pa', # Punjabi (India) 0x0446: 'gu', # Gujarati (India) 0x0447: 'or', # Odia (India) 0x044A: 'si', # Sinhala (Sri Lanka) 0x044B: 'lo', # Lao (Laos) 0x044D: 'bo', # Tibetan (PRC) 0x044F: 'sa', # Sanskrit (India) 0x0451: 'ky', # Kyrgyz (Kyrgyzstan) 0x0453: 'ka', # Georgian (Georgia) 0x0454: 'am', # Amharic (Ethiopia) 0x045C: 'ug', # Uyghur (PRC) 0x045D: 'gl', # Galician (Galicia) 0x045E: 'kok', # Konkani (India) 0x045F: 'syr', # Syriac (Syria) 0x0460: 'dv', # Divehi (Maldives) 0x0461: 'chr', # Cherokee (United States) 0x0462: 'iu', # Inuktitut (Canadian Aboriginal Syllabics) 0x0463: 'dz', # Dzongkha (Bhutan) 0x0464: 'km', # Khmer (Cambodia) 0x0465: 'lo_LA', # Lao (Laos) 0x0466: 'my', # Burmese (Myanmar) 0x0467: 'as', # Assamese (India) 0x0468: 'ml_IN', # Malayalam (India) 0x0469: 'kn', # Kannada (India) 0x046A: 'te_IN', # Telugu (India) 0x046B: 'bn_BD', # Bengali (Bangladesh) 0x046C: 'bn_IN', # Bengali (India) 0x046D: 'tzm', # Tamazight (Berber) (Morocco) 0x046E: 'ks', # Kashmiri (India) 0x046F: 'sd', # Sindhi (Pakistan) 0x0470: 'farsi', # Farsi (Persian) (Iran) 0x0471: 'ps', # Pashto (Afghanistan) 0x0472: 'ff', # Fulah (Senegal) 0x0473: 'ha', # Hausa (Nigeria) 0x0474: 'yo', # Yoruba (Nigeria) 0x0475: 'ig', # Igbo (Nigeria) 0x0476: 'kr', # Kanuri (Nigeria) 0x0477: 'om', # Oromo (Ethiopia) 0x0478: 'ti', # Tigrinya (Ethiopia) 0x0479: 'sn', # Shona (Zimbabwe) 0x047A: 'uz_UZ', # Uzbek (Latin) 0x047B: 'gl_ES', # Galician (Spain) 0x047C: 'af_ZA', # Afrikaans (South Africa) 0x047D: 'ka_GE', # Georgian (Georgia) } # Map keyed by platformID, then platEncID, then possibly langID # Macintosh # See # https://github.com/fonttools/fonttools/issues/236 # 0: { # Macintosh, platEncID==0, keyed by langID # 15: "mac_iceland", # 17: "mac_turkish", # 18: "mac_croatian", # 24: "mac_latin2", # 25: "mac_latin2", # 26: "mac_latin2", # 27: "mac_latin2", # 28: "mac_latin2", # 36: "mac_latin2", # 37: "mac_romanian", # 38: "mac_latin2", # 39: "mac_latin2", # 40: "mac_latin2", # Ellipsis: "mac_roman", # Other # platformID + encodingID -> 编码器名称 encoding_map = { # Unicode Platform (platformID = 0) (0, 0): 'Unicode 1.0 semantics[utf_16_be]', (0, 1): 'Unicode 1.1 semantics[utf_16_be]', (0, 2): 'ISO 10646:1993 semantics[utf_16_be]', (0, 3): 'Unicode 2.0 BMP only[utf_16_be]', (0, 4): 'Unicode 2.0 full repertoire[utf_16_be]', (0, 5): 'Unicode for ISO 10646:1997[utf_16_be]', (0, 6): 'Unicode Variation Sequences[utf_16_be]', (0, 7): 'Unicode full repertoire[utf_16_be]', # Macintosh Platform (platformID = 1) (1, 0): 'Mac Roman', (1, 1): 'x_mac_japanese_ttx[shift_jis]', (1, 2): 'x_mac_trad_chinese_ttx[big5]', (1, 3): 'x_mac_korean_ttx[euc_kr]', (1, 4): 'Mac Arabic', (1, 5): 'Mac Hebrew', (1, 6): 'Mac Greek', (1, 7): 'Mac Cyrillic', (1, 8): 'Mac Devanagari', (1, 9): 'Mac Bengali', (1, 10): 'Mac Gurmukhi', (1, 11): 'Mac Gujarati', (1, 12): 'Mac Oriya', (1, 13): 'Mac Tamil', (1, 14): 'Mac Telugu', (1, 15): 'Mac Kannada', (1, 16): 'Mac Malayalam', (1, 17): 'Mac Sinhalese', (1, 18): 'Mac Burmese', (1, 19): 'Mac Khmer', (1, 20): 'Mac Thai', (1, 21): 'Mac Laotian', (1, 22): 'Mac Georgian', (1, 23): 'Mac Armenian', (1, 24): 'Mac Chinese Simplified', (1, 25): 'x_mac_simp_chinese_ttx[gb2312]', (1, 26): 'Mac Mongolian', (1, 27): 'Mac Geez', (1, 28): 'Mac Slavic', (1, 29): 'mac_latin2', (1, 30): 'Mac Sindhi', (1, 31): 'Mac Uninterpreted', (1, 35): 'mac_turkish', (1, 37): 'mac_iceland', # iso (2, 0): 'ascii', (2, 1): 'utf_16_be', (2, 2): 'latin1', # Windows Platform (platformID = 3) (3, 0): 'Windows Symbol[utf_16_be]', (3, 1): 'Windows Unicode BMP[utf_16_be]', (3, 2): 'Windows ShiftJIS[shift_jis]', (3, 3): 'Windows PRC[gb2312]', (3, 4): 'Windows Big5[big5]', (3, 5): 'Windows Wansung[euc_kr]', (3, 6): 'Windows Johab[johab]', (3, 7): 'Windows Reserved 7', (3, 8): 'Windows Reserved 8', (3, 9): 'Windows Reserved 9', (3, 10): 'Windows Unicode UCS-4[utf_16_be]', (3, 11): 'Windows Reserved 11', (3, 12): 'Windows Reserved 12', (3, 13): 'Windows Reserved 13', (3, 14): 'Windows Reserved 14', (3, 15): 'Windows Reserved 15', (3, 16): 'Windows OEM Character Set', (3, 17): 'Windows Reserved 17', } def get_font_names(font_path): """ 提取字体文件中的名称信息,支持中文解析并映射 encoding_id 到可读编码名称。 Args: font_path: 字体文件的路径。 Returns: 一个字典,包含字体名称信息。 """ try: font = TTFont(font_path) name_table = font['name'] names = {} # 找出最长的 value 长度用于对齐 max_len = max(len(repr(v)) for v in lang_map.values()) for record in name_table.names: name_id = record.nameID platform_id = record.platformID encoding_id = record.platEncID language_id = record.langID lang_key = lang_map.get(language_id, f"0x{language_id:04X}") spaces = ' ' * (max_len - len(lang_key)) lang_key += spaces try: text = record.toUnicode() except UnicodeDecodeError: try: # 尝试手动使用 UTF-16BE 解码(常见于 Mac 平台) text = record.string.decode('utf-16-be') except Exception as e: text = f"[Decoding error: {e}]" if name_id not in names: names[name_id] = {} key = (platform_id, encoding_id, lang_key) names[name_id][key] = text name_map = { 1: 'familyName', 2: 'styleName', 4: 'fullName', 6: 'postScriptName', 16: 'preferredFamilyName', #TYPOGRAPHIC_FAMILY 17: 'preferredSubfamilyName', #TYPOGRAPHIC_SUBFAMILY 18: 'macFullName', #TT_NAME_ID_MAC_FULL_NAME 21: 'wwsFamilyName', #TT_NAME_ID_WWS_FAMILY 22: 'wwsStyleName', #TT_NAME_ID_WWS_SUBFAMILY } result = {} for name_id, name_type in name_map.items(): if name_id in names: result[name_type] = names[name_id] return result except Exception as e: print(f"Error processing font: {e}") return None finally: if 'font' in locals(): font.close() # 示例 # ===== 主程序入口 ===== if __name__ == "__main__": if len(sys.argv) < 2: print("请提供字体文件路径作为参数") print("用法: python script.py <字体文件路径>") sys.exit(1) fontPath = sys.argv[1] # fontPath = "C:\\AlibabaPuHuiTi.ttf" font_names = get_font_names(fontPath) if font_names: for name_type, name_values in font_names.items(): print(f"\nName Type: {name_type}") for (platform_id, encoding_id, lang), text in name_values.items(): encoding_desc = encoding_map.get((platform_id, encoding_id), f"Unknown ({platform_id}, {encoding_id})") print(f" - Lang: {lang} | Encoding: {encoding_desc}: {text}") else: print("无法提取字体名称")
运行

pip install fonttools
python parse.py

结果

Name Type: familyName
- Lang: default | Encoding: Mac Roman: Alibaba PuHuiTi 2.0
- Lang: zh-Hans | Encoding: x_mac_simp_chinese_ttx[gb2312]: 阿里巴巴普惠体 2.0
- Lang: en | Encoding: Windows Unicode BMP[utf_16_be]: Alibaba PuHuiTi 2.0 55 Regular
- Lang: zh-Hans | Encoding: Windows Unicode BMP[utf_16_be]: 阿里巴巴普惠体 2.0 55 Regular
Name Type: styleName
- Lang: default | Encoding: Mac Roman: 55 Regular
- Lang: zh-Hans | Encoding: x_mac_simp_chinese_ttx[gb2312]: 55 Regular
- Lang: en | Encoding: Windows Unicode BMP[utf_16_be]: Regular
- Lang: zh-Hans | Encoding: Windows Unicode BMP[utf_16_be]: Regular
Name Type: fullName
- Lang: default | Encoding: Mac Roman: Alibaba PuHuiTi 2 55 Regular
- Lang: zh-Hans | Encoding: x_mac_simp_chinese_ttx[gb2312]: 阿里巴巴普惠体 2 55 Regular
- Lang: en | Encoding: Windows Unicode BMP[utf_16_be]: Alibaba PuHuiTi 2 55 Regular
- Lang: zh-Hans | Encoding: Windows Unicode BMP[utf_16_be]: 阿里巴巴普惠体 2 55 Regular
Name Type: postScriptName
- Lang: default | Encoding: Mac Roman: AlibabaPuHuiTi_2_55_Regular
- Lang: en | Encoding: Windows Unicode BMP[utf_16_be]: AlibabaPuHuiTi_2_55_Regular
Name Type: preferredFamilyName
- Lang: en | Encoding: Windows Unicode BMP[utf_16_be]: Alibaba PuHuiTi 2.0
- Lang: zh-Hans | Encoding: Windows Unicode BMP[utf_16_be]: 阿里巴巴普惠体 2.0
Name Type: preferredSubfamilyName
- Lang: en | Encoding: Windows Unicode BMP[utf_16_be]: 55 Regular
- Lang: zh-Hans | Encoding: Windows Unicode BMP[utf_16_be]: 55 Regular

2.命令行

ttx -t name -o name_table.xml "C:\\AlibabaPuHuiTi-2-55-Regular_1.ttf"

结果

<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="4.58">

<name>
<namerecord nameID="0" platformID="1" platEncID="0" langID="0x0" unicode="True">
Copyright ?2020-2021 Alibaba (China) Co., Ltd. All rights reserved.
</namerecord>
<namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
Alibaba PuHuiTi 2.0
</namerecord>
<namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
55 Regular
</namerecord>
<namerecord nameID="3" platformID="1" platEncID="0" langID="0x0" unicode="True">
Hanyi Alibaba-PuHuiTi-2-55-Regular v2.00
</namerecord>
<namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
Alibaba PuHuiTi 2 55 Regular
</namerecord>
<namerecord nameID="5" platformID="1" platEncID="0" langID="0x0" unicode="True">
Version 2.00
</namerecord>
<namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
AlibabaPuHuiTi_2_55_Regular
</namerecord>
<namerecord nameID="7" platformID="1" platEncID="0" langID="0x0" unicode="True">
Alibaba is a trademark of Alibaba Group Holding Limited.
</namerecord>
<namerecord nameID="8" platformID="1" platEncID="0" langID="0x0" unicode="True">
Alibaba Design;Hanyi Fonts
</namerecord>
<namerecord nameID="10" platformID="1" platEncID="0" langID="0x0" unicode="True">
GB18030-2000
</namerecord>
<namerecord nameID="0" platformID="1" platEncID="25" langID="0x21" unicode="True">
(c) 2020-2021 阿里巴巴(中国)有限公司,版权所有
</namerecord>
<namerecord nameID="1" platformID="1" platEncID="25" langID="0x21" unicode="True">
阿里巴巴普惠体 2.0
</namerecord>
<namerecord nameID="2" platformID="1" platEncID="25" langID="0x21" unicode="True">
55 Regular
</namerecord>
<namerecord nameID="4" platformID="1" platEncID="25" langID="0x21" unicode="True">
阿里巴巴普惠体 2 55 Regular
</namerecord>
<namerecord nameID="7" platformID="1" platEncID="25" langID="0x21" unicode="True">
阿里巴巴、Alibaba是阿里巴巴集团在中国及其他国家或地区的商标或注册商标
</namerecord>
<namerecord nameID="8" platformID="1" platEncID="25" langID="0x21" unicode="True">
Alibaba Design;汉仪字库
</namerecord>
<namerecord nameID="10" platformID="1" platEncID="25" langID="0x21" unicode="True">
GB18030-2000
</namerecord>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x409">
Copyright © 2020-2021 Alibaba (China) Co., Ltd. All rights reserved.
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
Alibaba PuHuiTi 2.0 55 Regular
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
Regular
</namerecord>
<namerecord nameID="3" platformID="3" platEncID="1" langID="0x409">
Hanyi Alibaba-PuHuiTi-2-55-Regular v2.00
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
Alibaba PuHuiTi 2 55 Regular
</namerecord>
<namerecord nameID="5" platformID="3" platEncID="1" langID="0x409">
Version 2.00
</namerecord>
<namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
AlibabaPuHuiTi_2_55_Regular
</namerecord>
<namerecord nameID="7" platformID="3" platEncID="1" langID="0x409">
Alibaba is a trademark of Alibaba Group Holding Limited.
</namerecord>
<namerecord nameID="8" platformID="3" platEncID="1" langID="0x409">
Alibaba Design;Hanyi Fonts
</namerecord>
<namerecord nameID="10" platformID="3" platEncID="1" langID="0x409">
GB18030-2000
</namerecord>
<namerecord nameID="16" platformID="3" platEncID="1" langID="0x409">
Alibaba PuHuiTi 2.0
</namerecord>
<namerecord nameID="17" platformID="3" platEncID="1" langID="0x409">
55 Regular
</namerecord>
<namerecord nameID="0" platformID="3" platEncID="1" langID="0x804">
(c) 2020-2021 阿里巴巴(中国)有限公司,版权所有
</namerecord>
<namerecord nameID="1" platformID="3" platEncID="1" langID="0x804">
阿里巴巴普惠体 2.0 55 Regular
</namerecord>
<namerecord nameID="2" platformID="3" platEncID="1" langID="0x804">
Regular
</namerecord>
<namerecord nameID="4" platformID="3" platEncID="1" langID="0x804">
阿里巴巴普惠体 2 55 Regular
</namerecord>
<namerecord nameID="7" platformID="3" platEncID="1" langID="0x804">
阿里巴巴、Alibaba是阿里巴巴集团在中国及其他国家或地区的商标或注册商标
</namerecord>
<namerecord nameID="8" platformID="3" platEncID="1" langID="0x804">
Alibaba Design;汉仪字库
</namerecord>
<namerecord nameID="10" platformID="3" platEncID="1" langID="0x804">
GB18030-2000
</namerecord>
<namerecord nameID="16" platformID="3" platEncID="1" langID="0x804">
阿里巴巴普惠体 2.0
</namerecord>
<namerecord nameID="17" platformID="3" platEncID="1" langID="0x804">
55 Regular
</namerecord>
</name>

</ttFont>

3. 其它工具

ftcli info your_font.ttf --names

参考

https://github.com/fonttools/fonttools

https://github.com/qrealka/test_font_dwrite

C++字体库开发之字体回退策略十六-CSDN博客

https://github.com/adobe-type-tools/afdko

Font Names Table - TrueType Reference Manual - Apple Developer


创作不易,小小的支持一下吧!

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进