java - Apache Batik 1.7 + Apache FOP 1.1 不在 Ubuntu 上呈现字体

标签 java ubuntu pdf fonts apache-fop

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

但完整版只是稍微修改过的版本

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)并使用“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 将字体缓存在某个地方并且不会刷新它们。

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

所以我的问题是

  1. 我的 .ttf 字体都没有定义合适的字体系列

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

我的解决方案是

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

关于java - Apache Batik 1.7 + Apache FOP 1.1 不在 Ubuntu 上呈现字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48152492/

相关文章:

.net - 不用打印机打印?

java - 为什么 CriteriaBuilder 会为 "in"CollectionTable 创建格式错误的查询?

java - Server Stop responding because of [Pool-Cleaner] :Tomcat Connection Pool but has failed to stop it. 这很可能造成内存泄漏

java - 循环内变量的初始化

java - 用于Scala开发的java8中的gradle REPL

c# - 从 PDF 中仅提取粗体文本的最佳方法

ubuntu - 在 16.04 LTS 上安装 Docker

bash - 在 wget bash 命令中转义

ubuntu - 如何打开 rm 命令的警告?

java - 将多个 pdf 合并为一个 pdf