Apache Batik 1.7 + Apache FOP 1.1 无法在 Ubuntu 上呈现字体
Apache Batik 1.7 + Apache FOP 1.1 not rendering fonts on Ubuntu
我在 apache batik + apache fop svg pdf 转码器中配置字体时遇到问题。
配置文件似乎没有正确加载,只能在 Ubuntu 上加载。
我已经在 MacOSX 上尝试 运行ning 完全相同的代码并且它工作正常
很好...
尝试在两个系统上加载相同的 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 none 这很重要......基本上看起来字体文件从未被读取过。
我试过直接在系统中添加字体(在 /usr/share/fonts)并用 "fc-cache -fv" 强制更新 ubuntu 上的字体缓存,但这没有帮助。
我也尝试了各种嵌入-url 链接(在配置中)但它没有任何效果(即将嵌入-url="file://resources..." 更改为嵌入- 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 为真,则字体已正确加载,它将向 batik/fop 注册并正确呈现。
请注意,font.cfg.xml(来自我的问题)仍然需要存在并且字体路径需要与注册字体相匹配。
如果 loaded 为 false,则字体未加载。
主要原因似乎是具有相同字体系列或相同字体名称的字体已经注册。 (看这里http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/font/FontManager.java#2921)
在任何渲染发生之前注册字体也很重要,因为 batik/fop 将字体缓存在某处并且不会刷新它们。
我的解决方案是删除系统字体并保留本地字体。
所以我的问题是
none 我的 .ttf 字体定义了正确的字体系列
字体未在 java 中正确注册。
我的解决方案是
- 对于 1. 使用 fontforge 为我的所有字体添加正确的字体系列。
- 对于 2. 如上所述使用 GraphicsEnvironment 注册我的所有字体。
- 额外的步骤。从我的 ubuntu 系统中删除所有旧字体(那些没有正确字体系列的字体),因为我添加了它们以查看它是否修复了任何问题。
我在 apache batik + apache fop svg pdf 转码器中配置字体时遇到问题。
配置文件似乎没有正确加载,只能在 Ubuntu 上加载。 我已经在 MacOSX 上尝试 运行ning 完全相同的代码并且它工作正常 很好...
尝试在两个系统上加载相同的 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 none 这很重要......基本上看起来字体文件从未被读取过。
我试过直接在系统中添加字体(在 /usr/share/fonts)并用 "fc-cache -fv" 强制更新 ubuntu 上的字体缓存,但这没有帮助。
我也尝试了各种嵌入-url 链接(在配置中)但它没有任何效果(即将嵌入-url="file://resources..." 更改为嵌入- 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 为真,则字体已正确加载,它将向 batik/fop 注册并正确呈现。 请注意,font.cfg.xml(来自我的问题)仍然需要存在并且字体路径需要与注册字体相匹配。
如果 loaded 为 false,则字体未加载。
主要原因似乎是具有相同字体系列或相同字体名称的字体已经注册。 (看这里http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/font/FontManager.java#2921)
在任何渲染发生之前注册字体也很重要,因为 batik/fop 将字体缓存在某处并且不会刷新它们。
我的解决方案是删除系统字体并保留本地字体。
所以我的问题是
none 我的 .ttf 字体定义了正确的字体系列
字体未在 java 中正确注册。
我的解决方案是
- 对于 1. 使用 fontforge 为我的所有字体添加正确的字体系列。
- 对于 2. 如上所述使用 GraphicsEnvironment 注册我的所有字体。
- 额外的步骤。从我的 ubuntu 系统中删除所有旧字体(那些没有正确字体系列的字体),因为我添加了它们以查看它是否修复了任何问题。