KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > pdf > PDFSVGHandler


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: PDFSVGHandler.java 437210 2006-08-26 18:59:42Z jeremias $ */
19
20 package org.apache.fop.render.pdf;
21
22 import java.io.IOException JavaDoc;
23 import java.io.OutputStream JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.awt.Color JavaDoc;
26 import java.awt.geom.AffineTransform JavaDoc;
27
28 import org.w3c.dom.Document JavaDoc;
29
30 import org.apache.fop.render.AbstractGenericSVGHandler;
31 import org.apache.fop.render.Renderer;
32 import org.apache.fop.render.RendererContext;
33 import org.apache.fop.render.RendererContextConstants;
34 import org.apache.fop.pdf.PDFDocument;
35 import org.apache.fop.pdf.PDFPage;
36 import org.apache.fop.pdf.PDFState;
37 import org.apache.fop.pdf.PDFStream;
38 import org.apache.fop.pdf.PDFResourceContext;
39 import org.apache.fop.svg.PDFAElementBridge;
40 import org.apache.fop.svg.PDFBridgeContext;
41 import org.apache.fop.svg.PDFGraphics2D;
42 import org.apache.fop.svg.SVGUserAgent;
43 import org.apache.fop.util.QName;
44 import org.apache.fop.fo.extensions.ExtensionElementMapping;
45 import org.apache.fop.fonts.FontInfo;
46
47 // Commons-Logging
48
import org.apache.commons.logging.Log;
49 import org.apache.commons.logging.LogFactory;
50
51 import org.apache.avalon.framework.configuration.Configuration;
52
53 import org.apache.batik.bridge.GVTBuilder;
54 import org.apache.batik.bridge.BridgeContext;
55 import org.apache.batik.dom.svg.SVGDOMImplementation;
56 import org.apache.batik.gvt.GraphicsNode;
57 import org.apache.batik.util.SVGConstants;
58
59 /**
60  * PDF XML handler for SVG (uses Apache Batik).
61  * This handler handles XML for foreign objects when rendering to PDF.
62  * It renders SVG to the PDF document using the PDFGraphics2D.
63  * The properties from the PDF renderer are subject to change.
64  */

65 public class PDFSVGHandler extends AbstractGenericSVGHandler
66             implements PDFRendererContextConstants {
67
68     /** logging instance */
69     private static Log log = LogFactory.getLog(PDFSVGHandler.class);
70
71     /**
72      * Get the pdf information from the render context.
73      *
74      * @param context the renderer context
75      * @return the pdf information retrieved from the context
76      */

77     public static PDFInfo getPDFInfo(RendererContext context) {
78         PDFInfo pdfi = new PDFInfo();
79         pdfi.pdfDoc = (PDFDocument)context.getProperty(PDF_DOCUMENT);
80         pdfi.outputStream = (OutputStream JavaDoc)context.getProperty(OUTPUT_STREAM);
81         pdfi.pdfState = (PDFState)context.getProperty(PDF_STATE);
82         pdfi.pdfPage = (PDFPage)context.getProperty(PDF_PAGE);
83         pdfi.pdfContext = (PDFResourceContext)context.getProperty(PDF_CONTEXT);
84         pdfi.currentStream = (PDFStream)context.getProperty(PDF_STREAM);
85         pdfi.width = ((Integer JavaDoc)context.getProperty(WIDTH)).intValue();
86         pdfi.height = ((Integer JavaDoc)context.getProperty(HEIGHT)).intValue();
87         pdfi.fi = (FontInfo)context.getProperty(PDF_FONT_INFO);
88         pdfi.currentFontName = (String JavaDoc)context.getProperty(PDF_FONT_NAME);
89         pdfi.currentFontSize = ((Integer JavaDoc)context.getProperty(PDF_FONT_SIZE)).intValue();
90         pdfi.currentXPosition = ((Integer JavaDoc)context.getProperty(XPOS)).intValue();
91         pdfi.currentYPosition = ((Integer JavaDoc)context.getProperty(YPOS)).intValue();
92         pdfi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION);
93         Map JavaDoc foreign = (Map JavaDoc)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
94         QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode");
95         if (foreign != null
96                 && "bitmap".equalsIgnoreCase((String JavaDoc)foreign.get(qName))) {
97             pdfi.paintAsBitmap = true;
98         }
99         return pdfi;
100     }
101
102     /**
103      * PDF information structure for drawing the XML document.
104      */

105     public static class PDFInfo {
106         /** see PDF_DOCUMENT */
107         public PDFDocument pdfDoc;
108         /** see OUTPUT_STREAM */
109         public OutputStream JavaDoc outputStream;
110         /** see PDF_STATE */
111         public PDFState pdfState;
112         /** see PDF_PAGE */
113         public PDFPage pdfPage;
114         /** see PDF_CONTEXT */
115         public PDFResourceContext pdfContext;
116         /** see PDF_STREAM */
117         public PDFStream currentStream;
118         /** see PDF_WIDTH */
119         public int width;
120         /** see PDF_HEIGHT */
121         public int height;
122         /** see PDF_FONT_INFO */
123         public FontInfo fi;
124         /** see PDF_FONT_NAME */
125         public String JavaDoc currentFontName;
126         /** see PDF_FONT_SIZE */
127         public int currentFontSize;
128         /** see PDF_XPOS */
129         public int currentXPosition;
130         /** see PDF_YPOS */
131         public int currentYPosition;
132         /** see PDF_HANDLER_CONFIGURATION */
133         public Configuration cfg;
134         /** true if SVG should be rendered as a bitmap instead of natively */
135         public boolean paintAsBitmap;
136     }
137
138     /**
139      * @see org.apache.fop.render.AbstractGenericSVGHandler#renderSVGDocument(
140      * org.apache.fop.render.RendererContext, org.w3c.dom.Document)
141      */

