| Summary: | PDF report ignores trasnparency in SVG images | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | z_Archived | Reporter: | Jan Krakora <jan.krakora.cz> | ||||||
| Component: | BIRT | Assignee: | Yu Chen <yChen> | ||||||
| Status: | NEW --- | QA Contact: | Xiaoying Gu <bluesoldier> | ||||||
| Severity: | normal | ||||||||
| Priority: | P3 | CC: | bluesoldier, jan.krakora.cz, jouyang | ||||||
| Version: | 2.6.1 | ||||||||
| Target Milestone: | --- | ||||||||
| Hardware: | PC | ||||||||
| OS: | Windows 7 | ||||||||
| Whiteboard: | |||||||||
| Attachments: |
|
||||||||
Created attachment 192460 [details] The output PDF report icluding SVG image I attached the output PDF report where you can see how the transparency is ignored. This simplified report was created by Jason Weathersby. He's helping me with this problem at the eclipse forum (http://www.eclipse.org/forums/index.php?t=msg&th=207009&start=0&S=a1d69cb0ee38866b0123d3ef049c7d46) Nobody has the same problem? Well, I did my own "patch" for that. I found that the SVG to PDF conversion is done in the PDFPage's transSVG() method. PDFPage is a part of the BIRT's PDF emitter. There is used iText Graphics2D context and Batik's PrintTranscoder to print SVG's byte[] data to PDF template. But so far I understand, the SVG file that I generated from my JFreeChart using Batik contains 'group opacity' for representing translucent shapes and the problem is, that iText's Graphics2D doesn't understand it. (see this Batik's bug for more info https://issues.apache.org/bugzilla/show_bug.cgi?id=51105) So I checkout the PDF emitter bundle and edited the transSVG() method this way: private void transSVG( String svgPath, byte[] svgData, float x, float y, float height, float width, String helpText ) throws IOException, DocumentException { PdfTemplate template = null; Graphics2D g2D = null; Drawable drawable = null; ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(svgData)); try { drawable = (Drawable) inputStream.readObject(); } catch (ClassNotFoundException e) { logger.log(Level.SEVERE, "Chyba pri deserializaci!", e); } if (drawable != null) { Point2D prefferedSize = drawable.getPreffredSize(); float prefferedWidth = (float) prefferedSize.getX(); float prefferedHeight = (float) prefferedSize.getY(); template = contentByte.createTemplate(prefferedWidth, prefferedHeight); g2D = template.createGraphicsShapes(prefferedWidth, prefferedHeight); drawable.draw(g2D, prefferedWidth, prefferedHeight); g2D.dispose(); } else { template = contentByte.createTemplate(width, height); g2D = template.createGraphics(width, height); PrintTranscoder transcoder = new PrintTranscoder( ); if ( null != svgPath ) { transcoder.transcode( new TranscoderInput( svgPath ), null ); } else if ( null != svgData && svgData.length > 0 ) { transcoder.transcode( new TranscoderInput( new ByteArrayInputStream( svgData ) ), null ); } PageFormat pg = new PageFormat( ); Paper p = new Paper( ); p.setSize( width, height ); p.setImageableArea( 0, 0, width, height ); pg.setPaper( p ); transcoder.print( g2D, pg, 0 ); g2D.dispose( ); } drawImage( template, x, y, height, width, helpText ); } Note that Drawable is my interface that contains only a draw method and a method for obtaining the object's preferred size. My JFreeChart chart then implements this interface and is serialized to byte[], then set as data to the report image in its Imagehandler (exactly in its onCreate() method) and then deserialized and printed DIRECTLY using iText's graphics context. So all those translucent shapes are properly translucent. Note also the line where is Graphics2D object derived: g2D = template.createGraphicsShapes(prefferedWidth, prefferedHeight); It means, that all strings from the JFreeChart are drawn as shapes. I used this because of my problematic national (Czech) font encoding. Better solution is use regular graphics (template.createGraphics(prefferedWidth, prefferedHeight)), create a FontMapper, load all needed fonts from operating system and use UNICODE. More about this can be found in iText's javadoc. I know it's not the best solution, but it works for me now. The summary: - I say to BIRT this is an svg image, so it calls my edited transSVG method. - As image's data I dont set svg data but my serialized JFreeChart instead (that's the worst hack). - Then I draw my chart directly to the PDF using iText. |
Created attachment 192459 [details] SVG image with trasparent shapes I have an SVG Image created using the Apache Batik framework. It's a JFreeChart panel drawn into the SVG xml file. It contains some text and shapes (see the attached graph.svg file). This image is inserted to BIRT's dynamic Image report item and from the report is generated a PDF file. So far I have a table containing an dynamic image which is bound to a parameter of a scripted DataSet. This DataSet has an handler java class where I contribute byte array of the SVG document to the parameter. The image has also it's handler java class. In it's onCreate() method I just set image.setMimeType("image/svg+xml"). This way the PDF report contains my SVG image. The problem is it absolutely ignores all shapes which have set the opacity (or alpha) value less than 1. See the attached PDF file. It could be useful to mention that when I start generate the PDF report, it writes to the console about 20 of these messages: "Graphics2D from BufferedImage lacks BUFFERED_IMAGE hint" my render options: PDFRenderOption options = new PDFRenderOption(); options.setOption(IPDFRenderOption.PDF_HYPHENATION, true); options.setOption(IPDFRenderOption.PDF_TEXT_WRAPPING, true); options.setOption(IPDFRenderOption.PAGE_OVERFLOW, IPDFRenderOption.FIT_TO_PAGE_SIZE); options.setSupportedImageFormats("PNG;GIF;JPG;BMP;SWF;SVG"); options.setOutputFileName("output/resample/svgtest.pdf"); options.setOutputFormat(PDFRenderOption.OUTPUT_FORMAT_PDF);