PageRenderTime 62ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/src/share/classes/sun/print/PSPrinterJob.java

https://bitbucket.org/chegar/jigsaw_modulefileparser
Java | 2246 lines | 1344 code | 308 blank | 594 comment | 260 complexity | ab6bf12bdff750fdfcc62bc39e52a5ba MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25. package sun.print;
  26. import java.awt.Color;
  27. import java.awt.Component;
  28. import java.awt.Font;
  29. import java.awt.FontMetrics;
  30. import java.awt.GraphicsEnvironment;
  31. import java.awt.Graphics;
  32. import java.awt.Graphics2D;
  33. import java.awt.HeadlessException;
  34. import java.awt.Rectangle;
  35. import java.awt.Shape;
  36. import java.awt.image.BufferedImage;
  37. import java.awt.font.FontRenderContext;
  38. import java.awt.geom.AffineTransform;
  39. import java.awt.geom.PathIterator;
  40. import java.awt.geom.Rectangle2D;
  41. import java.awt.image.BufferedImage;
  42. import java.awt.print.Pageable;
  43. import java.awt.print.PageFormat;
  44. import java.awt.print.Paper;
  45. import java.awt.print.Printable;
  46. import java.awt.print.PrinterException;
  47. import java.awt.print.PrinterIOException;
  48. import java.awt.print.PrinterJob;
  49. import javax.print.DocFlavor;
  50. import javax.print.PrintService;
  51. import javax.print.StreamPrintService;
  52. import javax.print.attribute.HashPrintRequestAttributeSet;
  53. import javax.print.attribute.PrintRequestAttributeSet;
  54. import javax.print.attribute.standard.Chromaticity;
  55. import javax.print.attribute.standard.Copies;
  56. import javax.print.attribute.standard.Destination;
  57. import javax.print.attribute.standard.DialogTypeSelection;
  58. import javax.print.attribute.standard.JobName;
  59. import javax.print.attribute.standard.Sides;
  60. import java.io.BufferedInputStream;
  61. import java.io.BufferedOutputStream;
  62. import java.io.BufferedReader;
  63. import java.io.CharConversionException;
  64. import java.io.File;
  65. import java.io.InputStream;
  66. import java.io.InputStreamReader;
  67. import java.io.IOException;
  68. import java.io.FileInputStream;
  69. import java.io.FileOutputStream;
  70. import java.io.OutputStream;
  71. import java.io.PrintStream;
  72. import java.io.PrintWriter;
  73. import java.io.StringWriter;
  74. import java.util.ArrayList;
  75. import java.util.Enumeration;
  76. import java.util.Locale;
  77. import java.util.Properties;
  78. import sun.awt.CharsetString;
  79. import sun.awt.FontConfiguration;
  80. import sun.awt.FontDescriptor;
  81. import sun.awt.PlatformFont;
  82. import sun.awt.SunToolkit;
  83. import sun.font.FontManagerFactory;
  84. import sun.font.FontUtilities;
  85. import java.nio.charset.*;
  86. import java.nio.CharBuffer;
  87. import java.nio.ByteBuffer;
  88. //REMIND: Remove use of this class when IPPPrintService is moved to share directory.
  89. import java.lang.reflect.Method;
  90. /**
  91. * A class which initiates and executes a PostScript printer job.
  92. *
  93. * @author Richard Blanchard
  94. */
  95. public class PSPrinterJob extends RasterPrinterJob {
  96. /* Class Constants */
  97. /**
  98. * Passed to the <code>setFillMode</code>
  99. * method this value forces fills to be
  100. * done using the even-odd fill rule.
  101. */
  102. protected static final int FILL_EVEN_ODD = 1;
  103. /**
  104. * Passed to the <code>setFillMode</code>
  105. * method this value forces fills to be
  106. * done using the non-zero winding rule.
  107. */
  108. protected static final int FILL_WINDING = 2;
  109. /* PostScript has a 64K maximum on its strings.
  110. */
  111. private static final int MAX_PSSTR = (1024 * 64 - 1);
  112. private static final int RED_MASK = 0x00ff0000;
  113. private static final int GREEN_MASK = 0x0000ff00;
  114. private static final int BLUE_MASK = 0x000000ff;
  115. private static final int RED_SHIFT = 16;
  116. private static final int GREEN_SHIFT = 8;
  117. private static final int BLUE_SHIFT = 0;
  118. private static final int LOWNIBBLE_MASK = 0x0000000f;
  119. private static final int HINIBBLE_MASK = 0x000000f0;
  120. private static final int HINIBBLE_SHIFT = 4;
  121. private static final byte hexDigits[] = {
  122. (byte)'0', (byte)'1', (byte)'2', (byte)'3',
  123. (byte)'4', (byte)'5', (byte)'6', (byte)'7',
  124. (byte)'8', (byte)'9', (byte)'A', (byte)'B',
  125. (byte)'C', (byte)'D', (byte)'E', (byte)'F'
  126. };
  127. private static final int PS_XRES = 300;
  128. private static final int PS_YRES = 300;
  129. private static final String ADOBE_PS_STR = "%!PS-Adobe-3.0";
  130. private static final String EOF_COMMENT = "%%EOF";
  131. private static final String PAGE_COMMENT = "%%Page: ";
  132. private static final String READIMAGEPROC = "/imStr 0 def /imageSrc " +
  133. "{currentfile /ASCII85Decode filter /RunLengthDecode filter " +
  134. " imStr readstring pop } def";
  135. private static final String COPIES = "/#copies exch def";
  136. private static final String PAGE_SAVE = "/pgSave save def";
  137. private static final String PAGE_RESTORE = "pgSave restore";
  138. private static final String SHOWPAGE = "showpage";
  139. private static final String IMAGE_SAVE = "/imSave save def";
  140. private static final String IMAGE_STR = " string /imStr exch def";
  141. private static final String IMAGE_RESTORE = "imSave restore";
  142. private static final String COORD_PREP = " 0 exch translate "
  143. + "1 -1 scale"
  144. + "[72 " + PS_XRES + " div "
  145. + "0 0 "
  146. + "72 " + PS_YRES + " div "
  147. + "0 0]concat";
  148. private static final String SetFontName = "F";
  149. private static final String DrawStringName = "S";
  150. /**
  151. * The PostScript invocation to fill a path using the
  152. * even-odd rule. (eofill)
  153. */
  154. private static final String EVEN_ODD_FILL_STR = "EF";
  155. /**
  156. * The PostScript invocation to fill a path using the
  157. * non-zero winding rule. (fill)
  158. */
  159. private static final String WINDING_FILL_STR = "WF";
  160. /**
  161. * The PostScript to set the clip to be the current path
  162. * using the even odd rule. (eoclip)
  163. */
  164. private static final String EVEN_ODD_CLIP_STR = "EC";
  165. /**
  166. * The PostScript to set the clip to be the current path
  167. * using the non-zero winding rule. (clip)
  168. */
  169. private static final String WINDING_CLIP_STR = "WC";
  170. /**
  171. * Expecting two numbers on the PostScript stack, this
  172. * invocation moves the current pen position. (moveto)
  173. */
  174. private static final String MOVETO_STR = " M";
  175. /**
  176. * Expecting two numbers on the PostScript stack, this
  177. * invocation draws a PS line from the current pen
  178. * position to the point on the stack. (lineto)
  179. */
  180. private static final String LINETO_STR = " L";
  181. /**
  182. * This PostScript operator takes two control points
  183. * and an ending point and using the current pen
  184. * position as a starting point adds a bezier
  185. * curve to the current path. (curveto)
  186. */
  187. private static final String CURVETO_STR = " C";
  188. /**
  189. * The PostScript to pop a state off of the printer's
  190. * gstate stack. (grestore)
  191. */
  192. private static final String GRESTORE_STR = "R";
  193. /**
  194. * The PostScript to push a state on to the printer's
  195. * gstate stack. (gsave)
  196. */
  197. private static final String GSAVE_STR = "G";
  198. /**
  199. * Make the current PostScript path an empty path. (newpath)
  200. */
  201. private static final String NEWPATH_STR = "N";
  202. /**
  203. * Close the current subpath by generating a line segment
  204. * from the current position to the start of the subpath. (closepath)
  205. */
  206. private static final String CLOSEPATH_STR = "P";
  207. /**
  208. * Use the three numbers on top of the PS operator
  209. * stack to set the rgb color. (setrgbcolor)
  210. */
  211. private static final String SETRGBCOLOR_STR = " SC";
  212. /**
  213. * Use the top number on the stack to set the printer's
  214. * current gray value. (setgray)
  215. */
  216. private static final String SETGRAY_STR = " SG";
  217. /* Instance Variables */
  218. private int mDestType;
  219. private String mDestination = "lp";
  220. private boolean mNoJobSheet = false;
  221. private String mOptions;
  222. private Font mLastFont;
  223. private Color mLastColor;
  224. private Shape mLastClip;
  225. private AffineTransform mLastTransform;
  226. /* non-null if printing EPS for Java Plugin */
  227. private EPSPrinter epsPrinter = null;
  228. /**
  229. * The metrics for the font currently set.
  230. */
  231. FontMetrics mCurMetrics;
  232. /**
  233. * The output stream to which the generated PostScript
  234. * is written.
  235. */
  236. PrintStream mPSStream;
  237. /* The temporary file to which we spool before sending to the printer */
  238. File spoolFile;
  239. /**
  240. * This string holds the PostScript operator to
  241. * be used to fill a path. It can be changed
  242. * by the <code>setFillMode</code> method.
  243. */
  244. private String mFillOpStr = WINDING_FILL_STR;
  245. /**
  246. * This string holds the PostScript operator to
  247. * be used to clip to a path. It can be changed
  248. * by the <code>setFillMode</code> method.
  249. */
  250. private String mClipOpStr = WINDING_CLIP_STR;
  251. /**
  252. * A stack that represents the PostScript gstate stack.
  253. */
  254. ArrayList mGStateStack = new ArrayList();
  255. /**
  256. * The x coordinate of the current pen position.
  257. */
  258. private float mPenX;
  259. /**
  260. * The y coordinate of the current pen position.
  261. */
  262. private float mPenY;
  263. /**
  264. * The x coordinate of the starting point of
  265. * the current subpath.
  266. */
  267. private float mStartPathX;
  268. /**
  269. * The y coordinate of the starting point of
  270. * the current subpath.
  271. */
  272. private float mStartPathY;
  273. /**
  274. * An optional mapping of fonts to PostScript names.
  275. */
  276. private static Properties mFontProps = null;
  277. /* Class static initialiser block */
  278. static {
  279. //enable priviledges so initProps can access system properties,
  280. // open the property file, etc.
  281. java.security.AccessController.doPrivileged(
  282. new java.security.PrivilegedAction() {
  283. public Object run() {
  284. mFontProps = initProps();
  285. return null;
  286. }
  287. });
  288. }
  289. /*
  290. * Initialize PostScript font properties.
  291. * Copied from PSPrintStream
  292. */
  293. private static Properties initProps() {
  294. // search psfont.properties for fonts
  295. // and create and initialize fontProps if it exist.
  296. String jhome = System.getProperty("java.home");
  297. if (jhome != null){
  298. String ulocale = SunToolkit.getStartupLocale().getLanguage();
  299. try {
  300. File f = new File(jhome + File.separator +
  301. "lib" + File.separator +
  302. "psfontj2d.properties." + ulocale);
  303. if (!f.canRead()){
  304. f = new File(jhome + File.separator +
  305. "lib" + File.separator +
  306. "psfont.properties." + ulocale);
  307. if (!f.canRead()){
  308. f = new File(jhome + File.separator + "lib" +
  309. File.separator + "psfontj2d.properties");
  310. if (!f.canRead()){
  311. f = new File(jhome + File.separator + "lib" +
  312. File.separator + "psfont.properties");
  313. if (!f.canRead()){
  314. return (Properties)null;
  315. }
  316. }
  317. }
  318. }
  319. // Load property file
  320. InputStream in =
  321. new BufferedInputStream(new FileInputStream(f.getPath()));
  322. Properties props = new Properties();
  323. props.load(in);
  324. in.close();
  325. return props;
  326. } catch (Exception e){
  327. return (Properties)null;
  328. }
  329. }
  330. return (Properties)null;
  331. }
  332. /* Constructors */
  333. public PSPrinterJob()
  334. {
  335. }
  336. /* Instance Methods */
  337. /**
  338. * Presents the user a dialog for changing properties of the
  339. * print job interactively.
  340. * @returns false if the user cancels the dialog and
  341. * true otherwise.
  342. * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  343. * returns true.
  344. * @see java.awt.GraphicsEnvironment#isHeadless
  345. */
  346. public boolean printDialog() throws HeadlessException {
  347. if (GraphicsEnvironment.isHeadless()) {
  348. throw new HeadlessException();
  349. }
  350. if (attributes == null) {
  351. attributes = new HashPrintRequestAttributeSet();
  352. }
  353. attributes.add(new Copies(getCopies()));
  354. attributes.add(new JobName(getJobName(), null));
  355. boolean doPrint = false;
  356. DialogTypeSelection dts =
  357. (DialogTypeSelection)attributes.get(DialogTypeSelection.class);
  358. if (dts == DialogTypeSelection.NATIVE) {
  359. // Remove DialogTypeSelection.NATIVE to prevent infinite loop in
  360. // RasterPrinterJob.
  361. attributes.remove(DialogTypeSelection.class);
  362. doPrint = printDialog(attributes);
  363. // restore attribute
  364. attributes.add(DialogTypeSelection.NATIVE);
  365. } else {
  366. doPrint = printDialog(attributes);
  367. }
  368. if (doPrint) {
  369. JobName jobName = (JobName)attributes.get(JobName.class);
  370. if (jobName != null) {
  371. setJobName(jobName.getValue());
  372. }
  373. Copies copies = (Copies)attributes.get(Copies.class);
  374. if (copies != null) {
  375. setCopies(copies.getValue());
  376. }
  377. Destination dest = (Destination)attributes.get(Destination.class);
  378. if (dest != null) {
  379. try {
  380. mDestType = RasterPrinterJob.FILE;
  381. mDestination = (new File(dest.getURI())).getPath();
  382. } catch (Exception e) {
  383. mDestination = "out.ps";
  384. }
  385. } else {
  386. mDestType = RasterPrinterJob.PRINTER;
  387. PrintService pServ = getPrintService();
  388. if (pServ != null) {
  389. mDestination = pServ.getName();
  390. }
  391. }
  392. }
  393. return doPrint;
  394. }
  395. /**
  396. * Invoked by the RasterPrinterJob super class
  397. * this method is called to mark the start of a
  398. * document.
  399. */
  400. protected void startDoc() throws PrinterException {
  401. // A security check has been performed in the
  402. // java.awt.print.printerJob.getPrinterJob method.
  403. // We use an inner class to execute the privilged open operations.
  404. // Note that we only open a file if it has been nominated by
  405. // the end-user in a dialog that we ouselves put up.
  406. OutputStream output;
  407. if (epsPrinter == null) {
  408. if (getPrintService() instanceof PSStreamPrintService) {
  409. StreamPrintService sps = (StreamPrintService)getPrintService();
  410. mDestType = RasterPrinterJob.STREAM;
  411. if (sps.isDisposed()) {
  412. throw new PrinterException("service is disposed");
  413. }
  414. output = sps.getOutputStream();
  415. if (output == null) {
  416. throw new PrinterException("Null output stream");
  417. }
  418. } else {
  419. /* REMIND: This needs to be more maintainable */
  420. mNoJobSheet = super.noJobSheet;
  421. if (super.destinationAttr != null) {
  422. mDestType = RasterPrinterJob.FILE;
  423. mDestination = super.destinationAttr;
  424. }
  425. if (mDestType == RasterPrinterJob.FILE) {
  426. try {
  427. spoolFile = new File(mDestination);
  428. output = new FileOutputStream(spoolFile);
  429. } catch (IOException ex) {
  430. throw new PrinterIOException(ex);
  431. }
  432. } else {
  433. PrinterOpener po = new PrinterOpener();
  434. java.security.AccessController.doPrivileged(po);
  435. if (po.pex != null) {
  436. throw po.pex;
  437. }
  438. output = po.result;
  439. }
  440. }
  441. mPSStream = new PrintStream(new BufferedOutputStream(output));
  442. mPSStream.println(ADOBE_PS_STR);
  443. }
  444. mPSStream.println("%%BeginProlog");
  445. mPSStream.println(READIMAGEPROC);
  446. mPSStream.println("/BD {bind def} bind def");
  447. mPSStream.println("/D {def} BD");
  448. mPSStream.println("/C {curveto} BD");
  449. mPSStream.println("/L {lineto} BD");
  450. mPSStream.println("/M {moveto} BD");
  451. mPSStream.println("/R {grestore} BD");
  452. mPSStream.println("/G {gsave} BD");
  453. mPSStream.println("/N {newpath} BD");
  454. mPSStream.println("/P {closepath} BD");
  455. mPSStream.println("/EC {eoclip} BD");
  456. mPSStream.println("/WC {clip} BD");
  457. mPSStream.println("/EF {eofill} BD");
  458. mPSStream.println("/WF {fill} BD");
  459. mPSStream.println("/SG {setgray} BD");
  460. mPSStream.println("/SC {setrgbcolor} BD");
  461. mPSStream.println("/ISOF {");
  462. mPSStream.println(" dup findfont dup length 1 add dict begin {");
  463. mPSStream.println(" 1 index /FID eq {pop pop} {D} ifelse");
  464. mPSStream.println(" } forall /Encoding ISOLatin1Encoding D");
  465. mPSStream.println(" currentdict end definefont");
  466. mPSStream.println("} BD");
  467. mPSStream.println("/NZ {dup 1 lt {pop 1} if} BD");
  468. /* The following procedure takes args: string, x, y, desiredWidth.
  469. * It calculates using stringwidth the width of the string in the
  470. * current font and subtracts it from the desiredWidth and divides
  471. * this by stringLen-1. This gives us a per-glyph adjustment in
  472. * the spacing needed (either +ve or -ve) to make the string
  473. * print at the desiredWidth. The ashow procedure call takes this
  474. * per-glyph adjustment as an argument. This is necessary for WYSIWYG
  475. */
  476. mPSStream.println("/"+DrawStringName +" {");
  477. mPSStream.println(" moveto 1 index stringwidth pop NZ sub");
  478. mPSStream.println(" 1 index length 1 sub NZ div 0");
  479. mPSStream.println(" 3 2 roll ashow newpath} BD");
  480. mPSStream.println("/FL [");
  481. if (mFontProps == null){
  482. mPSStream.println(" /Helvetica ISOF");
  483. mPSStream.println(" /Helvetica-Bold ISOF");
  484. mPSStream.println(" /Helvetica-Oblique ISOF");
  485. mPSStream.println(" /Helvetica-BoldOblique ISOF");
  486. mPSStream.println(" /Times-Roman ISOF");
  487. mPSStream.println(" /Times-Bold ISOF");
  488. mPSStream.println(" /Times-Italic ISOF");
  489. mPSStream.println(" /Times-BoldItalic ISOF");
  490. mPSStream.println(" /Courier ISOF");
  491. mPSStream.println(" /Courier-Bold ISOF");
  492. mPSStream.println(" /Courier-Oblique ISOF");
  493. mPSStream.println(" /Courier-BoldOblique ISOF");
  494. } else {
  495. int cnt = Integer.parseInt(mFontProps.getProperty("font.num", "9"));
  496. for (int i = 0; i < cnt; i++){
  497. mPSStream.println(" /" + mFontProps.getProperty
  498. ("font." + String.valueOf(i), "Courier ISOF"));
  499. }
  500. }
  501. mPSStream.println("] D");
  502. mPSStream.println("/"+SetFontName +" {");
  503. mPSStream.println(" FL exch get exch scalefont");
  504. mPSStream.println(" [1 0 0 -1 0 0] makefont setfont} BD");
  505. mPSStream.println("%%EndProlog");
  506. mPSStream.println("%%BeginSetup");
  507. if (epsPrinter == null) {
  508. // Set Page Size using first page's format.
  509. PageFormat pageFormat = getPageable().getPageFormat(0);
  510. double paperHeight = pageFormat.getPaper().getHeight();
  511. double paperWidth = pageFormat.getPaper().getWidth();
  512. /* PostScript printers can always generate uncollated copies.
  513. */
  514. mPSStream.print("<< /PageSize [" +
  515. paperWidth + " "+ paperHeight+"]");
  516. final PrintService pservice = getPrintService();
  517. Boolean isPS = (Boolean)java.security.AccessController.doPrivileged(
  518. new java.security.PrivilegedAction() {
  519. public Object run() {
  520. try {
  521. Class psClass = Class.forName("sun.print.IPPPrintService");
  522. if (psClass.isInstance(pservice)) {
  523. Method isPSMethod = psClass.getMethod("isPostscript",
  524. (Class[])null);
  525. return (Boolean)isPSMethod.invoke(pservice, (Object[])null);
  526. }
  527. } catch (Throwable t) {
  528. }
  529. return Boolean.TRUE;
  530. }
  531. }
  532. );
  533. if (isPS) {
  534. mPSStream.print(" /DeferredMediaSelection true");
  535. }
  536. mPSStream.print(" /ImagingBBox null /ManualFeed false");
  537. mPSStream.print(isCollated() ? " /Collate true":"");
  538. mPSStream.print(" /NumCopies " +getCopiesInt());
  539. if (sidesAttr != Sides.ONE_SIDED) {
  540. if (sidesAttr == Sides.TWO_SIDED_LONG_EDGE) {
  541. mPSStream.print(" /Duplex true ");
  542. } else if (sidesAttr == Sides.TWO_SIDED_SHORT_EDGE) {
  543. mPSStream.print(" /Duplex true /Tumble true ");
  544. }
  545. }
  546. mPSStream.println(" >> setpagedevice ");
  547. }
  548. mPSStream.println("%%EndSetup");
  549. }
  550. // Inner class to run "privileged" to open the printer output stream.
  551. private class PrinterOpener implements java.security.PrivilegedAction {
  552. PrinterException pex;
  553. OutputStream result;
  554. public Object run() {
  555. try {
  556. /* Write to a temporary file which will be spooled to
  557. * the printer then deleted. In the case that the file
  558. * is not removed for some reason, request that it is
  559. * removed when the VM exits.
  560. */
  561. spoolFile = File.createTempFile("javaprint", ".ps", null);
  562. spoolFile.deleteOnExit();
  563. result = new FileOutputStream(spoolFile);
  564. return result;
  565. } catch (IOException ex) {
  566. // If there is an IOError we subvert it to a PrinterException.
  567. pex = new PrinterIOException(ex);
  568. }
  569. return null;
  570. }
  571. }
  572. // Inner class to run "privileged" to invoke the system print command
  573. private class PrinterSpooler implements java.security.PrivilegedAction {
  574. PrinterException pex;
  575. private void handleProcessFailure(final Process failedProcess,
  576. final String[] execCmd, final int result) throws IOException {
  577. try (StringWriter sw = new StringWriter();
  578. PrintWriter pw = new PrintWriter(sw)) {
  579. pw.append("error=").append(Integer.toString(result));
  580. pw.append(" running:");
  581. for (String arg: execCmd) {
  582. pw.append(" '").append(arg).append("'");
  583. }
  584. try (InputStream is = failedProcess.getErrorStream();
  585. InputStreamReader isr = new InputStreamReader(is);
  586. BufferedReader br = new BufferedReader(isr)) {
  587. while (br.ready()) {
  588. pw.println();
  589. pw.append("\t\t").append(br.readLine());
  590. }
  591. } finally {
  592. pw.flush();
  593. throw new IOException(sw.toString());
  594. }
  595. }
  596. }
  597. public Object run() {
  598. if (spoolFile == null || !spoolFile.exists()) {
  599. pex = new PrinterException("No spool file");
  600. return null;
  601. }
  602. try {
  603. /**
  604. * Spool to the printer.
  605. */
  606. String fileName = spoolFile.getAbsolutePath();
  607. String execCmd[] = printExecCmd(mDestination, mOptions,
  608. mNoJobSheet, getJobNameInt(),
  609. 1, fileName);
  610. Process process = Runtime.getRuntime().exec(execCmd);
  611. process.waitFor();
  612. final int result = process.exitValue();
  613. if (0 != result) {
  614. handleProcessFailure(process, execCmd, result);
  615. }
  616. } catch (IOException ex) {
  617. pex = new PrinterIOException(ex);
  618. } catch (InterruptedException ie) {
  619. pex = new PrinterException(ie.toString());
  620. } finally {
  621. spoolFile.delete();
  622. }
  623. return null;
  624. }
  625. }
  626. /**
  627. * Invoked if the application cancelled the printjob.
  628. */
  629. protected void abortDoc() {
  630. if (mPSStream != null && mDestType != RasterPrinterJob.STREAM) {
  631. mPSStream.close();
  632. }
  633. java.security.AccessController.doPrivileged(
  634. new java.security.PrivilegedAction() {
  635. public Object run() {
  636. if (spoolFile != null && spoolFile.exists()) {
  637. spoolFile.delete();
  638. }
  639. return null;
  640. }
  641. });
  642. }
  643. /**
  644. * Invoked by the RasterPrintJob super class
  645. * this method is called after that last page
  646. * has been imaged.
  647. */
  648. protected void endDoc() throws PrinterException {
  649. if (mPSStream != null) {
  650. mPSStream.println(EOF_COMMENT);
  651. mPSStream.flush();
  652. if (mDestType != RasterPrinterJob.STREAM) {
  653. mPSStream.close();
  654. }
  655. }
  656. if (mDestType == RasterPrinterJob.PRINTER) {
  657. if (getPrintService() != null) {
  658. mDestination = getPrintService().getName();
  659. }
  660. PrinterSpooler spooler = new PrinterSpooler();
  661. java.security.AccessController.doPrivileged(spooler);
  662. if (spooler.pex != null) {
  663. throw spooler.pex;
  664. }
  665. }
  666. }
  667. /**
  668. * The RasterPrintJob super class calls this method
  669. * at the start of each page.
  670. */
  671. protected void startPage(PageFormat pageFormat, Printable painter,
  672. int index, boolean paperChanged)
  673. throws PrinterException
  674. {
  675. double paperHeight = pageFormat.getPaper().getHeight();
  676. double paperWidth = pageFormat.getPaper().getWidth();
  677. int pageNumber = index + 1;
  678. /* Place an initial gstate on to our gstate stack.
  679. * It will have the default PostScript gstate
  680. * attributes.
  681. */
  682. mGStateStack = new ArrayList();
  683. mGStateStack.add(new GState());
  684. mPSStream.println(PAGE_COMMENT + pageNumber + " " + pageNumber);
  685. /* Check current page's pageFormat against the previous pageFormat,
  686. */
  687. if (index > 0 && paperChanged) {
  688. mPSStream.print("<< /PageSize [" +
  689. paperWidth + " " + paperHeight + "]");
  690. final PrintService pservice = getPrintService();
  691. Boolean isPS =
  692. (Boolean)java.security.AccessController.doPrivileged(
  693. new java.security.PrivilegedAction() {
  694. public Object run() {
  695. try {
  696. Class psClass =
  697. Class.forName("sun.print.IPPPrintService");
  698. if (psClass.isInstance(pservice)) {
  699. Method isPSMethod =
  700. psClass.getMethod("isPostscript",
  701. (Class[])null);
  702. return (Boolean)
  703. isPSMethod.invoke(pservice,
  704. (Object[])null);
  705. }
  706. } catch (Throwable t) {
  707. }
  708. return Boolean.TRUE;
  709. }
  710. }
  711. );
  712. if (isPS) {
  713. mPSStream.print(" /DeferredMediaSelection true");
  714. }
  715. mPSStream.println(" >> setpagedevice");
  716. }
  717. mPSStream.println(PAGE_SAVE);
  718. mPSStream.println(paperHeight + COORD_PREP);
  719. }
  720. /**
  721. * The RastePrintJob super class calls this method
  722. * at the end of each page.
  723. */
  724. protected void endPage(PageFormat format, Printable painter,
  725. int index)
  726. throws PrinterException
  727. {
  728. mPSStream.println(PAGE_RESTORE);
  729. mPSStream.println(SHOWPAGE);
  730. }
  731. /**
  732. * Convert the 24 bit BGR image buffer represented by
  733. * <code>image</code> to PostScript. The image is drawn at
  734. * <code>(destX, destY)</code> in device coordinates.
  735. * The image is scaled into a square of size
  736. * specified by <code>destWidth</code> and
  737. * <code>destHeight</code>. The portion of the
  738. * source image copied into that square is specified
  739. * by <code>srcX</code>, <code>srcY</code>,
  740. * <code>srcWidth</code>, and srcHeight.
  741. */
  742. protected void drawImageBGR(byte[] bgrData,
  743. float destX, float destY,
  744. float destWidth, float destHeight,
  745. float srcX, float srcY,
  746. float srcWidth, float srcHeight,
  747. int srcBitMapWidth, int srcBitMapHeight) {
  748. /* We draw images at device resolution so we probably need
  749. * to change the current PostScript transform.
  750. */
  751. setTransform(new AffineTransform());
  752. prepDrawing();
  753. int intSrcWidth = (int) srcWidth;
  754. int intSrcHeight = (int) srcHeight;
  755. mPSStream.println(IMAGE_SAVE);
  756. /* Create a PS string big enough to hold a row of pixels.
  757. */
  758. int psBytesPerRow = 3 * (int) intSrcWidth;
  759. while (psBytesPerRow > MAX_PSSTR) {
  760. psBytesPerRow /= 2;
  761. }
  762. mPSStream.println(psBytesPerRow + IMAGE_STR);
  763. /* Scale and translate the unit image.
  764. */
  765. mPSStream.println("[" + destWidth + " 0 "
  766. + "0 " + destHeight
  767. + " " + destX + " " + destY
  768. +"]concat");
  769. /* Color Image invocation.
  770. */
  771. mPSStream.println(intSrcWidth + " " + intSrcHeight + " " + 8 + "["
  772. + intSrcWidth + " 0 "
  773. + "0 " + intSrcHeight
  774. + " 0 " + 0 + "]"
  775. + "/imageSrc load false 3 colorimage");
  776. /* Image data.
  777. */
  778. int index = 0;
  779. byte[] rgbData = new byte[intSrcWidth * 3];
  780. try {
  781. /* Skip the parts of the image that are not part
  782. * of the source rectangle.
  783. */
  784. index = (int) srcY * srcBitMapWidth;
  785. for(int i = 0; i < intSrcHeight; i++) {
  786. /* Skip the left part of the image that is not
  787. * part of the source rectangle.
  788. */
  789. index += (int) srcX;
  790. index = swapBGRtoRGB(bgrData, index, rgbData);
  791. byte[] encodedData = rlEncode(rgbData);
  792. byte[] asciiData = ascii85Encode(encodedData);
  793. mPSStream.write(asciiData);
  794. mPSStream.println("");
  795. }
  796. /*
  797. * If there is an IOError we subvert it to a PrinterException.
  798. * Fix: There has got to be a better way, maybe define
  799. * a PrinterIOException and then throw that?
  800. */
  801. } catch (IOException e) {
  802. //throw new PrinterException(e.toString());
  803. }
  804. mPSStream.println(IMAGE_RESTORE);
  805. }
  806. /**
  807. * Prints the contents of the array of ints, 'data'
  808. * to the current page. The band is placed at the
  809. * location (x, y) in device coordinates on the
  810. * page. The width and height of the band is
  811. * specified by the caller. Currently the data
  812. * is 24 bits per pixel in BGR format.
  813. */
  814. protected void printBand(byte[] bgrData, int x, int y,
  815. int width, int height)
  816. throws PrinterException
  817. {
  818. mPSStream.println(IMAGE_SAVE);
  819. /* Create a PS string big enough to hold a row of pixels.
  820. */
  821. int psBytesPerRow = 3 * width;
  822. while (psBytesPerRow > MAX_PSSTR) {
  823. psBytesPerRow /= 2;
  824. }
  825. mPSStream.println(psBytesPerRow + IMAGE_STR);
  826. /* Scale and translate the unit image.
  827. */
  828. mPSStream.println("[" + width + " 0 "
  829. + "0 " + height
  830. + " " + x + " " + y
  831. +"]concat");
  832. /* Color Image invocation.
  833. */
  834. mPSStream.println(width + " " + height + " " + 8 + "["
  835. + width + " 0 "
  836. + "0 " + -height
  837. + " 0 " + height + "]"
  838. + "/imageSrc load false 3 colorimage");
  839. /* Image data.
  840. */
  841. int index = 0;
  842. byte[] rgbData = new byte[width*3];
  843. try {
  844. for(int i = 0; i < height; i++) {
  845. index = swapBGRtoRGB(bgrData, index, rgbData);
  846. byte[] encodedData = rlEncode(rgbData);
  847. byte[] asciiData = ascii85Encode(encodedData);
  848. mPSStream.write(asciiData);
  849. mPSStream.println("");
  850. }
  851. } catch (IOException e) {
  852. throw new PrinterIOException(e);
  853. }
  854. mPSStream.println(IMAGE_RESTORE);
  855. }
  856. /**
  857. * Examine the metrics captured by the
  858. * <code>PeekGraphics</code> instance and
  859. * if capable of directly converting this
  860. * print job to the printer's control language
  861. * or the native OS's graphics primitives, then
  862. * return a <code>PSPathGraphics</code> to perform
  863. * that conversion. If there is not an object
  864. * capable of the conversion then return
  865. * <code>null</code>. Returning <code>null</code>
  866. * causes the print job to be rasterized.
  867. */
  868. protected Graphics2D createPathGraphics(PeekGraphics peekGraphics,
  869. PrinterJob printerJob,
  870. Printable painter,
  871. PageFormat pageFormat,
  872. int pageIndex) {
  873. PSPathGraphics pathGraphics;
  874. PeekMetrics metrics = peekGraphics.getMetrics();
  875. /* If the application has drawn anything that
  876. * out PathGraphics class can not handle then
  877. * return a null PathGraphics.
  878. */
  879. if (forcePDL == false && (forceRaster == true
  880. || metrics.hasNonSolidColors()
  881. || metrics.hasCompositing())) {
  882. pathGraphics = null;
  883. } else {
  884. BufferedImage bufferedImage = new BufferedImage(8, 8,
  885. BufferedImage.TYPE_INT_RGB);
  886. Graphics2D bufferedGraphics = bufferedImage.createGraphics();
  887. boolean canRedraw = peekGraphics.getAWTDrawingOnly() == false;
  888. pathGraphics = new PSPathGraphics(bufferedGraphics, printerJob,
  889. painter, pageFormat, pageIndex,
  890. canRedraw);
  891. }
  892. return pathGraphics;
  893. }
  894. /**
  895. * Intersect the gstate's current path with the
  896. * current clip and make the result the new clip.
  897. */
  898. protected void selectClipPath() {
  899. mPSStream.println(mClipOpStr);
  900. }
  901. protected void setClip(Shape clip) {
  902. mLastClip = clip;
  903. }
  904. protected void setTransform(AffineTransform transform) {
  905. mLastTransform = transform;
  906. }
  907. /**
  908. * Set the current PostScript font.
  909. * Taken from outFont in PSPrintStream.
  910. */
  911. protected boolean setFont(Font font) {
  912. mLastFont = font;
  913. return true;
  914. }
  915. /**
  916. * Given an array of CharsetStrings that make up a run
  917. * of text, this routine converts each CharsetString to
  918. * an index into our PostScript font list. If one or more
  919. * CharsetStrings can not be represented by a PostScript
  920. * font, then this routine will return a null array.
  921. */
  922. private int[] getPSFontIndexArray(Font font, CharsetString[] charSet) {
  923. int[] psFont = null;
  924. if (mFontProps != null) {
  925. psFont = new int[charSet.length];
  926. }
  927. for (int i = 0; i < charSet.length && psFont != null; i++){
  928. /* Get the encoding of the run of text.
  929. */
  930. CharsetString cs = charSet[i];
  931. CharsetEncoder fontCS = cs.fontDescriptor.encoder;
  932. String charsetName = cs.fontDescriptor.getFontCharsetName();
  933. /*
  934. * sun.awt.Symbol perhaps should return "symbol" for encoding.
  935. * Similarly X11Dingbats should return "dingbats"
  936. * Forced to check for win32 & x/unix names for these converters.
  937. */
  938. if ("Symbol".equals(charsetName)) {
  939. charsetName = "symbol";
  940. } else if ("WingDings".equals(charsetName) ||
  941. "X11Dingbats".equals(charsetName)) {
  942. charsetName = "dingbats";
  943. } else {
  944. charsetName = makeCharsetName(charsetName, cs.charsetChars);
  945. }
  946. int styleMask = font.getStyle() |
  947. FontUtilities.getFont2D(font).getStyle();
  948. String style = FontConfiguration.getStyleString(styleMask);
  949. /* First we map the font name through the properties file.
  950. * This mapping provides alias names for fonts, for example,
  951. * "timesroman" is mapped to "serif".
  952. */
  953. String fontName = font.getFamily().toLowerCase(Locale.ENGLISH);
  954. fontName = fontName.replace(' ', '_');
  955. String name = mFontProps.getProperty(fontName, "");
  956. /* Now map the alias name, character set name, and style
  957. * to a PostScript name.
  958. */
  959. String psName =
  960. mFontProps.getProperty(name + "." + charsetName + "." + style,
  961. null);
  962. if (psName != null) {
  963. /* Get the PostScript font index for the PostScript font.
  964. */
  965. try {
  966. psFont[i] =
  967. Integer.parseInt(mFontProps.getProperty(psName));
  968. /* If there is no PostScript font for this font name,
  969. * then we want to termintate the loop and the method
  970. * indicating our failure. Setting the array to null
  971. * is used to indicate these failures.
  972. */
  973. } catch(NumberFormatException e){
  974. psFont = null;
  975. }
  976. /* There was no PostScript name for the font, character set,
  977. * and style so give up.
  978. */
  979. } else {
  980. psFont = null;
  981. }
  982. }
  983. return psFont;
  984. }
  985. private static String escapeParens(String str) {
  986. if (str.indexOf('(') == -1 && str.indexOf(')') == -1 ) {
  987. return str;
  988. } else {
  989. int count = 0;
  990. int pos = 0;
  991. while ((pos = str.indexOf('(', pos)) != -1) {
  992. count++;
  993. pos++;
  994. }
  995. pos = 0;
  996. while ((pos = str.indexOf(')', pos)) != -1) {
  997. count++;
  998. pos++;
  999. }
  1000. char []inArr = str.toCharArray();
  1001. char []outArr = new char[inArr.length+count];
  1002. pos = 0;
  1003. for (int i=0;i<inArr.length;i++) {
  1004. if (inArr[i] == '(' || inArr[i] == ')') {
  1005. outArr[pos++] = '\\';
  1006. }
  1007. outArr[pos++] = inArr[i];
  1008. }
  1009. return new String(outArr);
  1010. }
  1011. }
  1012. /* return of 0 means unsupported. Other return indicates the number
  1013. * of distinct PS fonts needed to draw this text. This saves us
  1014. * doing this processing one extra time.
  1015. */
  1016. protected int platformFontCount(Font font, String str) {
  1017. if (mFontProps == null) {
  1018. return 0;
  1019. }
  1020. CharsetString[] acs =
  1021. ((PlatformFont)(font.getPeer())).makeMultiCharsetString(str,false);
  1022. if (acs == null) {
  1023. /* AWT can't convert all chars so use 2D path */
  1024. return 0;
  1025. }
  1026. int[] psFonts = getPSFontIndexArray(font, acs);
  1027. return (psFonts == null) ? 0 : psFonts.length;
  1028. }
  1029. protected boolean textOut(Graphics g, String str, float x, float y,
  1030. Font mLastFont, FontRenderContext frc,
  1031. float width) {
  1032. boolean didText = true;
  1033. if (mFontProps == null) {
  1034. return false;
  1035. } else {
  1036. prepDrawing();
  1037. /* On-screen drawString renders most control chars as the missing
  1038. * glyph and have the non-zero advance of that glyph.
  1039. * Exceptions are \t, \n and \r which are considered zero-width.
  1040. * Postscript handles control chars mostly as a missing glyph.
  1041. * But we use 'ashow' specifying a width for the string which
  1042. * assumes zero-width for those three exceptions, and Postscript
  1043. * tries to squeeze the extra char in, with the result that the
  1044. * glyphs look compressed or even overlap.
  1045. * So exclude those control chars from the string sent to PS.
  1046. */
  1047. str = removeControlChars(str);
  1048. if (str.length() == 0) {
  1049. return true;
  1050. }
  1051. CharsetString[] acs =
  1052. ((PlatformFont)
  1053. (mLastFont.getPeer())).makeMultiCharsetString(str, false);
  1054. if (acs == null) {
  1055. /* AWT can't convert all chars so use 2D path */
  1056. return false;
  1057. }
  1058. /* Get an array of indices into our PostScript name
  1059. * table. If all of the runs can not be converted
  1060. * to PostScript fonts then null is returned and
  1061. * we'll want to fall back to printing the text
  1062. * as shapes.
  1063. */
  1064. int[] psFonts = getPSFontIndexArray(mLastFont, acs);
  1065. if (psFonts != null) {
  1066. for (int i = 0; i < acs.length; i++){
  1067. CharsetString cs = acs[i];
  1068. CharsetEncoder fontCS = cs.fontDescriptor.encoder;
  1069. StringBuffer nativeStr = new StringBuffer();
  1070. byte[] strSeg = new byte[cs.length * 2];
  1071. int len = 0;
  1072. try {
  1073. ByteBuffer bb = ByteBuffer.wrap(strSeg);
  1074. fontCS.encode(CharBuffer.wrap(cs.charsetChars,
  1075. cs.offset,
  1076. cs.length),
  1077. bb, true);
  1078. bb.flip();
  1079. len = bb.limit();
  1080. } catch(IllegalStateException xx){
  1081. continue;
  1082. } catch(CoderMalfunctionError xx){
  1083. continue;
  1084. }
  1085. /* The width to fit to may either be specified,
  1086. * or calculated. Specifying by the caller is only
  1087. * valid if the text does not need to be decomposed
  1088. * into multiple calls.
  1089. */
  1090. float desiredWidth;
  1091. if (acs.length == 1 && width != 0f) {
  1092. desiredWidth = width;
  1093. } else {
  1094. Rectangle2D r2d =
  1095. mLastFont.getStringBounds(cs.charsetChars,
  1096. cs.offset,
  1097. cs.offset+cs.length,
  1098. frc);
  1099. desiredWidth = (float)r2d.getWidth();
  1100. }
  1101. /* unprintable chars had width of 0, causing a PS error
  1102. */
  1103. if (desiredWidth == 0) {
  1104. return didText;
  1105. }
  1106. nativeStr.append('<');
  1107. for (int j = 0; j < len; j++){
  1108. byte b = strSeg[j];
  1109. // to avoid encoding conversion with println()
  1110. String hexS = Integer.toHexString(b);
  1111. int length = hexS.length();
  1112. if (length > 2) {
  1113. hexS = hexS.substring(length - 2, length);
  1114. } else if (length == 1) {
  1115. hexS = "0" + hexS;
  1116. } else if (length == 0) {
  1117. hexS = "00";
  1118. }
  1119. nativeStr.append(hexS);
  1120. }
  1121. nativeStr.append('>');
  1122. /* This comment costs too much in output file size */
  1123. // mPSStream.println("% Font[" + mLastFont.getName() + ", " +
  1124. // FontConfiguration.getStyleString(mLastFont.getStyle()) + ", "
  1125. // + mLastFont.getSize2D() + "]");
  1126. getGState().emitPSFont(psFonts[i], mLastFont.getSize2D());
  1127. // out String
  1128. mPSStream.println(nativeStr.toString() + " " +
  1129. desiredWidth + " " + x + " " + y + " " +
  1130. DrawStringName);
  1131. x += desiredWidth;
  1132. }
  1133. } else {
  1134. didText = false;
  1135. }
  1136. }
  1137. return didText;
  1138. }
  1139. /**
  1140. * Set the current path rule to be either
  1141. * <code>FILL_EVEN_ODD</code> (using the
  1142. * even-odd file rule) or <code>FILL_WINDING</code>
  1143. * (using the non-zero winding rule.)
  1144. */
  1145. protected void setFillMode(int fillRule) {
  1146. switch (fillRule) {
  1147. case FILL_EVEN_ODD:
  1148. mFillOpStr = EVEN_ODD_FILL_STR;
  1149. mClipOpStr = EVEN_ODD_CLIP_STR;
  1150. break;
  1151. case FILL_WINDING:
  1152. mFillOpStr = WINDING_FILL_STR;
  1153. mClipOpStr = WINDING_CLIP_STR;
  1154. break;
  1155. default:
  1156. throw new IllegalArgumentException();
  1157. }
  1158. }
  1159. /**
  1160. * Set the printer's current color to be that
  1161. * defined by <code>color</code>
  1162. */
  1163. protected void setColor(Color color) {
  1164. mLastColor = color;
  1165. }
  1166. /**
  1167. * Fill the current path using the current fill mode
  1168. * and color.
  1169. */
  1170. protected void fillPath() {
  1171. mPSStream.println(mFillOpStr);
  1172. }
  1173. /**
  1174. * Called to mark the start of a new path.
  1175. */
  1176. protected void beginPath() {
  1177. prepDrawing();
  1178. mPSStream.println(NEWPATH_STR);
  1179. mPenX = 0;
  1180. mPenY = 0;
  1181. }
  1182. /**
  1183. * Close the current subpath by appending a straight
  1184. * line from the current point to the subpath's
  1185. * starting point.
  1186. */
  1187. protected void closeSubpath() {
  1188. mPSStream.println(CLOSEPATH_STR);
  1189. mPenX = mStartPathX;
  1190. mPenY = mStartPathY;
  1191. }
  1192. /**
  1193. * Generate PostScript to move the current pen
  1194. * position to <code>(x, y)</code>.
  1195. */
  1196. protected void moveTo(float x, float y) {
  1197. mPSStream.println(trunc(x) + " " + trunc(y) + MOVETO_STR);
  1198. /* moveto marks the start of a new subpath
  1199. * and we need to remember that starting
  1200. * position so that we know where the
  1201. * pen returns to with a close path.
  1202. */
  1203. mStartPathX = x;
  1204. mStartPathY = y;
  1205. mPenX = x;
  1206. mPenY = y;
  1207. }
  1208. /**
  1209. * Generate PostScript to draw a line from the
  1210. * current pen position to <code>(x, y)</code>.
  1211. */
  1212. protected void lineTo(float x, float

Large files files are truncated, but you can click here to view the full file