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.

PSRenderer.java 11KB

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