高效的PDF格式SVG渲染(Java,Batik,Flying Saucer)

时间:2015-05-12 07:59:11

标签: java performance memory svg pdf-generation

我使用XHTML和飞碟渲染PDF。我也添加了SVG图像(图标等)。但是,当我尝试绘制大量图像(如5000+)时,渲染需要很长时间(显然)。只有10个左右的不同图像可以绘制,但只是重复它们很多次(相同的大小)。

有效的方法/库吗?

目前使用蜡染,飞碟组合绘制图像。以下代码用于解析xhtml并找到img标记以放置SVG图像:

@Override
public ReplacedElement createReplacedElement(LayoutContext layoutContext, BlockBox blockBox, UserAgentCallback userAgentCallback, int cssWidth, int cssHeight) {
    Element element = blockBox.getElement();
    if (element == null) {
        return null;
    }
    String nodeName = element.getNodeName();
    if ("img".equals(nodeName)) {
        SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
        SVGDocument svgImage = null;
        try {
            svgImage = factory.createSVGDocument(new File(element.getAttribute("src")).toURL().toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        Element svgElement = svgImage.getDocumentElement();
        element.appendChild(element.getOwnerDocument().importNode(svgElement, true));
        return new SVGReplacedElement(svgImage, cssWidth, cssHeight);
    }
    return this.superFactory.createReplacedElement(layoutContext, blockBox, userAgentCallback, cssWidth, cssHeight);
}

并绘制我使用的图像:

    @Override
public void paint(RenderingContext renderingContext, ITextOutputDevice outputDevice, 
        BlockBox blockBox) {

    PdfContentByte cb = outputDevice.getWriter().getDirectContent();
    float width = cssWidth / outputDevice.getDotsPerPoint();
    float height = cssHeight / outputDevice.getDotsPerPoint();

    PdfTemplate template = cb.createTemplate(width, height);
    Graphics2D g2d = template.createGraphics(width, height);
    PrintTranscoder prm = new PrintTranscoder();
    TranscoderInput ti = new TranscoderInput(svg);
    prm.transcode(ti, null);
    PageFormat pg = new PageFormat();
    Paper pp = new Paper();
    pp.setSize(width, height);
    pp.setImageableArea(0, 0, width, height);
    pg.setPaper(pp);
    prm.print(g2d, pg, 0);
    g2d.dispose();

    PageBox page = renderingContext.getPage();
    float x = blockBox.getAbsX() + page.getMarginBorderPadding(renderingContext, CalculatedStyle.LEFT);
    float y = (page.getBottom() - (blockBox.getAbsY() + cssHeight)) + page.getMarginBorderPadding(
            renderingContext, CalculatedStyle.BOTTOM);
    x /= outputDevice.getDotsPerPoint(); 
    y /= outputDevice.getDotsPerPoint();

    cb.addTemplate(template, x, y);
}

缩放的想法。 100张图像需要2秒,5000张图像在i5 8GB RAM上大约需要42秒。

那么有没有办法将绘制的SVG存储在内存中并更快地粘贴它?因为现在它似乎将所有图像作为单独的图像并且吃掉了我的所有记忆并且永远占据了它。

1 个答案:

答案 0 :(得分:1)

通过执行两项操作来管理以优化内存和速度。 我在.xcdatamodeld方法中预先生成了SVGDocuments,加快了它的速度。 主要的改进是为所有图像预生成所有pdfTemplates。由于模板已包含渲染图像,因此速度大大提高。 所有常规文本的呈现仍然很慢,因此我可能会拒绝DPI。

编辑:进一步优化,请参阅Is there any way improve the performance of FlyingSaucer?