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.

SVGUtilities.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * $Id: SVGUtilities.java,v 1.6 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.svg;
  52. import java.util.StringTokenizer;
  53. import java.awt.geom.AffineTransform;
  54. import java.awt.geom.Rectangle2D;
  55. import java.awt.font.FontRenderContext;
  56. import org.w3c.dom.Element;
  57. import org.w3c.dom.Document;
  58. import org.w3c.dom.DOMImplementation;
  59. import org.apache.batik.dom.svg.SVGDOMImplementation;
  60. /**
  61. * Some utilities for creating svg DOM documents and elements.
  62. */
  63. public class SVGUtilities {
  64. private static final String SVG_NS = SVGDOMImplementation.SVG_NAMESPACE_URI;
  65. /**
  66. * Create a new svg document with batik.
  67. * @param width the width of the root svg element
  68. * @param height the height of the root svg element
  69. * @return a new SVG Document
  70. */
  71. public static final Document createSVGDocument(float width,
  72. float height) {
  73. DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
  74. Document doc = impl.createDocument(SVG_NS, "svg", null);
  75. Element svgRoot = doc.getDocumentElement();
  76. svgRoot.setAttributeNS(null, "width", "" + width);
  77. svgRoot.setAttributeNS(null, "height", "" + height);
  78. return doc;
  79. }
  80. /**
  81. * Get the string width for a particular string given the font.
  82. * @param str the string
  83. * @param font the font
  84. * @return the width of the string in the given font
  85. */
  86. public static final float getStringWidth(String str, java.awt.Font font) {
  87. Rectangle2D rect =
  88. font.getStringBounds(str, 0, str.length(),
  89. new FontRenderContext(new AffineTransform(),
  90. true, true));
  91. return (float)rect.getWidth();
  92. }
  93. /**
  94. * Get the string height for a particular string given the font.
  95. * @param str the string
  96. * @param font the font
  97. * @return the height of the string in the given font
  98. */
  99. public static final float getStringHeight(String str,
  100. java.awt.Font font) {
  101. Rectangle2D rect =
  102. font.getStringBounds(str, 0, str.length(),
  103. new FontRenderContext(new AffineTransform(),
  104. true, true));
  105. return (float)rect.getHeight();
  106. }
  107. /**
  108. * Get the string bounds for a particular string given the font.
  109. * @param str the string
  110. * @param font the font
  111. * @return the bounds of the string
  112. */
  113. public static final Rectangle2D getStringBounds(String str,
  114. java.awt.Font font) {
  115. return font.getStringBounds(str, 0, str.length(),
  116. new FontRenderContext(new AffineTransform(),
  117. true, true));
  118. }
  119. /**
  120. * Create an SVG Line
  121. * @param doc the document to create the element
  122. * @param x the start x position
  123. * @param y the start y position
  124. * @param x2 the end x position
  125. * @param y2 the end y position
  126. * @return the new line element
  127. */
  128. public static final Element createLine(Document doc, float x, float y,
  129. float x2, float y2) {
  130. Element ellipse = doc.createElementNS(SVG_NS, "line");
  131. ellipse.setAttributeNS(null, "x1", "" + x);
  132. ellipse.setAttributeNS(null, "x2", "" + x2);
  133. ellipse.setAttributeNS(null, "y1", "" + y);
  134. ellipse.setAttributeNS(null, "y2", "" + y2);
  135. return ellipse;
  136. }
  137. /**
  138. * Create an SVG Ellipse
  139. * @param doc the document to create the element
  140. * @param cx the centre x position
  141. * @param cy the centre y position
  142. * @param rx the x axis radius
  143. * @param ry the y axis radius
  144. * @return the new ellipse element
  145. */
  146. public static final Element createEllipse(Document doc, float cx,
  147. float cy, float rx, float ry) {
  148. Element ellipse = doc.createElementNS(SVG_NS, "ellipse");
  149. ellipse.setAttributeNS(null, "cx", "" + cx);
  150. ellipse.setAttributeNS(null, "rx", "" + rx);
  151. ellipse.setAttributeNS(null, "cy", "" + cy);
  152. ellipse.setAttributeNS(null, "ry", "" + ry);
  153. return ellipse;
  154. }
  155. /**
  156. * Create an SVG Path.
  157. * @param doc the document to create the element
  158. * @param str the string for the d attribute on the path
  159. * @return the new path element
  160. */
  161. public static final Element createPath(Document doc, String str) {
  162. Element path = doc.createElementNS(SVG_NS, "path");
  163. path.setAttributeNS(null, "d", str);
  164. return path;
  165. }
  166. /**
  167. * Create an SVG Text object.
  168. * @param doc the document to create the element
  169. * @param x the start x position
  170. * @param y the start y position
  171. * @param str the string
  172. * @return the new text element
  173. */
  174. public static final Element createText(Document doc, float x, float y,
  175. String str) {
  176. Element textGraph = doc.createElementNS(SVG_NS, "text");
  177. textGraph.setAttributeNS(null, "x", "" + x);
  178. textGraph.setAttributeNS(null, "y", "" + y);
  179. org.w3c.dom.Text text = doc.createTextNode(str);
  180. textGraph.appendChild(text);
  181. return textGraph;
  182. }
  183. /**
  184. * Create an SVG Rectangle.
  185. * @param doc the document to create the element
  186. * @param x the start x position
  187. * @param y the start y position
  188. * @param width the width of the rectangle
  189. * @param height the height of the rectangle
  190. * @return the new rectangle element
  191. */
  192. public static final Element createRect(Document doc, float x, float y,
  193. float width, float height) {
  194. Element border = doc.createElementNS(SVG_NS, "rect");
  195. border.setAttributeNS(null, "x", "" + x);
  196. border.setAttributeNS(null, "y", "" + y);
  197. border.setAttributeNS(null, "width", "" + width);
  198. border.setAttributeNS(null, "height", "" + height);
  199. return border;
  200. }
  201. /**
  202. * Create an SVG G.
  203. * @param doc the document to create the element
  204. * @return the new g element
  205. */
  206. public static final Element createG(Document doc) {
  207. Element border = doc.createElementNS(SVG_NS, "g");
  208. return border;
  209. }
  210. /**
  211. * Create an SVG Clip.
  212. * @param doc the document to create the element
  213. * @param els the child elements that make the clip
  214. * @param id the id of the clipping path
  215. * @return the new clip element
  216. */
  217. public static final Element createClip(Document doc, Element els,
  218. String id) {
  219. Element border = doc.createElementNS(SVG_NS, "clipPath");
  220. border.setAttributeNS(null, "id", id);
  221. border.appendChild(els);
  222. return border;
  223. }
  224. /**
  225. * Create and svg image element.
  226. * @param doc the document to create the element
  227. * @param ref the href link to the image
  228. * @param width the width to set on the image
  229. * @param height the height to set on the image
  230. * @return a new image element
  231. */
  232. public static final Element createImage(Document doc, String ref,
  233. float width, float height) {
  234. Element border = doc.createElementNS(SVG_NS, "image");
  235. border.setAttributeNS("http://www.w3.org/1999/xlink", "href",
  236. ref);
  237. border.setAttributeNS(null, "width", "" + width);
  238. border.setAttributeNS(null, "height", "" + height);
  239. return border;
  240. }
  241. /**
  242. * Create some SVG text that is wrapped into a specified width.
  243. * @param doc the document to create the elements
  244. * @param str the string to wrap
  245. * @param font the font
  246. * @param width the width to wrap
  247. * @return the new element containing the wrapped text
  248. */
  249. public static final Element wrapText(Document doc, String str,
  250. java.awt.Font font, float width) {
  251. Element g = createG(doc);
  252. Element text;
  253. StringTokenizer st = new StringTokenizer(str, " \t\r\n");
  254. float totalWidth = 0;
  255. String totalStr = "";
  256. int line = 0;
  257. float height = getStringHeight(str, font);
  258. while (st.hasMoreTokens()) {
  259. String token = st.nextToken();
  260. float strwidth = getStringWidth(token, font);
  261. totalWidth += strwidth;
  262. if (totalWidth > width) {
  263. if (totalStr.equals("")) {
  264. totalStr = token;
  265. token = "";
  266. strwidth = 0;
  267. }
  268. text = createText(doc, 0, line * (height + 5), totalStr);
  269. g.appendChild(text);
  270. totalStr = token;
  271. totalWidth = strwidth;
  272. line++;
  273. } else {
  274. totalStr = totalStr + " " + token;
  275. }
  276. }
  277. return g;
  278. }
  279. }