Apache FOP使用SimSun显示###

时间:2014-09-17 16:40:54

标签: java apache-fop chinese-locale

我正在维护一个使用Apache FOP打印PDF文档的程序。有几个关于中文字符出现“####”的投诉。我找到了一个关于这个问题的现有线程,并在我身边做了一些研究。

http://apache-fop.1065347.n5.nabble.com/Chinese-Fonts-td10789.html

我的系统上安装了uming.tff语言文件。与此帖子中的人不同,我仍然得到“####”。

从现在开始,有没有人看过一个可以让你使用Apache FOP在PDF文档中打印复杂字符的工作?

赖安

1 个答案:

答案 0 :(得分:10)

必须采取三个步骤才能使中文字符正确显示在使用FOP 创建的PDF文件中(对于默认字体中不可用的所有字符也是如此,更常见的是使用非默认字体)

让我们使用这个简单的示例来显示FOP在出现问题时产生的警告:

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:layout-master-set>
        <fo:simple-page-master master-name="one">
            <fo:region-body />
        </fo:simple-page-master>
    </fo:layout-master-set>
    <fo:page-sequence master-reference="one">
        <fo:flow flow-name="xsl-region-body">
            <!-- a block of chinese text -->
            <fo:block>博洛尼亚大学中国学生的毕业论文</fo:block>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

处理此输入时,FOP会发出与此类似的几个警告:

org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "?" (0x535a) not available in font "Helvetica".
...

在FO文件中没有任何明确的字体系列指示,FOP默认使用Helvetica,这是Base-14 fonts之一(各地都可用的字体,所以不需要嵌入它们)。

每个字体都支持一组字符,为它们分配一个可见的字形;当字体不支持字符时,会产生上述警告, PDF显示&#34;#&#34;而不是缺少的字形

步骤1:在FO文件中设置font-family

如果默认字体不支持我们的文字的字符(或者我们只是想使用不同的字体),我们必须使用font-family属性来声明想要的。

font-family的值是继承的,所以如果我们想对整个文档使用相同的字体,我们可以在fo:page-sequence上设置属性;如果我们只需要一些段落或单词的特殊字体,我们可以在相关font-familyfo:block上设置fo:inline

因此,我们的输入变为(使用我所拥有的字体):

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <fo:layout-master-set>
        <fo:simple-page-master master-name="one">
            <fo:region-body />
        </fo:simple-page-master>
    </fo:layout-master-set>
    <fo:page-sequence master-reference="one">
        <fo:flow flow-name="xsl-region-body">
            <!-- a block of chinese text -->
            <fo:block font-family="SimSun">博洛尼亚大学中国学生的毕业论文</fo:block>
        </fo:flow>
    </fo:page-sequence>
</fo:root>

但是现在我们得到了一个新的警告,除了旧警告!

org.apache.fop.events.LoggingEventListener processEvent
WARNING: Font "SimSun,normal,400" not found. Substituting with "any,normal,400".
org.apache.fop.events.LoggingEventListener processEvent
WARNING: Glyph "?" (0x535a) not available in font "Times-Roman".
...

FOP不知道如何映射&#34; SimSun&#34;到一个字体文件,所以它默认为一般的Base-14字体(Times-Roman)不支持我们的中文字符, PDF仍然显示&#34;#&#34; < /强>

步骤2:在FOP的配置文件

中配置字体映射

在FOP文件夹中,文件conf/fop.xconf是一个示例配置;我们可以直接编辑它或制作副本来开始。

配置文件是一个XML文件,我们必须在/fop/renderers/renderer[@mime = 'application/pdf']/fonts/内添加font mappings(每个可能的输出mime类型都有一个renderer部分,所以请检查您是否插入你在右边的映射):

<?xml version="1.0"?>
<fop version="1.0">
  ...
  <renderers>
    <renderer mime="application/pdf">
      ...
      <fonts>

        <!-- specific font mapping -->
        <font kerning="yes" embed-url="/Users/furini/Library/Fonts/SimSun.ttf" embedding-mode="subset">
          <font-triplet name="SimSun" style="normal" weight="normal"/>
        </font>

        <!-- "bulk" font mapping -->
        <directory>/Users/furini/Library/Fonts</directory>

      </fonts>
      ...
    </renderer>
    ...
  </renderers>
</fop>
  • 每个font元素指向一个字体文件
  • 每个font-triplet条目标识font-family + font-style(正常,斜体,...)+ font-weight(普通,粗体,...)映射的组合到父font元素
  • 中的字体文件
  • 使用folder元素,也可以自动配置指定文件夹中的所有字体文件(但如果文件夹包含大量字体,则需要一些时间)

如果我们有一个完整的文件集,其中包含所需字体的特定版本(普通,斜体,粗体,浅色,粗体斜体......),我们可以将每个文件映射到精确的字体三元组,从而生成非常复杂的PDF

在光谱的另一端,我们可以将所有三元组映射到相同的字体文件,如果它们全部可用:在输出中所有文本将显示相同,即使在FO文件中它被标记为斜体或粗体。

请注意,我们不需要注册所有可能的字体三元组;如果缺少一个,FOP将使用为&#34;类似的&#34;注册的字体。一个(例如,如果我们不映射三元组&#34; SimSun,斜体,400和#34; FOP将使用映射到&#34; SimSun,正常,400&#34;的字体,警告我们字体替换)。

我们尚未完成,因为没有下一步和最后一步,我们处理输入文件时没有任何变化。

步骤3:告诉FOP使用配置文件

如果我们从命令行调用FOP,我们使用-c选项指向我们的配置文件,例如:

$ fop -c /path/to/our/fop.xconf input.fo input.pdf

我们可以使用java代码(另见FOP's site):

fopFactory.setUserConfig(new File("/path/to/our/fop.xconf"));

现在,最后,PDF应该正确使用所需的字体并按预期显示。

如果反而FOP突然终止,并出现如下错误:

org.apache.fop.cli.Main startFOP
SEVERE: Exception org.apache.fop.apps.FOPException: Failed to resolve font with embed-url '/Users/furini/Library/Fonts/doesNotExist.ttf'

这意味着FOP找不到字体文件,需要再次检查字体配置;典型的原因是

  • 字体网址中的拼写错误
  • 访问字体文件的权限不足