当前位置: 首页 > 知识库问答 >
问题:

Apache FOP显示###和SimSun

仲孙兴平
2023-03-14

我正在维护一个使用Apache FOP打印PDF文档的程序。有一些关于汉字出现“####”的抱怨。我已经找到了一个关于这个问题的现有线程,并在我这边做了一些研究。

http://Apache-fop . 1065347 . n5 . nab ble . com/Chinese-Fonts-TD 10789 . html

我的系统上安装了uming.tff语言文件。不像这个线程中的人,我仍然得到 "####".

从这一点开始,有没有人看到过一种可以让您使用ApacheFOP在PDF文档中打印复杂字符的解决方案?

共有1个答案

公西姚石
2023-03-14

必须采取三个步骤才能在使用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 字体之一(随处可见的字体,因此无需嵌入它们)。

每种字体都支持一组字符,给它们分配一个可见的字形;当字体不支持某个字符时,会产生上述警告,并且PDF会显示“#”而不是缺少的字形。

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

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

因此,我们的输入变成(使用我的字体作为示例):

<?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不知道如何将“SimSun”映射到字体文件,因此它默认为不支持我们的中文字符的通用Base-14字体(Time-Roman),并且PDF仍然显示“#”。

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

配置文件是一个XML文件,我们必须在/fop/renderers/renderer[@mime = 'application/pdf']/fonts/添加字体映射(每种可能的输出mime类型都有一个渲染器部分,因此请检查您是否在正确的映射中插入了映射):

<?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>
    < li >每个< code>font元素指向一个字体文件 < li >每个< code>font-triplet项目标识< code > font-family < code > font-style (正常,斜体,...)< code>font-weight(正常,粗体,...)映射到父< code>font元素中的字体文件 < li >使用< code>directory元素,还可以自动配置指定文件夹中的所有字体文件(但如果文件夹包含大量字体,这需要一些时间)

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

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

注意,我们不需要注册所有可能的字体三元组;如果缺少一个,FOP将使用为“类似”字体注册的字体(例如,如果我们不映射三元组“SimSun,italic,400”,FOP会使用映射到“SimSun,normal,400“的字体,警告我们字体替换)。

我们还没有完成,因为没有下一步和最后一步,当我们处理输入文件时什么都不会改变。

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

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

从我们可以使用的java代码中(另请参阅FOP的网站):

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找不到字体文件,需要再次检查字体配置;典型原因是

  • 字体url中的错别字
  • 访问字体文件的权限不足
 类似资料:
  • 问题内容: 我有一个PHP脚本,可以用来从数据库读取服务器并使用cURL连接到它们。服务器以sql查询的结果作为响应。问题是每个服务器响应后的脚本显示数字1。输出看起来像这样: 服务器1:一些结果 1服务器2:一些结果 1服务器3:一些结果 1个 这是从数据库读取服务器并连接到它们的代码: 我发现显示1时显示“ echo $ result;”。和用于创建响应的代码是这样的: 请帮我 问题答案: 使

  • 我创建了一个JFrame,其中包含一个JSplitPane,它在左侧包含一个画布,在右侧包含一个JPanel。画布包含LWJGL显示,而JPanel中几乎没有JTextFields。问题是,当我按下LWJGL显示器上的鼠标按钮时,我无法再将文本写入JTextFields。当我最小化应用程序并将其返回时,它会一直工作,直到我再次按下显示器。 为什么我会遇到这个问题?我怎么能修好它? 注意:我可以专注

  • 我试图使用Apache Fop和Java生成PDF,但生成的Pdf总是一个空白页。它都嵌套在一个网络应用程序中,割断器是玻璃鱼。 有人有什么建议吗? 以下是我的xsl: 示例XML文件如下所示: 编辑:应该生成pdf的Java代码。。。 第二次编辑: 我发现我的outputStream有问题。我想显示另存为对话框,以便从web应用程序下载生成的文件。我不明白,我的输出有什么问题。。。

  • 问题内容: 我有一个div的CSS动画,经过一定时间后会滑入。我想要几个div填充滑入的动画div的空间,然后它将这些元素向下推到页面上。 当我在第一个div尝试此操作时,即使看不见,幻灯片仍会占用空间。如果我将div更改为div,则根本不会滑入。 我如何让div在不定时的情况下不占用空间(使用CSS进行计时)。 我正在为动画使用Animate.css。 代码如下所示: 如代码所示,我希望隐藏主d

  • 我正在尝试将.obj文件加载到带有libgdx的Android项目中。这些文件没有纹理文件,但包含.mtl文件中的材料。我正在使用最新的官方每晚,并且呈现对象文件只会导致对象出现白色。如何让ObjLoader使用.mtl文件? 这就是如何调用呈现对象的代码。这里是指向ObjLoader类的链接 我是否需要在OpenGL端启用或以其他方式做一些事情来确保它正确使用这些材料?

  • 突然间得到了所有这些错误所有构建错误“在Android Studio中存在多个错误的清单合并失败” 当我没有得到这个建议的时候,我就用android studio提出了替换建议 "清单合并失败:属性application@appComponentFactoryvalue=(android.support.v4.app.CoreComponentFactory)from[com.android.su