生成 PDF 时出错:ITextFontResolver:java.lang.RuntimeException:无法识别带有 'Cp1252' 的字体 'Courier-BoldOblique'

Error Generating PDF: ITextFontResolver: java.lang.RuntimeException: Font 'Courier-BoldOblique' with 'Cp1252' is not recognized

最近需要对库进行一些更改,以便可以将 Apache POI 用于 docx 支持。这包括将 Itext 版本从 2.1.0 更改为 4.2.1

还将 Grails 渲染器插件与飞碟一起使用。来自 build.gradle:

compile 'org.xhtmlrenderer:flying-saucer-core:9.1.12'
compile 'org.xhtmlrenderer:flying-saucer-pdf:9.1.12'
compile 'org.xhtmlrenderer:flying-saucer-log4j:9.1.12'

compile ('org.grails.plugins:rendering:2.0.3') {
    exclude group: 'org.xhtmlrenderer', module: 'core-renderer'
}

compile("com.lowagie:itext:4.2.1")

生成 PDF 时出现以下异常:

java.lang.RuntimeException: Font 'Courier-BoldOblique' with 'Cp1252' is not recognized.
    at org.xhtmlrenderer.pdf.ITextFontResolver.createInitialFontMap(ITextFontResolver.java:470) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextFontResolver.<init>(ITextFontResolver.java:40) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.<init>(ITextRenderer.java:124) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.<init>(ITextRenderer.java:110) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.<init>(ITextRenderer.java:106) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextRenderer.<init>(ITextRenderer.java:102) ~[flying-saucer-pdf-9.1.12.jar:na]
Caused by: com.lowagie.text.DocumentException: Font 'Courier-BoldOblique' with 'Cp1252' is not recognized.
    at com.lowagie.text.pdf.BaseFont.createFont(BaseFont.java:696) ~[itext-4.2.1.jar:na]
    at com.lowagie.text.pdf.BaseFont.createFont(BaseFont.java:603) ~[itext-4.2.1.jar:na]
    at com.lowagie.text.pdf.BaseFont.createFont(BaseFont.java:438) ~[itext-4.2.1.jar:na]
    at org.xhtmlrenderer.pdf.ITextFontResolver.createFont(ITextFontResolver.java:483) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextFontResolver.createFont(ITextFontResolver.java:479) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextFontResolver.addCourier(ITextFontResolver.java:491) ~[flying-saucer-pdf-9.1.12.jar:na]
    at org.xhtmlrenderer.pdf.ITextFontResolver.createInitialFontMap(ITextFontResolver.java:459) ~[flying-saucer-pdf-9.1.12.jar:na]

在查看代码时,上述异常发生在我的代码中

  ITextRenderer theRenderer = new ITextRenderer()

我的代码是 运行 在部署在 Tomcat 上的 war 中。我可以看到字体文件(如 Courier-BoldOblique.afm,但它们在 /com/lowagie/text/pdf/fonts 中的 jar itext-4.2.1.jar 中。

如何获取正确查找字体的代码,以便创建 ITextRenderer 成功?

发现问题:

  • 字体在 com.lowagie.text.pdf.BaseFont 中在静态初始化程序中初始化为局部变量 BuiltinFonts14
  • 然而在fr.opensagres.xdocreport.itext.extension.font.AbstractFontRegistry中inner-classExtendedBaseFont有一个方法clearBuiltinFonts清除初始化的BuiltinFonts14

因此(丑陋的)解决方案如下:

创建 class:

public abstract class FixBaseFont extends BaseFont {

    public static void fixBuiltinFonts() {

        if (BuiltinFonts14.size() != 14) {
            BuiltinFonts14.clear();

            BuiltinFonts14.put(COURIER, PdfName.COURIER);
            BuiltinFonts14.put(COURIER_BOLD, PdfName.COURIER_BOLD);
            BuiltinFonts14.put(COURIER_BOLDOBLIQUE, PdfName.COURIER_BOLDOBLIQUE);
            BuiltinFonts14.put(COURIER_OBLIQUE, PdfName.COURIER_OBLIQUE);
            BuiltinFonts14.put(HELVETICA, PdfName.HELVETICA);
            BuiltinFonts14.put(HELVETICA_BOLD, PdfName.HELVETICA_BOLD);
            BuiltinFonts14.put(HELVETICA_BOLDOBLIQUE, PdfName.HELVETICA_BOLDOBLIQUE);
            BuiltinFonts14.put(HELVETICA_OBLIQUE, PdfName.HELVETICA_OBLIQUE);
            BuiltinFonts14.put(SYMBOL, PdfName.SYMBOL);
            BuiltinFonts14.put(TIMES_ROMAN, PdfName.TIMES_ROMAN);
            BuiltinFonts14.put(TIMES_BOLD, PdfName.TIMES_BOLD);
            BuiltinFonts14.put(TIMES_BOLDITALIC, PdfName.TIMES_BOLDITALIC);
            BuiltinFonts14.put(TIMES_ITALIC, PdfName.TIMES_ITALIC);
            BuiltinFonts14.put(ZAPFDINGBATS, PdfName.ZAPFDINGBATS);
        }
    }
}

然后每次在初始化ITextRenderer

之前添加对这个class的调用
FixBaseFont.fixBuiltinFonts()
ITextRenderer renderer = new ITextRenderer()

这个最新的依赖项 (xhtmlrenderer 9.1.22) 将解决这个问题。 以某种方式 fr.opensagres.xdocreport.itext.extension.font.AbstractFontRegistry 清除 BuiltinFonts14。

<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf-itext5</artifactId>
    <version>9.1.22</version>
</dependency>