Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 341785 - PDF report ignores trasnparency in SVG images
Summary: PDF report ignores trasnparency in SVG images
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: BIRT (show other bugs)
Version: 2.6.1   Edit
Hardware: PC Windows 7
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Yu Chen CLA
QA Contact: Xiaoying Gu CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-04 10:13 EDT by Jan Krakora CLA
Modified: 2011-05-02 16:20 EDT (History)
3 users (show)

See Also:


Attachments
SVG image with trasparent shapes (46.72 KB, image/svg+xml)
2011-04-04 10:13 EDT, Jan Krakora CLA
no flags Details
The output PDF report icluding SVG image (58.26 KB, application/pdf)
2011-04-04 10:21 EDT, Jan Krakora CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jan Krakora CLA 2011-04-04 10:13:51 EDT
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);
Comment 1 Jan Krakora CLA 2011-04-04 10:21:05 EDT
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)
Comment 2 Jan Krakora CLA 2011-04-21 09:13:32 EDT
Nobody has the same problem?
Comment 3 Jan Krakora CLA 2011-05-02 16:20:02 EDT
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.