我在 apache batik + apache fop svg pdf 转码器中配置字体时遇到问题。
配置文件似乎没有正确加载,但仅在 Ubuntu 上加载。 我试过在 MacOSX 上运行完全相同的代码,它只是 很好...
尝试在两个系统上加载相同的 svg 会产生不同的结果。
Java 的相关部分是这样的:
try {
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
Configuration effCfg = cfgBuilder.buildFromFile(new File(this.fontCfgFilePath));
if (effCfg != null) {
PDFDocumentGraphics2DConfigurator configurator = new PDFDocumentGraphics2DConfigurator();
configurator.configure(graphics, effCfg, false);
} else {
graphics.setupDefaultFontInfo();
}
} catch (Exception e) {
throw new TranscoderException("Error while setting up PDFDocumentGraphics2D", e);
}
但完整版只是稍微修改过的版本
唯一的区别是配置文件的传递方式。在原始版本中,配置文件是硬编码的,在我的版本中,配置文件是通过构造函数传入的。
this.fontCfgFilePath 在构造函数中设置为“resources/fonts.cfg.xml”
文件夹结构是
project/
resources/
font.cfg.xml
fonts/
0b0b385a-f6e8-4a33-887f-2f178a576139.ttf
... a bunch of other fonts ....
pdf-generator.jar
... other files that are not relevant to the problem...
font.cfg.xml 是这样设置的
<configuration>
<fonts>
... other fonts ....
<font kerning="no" embed-url="file:resources/fonts/0b0b385a-f6e8-4a33-887f-2f178a576139.ttf">
<font-triplet name="Papyrus" style="normal" weight="normal"></font-triplet>
</font>
<font kerning="no" embed-url="file:resources/fonts/0b0b385a-f6e8-4a33-887f-2f178a576139.ttf">
<font-triplet name="Papyrus" style="normal" weight="bold"></font-triplet>
</font>
<font kerning="no" embed-url="file:resources/fonts/0b0b385a-f6e8-4a33-887f-2f178a576139.ttf">
<font-triplet name="Papyrus" style="italic" weight="normal"></font-triplet>
</font>
<font kerning="no" embed-url="file:resources/fonts/0b0b385a-f6e8-4a33-887f-2f178a576139.ttf">
<font-triplet name="Papyrus" style="italic" weight="bold"></font-triplet>
</font>
... other fonts
</fonts>
</configuration>
如果同时在 Ubuntu 和 MacOSX 上运行,具有完全相同配置的完全相同的项目。
MacOSX 使用正确的字体生成正确的 PDF
Ubuntu 没有....
有趣的是 Ubuntu 甚至不尝试使用字体...
如果我从 mac 上的配置文件中删除字体,它将不会呈现该字体(如预期的那样)
如果我将字体文件更改为无效的内容,再次在 Mac 上,它会抛出 FileNotFoundException。
但在 Ubuntu 上这些都不重要......基本上看起来字体文件从未被读取过。
我试过直接在系统中添加字体(在/usr/share/fonts)并使用“fc-cache -fv”强制更新 ubuntu 上的字体缓存,但这没有帮助。
我还尝试了各种嵌入 url 链接(在配置中),但没有任何效果(即将 embed-url="file://resources..."更改为 embed-url="file:///resources...”和其他变体)。
两个系统都运行java1.8(ubuntu在Oracle JDK 1.8.151上,mac是Oracle JDK 1.8.131)
最佳答案
在网上大量搜索并阅读 batik/fop 和 java 本身的源代码后,我发现 Batik 和 FOP 需要在 java.awt.GraphicsEnvironment
中显示字体
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment()
将获取您可以在其上调用的 GraphicsEnvironment 实例
ge.getAvailableFontFamilyNames()
获取当前加载的字体系列的数组。
请注意,.ttf 字体无需定义字体系列即可正确加载。
但是 Batik 和 FOP DO 需要指定正确的字体系列...
碰巧 MacOSX 知道(在安装系统级字体时)设置正确的字体系列。但是 GNU/Linux 似乎不会做同样的事情。
如果字体在系统范围内不可用(我在 linux 上就是这种情况),则必须在 java 中注册它。
这可以像这样使用 GraphicsEnvironment 来完成:
boolean loaded = ge.registerFont(java.awt.Font.createFont(java.awt.Font/TRUETYPE_FONT, new File("<path to font>"));
如果 loaded 为 true,则字体已正确加载,它将在 batik/fop 中注册并正确呈现。 请注意,font.cfg.xml(来 self 的问题)仍然需要存在并且字体路径需要与注册字体相匹配。
如果 loaded 为 false 则字体未加载。
主要原因似乎是具有相同字体系列或相同字体名称的字体已经注册。 (请参阅此处 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/font/FontManager.java#2921)
在任何渲染发生之前注册字体也很重要,因为 batik/fop 将字体缓存在某个地方并且不会刷新它们。
我的解决方案是删除系统字体并保留本地字体。
所以我的问题是
我的 .ttf 字体都没有定义合适的字体系列
字体未在 java 中正确注册。
我的解决方案是
- 对于 1. 使用 fontforge 为我的所有字体添加正确的字体系列。
- 对于 2. 如上所述,在 GraphicsEnvironment 中注册我所有的字体。
- 额外的步骤。从我的 ubuntu 系统中删除所有旧字体(那些没有正确字体系列的字体),因为我添加了它们以查看它是否修复了任何问题。
关于java - Apache Batik 1.7 + Apache FOP 1.1 不在 Ubuntu 上呈现字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48152492/