Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

PSGenerator.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. * $Id$
  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.io.OutputStream;
  53. import java.io.IOException;
  54. import java.text.DateFormat;
  55. import java.text.NumberFormat;
  56. import java.util.Date;
  57. import java.util.Stack;
  58. /**
  59. * This class is used to output PostScript code to an OutputStream.
  60. *
  61. * @author <a href="mailto:fop-dev@xml.apache.org">Apache XML FOP Development Team</a>
  62. * @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
  63. * @version $Id$
  64. */
  65. public class PSGenerator {
  66. /**
  67. * Indicator for the PostScript interpreter that the value is provided
  68. * later in the document (mostly in the %%Trailer section).
  69. */
  70. public static final AtendIndicator ATEND = new AtendIndicator() {};
  71. private OutputStream out;
  72. private Stack graphicsStateStack = new Stack();
  73. private PSState currentState;
  74. private StringBuffer tempBuffer = new StringBuffer(256);
  75. /** @see java.io.FilterOutputStream **/
  76. public PSGenerator(OutputStream out) {
  77. this.out = out;
  78. this.currentState = new PSState();
  79. this.graphicsStateStack.push(this.currentState);
  80. }
  81. /**
  82. * Writes a newline character to the OutputStream.
  83. *
  84. * @throws IOException In case of an I/O problem
  85. */
  86. public final void newLine() throws IOException {
  87. out.write('\n');
  88. }
  89. /**
  90. * Formats a double value for PostScript output.
  91. *
  92. * @param value value to format
  93. * @return the formatted value
  94. */
  95. public String formatDouble(double value) {
  96. NumberFormat nf = new java.text.DecimalFormat("0.#");
  97. return nf.format(value);
  98. }
  99. /**
  100. * Writes a PostScript command to the stream.
  101. *
  102. * @param cmd The PostScript code to be written.
  103. * @exception IOException In case of an I/O problem
  104. */
  105. public void write(String cmd) throws IOException {
  106. if (cmd.length() > 255) {
  107. throw new RuntimeException("PostScript command exceeded limit of 255 characters");
  108. }
  109. out.write(cmd.getBytes("US-ASCII"));
  110. }
  111. /**
  112. * Writes a PostScript command to the stream and ends the line.
  113. *
  114. * @param cmd The PostScript code to be written.
  115. * @exception IOException In case of an I/O problem
  116. */
  117. public void writeln(String cmd) throws IOException {
  118. write(cmd);
  119. newLine();
  120. }
  121. /**
  122. * Writes encoded data to the PostScript stream.
  123. *
  124. * @param cmd The encoded PostScript code to be written.
  125. * @exception IOException In case of an I/O problem
  126. */
  127. public void writeByteArr(byte[] cmd) throws IOException {
  128. out.write(cmd);
  129. newLine();
  130. }
  131. /**
  132. * Flushes the OutputStream.
  133. *
  134. * @exception IOException In case of an I/O problem
  135. */
  136. public void flush() throws IOException {
  137. out.flush();
  138. }
  139. /**
  140. * Escapes a character conforming to the rules established in the PostScript
  141. * Language Reference (Search for "Literal Text Strings").
  142. * @param c character to escape
  143. * @param target target StringBuffer to write the escaped character to
  144. */
  145. public static final void escapeChar(char c, StringBuffer target) {
  146. if (c > 127) {
  147. target.append("\\");
  148. target.append(Integer.toOctalString(c));
  149. } else {
  150. switch (c) {
  151. case '\n':
  152. target.append("\\n");
  153. break;
  154. case '\r':
  155. target.append("\\r");
  156. break;
  157. case '\t':
  158. target.append("\\t");
  159. break;
  160. case '\b':
  161. target.append("\\b");
  162. break;
  163. case '\f':
  164. target.append("\\f");
  165. break;
  166. case '\\':
  167. target.append("\\\\");
  168. break;
  169. case '(':
  170. target.append("\\(");
  171. break;
  172. case ')':
  173. target.append("\\)");
  174. break;
  175. default:
  176. target.append(c);
  177. }
  178. }
  179. }
  180. /**
  181. * Converts text by applying escaping rules established in the DSC specs.
  182. * @param text Text to convert
  183. * @return String The resulting String
  184. */
  185. public static final String convertStringToDSC(String text) {
  186. return convertStringToDSC(text, false);
  187. }
  188. /**
  189. * Converts text by applying escaping rules established in the DSC specs.
  190. * @param text Text to convert
  191. * @param forceParentheses Force the use of parentheses
  192. * @return String The resulting String
  193. */
  194. public static final String convertStringToDSC(String text,
  195. boolean forceParentheses) {
  196. if ((text == null) || (text.length() == 0)) {
  197. return "()";
  198. } else {
  199. int initialSize = text.length();
  200. initialSize += initialSize / 2;
  201. StringBuffer sb = new StringBuffer(initialSize);
  202. if ((Long.getLong(text) != null)
  203. || (text.indexOf(" ") >= 0)
  204. || forceParentheses) {
  205. sb.append("(");
  206. for (int i = 0; i < text.length(); i++) {
  207. final char c = text.charAt(i);
  208. escapeChar(c, sb);
  209. }
  210. sb.append(")");
  211. return sb.toString();
  212. } else {
  213. return text;
  214. }
  215. }
  216. }
  217. /**
  218. * Writes a DSC comment to the output stream.
  219. * @param name Name of the DSC comment
  220. * @exception IOException In case of an I/O problem
  221. * @see org.apache.fop.render.ps.DSCConstants
  222. */
  223. public void writeDSCComment(String name) throws IOException {
  224. writeln("%%" + name);
  225. }
  226. /**
  227. * Writes a DSC comment to the output stream. The parameter to the DSC
  228. * comment can be any object. The object is converted to a String as
  229. * necessary.
  230. * @param name Name of the DSC comment
  231. * @param param Single parameter to the DSC comment
  232. * @exception IOException In case of an I/O problem
  233. * @see org.apache.fop.render.ps.DSCConstants
  234. */
  235. public void writeDSCComment(String name, Object param) throws IOException {
  236. writeDSCComment(name, new Object[] {param});
  237. }
  238. /**
  239. * Writes a DSC comment to the output stream. The parameters to the DSC
  240. * comment can be any object. The objects are converted to Strings as
  241. * necessary. Please see the source code to find out what parameters are
  242. * currently supported.
  243. * @param name Name of the DSC comment
  244. * @param params Array of parameters to the DSC comment
  245. * @exception IOException In case of an I/O problem
  246. * @see org.apache.fop.render.ps.DSCConstants
  247. */
  248. public void writeDSCComment(String name, Object[] params) throws IOException {
  249. tempBuffer.setLength(0);
  250. tempBuffer.append("%%");
  251. tempBuffer.append(name);
  252. if ((params != null) && (params.length > 0)) {
  253. tempBuffer.append(": ");
  254. for (int i = 0; i < params.length; i++) {
  255. if (i > 0) {
  256. tempBuffer.append(" ");
  257. }
  258. if (params[i] instanceof String) {
  259. tempBuffer.append(convertStringToDSC((String)params[i]));
  260. } else if (params[i] instanceof AtendIndicator) {
  261. tempBuffer.append("(atend)");
  262. } else if (params[i] instanceof Number) {
  263. tempBuffer.append(params[i].toString());
  264. } else if (params[i] instanceof Date) {
  265. DateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
  266. tempBuffer.append(convertStringToDSC(df.format((Date)params[i])));
  267. } else {
  268. throw new IllegalArgumentException("Unsupported parameter type: "
  269. + params[i].getClass().getName());
  270. }
  271. }
  272. }
  273. writeln(tempBuffer.toString());
  274. }
  275. /**
  276. * Saves the graphics state of the rendering engine.
  277. * @exception IOException In case of an I/O problem
  278. */
  279. public void saveGraphicsState() throws IOException {
  280. writeln("gsave");
  281. PSState state = (PSState)this.currentState.clone();
  282. this.graphicsStateStack.push(this.currentState);
  283. this.currentState = state;
  284. }
  285. /**
  286. * Restores the last graphics state of the rendering engine.
  287. * @exception IOException In case of an I/O problem
  288. */
  289. public void restoreGraphicsState() throws IOException {
  290. writeln("grestore");
  291. this.currentState = (PSState)this.graphicsStateStack.pop();
  292. }
  293. /**
  294. * Concats the transformation matrix.
  295. * @param a A part
  296. * @param b B part
  297. * @param c C part
  298. * @param d D part
  299. * @param e E part
  300. * @param f F part
  301. * @exception IOException In case of an I/O problem
  302. */
  303. public void concatMatrix(double a, double b,
  304. double c, double d,
  305. double e, double f) throws IOException {
  306. writeln("[" + formatDouble(a) + " "
  307. + formatDouble(b) + " "
  308. + formatDouble(c) + " "
  309. + formatDouble(d) + " "
  310. + formatDouble(e) + " "
  311. + formatDouble(f) + "] concat");
  312. }
  313. /**
  314. * Concats the transformations matrix.
  315. * @param matrix Matrix to use
  316. * @exception IOException In case of an I/O problem
  317. */
  318. public void concatMatrix(double[] matrix) throws IOException {
  319. concatMatrix(matrix[0], matrix[1],
  320. matrix[2], matrix[3],
  321. matrix[4], matrix[5]);
  322. }
  323. /**
  324. * Returns the current graphics state.
  325. * @return the current graphics state
  326. */
  327. public PSState getCurrentState() {
  328. return this.currentState;
  329. }
  330. /** Used for the ATEND constant. See there. */
  331. private static interface AtendIndicator {
  332. }
  333. }