如何用Python将woff/ttf/otf转为ReportLab兼容的TTF字体
解决ReportLab兼容的字体转换问题:OTF/TTF/WOFF转可用TTF
问题概述
需要将包含自定义字体的SVG转PNG,通过svglib+ReportLab实现。部分字体转换后可正常加载,但无法预判兼容性;使用fonttools转换后的字体无法适配代码,但在线工具转换后的字体只要文件名与字体族名一致就能正常工作。核心需求是用Python实现任意OTF/TTF/WOFF(至少支持WOFF)转换为ReportLab兼容的TTF字体。
关键问题分析
- WOFF转TTF: 单纯使用
woff2.decompress可能丢失ReportLab依赖的字体元数据或必要表结构,导致加载失败。 - OTF转TTF: fonttools的
font.flavor = None仅移除OTF的格式标记,并未将PostScript轮廓转换为ReportLab要求的TrueType轮廓,因此无法正常识别。 - 字体匹配: ReportLab加载字体时依赖文件名与字体族名一致,这是在线工具转换后能工作的核心原因之一。
解决方案
1. WOFF转TTF(保留完整结构)
解压WOFF后验证并确保必要字体表存在:
import woff2 from fontTools.ttLib import TTFont def woff_to_ttf(woff_path, output_ttf_path): # 解压WOFF到TTF with open(woff_path, 'rb') as woff_file, open(output_ttf_path, 'wb') as ttf_file: woff2.decompress(woff_file, ttf_file) # 验证必要字体表 required_tables = ['cmap', 'head', 'hhea', 'maxp', 'name', 'post'] font = TTFont(output_ttf_path) for table in required_tables: if table not in font: raise ValueError(f"转换后的字体缺少必要表:{table}") font.save(output_ttf_path)
2. OTF转TTF(轮廓转换)
OTF的PostScript轮廓需转为TrueType,借助fontforge完成转换:
import fontforge def otf_to_ttf(otf_path, output_ttf_path): f = fontforge.open(otf_path) # 生成无提示、无位图的TTF f.generate(output_ttf_path, flags=("no-hints", "no-bitmaps")) f.close()
3. 确保文件名与字体族名一致
ReportLab依赖文件名匹配字体族名,转换后自动调整:
from fontTools.ttLib import TTFont import os def ensure_filename_matches_family(ttf_path): font = TTFont(ttf_path) # 获取字体族名,替换空格为下划线 family_name = font['name'].getDebugName(1).replace(' ', '_') new_path = os.path.join(os.path.dirname(ttf_path), f"{family_name}.ttf") if ttf_path != new_path: os.rename(ttf_path, new_path) return new_path
4. 完整转换函数整合
import os import shutil import woff2 from fontTools.ttLib import TTFont import fontforge def convert_to_reportlab_ttf(input_path, output_dir=None): if output_dir is None: output_dir = os.path.dirname(input_path) ext = os.path.splitext(input_path)[1].lower() temp_ttf = os.path.join(output_dir, "temp_ttf_conversion.ttf") try: if ext in ('.woff', '.woff2'): woff_to_ttf(input_path, temp_ttf) elif ext == '.otf': otf_to_ttf(input_path, temp_ttf) elif ext == '.ttf': shutil.copy(input_path, temp_ttf) else: raise ValueError(f"不支持的字体格式:{ext}") # 调整文件名并返回最终路径 final_ttf = ensure_filename_matches_family(temp_ttf) return final_ttf except Exception as e: if os.path.exists(temp_ttf): os.remove(temp_ttf) raise RuntimeError(f"字体转换失败:{str(e)}") # 使用示例 # converted_font = convert_to_reportlab_ttf("./my_custom_font.woff") # 将转换后的字体放在SVG同目录,运行原SVG转PNG代码即可
依赖安装
fonttools:pip install fonttoolspython-woff2:pip install python-woff2fontforge-python: 系统级安装,如Ubuntu用apt install fontforge-python3,Windows需下载预编译包
内容的提问来源于stack exchange,提问作者Shmack
相关产品推荐
相关产品推荐

