You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Batik+FOP在Ubuntu下无法渲染字体的配置故障

解决Ubuntu下Apache Batik+FOP SVG转PDF的字体加载问题

我之前也踩过类似的跨平台字体加载坑,结合你的场景,咱们一步步拆解问题并解决:

核心问题分析

你的代码和配置在Mac上正常运行,但Ubuntu下无法加载自定义字体,大概率是路径解析差异或文件权限/资源加载方式导致的——毕竟Mac和Linux的文件系统、Java资源加载逻辑存在细微区别。


解决方案步骤

1. 改用类路径加载资源(最关键)

你当前使用的相对路径resources/fonts.cfg.xml和file:resources/fonts/xxx.ttf,这种方式严重依赖Java进程的当前工作目录(CWD)。而Ubuntu下运行JAR时的CWD可能和Mac不一致(比如你在project/下运行和在project/target/下运行,相对路径的基准就完全变了)。

修改代码:把从文件加载配置改为从类路径加载,确保资源位置不受CWD影响:

try { 
    DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); 
    // 从类路径根目录加载配置文件(确保resources目录在类路径中)
    InputStream cfgStream = getClass().getResourceAsStream("/fonts.cfg.xml");
    if (cfgStream != null) {
        Configuration effCfg = cfgBuilder.build(cfgStream); 
        PDFDocumentGraphics2DConfigurator configurator = new PDFDocumentGraphics2DConfigurator(); 
        configurator.configure(graphics, effCfg, false); 
        cfgStream.close();
    } else { 
        graphics.setupDefaultFontInfo(); 
        System.err.println("字体配置文件未找到,将使用默认字体");
    } 
} catch (Exception e) { 
    // 打印详细堆栈,便于排查加载异常
    e.printStackTrace();
    throw new TranscoderException("Error while setting up PDFDocumentGraphics2D", e); 
}

修改font.cfg.xml:把字体的embed-url改成classpath:前缀,让Batik从类路径读取字体:

<configuration>
  <fonts>
    ...
    <font kerning="no" embed-url="classpath:fonts/0b0b385a-f6e8-4a33-887f-2f178a576139.ttf">
      <font-triplet name="Papyrus" style="normal" weight="normal"></font-triplet>
    </font>
    ...
  </fonts>
</configuration>

2. 检查Ubuntu下的文件权限

Ubuntu的权限机制比Mac严格,需要确保:

  • 打包到JAR中的字体文件权限至少为644(可读),如果是外部目录的字体,执行chmod -R 644 project/resources/fonts/
  • 如果把字体放到/usr/share/fonts,执行fc-cache -fv后,用fc-list | grep Papyrus验证系统是否能识别该字体。此时配置中可以去掉embed-url,直接用font-triplet引用系统字体。

3. 验证配置是否真的被加载

在代码中添加日志,确认配置文件是否成功读取:

if (effCfg != null) {
    // 打印配置中的字体节点数量,验证是否加载成功
    Configuration[] fontConfigs = effCfg.getChildren("fonts/font");
    System.out.println("成功加载到" + fontConfigs.length + "个自定义字体配置");
    PDFDocumentGraphics2DConfigurator configurator = new PDFDocumentGraphics2DConfigurator(); 
    configurator.configure(graphics, effCfg, false); 
}

如果输出为0,说明配置文件没被正确解析,检查XML格式是否有语法错误。

4. 排查Java 8的细微差异

虽然都是Java 8,但Oracle JDK在Ubuntu和Mac上的file:协议解析可能存在差异,避免使用file:前缀是最稳妥的选择——类路径加载在所有平台上的行为都是一致的。


总结

跨平台资源加载的核心原则是不依赖当前工作目录,优先用类路径加载,同时确保文件权限和配置格式正确。按上面的步骤修改后,Ubuntu下应该能正常加载自定义字体了。

内容的提问来源于stack exchange,提问作者boogie666

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:41:34