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
相关产品推荐
相关产品推荐

