SVG背景图像与飞碟

时间:2016-08-15 21:10:33

标签: java svg pdf-generation flying-saucer

我正在使用FlyingSaucer的ITextRenderer从XML和CSS创建PDF。我想指定一个引用SVG图像的CSS背景图像。我使用PNG但没有SVG图像可以正常工作。

我试图制作一个ChainedReplacedElementFactory来替换SVG节点,但这不起作用,因为这些SVG文件没有从文档引用,而是通过url()引用CSS。

有没有办法教FlyingSaucer如何处理从CSS引用的SVG文件?

1 个答案:

答案 0 :(得分:1)

我确实设法解决了这个问题。诀窍是自定义用户代理。

class CustomUserAgent extends ITextUserAgent 
{
  private final ITextOutputDevice mDevice;

  public CustomUserAgent(ITextOutputDevice dev)
  {
    super(dev);
    mDevice = dev;
  }

  private static final SAXSVGDocumentFactory mFactory = 
    new SAXSVGDocumentFactory(null);

  private ImageResource getSVGImage(String uri)
    throws IOException, BadElementException
  {
    InputStream is = null;

    try
    {
      is = resolveAndOpenStream(uri);
      InputStreamReader isr = new InputStreamReader(is);
      Document doc = mFactory.createSVGDocument(null, isr);
      UserAgent ua = new UserAgentAdapter();
      DocumentLoader loader = new DocumentLoader(ua);
      BridgeContext ctx = new BridgeContext(ua, loader);
      ctx.setDynamicState(BridgeContext.DYNAMIC);
      GVTBuilder builder = new GVTBuilder();
      String not_numbers = "[^0-9.,]";
      float width = 
        Float.parseFloat(doc.getDocumentElement().
                         getAttribute("width").replaceAll(not_numbers, ""));
      float height =
        Float.parseFloat(doc.getDocumentElement().
                         getAttribute("height").replaceAll(not_numbers, ""));
      PdfWriter writer = mDevice.getWriter();
      PdfTemplate templ = PdfTemplate.createTemplate(writer, width, height);
      Graphics2D g2d = templ.createGraphics(width, height);
      GraphicsNode gfx = builder.build(ctx, doc);
      gfx.paint(g2d);
      g2d.dispose();
      Image img = new ImgTemplate(templ);
      img.setAlignment(Image.ALIGN_CENTER);

      SharedContext shctx = getSharedContext();
      float dpi = shctx.getDotsPerPixel();
      if (dpi != 1.0f)
        img.scaleAbsolute(img.getPlainWidth()  * dpi,
                          img.getPlainHeight() * dpi);

      return new ImageResource(uri, new ITextFSImage(img));
    }
    finally
    {
      if (is != null)
        is.close();
    }
  }

  @Override
  public ImageResource getImageResource(String uri)
  {
    if (uri.endsWith(".svg"))
    {
      try
      { return (getSVGImage(uri)); }
      catch(IOException io)
      { throw new RuntimeException(io); }
      catch(BadElementException be)
      { throw new RuntimeException(be); }
    }
    else
      return (super.getImageResource(uri));
  }   
}

然后使用它只需将其应用于渲染器:

CustomUserAgent callback =
  new CustomUserAgent(renderer.getOutputDevice());
callback.setSharedContext(renderer.getSharedContext());
renderer.getSharedContext().setUserAgentCallback(callback);