我正在使用飞碟库(旧的但开源的)使用X
HTML生成PDF.我有那个工作,但我也想添加SVG图像.我开始致力于整合蜡染试图让它工作,但我遇到了问题.未绘制SVG图像. XHTML仍然呈现,但它似乎没有显示SVG.我已经让SVG在单独的PDF上渲染,但从未与飞碟结果一起渲染.
我添加了通常的ReplacedElementFactory(它也适用于常规图像,但还没有包含该代码).唯一相关的方法(确实被调用和所有内容)如下:
我添加了通常的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等有关.无论如何它现在都有效.希望它能帮助将来的某个人.如果人们想要评论或重新说明为什么现在这样做,这可能有助于其他人稍后阅读.