微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将SVG图像添加到使用HTML和Flying Saucer库(和Batik)构建的PDF?

我正在使用飞碟库(旧的但开源的)使用X HTML生成PDF.我有那个工作,但我也想添加SVG图像.我开始致力于整合蜡染试图让它工作,但我遇到了问题.未绘制SVG图像. XHTML仍然呈现,但它似乎没有显示SVG.我已经让SVG在单独的PDF上渲染,但从未与飞碟结果一起渲染.
添加了通常的ReplacedElementFactory(它也适用于常规图像,但还没有包含该代码).唯一相关的方法(确实被调用和所有内容)如下:

@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("logo.svg").toURL()
                    .toString());
        } catch (IOException e) {
            e.printstacktrace();
        }
        Element svgElement = svgImage.getDocumentElement();
        Document htmlDoc = element.getownerDocument();
        Node importednode = htmlDoc.importNode(svgElement,true);
        element.appendChild(importednode);
        return new SVGReplacedElement(svgImage,cssWidth,cssHeight);
    }
    return this.superFactory.createReplacedElement(layoutContext,blockBox,userAgentCallback,cssHeight);
}

之后我尝试用它绘画:

import java.awt.Graphics2D;
import java.awt.Point;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.gvt.GraphicsNode;
import org.w3c.dom.svg.SVGDocument;
import org.xhtmlrenderer.css.style.CalculatedStyle;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.pdf.ItextoutputDevice;
import org.xhtmlrenderer.pdf.ITextReplacedElement;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.render.PageBox;
import org.xhtmlrenderer.render.RenderingContext;

import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfTemplate;

public class SVGReplacedElement implements ITextReplacedElement {

private Point location = new Point(0,0);
private SVGDocument svg;
private int cssWidth;
private int cssHeight;

public SVGReplacedElement(SVGDocument importednode,int cssHeight) {
    this.cssWidth = cssWidth;
    this.cssHeight = cssHeight;
    this.svg = importednode;
}

@Override
Methods....

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

    UserAgent userAgent = new UserAgentAdapter();
    DocumentLoader loader = new DocumentLoader(userAgent);
    BridgeContext ctx = new BridgeContext(userAgent,loader);
    ctx.setDynamicState(BridgeContext.DYNAMIC);
    GVTBuilder builder = new GVTBuilder();

    blockBox.paintDebugOutline(renderingContext);

    PdfContentByte cb = outputDevice.getWriter().getDirectContent();

    float width = cssWidth / outputDevice.getDotsPerPoint();
    float height = cssHeight / outputDevice.getDotsPerPoint();

    PdfTemplate map = cb.createTemplate(width,height);

    Graphics2D g2d = map.createGraphics(width,height);

    GraphicsNode mapGraphics = builder.build(ctx,svg);
    mapGraphics.paint(g2d);
    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);

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

有趣的是,blockBox.paintDebugOutline(renderingContext);确实绘制了图像应该在哪里的轮廓. Eclipse调试还显示正确的文件连接到IMG元素.
CSS看起来如下:

.header {
position: absolute;
display: inline-block;
right: 0;
top: 0;
width: 150px;
height: 54px;
}

我也尝试过display:block; .示例xhtml我试过:

<img class='header' src='icon.svg' alt='logo'/> 
<svg class='header' type='image/svg+xml' data='icon.svg' />
<object class='header' type='image/svg+xml' data='icon.svg' />

非常感谢您的关注和反馈(以及可能的答案)

编辑:最初的问题略有不同,但我已经解决了. SVGImage无法附加到实际文档中.现在它只是没有画.我已经添加了CSS来显示:块等,如指南中所述.

编辑:清洁代码

编辑:添加了更多关于我尝试过的内容

解决方法

我不知道为什么,但更换SVGReplacedElement.paint(…)中的代码修复它.

代码

@Override
public void paint(RenderingContext renderingContext,BlockBox blockBox) {
    PdfContentByte cb = outputDevice.getWriter().getDirectContent();
    float width = (float) (cssWidth / outputDevice.getDotsPerPoint());
    float height = (float) (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,width,height);
    pg.setPaper(pp);
    prm.print(g2d,pg,0);
    g2d.dispose();

    PageBox page = renderingContext.getPage();
    float x = blockBox.getAbsX() + page.getMarginBorderPadding(renderingContext,CalculatedStyle.BottOM);
    x /= outputDevice.getDotsPerPoint(); 
    y /= outputDevice.getDotsPerPoint();

    cb.addTemplate(template,y);
}

得到它:http://www.samuelrossille.com/posts/2013-08-13-render-html-with-svg-to-pdf-with-flying-saucer.html

可能与我创建的没有链接到原始文档的新UserAgent和DocumentLoader等有关.无论如何它现在都有效.希望它能帮助将来的某个人.如果人们想要评论或重新说明为什么现在这样做,这可能有助于其他人稍后阅读.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