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 12KB

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