这是我如何让 AWS S3 上的自定义字体文件被加载的方法(但是这个例子中我使用的是本地文件系统)- 请注意,它们都是 woff 格式的。
如果你的所有字体都可以被 fontTools 的 TTFont 类加载,你可以像这样做 - 这个库还可以将不同的字体转换为其他字体:
from fontTools.ttLib import TTFont
from pathlib import Path
import xml.etree.ElementTree as ET
from io import BytesIO
from reportlab.graphics import renderPM
import svglib.fonts
from svglib.svglib import svg2rlg
def to_pdf_buffer(d, *args, **kwargs):
buffer = BytesIO()
renderPDF.drawToFile(d, buffer, *args, **kwargs)
return buffer
def to_pil(d, *args, **kwargs):
pil = renderPM.drawToPIL(d, *args, **kwargs)
return pil
ET.register_namespace('', "http://www.w3.org/2000/svg")
file_path = Path("my_svg.svg")
root = ET.parse(str(file_path)).getroot()
font_map = svglib.fonts.get_global_font_map()
fonts = []
unloaded_fonts = []
Folder = "./"
for e in self.root.findall(".//{http://www.w3.org/2000/svg}text"):
font_family_name = e.get('font-family')
if font_family_name is not None and font_family_name not in fonts:
fonts.append(font_family_name)
path = Path(Folder)
if path.exists() and path.is_dir():
file = path.joinpath(Path(f"./{font_family_name}.woff"))
data = file.read_bytes()
try:
TTFont(data)
except:
unloaded_fonts.append(font_family_name)
continue
else:
try:
font = BytesIO(file.read_bytes())
font_map.register_font(font_family_name, font_path=font)
except:
unloaded_fonts.append(font_family_name)
if len(unloaded_fonts) > 0:
print(f"Could not load fonts: {', '.join(unloaded_fonts)}")
drawing = svg2rlg(BytesIO(ET.tostring(root)), font_map=font_map)
pil = to_pil(drawing, dpi=1200)
pil.save(str(file_path.with_suffix(".png")))
svglib
有一个字体映射,可以通过调用svglib.get_global_font_map()
函数来获取。您可以使用字体映射的register_fonts
方法加载字体,该方法接受字体名称和路径或数据(在他们的文档中有介绍 - 不能同时提供两者或类似的情况)。
这使用ElementTree库来解析文本元素的font-family标签。它获取它们的名称并找到具有该字体族名称的字体文件并加载它,这对我的应用程序有效,但对其他人可能无效,因为通常您使用css @font-face加载字体。为了使@font-face选项起作用,您必须解析它并获取其数据,并将这些字体注册到字体映射中。这并不是非常困难,但我确实懒得做,并且我的注意力此时被转移到了另一个问题上,所以我没有意愿去做,但这对于其他开发者来说已经提供了足够的基础信息。
再次澄清一下:要使此功能正常工作,您的文本必须具有font-family,并且您的字体文件必须是这些字体族的名称;此外,我的所有字体文件都是woff格式的,所以您可能需要更换文件扩展名。