Apache FOP 2.11 配置参数详解

剖析 fop.xconf 顶层结构与各渲染器配置,重点实测 TrueType/TTC 字体注册、CFF 轮廓不兼容坑、triplet 匹配替换、字体缓存与 TIFF 压缩,附内存压测数据

Apache FOPFOPApacheJava配置详解参数调优2026/10/14

Apache FOP 2.11 配置参数详解

一、配置体系概览

FOP 的行为由一个 XML 配置文件控制,习惯命名为 fop.xconf。三层事实需要先弄清:

层说明
内置默认值编译在 fop.jar 里,不提供任何配置文件时全部行为按默认值走
发行包示例/opt/fop/fop/conf/fop.xconf,官方注明「contains the same settings as the default values and will have no effect if used unchanged」,即内容等于默认值,仅作模板参考
用户配置通过 -c cfg.xml 显式传入的文件,与默认值合并后生效

本文所有实验基于发行包 + 自定义配置实测,环境为 Ubuntu 22.04.5 / OpenJDK 11.0.32.1 / Apache FOP 2.11,安装目录 /opt/fop(软链 /opt/fop-2.11)。

验证配置是否被加载,最直接的办法是看启动日志——顶层元素的设置会打印 INFO 行:

Oct 14, 2026 2:02:05 PM org.apache.fop.apps.FopConfParser configure
INFO: Default page-height set to: 297mm
Oct 14, 2026 2:02:05 PM org.apache.fop.apps.FopConfParser configure
INFO: Default page-width set to: 210mm

也可以用 -x 把解析后的配置转储出来辅助排查:

cd /opt/fop/fop && ./fop -c /work/conf/fop-cjk.xconf -x

实测输出(节选):

INFO: Input mode:
INFO: not set
INFO: Output mode:
INFO: not set

二、顶层结构

fop.xconf 的骨架(发行包 conf/fop.xconf 原文,注释略):

<fop version="1.0">
  <base>.</base>
  <source-resolution>72</source-resolution>
  <target-resolution>72</target-resolution>
  <default-page-settings height="11.00in" width="8.50in"/>
  <renderers>
    <renderer mime="application/pdf">...</renderer>
    ...
  </renderers>
</fop>
元素/属性说明实测备注
fop@version配置格式版本固定写 1.0;写错值会解析告警
base相对 URL 解析基准默认 .;font embed-url、fo 里引用图片的相对路径都基于它
source-resolution输入位图/SVG 的像素密度默认 72 dpi,影响 fo:external-graphic 无 intrinsic size 时换算
target-resolution输出位图目标密度默认 72 dpi;可被 CLI -dpi 覆盖
default-page-settingspage-width/height 为 auto 时的兜底发行包默认 8.5in×11in(US Letter),中文场景常改为 210mm×297mm(A4)
renderers按输出格式分节每个 renderer 用 mime 类型区分

实测:把 default-page-settings 改为 A4 后启动,日志出现 Default page-height set to: 297mm / Default page-width set to: 210mm(见第一章),确认加载成功。

三、字体配置(重点)

字体是 FOP 使用中最容易踩坑的部分,本章全部结论来自容器内实测。

3.1 Base-14 内置字体与缺字行为

FOP 不配置任何字体时,PDF 使用 Adobe Base-14 字体(Times-Roman、Helvetica、Courier 及其变体),只覆盖拉丁字符。渲染中文时逐字告警且内容丢失:

WARNING: Glyph "?" (0x67d3) not available in font "Times-Roman".
WARNING: Glyph "文" (0x6587) not available in font "Times-Roman".

(0x67d3 = 染,0x6587 = 文。)规则:必须在 PDF renderer 的 fonts 节显式注册 CJK 字体。

3.2 TrueType 字体内联注册

基本写法:

<renderer mime="application/pdf">
  <fonts>
    <font kerning="yes" embed-url="file:///usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf">
      <font-triplet name="DroidSansFallback" style="normal" weight="normal"/>
    </font>
  </fonts>
