| 1 17 18 19 20 package org.apache.fop.render.pdf; 21 22 import java.io.IOException ; 23 import java.io.OutputStream ; 24 import java.util.Map ; 25 import java.awt.Color ; 26 import java.awt.geom.AffineTransform ; 27 28 import org.w3c.dom.Document ; 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 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 65 public class PDFSVGHandler extends AbstractGenericSVGHandler 66 implements PDFRendererContextConstants { 67 68 69 private static Log log = LogFactory.getLog(PDFSVGHandler.class); 70 71 77 public static PDFInfo getPDFInfo(RendererContext context) { 78 PDFInfo pdfi = new PDFInfo(); 79 pdfi.pdfDoc = (PDFDocument)context.getProperty(PDF_DOCUMENT); 80 pdfi.outputStream = (OutputStream )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 )context.getProperty(WIDTH)).intValue(); 86 pdfi.height = ((Integer )context.getProperty(HEIGHT)).intValue(); 87 pdfi.fi = (FontInfo)context.getProperty(PDF_FONT_INFO); 88 pdfi.currentFontName = (String )context.getProperty(PDF_FONT_NAME); 89 pdfi.currentFontSize = ((Integer )context.getProperty(PDF_FONT_SIZE)).intValue(); 90 pdfi.currentXPosition = ((Integer )context.getProperty(XPOS)).intValue(); 91 pdfi.currentYPosition = ((Integer )context.getProperty(YPOS)).intValue(); 92 pdfi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION); 93 Map foreign = (Map )context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); 94 QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode"); 95 if (foreign != null 96 && "bitmap".equalsIgnoreCase((String )foreign.get(qName))) { 97 pdfi.paintAsBitmap = true; 98 } 99 return pdfi; 100 } 101 102 105 public static class PDFInfo { 106 107 public PDFDocument pdfDoc; 108 109 public OutputStream outputStream; 110 111 public PDFState pdfState; 112 113 public PDFPage pdfPage; 114 115 public PDFResourceContext pdfContext; 116 117 public PDFStream currentStream; 118 119 public int width; 120 121 public int height; 122 123 public FontInfo fi; 124 125 public String currentFontName; 126 127 public int currentFontSize; 128 129 public int currentXPosition; 130 131 public int currentYPosition; 132 133 public Configuration cfg; 134 135 public boolean paintAsBitmap; 136 } 137 138 142 protected void renderSVGDocument(RendererContext context, 143 Document 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 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 ()); 165 166 double s = uaResolution / deviceResolution; 168 AffineTransform resolutionScaling = new AffineTransform (); 169 resolutionScaling.scale(s, s); 170 171 GVTBuilder builder = new GVTBuilder(); 172 173 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 ()); 183 184 GraphicsNode root; 185 try { 186 root = builder.build(ctx, doc); 187 builder = null; 188 } catch (Exception e) { 189 log.error("svg graphic could not be built: " 190 + e.getMessage(), e); 191 return; 192 } 193 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 AffineTransform scaling = new AffineTransform ( 202 sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f); 203 204 AffineTransform imageTransform = new AffineTransform (); 207 imageTransform.concatenate(scaling); 208 imageTransform.concatenate(resolutionScaling); 209 210 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 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 pdfInfo.pdfState.push(); 248 pdfInfo.pdfState.concatenate(imageTransform); 249 250 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 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 271 public boolean supportsRenderer(Renderer renderer) { 272 return (renderer instanceof PDFRenderer); 273 } 274 } 275 | Popular Tags |