You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PSTranscoder.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * $Id: PDFTranscoder.java,v 1.24 2003/03/07 09:51:26 jeremias Exp $
  3. * ============================================================================
  4. * The Apache Software License, Version 1.1
  5. * ============================================================================
  6. *
  7. * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without modifica-
  10. * tion, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if any, must
  20. * include the following acknowledgment: "This product includes software
  21. * developed by the Apache Software Foundation (http://www.apache.org/)."
  22. * Alternately, this acknowledgment may appear in the software itself, if
  23. * and wherever such third-party acknowledgments normally appear.
  24. *
  25. * 4. The names "FOP" and "Apache Software Foundation" must not be used to
  26. * endorse or promote products derived from this software without prior
  27. * written permission. For written permission, please contact
  28. * apache@apache.org.
  29. *
  30. * 5. Products derived from this software may not be called "Apache", nor may
  31. * "Apache" appear in their name, without prior written permission of the
  32. * Apache Software Foundation.
  33. *
  34. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  35. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  37. * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  38. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  39. * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  40. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  41. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  43. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. * ============================================================================
  45. *
  46. * This software consists of voluntary contributions made by many individuals
  47. * on behalf of the Apache Software Foundation and was originally created by
  48. * James Tauber <jtauber@jtauber.com>. For more information on the Apache
  49. * Software Foundation, please see <http://www.apache.org/>.
  50. */
  51. package org.apache.fop.render.ps;
  52. import java.awt.geom.AffineTransform;
  53. import java.awt.geom.Rectangle2D;
  54. import java.awt.Color;
  55. import java.net.MalformedURLException;
  56. import java.net.URL;
  57. import java.io.IOException;
  58. import org.apache.batik.bridge.BridgeContext;
  59. import org.apache.batik.bridge.BridgeException;
  60. import org.apache.batik.bridge.GVTBuilder;
  61. import org.apache.batik.bridge.SVGTextElementBridge;
  62. import org.apache.batik.bridge.ViewBox;
  63. import org.apache.batik.dom.svg.SVGOMDocument;
  64. import org.apache.batik.gvt.GraphicsNode;
  65. import org.apache.batik.transcoder.TranscoderException;
  66. import org.apache.batik.transcoder.TranscoderOutput;
  67. import org.apache.batik.transcoder.image.resources.Messages;
  68. import org.apache.batik.transcoder.image.ImageTranscoder;
  69. import org.apache.fop.svg.AbstractFOPTranscoder;
  70. import org.apache.batik.gvt.TextPainter;
  71. import org.apache.batik.gvt.renderer.StrokingTextPainter;
  72. import org.w3c.dom.Document;
  73. import org.w3c.dom.svg.SVGDocument;
  74. import org.w3c.dom.svg.SVGSVGElement;
  75. /**
  76. * This class enables to transcode an input to a PostScript document.
  77. *
  78. * <p>Two transcoding hints (<tt>KEY_WIDTH</tt> and
  79. * <tt>KEY_HEIGHT</tt>) can be used to respectively specify the image
  80. * width and the image height. If only one of these keys is specified,
  81. * the transcoder preserves the aspect ratio of the original image.
  82. *
  83. * <p>The <tt>KEY_BACKGROUND_COLOR</tt> defines the background color
  84. * to use for opaque image formats, or the background color that may
  85. * be used for image formats that support alpha channel.
  86. *
  87. * <p>The <tt>KEY_AOI</tt> represents the area of interest to paint
  88. * in device space.
  89. *
  90. * <p>Three additional transcoding hints that act on the SVG
  91. * processor can be specified:
  92. *
  93. * <p><tt>KEY_LANGUAGE</tt> to set the default language to use (may be
  94. * used by a &lt;switch> SVG element for example),
  95. * <tt>KEY_USER_STYLESHEET_URI</tt> to fix the URI of a user
  96. * stylesheet, and <tt>KEY_PIXEL_TO_MM</tt> to specify the pixel to
  97. * millimeter conversion factor.
  98. *
  99. * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
  100. * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
  101. * @version $Id: PDFTranscoder.java,v 1.24 2003/03/07 09:51:26 jeremias Exp $
  102. */
  103. public class PSTranscoder extends AbstractFOPTranscoder {
  104. /**
  105. * Constructs a new <tt>PSTranscoder</tt>.
  106. */
  107. public PSTranscoder() {
  108. super();
  109. }
  110. /**
  111. * Transcodes the specified Document as an image in the specified output.
  112. *
  113. * @param document the document to transcode
  114. * @param uri the uri of the document or null if any
  115. * @param output the ouput where to transcode
  116. * @exception TranscoderException if an error occured while transcoding
  117. */
  118. protected void transcode(Document document, String uri,
  119. TranscoderOutput output) throws TranscoderException {
  120. if (!(document instanceof SVGOMDocument)) {
  121. throw new TranscoderException(Messages.formatMessage("notsvg",
  122. null));
  123. }
  124. SVGDocument svgDoc = (SVGDocument)document;
  125. SVGSVGElement root = svgDoc.getRootElement();
  126. // initialize the SVG document with the appropriate context
  127. String parserClassname = (String)hints.get(KEY_XML_PARSER_CLASSNAME);
  128. PSDocumentGraphics2D graphics = new PSDocumentGraphics2D(false);
  129. // build the GVT tree
  130. GVTBuilder builder = new GVTBuilder();
  131. BridgeContext ctx = new BridgeContext(userAgent);
  132. TextPainter textPainter = null;
  133. textPainter = new StrokingTextPainter();
  134. ctx.setTextPainter(textPainter);
  135. SVGTextElementBridge textElementBridge =
  136. new PSTextElementBridge(graphics.getFontInfo());
  137. ctx.putBridge(textElementBridge);
  138. //PDFAElementBridge pdfAElementBridge = new PDFAElementBridge();
  139. //AffineTransform currentTransform = new AffineTransform(1, 0, 0, 1, 0, 0);
  140. //pdfAElementBridge.setCurrentTransform(currentTransform);
  141. //ctx.putBridge(pdfAElementBridge);
  142. //ctx.putBridge(new PSImageElementBridge());
  143. GraphicsNode gvtRoot;
  144. try {
  145. gvtRoot = builder.build(ctx, svgDoc);
  146. } catch (BridgeException ex) {
  147. throw new TranscoderException(ex);
  148. }
  149. // get the 'width' and 'height' attributes of the SVG document
  150. float docWidth = (float)ctx.getDocumentSize().getWidth();
  151. float docHeight = (float)ctx.getDocumentSize().getHeight();
  152. ctx = null;
  153. builder = null;
  154. // compute the image's width and height according the hints
  155. float imgWidth = -1;
  156. if (hints.containsKey(ImageTranscoder.KEY_WIDTH)) {
  157. imgWidth =
  158. ((Float)hints.get(ImageTranscoder.KEY_WIDTH)).floatValue();
  159. }
  160. float imgHeight = -1;
  161. if (hints.containsKey(ImageTranscoder.KEY_HEIGHT)) {
  162. imgHeight =
  163. ((Float)hints.get(ImageTranscoder.KEY_HEIGHT)).floatValue();
  164. }
  165. float width, height;
  166. if (imgWidth > 0 && imgHeight > 0) {
  167. width = imgWidth;
  168. height = imgHeight;
  169. } else if (imgHeight > 0) {
  170. width = (docWidth * imgHeight) / docHeight;
  171. height = imgHeight;
  172. } else if (imgWidth > 0) {
  173. width = imgWidth;
  174. height = (docHeight * imgWidth) / docWidth;
  175. } else {
  176. width = docWidth;
  177. height = docHeight;
  178. }
  179. // compute the preserveAspectRatio matrix
  180. AffineTransform px;
  181. String ref = null;
  182. try {
  183. ref = new URL(uri).getRef();
  184. } catch (MalformedURLException ex) {
  185. // nothing to do, catched previously
  186. }
  187. try {
  188. px = ViewBox.getViewTransform(ref, root, width, height);
  189. } catch (BridgeException ex) {
  190. throw new TranscoderException(ex);
  191. }
  192. if (px.isIdentity() && (width != docWidth || height != docHeight)) {
  193. // The document has no viewBox, we need to resize it by hand.
  194. // we want to keep the document size ratio
  195. float d = Math.max(docWidth, docHeight);
  196. float dd = Math.max(width, height);
  197. float scale = dd / d;
  198. px = AffineTransform.getScaleInstance(scale, scale);
  199. }
  200. // take the AOI into account if any
  201. if (hints.containsKey(ImageTranscoder.KEY_AOI)) {
  202. Rectangle2D aoi = (Rectangle2D)hints.get(ImageTranscoder.KEY_AOI);
  203. // transform the AOI into the image's coordinate system
  204. aoi = px.createTransformedShape(aoi).getBounds2D();
  205. AffineTransform mx = new AffineTransform();
  206. double sx = width / aoi.getWidth();
  207. double sy = height / aoi.getHeight();
  208. mx.scale(sx, sy);
  209. double tx = -aoi.getX();
  210. double ty = -aoi.getY();
  211. mx.translate(tx, ty);
  212. // take the AOI transformation matrix into account
  213. // we apply first the preserveAspectRatio matrix
  214. px.preConcatenate(mx);
  215. }
  216. // prepare the image to be painted
  217. int w = (int)width;
  218. int h = (int)height;
  219. try {
  220. graphics.setupDocument(output.getOutputStream(), w, h);
  221. graphics.setSVGDimension(docWidth, docHeight);
  222. if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) {
  223. graphics.setBackgroundColor((Color)hints.get(ImageTranscoder.KEY_BACKGROUND_COLOR));
  224. }
  225. graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext());
  226. graphics.setTransform(px);
  227. gvtRoot.paint(graphics);
  228. graphics.finish();
  229. } catch (IOException ex) {
  230. throw new TranscoderException(ex);
  231. }
  232. }
  233. }