Вопрос по pdf, itext, java, fonts, embed – Как избавиться от Helvetica в iText XMLWorker?

5

Мы используем iText для генерации PDF-файлов из кода Java, который в большинстве случаев работает довольно хорошо. Несколько дней назад мы начали генерировать PDF / A вместо обычных PDF-файлов, в которые нужно встроить все шрифты. ITextDocument в основном сборка на заказ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();
    }

Теперь мы используем один конкретный тип содержимого в PDF, который генерируется из кода HTML. Мы используемXMLWorkerчтобы справиться с этой частью. Это работало просто отлично, если мы не встраивали шрифты. Но с PDF / A мыneed встроить все шрифты, и теперь мы боремся с неизвестным источником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 и продолжают использоватьHelvetica который не будет встроен в PDF / A (у нас нет этого шрифта). Например<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 с лишним часов ... еще идеи?

Даже если мы встраиваемHelvetica из файлов TTF, извлеченных из файла OSX Helvetica.dfont, генерируется исключение. Он просто игнорирует ранее встроенный шрифт. Daniel Bleisteiner
Обновлен до iText v5.3.2 и XMLWorker v1.1.6 ... все тот же. Не могу избавиться отHelvetica е & # XFC; г<ol> Daniel Bleisteiner
Как я выяснил, он просто игнорирует любое семейство шрифтов для символа / числа ... использует ZapfDingbats для маркеров и по умолчанию (Helvetica) для нумерованных списков. Толькоol { list-style-type: disc; } что-то изменило ... семья шрифтов не коснулась цифр и маркеров. Daniel Bleisteiner
<ol> в настоящее время наша проблема ...<ul> работает просто отлично. Я заметил, что<ul> проситZapfDingbats но<ol> вообще не запрашивает какой-либо шрифт. Я полагаю, он используетHelvetica не спрашивая ... когда я подаю заявкуlist-style-type: disc; он не пытается встроить этот шрифт. Daniel Bleisteiner
Можете ли вы повторно реализовать CssAppliersImpl и посмотреть, что именно CSS применяет к & lt; ol & gt; тег? user1516873

Ваш Ответ

1   ответ
2

OrderedUnorderedList надListItem вList...

/**
 * 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 мой и вуаля ...SOLVED, Нумерованный список больше не используетHelvetica но мой собственный шрифт, который вставлен правильно.

Это заняло у меня целую вечность! Другим способом было бы реализовать собственный TagProcessor для<ol> но у нас больше нет времени на это. Для этого я подам отчет об ошибке ... посмотрим, будет ли он исправлен более гибко.

Не могли бы вы предложить решениеstackoverflow.com/q/52736441/3169868
sourceforge.net/tracker/… Daniel Bleisteiner

Похожие вопросы