CSS 样式在 iText7 中的编程应用不是 html2pdf

问题描述

我正在努力从 iText5 升级到 iText7。我想利用使用 CSS 来定义和应用样式的能力 - 但我没有进行 html2pdf 转换。我们目前正在以编程方式构建我们的报告。有没有一种很好的方法可以为 Document 设置 CSS 并在构造 Document 时应用样式?谢谢!

解决方法

我假设您正在基于 layout 模块中的元素构建元素结构,因为您没有使用 pdfHTML。 CSS 样式与您可以从 layout 模块为元素设置的样式之间没有 1-1 对应关系 - 某些 CSS 样式会影响元素的结果结构和元素的内容(例如大小写的更改等),而 pdfHTML 插件会处理所有这些。

这意味着将现有 CSS 样式应用到 layout 模块中的元素结构的可能性非常有限。最好的方法是编写 HTML+CSS 标记并使用 HtmlConverter#convertToElements 转换为 layout 元素结构。您将不得不编写一些代码来充当 CSS 和布局之间的桥梁。示例:

Document document = new Document(new PdfDocument(new PdfWriter("C:/out.pdf")));

Paragraph p = new Paragraph("Hello world");

Map<String,String> cssStyles = new HashMap<>();
// Font size is the required field
cssStyles.put("font-size","12pt");
cssStyles.put("color","red");
// No shorthand properties are allowed
cssStyles.put("border-left-color","black");
cssStyles.put("border-left-style","solid");
cssStyles.put("border-left-width","1px");

DummyStylesContainer container = new DummyStylesContainer();
container.setStyles(cssStyles);

ProcessorContext context = new ProcessorContext(new ConverterProperties());
context.getCssContext().setRootFontSize(12);

BlockCssApplier applier = new BlockCssApplier();
applier.apply(context,container,new DummyTagWorker(p));

document.add(p);

document.close();

辅助类定义:

private static class DummyStylesContainer implements IStylesContainer {
    private Map<String,String> map;

    @Override
    public void setStyles(Map<String,String> stringStringMap) {
        this.map = stringStringMap;
    }

    @Override
    public Map<String,String> getStyles() {
        return map;
    }
}

private static class DummyTagWorker implements ITagWorker {
    private IPropertyContainer container;

    public DummyTagWorker(IPropertyContainer container) {
        this.container = container;
    }

    @Override
    public void processEnd(IElementNode element,ProcessorContext context) {
    }

    @Override
    public boolean processContent(String content,ProcessorContext context) {
        return false;
    }

    @Override
    public boolean processTagChild(ITagWorker childTagWorker,ProcessorContext context) {
        return false;
    }

    @Override
    public IPropertyContainer getElementResult() {
        return container;
    }
}

结果:result