Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

PSRenderer.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.render.ps;
  8. // FOP
  9. import org.apache.fop.svg.SVGArea;
  10. import org.apache.fop.render.AbstractRenderer;
  11. import org.apache.fop.render.Renderer;
  12. import org.apache.fop.image.ImageArea;
  13. import org.apache.fop.image.FopImage;
  14. import org.apache.fop.image.FopImageException;
  15. import org.apache.fop.layout.*;
  16. import org.apache.fop.layout.inline.*;
  17. import org.apache.fop.datatypes.*;
  18. import org.apache.fop.fo.properties.*;
  19. import org.apache.fop.render.pdf.Font;
  20. import org.apache.fop.image.*;
  21. import org.apache.batik.bridge.*;
  22. import org.apache.batik.swing.svg.*;
  23. import org.apache.batik.swing.gvt.*;
  24. import org.apache.batik.gvt.*;
  25. import org.apache.batik.gvt.renderer.*;
  26. import org.apache.batik.gvt.filter.*;
  27. import org.apache.batik.gvt.event.*;
  28. import org.apache.log.Logger;
  29. // SVG
  30. import org.w3c.dom.svg.SVGSVGElement;
  31. import org.w3c.dom.svg.SVGDocument;
  32. import org.w3c.dom.*;
  33. import org.w3c.dom.svg.*;
  34. // Java
  35. import java.io.*;
  36. import java.util.*;
  37. import java.io.IOException;
  38. import java.io.OutputStream;
  39. import java.util.Enumeration;
  40. import java.util.Vector;
  41. import java.util.Hashtable;
  42. import java.awt.geom.AffineTransform;
  43. import java.awt.geom.Dimension2D;
  44. import java.awt.Point;
  45. import java.awt.RenderingHints;
  46. import java.awt.Dimension;
  47. /**
  48. * Renderer that renders to PostScript.
  49. * <br>
  50. * This class currently generates PostScript Level 2 code. The only exception
  51. * is the FlateEncode filter which is a Level 3 feature. The filters in use
  52. * are hardcoded at the moment.
  53. * <br>
  54. * This class follows the Document Structuring Conventions (DSC) version 3.0
  55. * (If I did everything right). If anyone modifies this renderer please make
  56. * sure to also follow the DSC to make it simpler to programmatically modify
  57. * the generated Postscript files (ex. extract pages etc.).
  58. * <br>
  59. * TODO: Character size/spacing, SVG Transcoder for Batik, configuration, move
  60. * to PrintRenderer, maybe improve filters (I'm not very proud of them), add a
  61. * RunLengthEncode filter (useful for Level 2 Postscript), Improve
  62. * DocumentProcessColors stuff (probably needs to be configurable, then maybe
  63. * add a color to grayscale conversion for bitmaps to make output smaller (See
  64. * PCLRenderer), font embedding, support different character encodings, try to
  65. * implement image transparency, positioning of images is wrong etc. <P>
  66. *
  67. * Modified by Mark Lillywhite mark-fop@inomial.com, to use the new
  68. * Renderer interface. This PostScript renderer appears to be the
  69. * most efficient at producing output.
  70. *
  71. * @author Jeremias Märki
  72. */
  73. public class PSRenderer extends AbstractRenderer {
  74. /**
  75. * the application producing the PostScript
  76. */
  77. protected String producer;
  78. int imagecount = 0; // DEBUG
  79. private boolean enableComments = true;
  80. /**
  81. * the stream used to output the PostScript
  82. */
  83. protected PSStream out;
  84. private boolean ioTrouble = false;
  85. private String currentFontName;
  86. private int currentFontSize;
  87. private int pageHeight;
  88. private int pageWidth;
  89. private float currRed;
  90. private float currGreen;
  91. private float currBlue;
  92. private FontInfo fontInfo;
  93. protected IDReferences idReferences;
  94. /**
  95. * set the document's producer
  96. *
  97. * @param producer string indicating application producing the PostScript
  98. */
  99. public void setProducer(String producer) {
  100. this.producer = producer;
  101. }
  102. /**
  103. * write out a command
  104. */
  105. protected void write(String cmd) {
  106. try {
  107. out.write(cmd);
  108. } catch (IOException e) {
  109. if (!ioTrouble)
  110. e.printStackTrace();
  111. ioTrouble = true;
  112. }
  113. }
  114. /**
  115. * write out a comment
  116. */
  117. protected void comment(String comment) {
  118. if (this.enableComments)
  119. write(comment);
  120. }
  121. protected void writeFontDict(FontInfo fontInfo) {
  122. write("%%BeginResource: procset FOPFonts");
  123. write("%%Title: Font setup (shortcuts) for this file");
  124. write("/FOPFonts 100 dict dup begin");
  125. write("/bd{bind def}bind def");
  126. write("/ld{load def}bd");
  127. write("/M/moveto ld");
  128. write("/RM/rmoveto ld");
  129. write("/t/show ld");
  130. write("/ux 0.0 def");
  131. write("/uy 0.0 def");
  132. // write("/cf /Helvetica def");
  133. // write("/cs 12000 def");
  134. // <font> <size> F
  135. write("/F {");
  136. write(" /Tp exch def");
  137. // write(" currentdict exch get");
  138. write(" /Tf exch def");
  139. write(" Tf findfont Tp scalefont setfont");
  140. write(" /cf Tf def /cs Tp def /cw ( ) stringwidth pop def");
  141. write("} bd");
  142. write("/ULS {currentpoint /uy exch def /ux exch def} bd");
  143. write("/ULE {");
  144. write(" /Tcx currentpoint pop def");
  145. write(" gsave");
  146. write(" newpath");
  147. write(" cf findfont cs scalefont dup");
  148. write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
  149. write(" /UnderlinePosition get Ts mul /To exch def");
  150. write(" /UnderlineThickness get Ts mul /Tt exch def");
  151. write(" ux uy To add moveto Tcx uy To add lineto");
  152. write(" Tt setlinewidth stroke");
  153. write(" grestore");
  154. write("} bd");
  155. write("/OLE {");
  156. write(" /Tcx currentpoint pop def");
  157. write(" gsave");
  158. write(" newpath");
  159. write(" cf findfont cs scalefont dup");
  160. write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
  161. write(" /UnderlinePosition get Ts mul /To exch def");
  162. write(" /UnderlineThickness get Ts mul /Tt exch def");
  163. write(" ux uy To add cs add moveto Tcx uy To add cs add lineto");
  164. write(" Tt setlinewidth stroke");
  165. write(" grestore");
  166. write("} bd");
  167. write("/SOE {");
  168. write(" /Tcx currentpoint pop def");
  169. write(" gsave");
  170. write(" newpath");
  171. write(" cf findfont cs scalefont dup");
  172. write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup");
  173. write(" /UnderlinePosition get Ts mul /To exch def");
  174. write(" /UnderlineThickness get Ts mul /Tt exch def");
  175. write(" ux uy To add cs 10 mul 26 idiv add moveto Tcx uy To add cs 10 mul 26 idiv add lineto");
  176. write(" Tt setlinewidth stroke");
  177. write(" grestore");
  178. write("} bd");
  179. // write("/gfF1{/Helvetica findfont} bd");
  180. // write("/gfF3{/Helvetica-Bold findfont} bd");
  181. Hashtable fonts = fontInfo.getFonts();
  182. Enumeration enum = fonts.keys();
  183. while (enum.hasMoreElements()) {
  184. String key = (String)enum.nextElement();
  185. Font fm = (Font)fonts.get(key);
  186. write("/" + key + " /" + fm.fontName() + " def");
  187. }
  188. write("end def");
  189. write("%%EndResource");
  190. enum = fonts.keys();
  191. while (enum.hasMoreElements()) {
  192. String key = (String)enum.nextElement();
  193. Font fm = (Font)fonts.get(key);
  194. write("/" + fm.fontName() + " findfont");
  195. write("dup length dict begin");
  196. write(" {1 index /FID ne {def} {pop pop} ifelse} forall");
  197. write(" /Encoding ISOLatin1Encoding def");
  198. write(" currentdict");
  199. write("end");
  200. write("/" + fm.fontName() + " exch definefont pop");
  201. }
  202. }
  203. protected void movetoCurrPosition() {
  204. write(this.currentIPPosition + " " + this.currentBPPosition + " M");
  205. }
  206. /**
  207. * set up the font info
  208. *
  209. * @param fontInfo the font info object to set up
  210. */
  211. public void setupFontInfo(FontInfo fontInfo) {
  212. /* use PDF's font setup to get PDF metrics */
  213. org.apache.fop.render.pdf.FontSetup.setup(fontInfo);
  214. this.fontInfo = fontInfo;
  215. }
  216. protected void addFilledRect(int x, int y, int w, int h,
  217. ColorType col) {
  218. write("newpath");
  219. write(x + " " + y + " M");
  220. write(w + " 0 rlineto");
  221. write("0 " + (-h) + " rlineto");
  222. write((-w) + " 0 rlineto");
  223. write("0 " + h + " rlineto");
  224. write("closepath");
  225. useColor(col);
  226. write("fill");
  227. }
  228. private long copyStream(InputStream in, OutputStream out,
  229. int bufferSize) throws IOException {
  230. long bytes_total = 0;
  231. byte[] buf = new byte[bufferSize];
  232. int bytes_read;
  233. while ((bytes_read = in.read(buf)) != -1) {
  234. bytes_total += bytes_read;
  235. out.write(buf, 0, bytes_read);
  236. }
  237. return bytes_total;
  238. }
  239. private long copyStream(InputStream in,
  240. OutputStream out) throws IOException {
  241. return copyStream(in, out, 4096);
  242. }
  243. public void useFont(String name, int size) {
  244. if ((currentFontName != name) || (currentFontSize != size)) {
  245. write(name + " " + size + " F");
  246. currentFontName = name;
  247. currentFontSize = size;
  248. }
  249. }
  250. private void useColor(ColorType col) {
  251. useColor(col.red(), col.green(), col.blue());
  252. }
  253. private void useColor(float red, float green, float blue) {
  254. if ((red != currRed) || (green != currGreen) || (blue != currBlue)) {
  255. write(red + " " + green + " " + blue + " setrgbcolor");
  256. currRed = red;
  257. currGreen = green;
  258. currBlue = blue;
  259. }
  260. }
  261. /**
  262. */
  263. public void startRenderer(OutputStream outputStream)
  264. throws IOException {
  265. log.debug("rendering areas to PostScript");
  266. this.out = new PSStream(outputStream);
  267. write("%!PS-Adobe-3.0");
  268. write("%%Creator: "+this.producer);
  269. write("%%DocumentProcessColors: Black");
  270. write("%%DocumentSuppliedResources: procset FOPFonts");
  271. write("%%EndComments");
  272. write("%%BeginDefaults");
  273. write("%%EndDefaults");
  274. write("%%BeginProlog");
  275. write("%%EndProlog");
  276. write("%%BeginSetup");
  277. writeFontDict(fontInfo);
  278. write("%%EndSetup");
  279. write("FOPFonts begin");
  280. }
  281. /**
  282. */
  283. public void stopRenderer()
  284. throws IOException {
  285. write("%%Trailer");
  286. write("%%EOF");
  287. this.out.flush();
  288. }
  289. }