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.

PSXMLHandler.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /*
  2. * $Id: PSXMLHandler.java,v 1.4 2003/03/11 08:42:24 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. // Java
  53. import java.awt.geom.AffineTransform;
  54. import java.io.IOException;
  55. // DOM
  56. /* org.w3c.dom.Document is not imported to avoid conflict with
  57. org.apache.fop.control.Document */
  58. import org.w3c.dom.svg.SVGDocument;
  59. import org.w3c.dom.svg.SVGSVGElement;
  60. // Batik
  61. import org.apache.batik.bridge.GVTBuilder;
  62. import org.apache.batik.bridge.BridgeContext;
  63. import org.apache.batik.bridge.ViewBox;
  64. import org.apache.batik.gvt.GraphicsNode;
  65. import org.apache.batik.gvt.TextPainter;
  66. // FOP
  67. import org.apache.fop.apps.Document;
  68. import org.apache.fop.render.XMLHandler;
  69. import org.apache.fop.render.RendererContext;
  70. import org.apache.fop.svg.SVGUserAgent;
  71. import org.apache.fop.apps.*;
  72. /**
  73. * PostScript XML handler.
  74. * This handler handles XML for foreign objects when rendering to PostScript.
  75. * It renders SVG to the PostScript document using the PSGraphics2D.
  76. * The properties from the PostScript renderer are subject to change.
  77. *
  78. * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
  79. * @version $Id: PSXMLHandler.java,v 1.4 2003/03/11 08:42:24 jeremias Exp $
  80. */
  81. public class PSXMLHandler implements XMLHandler {
  82. /**
  83. * The PostScript generator that is being used to drawn into.
  84. */
  85. public static final String PS_GENERATOR = "psGenerator";
  86. /**
  87. * The font information for the PostScript renderer.
  88. */
  89. public static final String PS_FONT_INFO = "psFontInfo";
  90. /**
  91. * The width of the SVG graphic.
  92. */
  93. public static final String PS_WIDTH = "width";
  94. /**
  95. * The height of the SVG graphic.
  96. */
  97. public static final String PS_HEIGHT = "height";
  98. /**
  99. * The x position that this is being drawn at.
  100. */
  101. public static final String PS_XPOS = "xpos";
  102. /**
  103. * The y position that this is being drawn at.
  104. */
  105. public static final String PS_YPOS = "ypos";
  106. /**
  107. * Create a new PostScript XML handler for use by the PostScript renderer.
  108. */
  109. public PSXMLHandler() {
  110. }
  111. /**
  112. * Handle the XML.
  113. * This checks the type of XML and handles appropraitely.
  114. *
  115. * @param context the renderer context
  116. * @param doc the XML document to render
  117. * @param ns the namespace of the XML document
  118. * @throws Exception any sort of exception could be thrown and shuld be handled
  119. */
  120. public void handleXML(RendererContext context, org.w3c.dom.Document doc,
  121. String ns) throws Exception {
  122. PSInfo psi = getPSInfo(context);
  123. String svg = "http://www.w3.org/2000/svg";
  124. if (svg.equals(ns)) {
  125. SVGHandler svghandler = new SVGHandler();
  126. svghandler.renderSVGDocument(context, doc, psi);
  127. } else {
  128. }
  129. }
  130. /**
  131. * Get the pdf information from the render context.
  132. *
  133. * @param context the renderer context
  134. * @return the pdf information retrieved from the context
  135. */
  136. public static PSInfo getPSInfo(RendererContext context) {
  137. PSInfo psi = new PSInfo();
  138. psi.psGenerator = (PSGenerator)context.getProperty(PS_GENERATOR);
  139. psi.fontInfo = (org.apache.fop.apps.Document)context.getProperty(PS_FONT_INFO);
  140. psi.width = ((Integer)context.getProperty(PS_WIDTH)).intValue();
  141. psi.height = ((Integer)context.getProperty(PS_HEIGHT)).intValue();
  142. psi.currentXPosition = ((Integer)context.getProperty(PS_XPOS)).intValue();
  143. psi.currentYPosition = ((Integer)context.getProperty(PS_YPOS)).intValue();
  144. return psi;
  145. }
  146. /**
  147. * PostScript information structure for drawing the XML document.
  148. */
  149. public static class PSInfo {
  150. /** see PS_GENERATOR */
  151. private PSGenerator psGenerator;
  152. /** see PS_FONT_INFO */
  153. private org.apache.fop.apps.Document fontInfo;
  154. /** see PS_PAGE_WIDTH */
  155. private int width;
  156. /** see PS_PAGE_HEIGHT */
  157. private int height;
  158. /** see PS_XPOS */
  159. private int currentXPosition;
  160. /** see PS_YPOS */
  161. private int currentYPosition;
  162. /**
  163. * Returns the PSGenerator.
  164. * @return PSGenerator
  165. */
  166. public PSGenerator getPSGenerator() {
  167. return psGenerator;
  168. }
  169. /**
  170. * Sets the PSGenerator.
  171. * @param psGenerator The PSGenerator to set
  172. */
  173. public void setPsGenerator(PSGenerator psGenerator) {
  174. this.psGenerator = psGenerator;
  175. }
  176. /**
  177. * Returns the fontInfo.
  178. * @return FontInfo
  179. */
  180. public org.apache.fop.apps.Document getFontInfo() {
  181. return fontInfo;
  182. }
  183. /**
  184. * Sets the fontInfo.
  185. * @param fontInfo The fontInfo to set
  186. */
  187. public void setFontInfo(org.apache.fop.apps.Document fontInfo) {
  188. this.fontInfo = fontInfo;
  189. }
  190. /**
  191. * Returns the currentXPosition.
  192. * @return int
  193. */
  194. public int getCurrentXPosition() {
  195. return currentXPosition;
  196. }
  197. /**
  198. * Sets the currentXPosition.
  199. * @param currentXPosition The currentXPosition to set
  200. */
  201. public void setCurrentXPosition(int currentXPosition) {
  202. this.currentXPosition = currentXPosition;
  203. }
  204. /**
  205. * Returns the currentYPosition.
  206. * @return int
  207. */
  208. public int getCurrentYPosition() {
  209. return currentYPosition;
  210. }
  211. /**
  212. * Sets the currentYPosition.
  213. * @param currentYPosition The currentYPosition to set
  214. */
  215. public void setCurrentYPosition(int currentYPosition) {
  216. this.currentYPosition = currentYPosition;
  217. }
  218. /**
  219. * Returns the width.
  220. * @return int
  221. */
  222. public int getWidth() {
  223. return width;
  224. }
  225. /**
  226. * Sets the width.
  227. * @param width The pageWidth to set
  228. */
  229. public void setWidth(int width) {
  230. this.width = width;
  231. }
  232. /**
  233. * Returns the height.
  234. * @return int
  235. */
  236. public int getHeight() {
  237. return height;
  238. }
  239. /**
  240. * Sets the height.
  241. * @param height The height to set
  242. */
  243. public void setHeight(int height) {
  244. this.height = height;
  245. }
  246. }
  247. /**
  248. * This method is placed in an inner class so that we don't get class
  249. * loading errors if batik is not present.
  250. */
  251. protected class SVGHandler {
  252. /**
  253. * Render the svg document.
  254. * @param context the renderer context
  255. * @param doc the svg document
  256. * @param psInfo the pdf information of the current context
  257. */
  258. protected void renderSVGDocument(RendererContext context,
  259. org.w3c.dom.Document doc, PSInfo psInfo) {
  260. int xOffset = psInfo.currentXPosition;
  261. int yOffset = psInfo.currentYPosition;
  262. PSGenerator gen = psInfo.psGenerator;
  263. SVGUserAgent ua
  264. = new SVGUserAgent(context.getUserAgent(), new AffineTransform());
  265. GVTBuilder builder = new GVTBuilder();
  266. BridgeContext ctx = new BridgeContext(ua);
  267. PSTextElementBridge tBridge = new PSTextElementBridge(psInfo.getFontInfo());
  268. ctx.putBridge(tBridge);
  269. //PSAElementBridge aBridge = new PSAElementBridge();
  270. // to get the correct transform we need to use the PDFState
  271. AffineTransform transform = gen.getCurrentState().getTransform();
  272. transform.translate(xOffset / 1000f, yOffset / 1000f);
  273. //aBridge.setCurrentTransform(transform);
  274. //ctx.putBridge(aBridge);
  275. TextPainter textPainter = new PSTextPainter(psInfo.getFontInfo());
  276. ctx.setTextPainter(textPainter);
  277. GraphicsNode root;
  278. try {
  279. root = builder.build(ctx, doc);
  280. } catch (Exception e) {
  281. context.getUserAgent().getLogger().error("SVG graphic could not be built: "
  282. + e.getMessage(), e);
  283. return;
  284. }
  285. // get the 'width' and 'height' attributes of the SVG document
  286. float w = (float)ctx.getDocumentSize().getWidth() * 1000f;
  287. float h = (float)ctx.getDocumentSize().getHeight() * 1000f;
  288. float sx = psInfo.getWidth() / (float)w;
  289. float sy = psInfo.getHeight() / (float)h;
  290. ctx = null;
  291. builder = null;
  292. try {
  293. gen.writeln("%SVG graphic start ---");
  294. /*
  295. * Clip to the svg area.
  296. * Note: To have the svg overlay (under) a text area then use
  297. * an fo:block-container
  298. */
  299. gen.saveGraphicsState();
  300. // transform so that the coordinates (0,0) is from the top left
  301. // and positive is down and to the right. (0,0) is where the
  302. // viewBox puts it.
  303. gen.concatMatrix(sx, 0, 0, sy, xOffset, yOffset);
  304. SVGSVGElement svg = ((SVGDocument)doc).getRootElement();
  305. AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg,
  306. w / 1000f, h / 1000f);
  307. if (!at.isIdentity()) {
  308. double[] vals = new double[6];
  309. at.getMatrix(vals);
  310. gen.concatMatrix(vals);
  311. }
  312. /*
  313. if (psInfo.pdfContext == null) {
  314. psInfo.pdfContext = psInfo.pdfPage;
  315. }*/
  316. PSGraphics2D graphics = new PSGraphics2D(true, gen);
  317. graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext());
  318. //psInfo.pdfState.push();
  319. transform = new AffineTransform();
  320. // scale to viewbox
  321. transform.translate(xOffset, yOffset);
  322. gen.getCurrentState().concatMatrix(transform);
  323. //graphics.setPDFState(psInfo.pdfState);
  324. try {
  325. root.paint(graphics);
  326. //psInfo.currentStream.add(graphics.getString());
  327. } catch (Exception e) {
  328. context.getUserAgent().getLogger().error("SVG graphic could not be rendered: "
  329. + e.getMessage(), e);
  330. }
  331. psInfo.psGenerator.restoreGraphicsState();
  332. //psInfo.pdfState.pop();
  333. gen.writeln("%SVG graphic end ---");
  334. } catch (IOException ioe) {
  335. context.getUserAgent().getLogger().error("SVG graphic could not be rendered: "
  336. + ioe.getMessage(), ioe);
  337. }
  338. }
  339. }
  340. }