</renderer>
属性/元素说明
embed-url字体文件 URL,支持 file:// 绝对路径;省略该属性则字体度量用于排版但不嵌入 PDF(读者机器没装该字体就显示不出来)
kerning是否启用 kerning 对,中文场景无感
font-triplet@nameFO 里 font-family 要写的名字(自定义,与文件内部名无关)
font-triplet@stylenormal / italic / oblique / backslant
font-triplet@weightnormal(400) / bold(700) 或 100~900

同一物理字体文件可以挂多个 triplet。实测验证嵌入结果(pdffonts 属 poppler-utils):

name                     type          encoding    emb sub uni
EAAAAB+DroidSansFallback CID TrueType  Identity-H  yes yes yes

emb=yes 表示已嵌入,Identity-H 是 CID 编码,uni=yes 表示带 ToUnicode 映射(文本可复制检索)。

3.3 TTC 字体集合与 sub-font 属性

Ubuntu 的 fonts-wqy-zenhei 包提供 wqy-zenhei.ttc(TrueType Collection,内含 3 个字体)。TTC 必须用 sub-font 属性指定集合成员,值是字体在集合内的内部名:

<font kerning="yes" embed-url="file:///usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"
      sub-font="WenQuanYi Zen Hei">
  <font-triplet name="WQYZenHei" style="normal" weight="normal"/>
</font>

实测渲染成功后 pdffonts 显示:

EAAAAA+WenQuanYiZenHei  CID TrueType  Identity-H  yes yes yes

sub-font 写错的报错非常直白,例如对 fonts-noto-cjk 的 TTC 写 sub-font="Noto Serif CJK SC"(实际内部名是 Noto Serif CJK SC Bold):

SEVERE: Failed to read font file file:///usr/share/fonts/opentype/noto/NotoSerifCJK-Bold.ttc
Name does not exist in the TrueType collection: Noto Serif CJK SC

排查子字体名可用 FOP 的自报告:加载 TTC 时它会打印集合成员清单到 INFO 日志:

INFO: This is a TrueType collection file with 5 fonts
INFO: Containing the following fonts:
INFO: Noto Serif CJK JP Bold
INFO: Noto Serif CJK KR Bold
INFO: Noto Serif CJK SC Bold
...

注意内部名带样式后缀:Regular TTC 的成员是 Noto Serif CJK SC,Bold TTC 的成员是 Noto Serif CJK SC Bold。

3.4 CFF 轮廓字体是硬伤(fonts-noto-cjk 不可用)

Ubuntu 22.04 的 fonts-noto-cjk 包(NotoSerifCJK-.ttc / NotoSansCJK-.ttc)是 OpenType/CFF 轮廓(sfnt 容器里是 CFF 表而非 glyf 表)。FOP 2.11 的 TrueType 加载器读不了它,注册后渲染直接失败:

SEVERE: Failed to read font file file:///usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc
'loca' table not found, happens when the font file doesn't contain TrueType outlines (trying to read an OpenType CFF font maybe?)

实测结论(用 python 解析 sfnt 表验证过两个 ttc 都是 CFF):

字体来源轮廓格式FOP 2.11 PDF 渲染
fonts-noto-cjk(*.ttc)CFF失败('loca' not found)
fonts-wqy-zenhei(wqy-zenhei.ttc)TrueType/glyf成功,中文正常嵌入
fonts-droid-fallback(DroidSansFallbackFull.ttf)TrueType/glyf成功,但该字体只有 CJK 字形

可用字体的判断标准:fc-list 能看到只是入场券,轮廓必须是 TrueType(glyf 表)。文泉驿正黑是 Ubuntu 下最省心的选择,一个字体同时覆盖中文与拉丁字符。

3.5 CJK 专属字体缺拉丁字形

Droid Sans Fallback 是纯 CJK 字体,拉丁字符也走它时会缺字:

WARNING: Glyph "D" (0x44, D) not available in font "DroidSansFallback".
WARNING: Glyph "r" (0x72, r) not available in font "DroidSansFallback".

方案:正文用覆盖面广的字体(文泉驿正黑),或为拉丁与 CJK 分别注册并在 FO 里用 font-family 列表声明回退顺序。

