【问题标题】:SVG background images with Flying Saucer带有飞碟的 SVG 背景图像
【发布时间】:2016-12-22 03:12:30
【问题描述】:

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

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

有什么方法可以教 FlyingSaucer 如何处理从 CSS 引用的 SVG 文件?

【问题讨论】:

    标签: java svg pdf-generation flying-saucer


    【解决方案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);
    

    【讨论】:

    • 我们在项目中使用了这段代码,发现它可以工作。但是当被多个线程使用时,mFactory.createSVGDocument(null, isr) 开始抛出随机 NullPointerExceptions。根本原因是 mFactory 被声明为静态的。所以为了解决这个问题,我们只是删除了静态声明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    相关资源
    最近更新 更多