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

2023-11-23

我正在使用飞碟库(旧但开源)使用 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(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 添加到 display:block 等,如指南中所述。

编辑:更清晰的代码

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


我不知道到底为什么,但替换 SVGReplacedElement.paint(...) 中的代码修复了它。

新代码:

@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);
}

从一个得到它tutorial.

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • 重新编码/重新调整不同级别的 data.frame 因素

    每次当我必须重新编码一组变量时 我都会想到 SPSS 重新编码功能 我必须承认这非常简单 有一个类似的recode函数于car包 它确实有效 但我们假设我想用factor I have data frame有多个值范围从 1 到 7 的变量
  • 如何使用二分查找从排序的 TreeSet 中检索元素?

    我正在尝试将多个排序列表合并到一个 TreeSet 中 然后我正在考虑在该 TreeSet 上应用二分搜索算法以 O log n 时间复杂度检索元素 下面是我的代码 其中我在我的方法之一中传递列表列表并将它们组合成TreeSet避免重复 里
  • 如何将 Promise.all() 与 chrome.storage() 一起使用?

    我有几个异步函数正在运行 我想等他们全部完成后再采取下一步行动 这是我用来获取所有键 值的代码chrome storage和Promise all 执行 var promise1 Promise resolve 3 var promise2
  • 在 Android 上使用 EWS Java API 时出现问题

    我尝试在 Android 应用程序中使用 EWS Java API v1 1 5 http archive msdn microsoft com ewsjavaapi 但遇到了许多问题 我下载了源代码 并按照提供的说明在 Eclipse 中
  • Java比较器用于多列排序?

    有没有Java开源比较器可以通过多个字段比较bean以进行多列排序 每列都可以升序或降序排序 对于单列排序 可以通过使用来实现org apache commons beanutils BeanComparator和 一起org spring
  • 如何在 Python 中将 H:MM:SS 时间字符串转换为秒?

    基本上我有这个问题的反面 Python 时间秒转 h m s 我有一个格式为 H MM SS 的字符串 始终为 2 位数字表示分钟和秒 我需要它代表的整数秒数 我怎样才能在Python中做到这一点 例如 1 23 45 将产生 5025 的
  • 当在标准错误中看到特定字符串时,如何终止进程?

    我需要启动一个流程 比如说foo 我希望看到标准输出 标准错误正常 但是grep字符串的 stderrbar Once bar发现于 标准错误foo应该被杀 这可能吗 我最初编写了一种涉及流混合的方法来做到这一点 但它不是很好 一些评论与该
  • 如何使用 PHP 和 CURL 上传具有多维 POSTFIELDS 的文件(多部分/表单数据)?

    我在使用 PHP 和 CURL 发布带有文件上传的多维数组时遇到问题 多维数组例如 post question Are you human post answers array yes no maybe post file path to
  • Chrome:未捕获的语法错误:输入意外结束

    在 Google Chrome 中加载页面时 我在控制台中收到模糊错误 未捕获的语法错误 输入意外结束 我不知道是什么原因造成的 我将如何调试这个错误 这个特殊的错误是一个令人烦恼的事实v8 在大多数情况下 您的 JavaScript 会以
  • 默认 WordML 单位测量?像素或点或英寸

    请澄清我的疑问WordML DOCX 默认单位测量是像素或点或 EMU 或英寸 这就是所谓的 DXA 每英寸有 1440 DXA 1英寸为72点 1 DXA 是一个点的 1 20 20 DXA 是 1 点 还有一种叫做动车组的东西 9144
  • HTML/HTML5 的默认命名空间是什么? [关闭]

    Closed 这个问题需要细节或清晰度 目前不接受答案 根据这个page由一些名为 w3c 的用户指定的 HTML 的默认命名空间是 http www w3 org 1999 xhtml 他显然错了 因为 xhtml 被用于失败的基于 XM
  • 集成(Selenium)测试后回滚数据库

    有人对回滚由 Selenium 等集成测试框架进行的数据库事务的最佳实践或首选方式有什么建议吗 这是我们当前的情况 我们有一个 net web 项目 其中包含许多单元测试 这些单元测试在我们的单元测试环境中运行良好 每个测试都继承一个父类
  • 删除 Unix 中的回车符

    删除所有回车符的最简单方法是什么 r来自 Unix 中的文件 I m going to assume you mean carriage returns CR r 0x0d at the ends of lines rather than
  • 用于 iPod 同步的优秀 Python 库

    我正在制作一个音乐应用程序 并且希望能够从我的应用程序与 iPod 同步 有没有人有使用 python 做这件事的经验 如果有的话你会推荐什么 我没用过 但是libgpod似乎确实有 python 绑定
  • Git 表示刚刚签出的文件“不在版本控制之下”

    我有一个明显的印象 我的 Git 存储库不知何故被破坏了 这是我正在执行的顺序 git clone 远程的克隆字符串 这将创建一个文件 App android AndroidManifest xml git mv 应用程序 android
  • 如何使用私有存储库中存在的复合操作?

    我们对第三方服务进行了大量的健康检查 我们希望它们定期运行 因为当它们出现故障时 它会像代码中的错误一样影响我们的应用程序 知道 是他们而不是我们 可以显着减少故障排除时间 我们已经通过 github 操作设置了此运行状况检查并计划运行 但
  • 自定义蜘蛛图 --> 在 matplotlib 中显示极坐标图上点之间的曲线而不是直线

    我测量了不同产品在不同角度位置的位置 在完整旋转过程中以 60 度为步长的 6 个值 我想使用极坐标图 而不是在笛卡尔图上表示我的值 其中 0 和 360 是同一点 With matplotlib 我有一个蜘蛛图类型的图表 但我想避免点之间
  • Swift 中的应用程序 openURL

    我在使用 Appdelegate 方法 OpenURL 时遇到问题 我已经设置了导入的 UTI 和文档类型 但是 当从邮件附件打开我的应用程序时 应用程序会在我实现该方法后立即崩溃 折旧的handleOpenURL可以用 但OpenURL不
  • 使用 Python 和 poplib 获取电子邮件

    我想用Python登录我的帐户并让Python打印我在邮箱中收到的消息 我知道如何连接 import getpass poplib user my user name Mailbox poplib POP3 SSL pop googlema
  • 如何将 SVG 图像添加到使用 HTML 和 Flying Saucer 库(和 Batik)构建的 PDF 中?

    我正在使用飞碟库 旧但开源 使用 XHTML 生成 PDF 我已经成功了 但我还想添加 SVG 图像 我已经开始致力于集成蜡染以尝试使其正常工作 但我遇到了问题 不绘制 SVG 图像 XHTML 仍然呈现 但似乎没有显示 SVG 我已经让