当前位置: 首页 > 知识库问答 >
问题:

如何将SVG图像添加到使用超文本标记语言和飞碟库(和蜡染)构建的PDF?

葛言
2023-03-14

我正在使用飞碟库(旧但开源)使用XHTML生成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, cssWidth, 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 cssWidth, 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(渲染上下文) 确实绘制了图像应该在哪里的轮廓。Eclipse调试还显示,正确的文件连接到IMG元素。CSS如下所示:

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

我还尝试过show: 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以显示:block等,如指南中所述。

编辑:更干净的代码

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


共有1个答案

柯唯
2023-03-14

我不知道为什么,但替换了SVGReplacedElement中的代码。油漆(…)修复了它。

新代码:

@Override
public void paint(RenderingContext renderingContext, ITextOutputDevice outputDevice, 
        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, 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);
}

从教程中得到的。

可能与我创建的未链接到原始文档的新UserAgent和DocumentLoader等有关。无论如何,它现在起作用了。希望这对将来的人有帮助。如果人们想评论或添加另一个答案来解释为什么现在这样做有效,这可能有助于其他人以后阅读本文。

 类似资料:
  • 问题内容: 我正在使用飞碟库(旧但开源)使用XHTML生成PDF。我可以正常工作,但我也想添加SVG图像。Ive开始着手整合蜡染以尝试使其正常工作,但我遇到了问题。未绘制SVG图像。XHTML仍会渲染,但似乎没有显示SVG。我已经将SVG渲染为单独的PDF,但从未与飞碟的结果一起使用。我添加了通常的ReplacedElementFactory(它也可以与常规图像一起使用,但尚未包含该代码)。唯一相

  • 问题内容: 简而言之,我正在寻找一种使用蜡染库从SVG文件制作ImageIcon的方法。我不想先将SVG光栅化到磁盘上,我只想能够将一个svg从jar文件中拉出并将其作为UI元素放置。 我觉得这应该相当容易,但是蜡染的javadocs并没有告诉我我需要知道的内容。 (为什么要使用蜡染呢?好吧,我们已经在使用它了,所以我们不必在合法的情况下运行另一个图书馆。) 问题答案: 这确实很容易,但不是很直观

  • 我需要将所有html报告转换为PDF。 这是一个nodejs应用程序,所以我找不到任何将html转换为pdf的核心模块。 所以我使用JAVA飞碟罐将html转换为PDF。除了html中嵌入的svg之外,其他一切都可以完美地工作。我在谷歌上搜索到了这个教程和Stackoverflow链接。我是一名nodejs开发人员,对java有基本的了解。我不知道如何将此代码与飞碟集成。 请指导我做什么 . 下面

  • 我想使用flatter和dart在webview中呈现存储在手机内存中的本地HTML文件。

  • 问题内容: 我正在使用飞碟将XHTML转换为PDF文档。我已经获得了仅可用于基本HTML和嵌入式CSS的代码,但是,现在,我试图将图像添加为PDF的标题。我想知道的是,是否有任何办法通过将图像文件读取为Java Image对象来添加图像,然后以某种方式将其添加到PDF(或XHTML中,就像它获得了虚拟的“ URL”一样)表示可用于呈现PDF的Image对象。有没有人做过这样的事情? 预先感谢您提供

  • 我正在使用飞碟将XHTML转换为PDF文档。我已经让代码只使用基本的HTML和内嵌CSS,然而,现在我正试图将一个图像作为某种头添加到PDF中。我想知道的是,是否有任何方法可以添加图像,通过读取图像文件作为Java图像对象,然后以某种方式将其添加到PDF(或XHTML——就像它得到一个虚拟的“url”,表示可以用于呈现PDF的图像对象)。有人做过这样的事吗? 提前感谢您提供的任何帮助!