java - 如何摆脱 iText XMLWorker 中的 Helvetica?

标签 java pdf fonts embed itext

我们使用 iText 从 Java 代码生成 PDF 文件,这在大多数情况下都运行良好。几天前,我们开始生成 PDF/A,而不是需要嵌入所有字体的普通 PDF 文件。 iText Document主要是自定义构建 PdfPTable以及我们直接控制字体的其他类。所有使用的字体都是从通过以下代码加载的 TTF 文件创建的 - 它工作得很好:

    private BaseFont load(String path) {
        try {
            URL fontResource = PrintSettings.class.getResource(path);
            if (fontResource == null) {
                return null;
            }
            String fontPath = fontResource.toExternalForm();
            BaseFont baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            baseFont.setSubset(true);
            return baseFont;
        }
        catch (DocumentException ex) {
            Logger.getLogger(PrintSettings.class).warn("...");
        }
        catch (IOException ex) {
            Logger.getLogger(PrintSettings.class).warn("...");
        }
        return FontFactory.getFont(PrintSettings.FONT, "UTF-8", true, 8f, Font.NORMAL, PrintSettings.COLOR_TEXT).getBaseFont();
    }

现在我们在从 HTML 代码生成的 PDF 中使用一种特定的内容类型。我们使用 XMLWorker来处理那部分。这工作得很好,只要我们没有嵌入字体。但是对于 PDF/A,我们需要嵌入所有字体,现在我们正在为未知来源的 Helvetica 使用而苦苦挣扎。

我们尝试使用我们自己的 FontProvider 类来解决这个问题,如下所示:

public class PrintFontProvider extends FontFactoryImp {

    @Override
    public Font getFont(String fontName, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {

        // LiberationSans – http://de.wikipedia.org/wiki/Liberation_(Schriftart) – http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web
        if (style == Font.NORMAL)     return new Font(this.load("fonts/Liberation/LiberationSans-Regular.ttf"),    size, Font.NORMAL, color);
        if (style == Font.BOLD)       return new Font(this.load("fonts/Liberation/LiberationSans-Bold.ttf"),       size, Font.NORMAL, color);
        if (style == Font.BOLDITALIC) return new Font(this.load("fonts/Liberation/LiberationSans-BoldItalic.ttf"), size, Font.NORMAL, color);
        if (style == Font.ITALIC)     return new Font(this.load("fonts/Liberation/LiberationSans-Italic.ttf"),     size, Font.NORMAL, color);
        return new Font(this.load("fonts/Liberation/LiberationSans-Regular.ttf"), size, style, color);
    }

    private BaseFont load(String path) { ... }
}

它与 XMLWorker 相关联使用以下代码:

HtmlPipelineContext html = new HtmlPipelineContext(null);
html.setTagFactory(Tags.getHtmlTagProcessorFactory());
CSSResolver css = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);

// We need to control the FontProdiver!
html.setCssAppliers(new CssAppliersImpl(new PrintFontProvider()));

Pipeline<?> pipeline = new CssResolverPipeline(css, new HtmlPipeline(html, new PdfWriterPipeline(this.document, writer)));
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser p = new XMLParser(worker);
p.parse(new ByteArrayInputStream(StringUtils.iTextHTML(string).getBytes()));

大多数简单的 HTML 元素都是这样工作的...但是有些元素似乎忽略了 FontProvider 并继续使用不会嵌入 PDF/A 中的 Helvetica(我们不有那个字体)。例如<ol><li>...</li></ol>利用这个。

Caused by: com.itextpdf.text.pdf.PdfXConformanceException: All the fonts must be embedded. This one isn't: Helvetica
at com.itextpdf.text.pdf.internal.PdfXConformanceImp.checkPDFXConformance(PdfXConformanceImp.java:225)
at com.itextpdf.text.pdf.PdfWriter.addSimple(PdfWriter.java:2192)
at com.itextpdf.text.pdf.PdfContentByte.setFontAndSize(PdfContentByte.java:1444)
at com.itextpdf.text.pdf.PdfDocument.writeLineToContent(PdfDocument.java:1463)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:968)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:841)
at com.itextpdf.text.pdf.ColumnText.showTextAligned(ColumnText.java:1189)
at com.itextpdf.text.pdf.ColumnText.showTextAligned(ColumnText.java:1208)
at com.itextpdf.text.pdf.PdfDocument.flushLines(PdfDocument.java:1193)
at com.itextpdf.text.pdf.PdfDocument.newPage(PdfDocument.java:830)
at com.itextpdf.text.Document.newPage(Document.java:367)

我现在已经想不出如何摆脱 Helvetica 的想法了……现在已经尝试解决这个问题 8 个多小时了……还有更多想法吗?

最佳答案

我挖得更深一点,从 OrderedUnorderedList 开始在 ListItemList ...

/**
 * Adds an <CODE>Element</CODE> to the <CODE>List</CODE>.
 *
 * @param   o       the element to add.
 * @return true if adding the object succeeded
 * @since 5.0.1 (signature changed to use Element)
 */
@Override
public boolean add(final Element o) {
    if (o instanceof ListItem) {
        ListItem item = (ListItem) o;
        if (this.numbered || this.lettered) {
            Chunk chunk = new Chunk(this.preSymbol, this.symbol.getFont());
            chunk.setAttributes(this.symbol.getAttributes());
            int index = this.first + this.list.size();
            if ( this.lettered )
                chunk.append(RomanAlphabetFactory.getString(index, this.lowercase));
            else
                chunk.append(String.valueOf(index));
            chunk.append(this.postSymbol);
            item.setListSymbol(chunk);
        }
        else {
            item.setListSymbol(this.symbol);
        }
        item.setIndentationLeft(this.symbolIndent, this.autoindent);
        item.setIndentationRight(0);
        return this.list.add(item);
    }
    else if (o instanceof List) {
        List nested = (List) o;
        nested.setIndentationLeft(nested.getIndentationLeft() + this.symbolIndent);
        this.first--;
        return this.list.add(nested);
    }
    return false;
}

此代码引用this.symbol.getFont()在类初始化时设置为未定义...

public class List implements TextElementArray, Indentable {

    [...]    

    /** This is the listsymbol of a list that is not numbered. */
    protected Chunk symbol = new Chunk("- ");

我只是用了另一个 Chunk采用 Font 的构造函数我的和瞧...已解决。编号列表不再使用 Helvetica,而是使用我自己的正确嵌入的字体。

这花了我很长时间!另一种方法可能是为 <ol> 实现自己的 TagProcessor但我们没有时间了。我会为此提交一份错误报告...我们会看看它是否会得到更灵活的修复。

关于java - 如何摆脱 iText XMLWorker 中的 Helvetica?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12093236/

相关文章:

java - 如何在 JPA 中映射自定义集合?

java - 在抽象类中创建方法而不是在扩展它的类中重写它们是一个好习惯吗?

css - CSS 中指定的 Arial 中断了 IE9 中的站点

html - 如何使用 CSS 中的特定字体样式,来自 Google 字体(即细、超轻……)

java - 从 BufferedReader 读取时出现 NullPointerException,仅当作为 jar 运行时

java - 重绘线程在触发业务功能时工作正常,但在引用触发时卡住

sql - 在sql server中创建pdf文件

php - 是否可以使用 PHP 从 MS office 文件和/或 PDF 中提取元信息?

php - 如何删除 TCPDF 中标题下方和 $html 上方的行?

html - 第一个字母 CSS 上的左空格