2016-08-15 104 views
0

我使用FlyingSaucer的ITextRenderer從XML和CSS創建PDF。我想指定一個引用SVG圖像的CSS背景圖像。我用PNG工作正常,但不是SVG圖像。使用Flying Saucer的SVG背景圖像

我試圖讓一個ChainedReplacedElementFactory來替換SVG節點,但是這不起作用,因爲這些SVG文件沒有從文檔引用,而是通過url()引用CSS。

有什麼方法可以教FlyingSaucer如何處理從CSS引用的SVG文件?

回答

0

我確實設法弄清楚了這一點。訣竅是定製用戶代理。

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); 
+0

我們在項目中使用這些代碼,並發現它的作品。但是當被多個線程使用時,mFactory.createSVGDocument(null,isr)開始拋出隨機的NullPointerExceptions。造成這種情況的根本原因是mFactory被聲明爲靜態。所以爲了解決這個問題,我們只是刪除了靜態聲明。 – webguy