使用PyMuPDF对pdf文件插入文字时 遇到配置本地的字体文件缺仍然使用默认Helvetica字体问题

背景

昨天收到的新需求,一份文件从其他部门发起,进行一些文字填写后盖章,再到我们部门,我们接收到的是pdf文件,所以需要在pdf文件中进行修改,插入当日日期等文字。但有要求字体必须和原文档字体相同。

问题代码

开始时通过fontfile传本地文件夹中的指定字体包,但是无论怎么修改最终在pdf中插入的文字格式都是PyMuPDF的默认Helvetica字体。

复制代码
inserter = SmartDateInserterV6(fontfile="./fonts/fangsongGB2312.ttf", fontsize=16)

    def _insert_before(self, page, span, text, offset_x, offset_y):
        x, y = span["bbox"][:2]
        rgb = int_to_rgb_tuple(span.get("color", 0))
        page.insert_text(
            (x - offset_x, y + offset_y),
            text,
            fontfile=self.fontfile,
            fontsize=self.fontsize,
            color=rgb
        )

如上图所示

根本原因

page.insert_text() 在没有显式 fontname 参数时会把字体名默认为 "Helv" / "Helvetica"。

"Helv" 属于 PDF 的 Base‑14 保留字体名。只要传入的 fontname 是保留名,PyMuPDF 就 忽略 fontfile / fontbuffer 参数,直接调用内置 Helvetica,所以看到的始终是 Helvetica,而不是自己的仿宋字体。

解决办法

解决办法一:在 insert_text 时同时指定 自定义 fontname

复制代码
page.insert_text(
            (x - offset_x, y + offset_y),
            text,
            fontfile=self.fontfile,
            fontsize=self.fontsize,
            color=rgb,
            fontname="FangSongGB"        # 避免 Helv
        )

只要 fontname 不是保留名,PyMuPDF 就会把 fontfile 嵌入 PDF,并真正使用你的仿宋字体。

解决办法二:先把字体注册到页面,再写入文本

复制代码
import fitz

doc  = fitz.open()
page = doc.new_page()

font_path = "./fonts/fangsongGB2312.ttf"

# 1️⃣ 先把字体嵌入并得到 xref
xref = page.insert_font(fontname="FangSongGB", fontfile=font_path)

# 2️⃣ 写文本时只需要给出 fontname
page.insert_text(
    (100, 100),
    "测试 2025 年",
    fontname = "FangSongGB",
    fontsize = 20
)

doc.save("test_font.pdf")
doc.close()

我使用方法一,最终效果如图