142     protected void renderSVGDocument(RendererContext context,
143             Document JavaDoc doc) {
144         PDFRenderer renderer = (PDFRenderer)context.getRenderer();
145         PDFInfo pdfInfo = getPDFInfo(context);
146         if (pdfInfo.paintAsBitmap) {
147             try {
148                 super.renderSVGDocument(context, doc);
149             } catch (IOException JavaDoc ioe) {
150                 log.error("I/O error while rendering SVG graphic: "
151                                        + ioe.getMessage(), ioe);
152             }
153             return;
154         }
155         int xOffset = pdfInfo.currentXPosition;
156         int yOffset = pdfInfo.currentYPosition;
157
158         log.debug("Generating SVG at "
159                 + context.getUserAgent().getTargetResolution()
160                 + "dpi.");
161         final float deviceResolution = context.getUserAgent().getTargetResolution();
162         
163         final float uaResolution = context.getUserAgent().getSourceResolution();
164         SVGUserAgent ua = new SVGUserAgent(25.4f / uaResolution, new AffineTransform JavaDoc());
165
166         //Scale for higher resolution on-the-fly images from Batik
167
double s = uaResolution / deviceResolution;
168         AffineTransform JavaDoc resolutionScaling = new AffineTransform JavaDoc();
169         resolutionScaling.scale(s, s);
170         
171         GVTBuilder builder = new GVTBuilder();
172         
173         //Controls whether text painted by Batik is generated using text or path operations
174
boolean strokeText = false;
175         Configuration cfg = pdfInfo.cfg;
176         if (cfg != null) {
177             strokeText = cfg.getChild("stroke-text", true).getValueAsBoolean(strokeText);
178         }
179         
180         BridgeContext ctx = new PDFBridgeContext(ua,
181                 (strokeText ? null : pdfInfo.fi),
182                 new AffineTransform JavaDoc());
183         
184         GraphicsNode root;
185         try {
186             root = builder.build(ctx, doc);
187             builder = null;
188         } catch (Exception JavaDoc e) {
189             log.error("svg graphic could not be built: "
190                                    + e.getMessage(), e);
191             return;
192         }
193         // get the 'width' and 'height' attributes of the SVG document
194
float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
195         float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
196
197         float sx = pdfInfo.width / (float)w;
198         float sy = pdfInfo.height / (float)h;
199
200         //Scaling and translation for the bounding box of the image
201
AffineTransform JavaDoc scaling = new AffineTransform JavaDoc(
202                 sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f);
203
204         //Transformation matrix that establishes the local coordinate system for the SVG graphic
205
//in relation to the current coordinate system
206
AffineTransform JavaDoc imageTransform = new AffineTransform JavaDoc();
207         imageTransform.concatenate(scaling);
208         imageTransform.concatenate(resolutionScaling);
209         
210         /*
211          * Clip to the svg area.
212          * Note: To have the svg overlay (under) a text area then use
213          * an fo:block-container
214          */

215         pdfInfo.currentStream.add("%SVG setup\n");
216         renderer.saveGraphicsState();
217         renderer.setColor(Color.black, false, null);
218         renderer.setColor(Color.black, true, null);
219
220         if (!scaling.isIdentity()) {
221             pdfInfo.currentStream.add("%viewbox\n");
222             pdfInfo.currentStream.add(CTMHelper.toPDFString(scaling, false) + " cm\n");
223         }
224
225         //SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
226

227         if (pdfInfo.pdfContext == null) {
228             pdfInfo.pdfContext = pdfInfo.pdfPage;
229         }
230         PDFGraphics2D graphics = new PDFGraphics2D(true, pdfInfo.fi,
231                 pdfInfo.pdfDoc,
232                 pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(),
233                 pdfInfo.currentFontName, pdfInfo.currentFontSize);
234         graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
235
236         if (!resolutionScaling.isIdentity()) {
237             pdfInfo.currentStream.add("%resolution scaling for " + uaResolution
238                         + " -> " + deviceResolution + "\n");
239             pdfInfo.currentStream.add(
240                     CTMHelper.toPDFString(resolutionScaling, false) + " cm\n");
241             graphics.scale(1 / s, 1 / s);
242         }
243         
244         pdfInfo.currentStream.add("%SVG start\n");
245
246         //Save state and update coordinate system for the SVG image
247
pdfInfo.pdfState.push();
248         pdfInfo.pdfState.concatenate(imageTransform);
249
250         //Now that we have the complete transformation matrix for the image, we can update the
251
//transformation matrix for the AElementBridge.
252
PDFAElementBridge aBridge = (PDFAElementBridge)ctx.getBridge(
253                 SVGDOMImplementation.SVG_NAMESPACE_URI, SVGConstants.SVG_A_TAG);
254         aBridge.getCurrentTransform().setTransform(pdfInfo.pdfState.getTransform());
255
256         graphics.setPDFState(pdfInfo.pdfState);
257         graphics.setOutputStream(pdfInfo.outputStream);
258         try {
259             root.paint(graphics);
260             pdfInfo.currentStream.add(graphics.getString());
261         } catch (Exception JavaDoc e) {
262             log.error("svg graphic could not be rendered: "
263                                    + e.getMessage(), e);
264         }
265         pdfInfo.pdfState.pop();
266         renderer.restoreGraphicsState();
267         pdfInfo.currentStream.add("%SVG end\n");
268     }
269     
270     /** @see org.apache.fop.render.XMLHandler#supportsRenderer(org.apache.fop.render.Renderer) */
271     public boolean supportsRenderer(Renderer renderer) {
272         return (renderer instanceof PDFRenderer);
273     }
274 }
275
Popular Tags