3.6 triplet 匹配与替换行为

FO 里的 font-family/font-weight/font-style 组合必须命中已注册的 triplet,否则替换为默认字体并告警。实测 FO 中写 font-weight="bold" 但只注册了 weight="normal" 的 triplet:

WARNING: Font "WQYZenHei,normal,700" not found. Substituting with "WQYZenHei,normal,400".

PDF 照常生成,只是粗体被弱化为同字重的伪加粗(FOP 用描边模拟或直接不加粗,取决于渲染器)。工程实践:同一 ttc/ttf 给 normal 和 bold 各挂一个 triplet(可指向同一物理文件或对应的 Bold 文件):

<font kerning="yes" embed-url="file:///usr/share/fonts/truetype/wqy/wqy-zenhei.ttc" sub-font="WenQuanYi Zen Hei">
  <font-triplet name="WQYZenHei" style="normal" weight="normal"/>
  <font-triplet name="WQYZenHei" style="normal" weight="bold"/>
</font>

3.7 连字符替换告警

CJK 字体通常没有 U+002D 连字符字形,启用断词时会出现:

WARNING: Substituted specified hyphenation character (0x2d) with 0x20 because the font doesn't have the specified hyphenation character: DroidSansFallback,normal,400

无功能影响,可忽略或换字体消除。

3.8 auto-detect 自动探测

fonts 节写 <auto-detect/> 时,FOP 扫描平台字体目录并按 fontconfig 名注册全部字体:

<fonts>
  <auto-detect/>
</fonts>

优点是零维护;缺点是 triplet 名由字体内部名决定(如 font-family="WenQuanYi Zen Hei"),且系统装了 CFF 字体(如 Noto)后仍会触发 3.4 的加载失败。生产环境建议显式注册而非 auto-detect。

3.9 字体缓存

FOP 解析字体文件的开销不小,度量结果缓存在 $HOME/.fop/fop-fonts.cache:

ls -l /root/.fop/

实测输出:

-rw-r--r-- 1 root root 2105 Oct 14 14:04 fop-fonts.cache
选项作用
-cache 路径指定缓存文件/目录位置(无家目录的 CI 环境必备)
-flush清空当前字体缓存

换字体文件后若排版结果诡异,先 -flush 再试。

3.10 metrics-url 与老式注册

<font metrics-url="arial.xml" embed-url="arial.ttf"> 是 FOP 1.x 时代用 TTFReader 预生成度量 XML 的写法,2.x 仍兼容(发行包 fop.xconf 注释里有示例),新部署直接用 embed-url 即可,无需预生成。

四、PDF 渲染器配置

4.1 filterList:PDF 流压缩

<renderer mime="application/pdf">
  <filterList>
    <value>flate</value>
    <!-- <value>ascii-85</value> -->
    <!-- <value>ascii-hex</value> -->
  </filterList>
</renderer>
滤镜说明实测建议
flatezlib 压缩默认开启,保持即可
ascii-85二进制转 ASCII(约 4:5 膨胀)仅兼容极老设备时开
ascii-hex十六进制编码(体积翻倍)不建议

4.2 xml-handler:内嵌 SVG 的行为

<xml-handler namespace="http://www.w3.org/2000/svg">
  <stroke-text>false</stroke-text>
</xml-handler>

stroke-text=false(默认)时 SVG 文本以文本对象写入 PDF(可选中复制),true 则描边成路径。

五、位图渲染器配置

5.1 TIFF 压缩

TIFF 渲染器默认不压缩,A4 文本页实测一张 2,010,936 字节;配置 CCITT T.6 后同一页仅 12,214 字节(约 165 倍差距):

<renderer mime="image/tiff">
  <compression>CCITT T.6</compression>
</renderer>
compression 取值说明
CCITT T.6传真级二值压缩,黑白文本文档首选
CCITT T.4老式传真压缩
PackBits / Deflate / LZW通用无损

5.2 PNG / TIFF 透明背景

<renderer mime="image/png">
  <transparent-page-background>true</transparent-page-background>
</renderer>

