PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/examples/src/in_action/chapter10/FoobarSvgHandler.java

https://bitbucket.org/ivertex/itext-fork
Java | 397 lines | 251 code | 27 blank | 119 comment | 64 complexity | 09f90d112458aec19bac90adbc5dd426 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0
  1. /* in_action/chapter10/FoobarSvgHandler */
  2. package in_action.chapter10;
  3. import java.awt.Color;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.util.StringTokenizer;
  7. import javax.xml.parsers.FactoryConfigurationError;
  8. import javax.xml.parsers.ParserConfigurationException;
  9. import javax.xml.parsers.SAXParser;
  10. import javax.xml.parsers.SAXParserFactory;
  11. import org.xml.sax.Attributes;
  12. import org.xml.sax.InputSource;
  13. import org.xml.sax.SAXException;
  14. import org.xml.sax.helpers.DefaultHandler;
  15. import com.lowagie.text.BadElementException;
  16. import com.lowagie.text.Image;
  17. import com.lowagie.text.html.WebColors;
  18. import com.lowagie.text.pdf.PdfContentByte;
  19. import com.lowagie.text.pdf.PdfTemplate;
  20. import com.lowagie.text.pdf.PdfWriter;
  21. /**
  22. * This example was written by Bruno Lowagie. It is part of the book 'iText in
  23. * Action' by Manning Publications.
  24. * ISBN: 1932394796
  25. * http://www.1t3xt.com/docs/book.php
  26. * http://www.manning.com/lowagie/
  27. *
  28. * WARNING: iText doesn't really do SVG parsing. You should use Batik in
  29. * combination with iText's PdfGraphics2D if you want full blown SVG parsing.
  30. * This class only demonstrates how you could write an SVG parser if you would
  31. * want to.
  32. */
  33. public class FoobarSvgHandler extends DefaultHandler {
  34. /** Inner class that holds an int and two floats */
  35. protected class iXY {
  36. /** position of the next character in a data string */
  37. public int i;
  38. /** x coordinate */
  39. public float x;
  40. /** y coordinate */
  41. public float y;
  42. /**
  43. * @param value
  44. * @param pos
  45. */
  46. public iXY(String value, int pos) {
  47. i = pos;
  48. char digit;
  49. // skip extra non-numerical characters
  50. while (i < value.length()) {
  51. digit = value.charAt(i);
  52. if (digit >= '0' && digit <= '9')
  53. break;
  54. if (digit == '.')
  55. break;
  56. i++;
  57. }
  58. pos = i;
  59. // retrieve the x value
  60. while (i < value.length()) {
  61. digit = value.charAt(i);
  62. if (digit != '.' && (digit < '0' || digit > '9')) {
  63. x = getFloat(value.substring(pos));
  64. break;
  65. }
  66. i++;
  67. }
  68. // skip extra non-numerical characters
  69. while (i < value.length()) {
  70. digit = value.charAt(i);
  71. if (digit >= '0' && digit <= '9')
  72. break;
  73. if (digit == '.')
  74. break;
  75. i++;
  76. }
  77. pos = i;
  78. // retrieve the y value
  79. while (i < value.length()) {
  80. digit = value.charAt(i);
  81. if (digit != '.' && (digit < '0' || digit > '9')) {
  82. y = getFloat(value.substring(pos));
  83. break;
  84. }
  85. i++;
  86. if (i == value.length()) {
  87. y = getFloat(value.substring(pos));
  88. }
  89. }
  90. }
  91. }
  92. /** The PdfWriter that is writing the PDF. */
  93. protected PdfWriter writer;
  94. /** The PdfContentByte we are going to draw to. */
  95. protected PdfTemplate template = null;
  96. /** Content between the tags. */
  97. protected StringBuffer buf = new StringBuffer();
  98. /** PageSize and Viewbox parameters. */
  99. protected float[] coordinates = new float[6];
  100. /**
  101. * Creates a FoobarSvgHandler that will create a PdfTemplate for the writer,
  102. * containing the image that is provided through InputSource.
  103. *
  104. * @param writer
  105. * the PdfWriter responsible for the PDF
  106. * @param is
  107. * the inputstream with the SVG
  108. * @throws SAXException
  109. * @throws ParserConfigurationException
  110. * @throws FactoryConfigurationError
  111. * @throws IOException
  112. * @throws FileNotFoundException
  113. */
  114. public FoobarSvgHandler(PdfWriter writer, InputSource is)
  115. throws FileNotFoundException, SAXException, IOException,
  116. ParserConfigurationException, FactoryConfigurationError {
  117. this.writer = writer;
  118. SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
  119. parser.parse(is, this);
  120. }
  121. /**
  122. * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
  123. * java.lang.String, java.lang.String, org.xml.sax.Attributes)
  124. */
  125. public void startElement(String uri, String localName, String qName,
  126. Attributes attributes) throws SAXException {
  127. if ("polyline".equals(qName)) {
  128. drawPolyline(attributes);
  129. } else if ("path".equals(qName)) {
  130. drawPath(attributes);
  131. } else if ("svg".equals(qName)) {
  132. calcSize(attributes);
  133. }
  134. }
  135. /**
  136. * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
  137. * java.lang.String, java.lang.String)
  138. */
  139. public void endElement(String uri, String localName, String qName)
  140. throws SAXException {
  141. buf = new StringBuffer();
  142. }
  143. /**
  144. * @see org.xml.sax.ContentHandler#characters(char[], int, int)
  145. */
  146. public void characters(char[] ch, int start, int length)
  147. throws SAXException {
  148. buf.append(ch, start, length);
  149. }
  150. /**
  151. * Draws a polyline.
  152. *
  153. * @param attributes
  154. * the attributes of the polyline-tag
  155. */
  156. private void drawPolyline(Attributes attributes) {
  157. template.saveState();
  158. setFill(attributes);
  159. setStroke(attributes);
  160. computePoints(attributes);
  161. template.stroke();
  162. template.restoreState();
  163. }
  164. /**
  165. * Draws a path.
  166. *
  167. * @param attributes
  168. * the attributes of the path-tag
  169. */
  170. private void drawPath(Attributes attributes) {
  171. template.saveState();
  172. setFill(attributes);
  173. setStroke(attributes);
  174. computeData(attributes);
  175. template.stroke();
  176. template.restoreState();
  177. }
  178. /**
  179. * Sets the fill color.
  180. *
  181. * @param attributes
  182. * attributes that can contain a fill attribute
  183. */
  184. private void setFill(Attributes attributes) {
  185. String name = attributes.getValue("fill");
  186. if (name == null || "none".equals(name))
  187. return;
  188. Color c = WebColors.getRGBColor(name);
  189. if (c != null) {
  190. template.setColorFill(c);
  191. }
  192. }
  193. /**
  194. * Sets the stroke color.
  195. *
  196. * @param attributes
  197. * attributes that can contain a fill attribute
  198. */
  199. private void setStroke(Attributes attributes) {
  200. String name = attributes.getValue("stroke");
  201. if (name == null || "none".equals(name))
  202. return;
  203. Color c = WebColors.getRGBColor(name);
  204. if (c != null) {
  205. template.setColorStroke(c);
  206. }
  207. name = attributes.getValue("stroke-width");
  208. if (name == null)
  209. return;
  210. float w = getPixels(name);
  211. template.setLineWidth(w);
  212. }
  213. /**
  214. * Computes the data of the <code>d</code> attribute.
  215. *
  216. * @param attributes
  217. */
  218. private void computeData(Attributes attributes) {
  219. String value = attributes.getValue("d");
  220. if (value == null)
  221. return;
  222. int digit;
  223. iXY ixy;
  224. for (int i = 0; i < value.length(); i++) {
  225. digit = (int) value.charAt(i);
  226. switch (digit) {
  227. case 'M':
  228. ixy = new iXY(value, i);
  229. template.moveTo(ixy.x, coordinates[5] - ixy.y);
  230. i = ixy.i;
  231. break;
  232. case 'm':
  233. break;
  234. case 'L':
  235. ixy = new iXY(value, i);
  236. template.lineTo(ixy.x, coordinates[5] - ixy.y);
  237. i = ixy.i;
  238. break;
  239. case 'l':
  240. break;
  241. case 'z':
  242. case 'Z':
  243. template.closePathFillStroke();
  244. break;
  245. }
  246. }
  247. }
  248. /**
  249. * Computes the data of the <code>d</code> attribute.
  250. *
  251. * @param attributes
  252. */
  253. private void computePoints(Attributes attributes) {
  254. String value = attributes.getValue("points");
  255. if (value == null)
  256. return;
  257. int i = 0;
  258. iXY ixy = new iXY(value, i);
  259. template.moveTo(ixy.x, coordinates[5] - ixy.y);
  260. i = ixy.i;
  261. while (i < value.length()) {
  262. ixy = new iXY(value, i);
  263. template.lineTo(ixy.x, coordinates[5] - ixy.y);
  264. i = ixy.i;
  265. }
  266. }
  267. /**
  268. * Sets the pages size of the document.
  269. *
  270. * @param attributes
  271. * the attributes of the svg-tag.
  272. */
  273. private void calcSize(Attributes attributes) {
  274. String width, height;
  275. width = attributes.getValue("width");
  276. coordinates[0] = getPixels(width);
  277. height = attributes.getValue("height");
  278. coordinates[1] = getPixels(height);
  279. coordinates[2] = 0;
  280. coordinates[3] = 0;
  281. coordinates[4] = coordinates[0];
  282. coordinates[5] = coordinates[1];
  283. String viewBox = attributes.getValue("viewBox");
  284. if (viewBox != null) {
  285. StringTokenizer tokenizer = new StringTokenizer(viewBox);
  286. if (tokenizer.hasMoreElements()) {
  287. coordinates[2] = getFloat(tokenizer.nextToken());
  288. }
  289. if (tokenizer.hasMoreElements()) {
  290. coordinates[3] = getFloat(tokenizer.nextToken());
  291. }
  292. if (tokenizer.hasMoreElements()) {
  293. coordinates[4] = getFloat(tokenizer.nextToken());
  294. }
  295. if (tokenizer.hasMoreElements()) {
  296. coordinates[5] = getFloat(tokenizer.nextToken());
  297. }
  298. }
  299. PdfContentByte content = writer.getDirectContent();
  300. template = content.createTemplate(coordinates[4], coordinates[5]);
  301. }
  302. /**
  303. * Parses a string that represents a float.
  304. *
  305. * @param value
  306. * the string
  307. * @return the float defined by the String
  308. */
  309. private float getFloat(String value) {
  310. char digit;
  311. float total = 0;
  312. int decimals = 0;
  313. boolean decimal = false;
  314. for (int i = 0; i < value.length(); i++) {
  315. digit = value.charAt(i);
  316. if (digit == '.') {
  317. decimal = true;
  318. continue;
  319. }
  320. if (digit < '0' || digit > '9') {
  321. break;
  322. }
  323. total = (total * 10) + (digit - '0');
  324. if (decimal)
  325. decimals++;
  326. }
  327. total = total / (float) Math.pow(10, decimals);
  328. return total;
  329. }
  330. /**
  331. * Parses a string that represents a length.
  332. *
  333. * @param length
  334. * the string
  335. * @return the length defined by the String in pixels.
  336. */
  337. private float getPixels(String length) {
  338. float total = getFloat(length);
  339. if (length.endsWith("pt"))
  340. return total / 1.25f;
  341. if (length.endsWith("pc"))
  342. return total / 15f;
  343. if (length.endsWith("pt"))
  344. return total / 1.25f;
  345. if (length.endsWith("mm"))
  346. return total / 3.543307f;
  347. if (length.endsWith("cm"))
  348. return total / 35.443307f;
  349. if (length.endsWith("in"))
  350. return total / 90f;
  351. return total;
  352. }
  353. /**
  354. * Returns the PdfTemplate as a com.lowagie.text.Image.
  355. *
  356. * @return a com.lowagie.text.Image
  357. * @throws BadElementException
  358. */
  359. public Image getImage() throws BadElementException {
  360. return Image.getInstance(template);
  361. }
  362. /**
  363. * Returns the PdfTemplate.
  364. *
  365. * @return a com.lowagie.text.pdf.PdfTemplate
  366. */
  367. public PdfTemplate getTemplate() {
  368. return template;
  369. }
  370. }