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);
}

但完整版只是

的略微修改版本

https://github.com/naofum/thinreports-java/blob/master/src/com/github/naofum/thinreports/MultiPagePDFTranscoder.java

唯一的区别是配置文件的传递方式。在原始版本中,配置文件是硬编码的,在我的版本中,配置文件是通过构造函数传入的。

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 将字体缓存在某处并且不会刷新它们。

我的解决方案是删除系统字体并保留本地字体。

所以我的问题是

  1. none 我的 .ttf 字体定义了正确的字体系列

  2. 字体未在 java 中正确注册。

我的解决方案是

  1. 对于 1. 使用 fontforge 为我的所有字体添加正确的字体系列。
  2. 对于 2. 如上所述使用 GraphicsEnvironment 注册我的所有字体。
  3. 额外的步骤。从我的 ubuntu 系统中删除所有旧字体(那些没有正确字体系列的字体),因为我添加了它们以查看它是否修复了任何问题。