默认 false(白底),true 时不绘制页面背景,便于叠加合成。

5.3 target-resolution 与 -dpi

renderer 节的 <target-resolution>300</target-resolution> 与命令行 -dpi 300 等效(CLI 优先)。实测同一 .fo 渲染 PNG:默认 72 dpi 时 14,312 字节,-dpi 300 时 98,728 字节。位图批产建议在配置里固化目标 dpi,避免每次传参。

六、PS / AFP 渲染器要点

renderer关键配置说明
application/postscriptauto-rotate-landscapetrue 时横向页强制旋转输出
application/x-afpimages mode/bits-per-pixel、renderer-resolution、resource-group-file、afp-font 字体表AFP 面向大型机打印,发行包 fop.xconf 内置完整 Times/Helvetica/Courier raster 字体映射表,可直接参考

七、运行时选项与内存

配置文件之外,CLI 还有 -conserve(内存保守策略,序列化 area tree 换取内存)。实测 300 页 A4 纯文本文档(Ubuntu 22.04 / OpenJDK 11 / 默认堆):

场景命令耗时峰值 RSS
默认fop big.fo -pdf out.pdf1.95s235,796 KB
保守内存fop -conserve big.fo ...1.90s234,624 KB
限 64MB 堆FOP_OPTS="-Xmx64m" fop ...1.85s193,068 KB

简单文本文档下三者都能跑完;含大图、复杂表格的文档才需要 -conserve 与加大堆。JVM 堆通过环境变量 FOP_OPTS 传递(见安装篇 6.2)。

八、编码与国际化

  • 配置文件与 .fo 文件本体统一 UTF-8(XML 声明 encoding="UTF-8"),文件内容不受系统 locale 影响。
  • 命令行参数受 locale 影响:POSIX locale 下 -param 传中文会变问号(实测确认),解决方法是 export LANG=C.UTF-8。
  • -nocs 关闭复杂文字布局(complex script),对阿拉伯语等 RTL 场景有影响,中文不需要动它。
  • 断词(hyphenation)需要对应语言的 hyphenation pattern(发行包 fop-hyph.jar 内置常用语言)。

九、常见问题

9.1 报 Name does not exist in the TrueType collection

sub-font 值与集合内部名不完全一致(注意样式后缀 Bold/Regular)。用加载时的 INFO 日志清单核对(3.3)。

9.2 报 'loca' table not found

字体是 CFF 轮廓(如 fonts-noto-cjk),FOP 2.11 的 PDF 渲染器无法使用,换 TrueType 轮廓字体(3.4)。

9.3 粗体没效果且有 WARNING: Font ...,normal,700 not found

triplet 没覆盖 bold 字重,按 3.6 补注册。

9.4 换了字体文件渲染结果没变

字体缓存未失效,fop -flush 后重试(3.9)。

9.5 auto-detect 后中文还是缺字

auto-detect 按内部名注册,FO 里的 font-family 必须写 fontconfig 名(如 WenQuanYi Zen Hei);且若系统只有 CFF 字体同样会失败。生产环境建议显式注册(3.8)。

9.6 PDF 里中文可复制但显示为方块

字体嵌入了(emb=yes)但查看器用了替代字体渲染,或 uni 映射缺失。用 pdffonts 检查 emb/sub/uni 三列应全为 yes(3.2)。

9.7 页面尺寸不对(US Letter 而非 A4)

default-page-settings 默认 8.5in×11in;要么改配置,要么在 FO 的 simple-page-master 里显式写 page-width/page-height(后者优先级更高)。

9.8 相对路径图片加载失败

检查 base 元素:相对 URL 基于它解析,cron/systemd 环境下工作目录与调试时不同,建议 base 写绝对路径。

十、参考链接

资源地址
Configuration 官方文档https://xmlgraphics.apache.org/fop/2.11/configuration.html
Fonts 官方文档https://xmlgraphics.apache.org/fop/2.11/fonts.html
Output 渲染器文档https://xmlgraphics.apache.org/fop/2.11/output.html
发现代码示例https://xmlgraphics.apache.org/fop/2.11/examples.html