iText:从PdfAChecker抛出的误导性异常消息?

时间:2017-10-09 15:51:33

标签: fonts itext

我一直试图将HTML写入符合PDF / A标准的PDF格式。 我使用以下库:

  • iText的-PDFA-5.5.12
  • itextpdf-5.5.12
  • xmlworker-5.5.12

以下错误似乎定期出现:

Exception in thread "main" com.itextpdf.text.pdf.PdfAConformanceException: All the fonts must be embedded. This one isn't: Helvetica

在某些情况下,该消息似乎具有误导性。我的代码与another post非常相似。 关键行在代码中注释。

  • 当评论时,我得到了一个关于缺少Helvetica字体的例外。
  • 取消注释时,程序无一例外地执行。

在生成的PDF文件中,我可以看到一个嵌入字体(ArialMT)。我发现异常消息很奇怪,但我无法弄清楚为什么只使用 Arial 时会出现 Helvetica 。这是一个问题(错误)还是我错过了什么?

public class BugFontExceptionDemo {
    public static void main(String[] args) {
        StringBuffer buf = new StringBuffer();
        buf.append("<body>");
        buf.append("<h1 style=\"font-family:arial\">Text in arial</h1>");
        buf.append("</body>");

        OutputStream file = null;
        Document document = null;
        PdfAWriter writer = null;
        try {
            file = new FileOutputStream(
                    new File("C:\\Users\\Emilien\\PROJECTS_FILES\\PROJECT_EXPORT_TEST\\PDF_A_HTML_WORKING.pdf"));
            document = new Document();
            writer = PdfAWriter.getInstance(document, file, PdfAConformanceLevel.PDF_A_1B);
            document.addTitle("Test document");
            writer.createXmpMetadata();
            document.open();

            ICC_Profile icc = ICC_Profile.getInstance(new FileInputStream(
                    "C:\\Users\\Emilien\\PROJECTS_FILES\\PROJECT_EXPORT_TEST\\sRGB_CS_profile.icm"));
            writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);

            CSSResolver cssResolver = new StyleAttrCSSResolver();
            CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream("./css/style.css"));
            cssResolver.addCss(cssFile);

            MyFontProvider fontProvider = new MyFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
//          fontProvider.register("./fonts/arial.ttf");

            CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
            HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
            htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

            PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
            HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
            CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

            XMLWorker worker = new XMLWorker(css, true);
            XMLParser p = new XMLParser(worker);

            Reader reader = new StringReader(buf.toString());
            p.parse(reader);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document != null && document.isOpen())
                document.close();
            try {
                if (file != null)
                    file.close();
            } catch (IOException e) {
            }
            if (writer != null && !writer.isCloseStream())
                writer.close();
        }
    }
}


public static class MyFontProvider extends XMLWorkerFontProvider {

        public MyFontProvider(String path) {
            super(path);
        }

        @Override
        public Font getFont(final String fontname, String encoding, float size, final int style) {
            System.out.println("registered: " + isRegistered(fontname) + " fontname: " + fontname + " encoding: "
                    + encoding + " size: " + size + " style: " + style);
            Font font = super.getFont(fontname, encoding, size, style);
            return font;
        }

        @Override
        public Font getFont(String fontname, String encoding, boolean embedded, float size, int style,
                BaseColor color) {
            System.out.println("registered: " + isRegistered(fontname) + " fontname: " + fontname + " encoding: "
                    + encoding + " embedded : " + embedded + " size: " + size + " style: " + style + " BaseColor: "
                    + color);
            Font font = super.getFont(fontname, encoding, embedded, size, style, color);
            return font;
        }
    }

1 个答案:

答案 0 :(得分:3)

您使用MyFontProvider参数注册DONTLOOKFORFONTS;因此,它不会知道任何字体(除了“内置”标准14字体)。

如果您不手动注册任何字体,那么仍然如此。这正是你对焦点线进行评论的情况。

因此,在请求HTML处理Arial期间,使用标准14种字体替换,在这种情况下使用Helvetica。但iText没有带来这些“内置”字体,只有PDF观众必须这样,iText只知道它的一些指标。因此,iText不能也不会嵌入字体程序,只是引用它,然后导致基础PDF / A检查代码的错误消息。

然后你想知道

  

当请求字体但不可用时,是否可以要求XMLWorker抛出异常,而不是用Helvetica静默替换字体?

当然,正如你自己发现的那样

  

我只需检查XMLWorkerFontProvider中的注册情况即可。如果没有注册字体,我会抛出异常。