Apache Batik 1.7 + Apache FOP 1.1无法在Ubuntu上渲染字体

时间:2018-01-08 14:38:43

标签: java ubuntu pdf fonts apache-fop

我在apache batik + apache fop svg pdf transcoder中配置字体时遇到了问题。

配置文件似乎没有正确加载,只能在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);
}

但完整版只是

的略微修改版本

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上这一切都不重要......基本上看起来字体文件永远不会被读取。

我已尝试直接在系统中添加字体(在/ usr / share / fonts中)并强制使用&#34; fc-cache -fv&#34;更新ubuntu上的字体缓存。但这没有帮助。

我也尝试了各种embed-url链接(在配置中),但它没有任何效果(即更改embed-url =&#34; file://resources ...。&#34; to embed-url =&#34; file:///resources..."以及其他变体。)

两个系统都运行java1.8(Oracle JDK 1.8.151上为ubuntu,mac为Oracle JDK 1.8.131)

1 个答案:

答案 0 :(得分:2)

经过多次在线搜索并在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>"));

如果加载为true,则表示字体已正确加载,它将使用batik / fop注册并正确呈现。 请注意,font.cfg.xml(来自我的问题)仍然需要存在,并且字体的路径需要与regitered字体匹配。

如果加载为false,则表示未加载字体。

这主要原因似乎是已经注册了具有相同字体名称 OR 相同字体名称的字体。 (见http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/font/FontManager.java#2921

在任何渲染发生之前注册字体也很重要,因为batik / fop会在某处缓存字体并且不会刷新它们。

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

所以我的问题是

  1. 我的.ttf字体都没有定义正确的字体系列

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

  3. 我的解决方案是

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