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.

PSGraphics2D.java 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  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. import org.apache.fop.pdf.*;
  9. import org.apache.fop.layout.*;
  10. import org.apache.fop.fonts.*;
  11. import org.apache.fop.render.pdf.*;
  12. import org.apache.fop.image.*;
  13. import org.apache.fop.datatypes.ColorSpace;
  14. import org.apache.batik.ext.awt.g2d.*;
  15. import java.text.AttributedCharacterIterator;
  16. import java.text.CharacterIterator;
  17. import java.awt.*;
  18. import java.awt.Font;
  19. import java.awt.Image;
  20. import java.awt.image.*;
  21. import java.awt.font.*;
  22. import java.awt.geom.*;
  23. import java.awt.image.renderable.*;
  24. import java.io.*;
  25. import java.util.Map;
  26. import java.util.Vector;
  27. /**
  28. * This concrete implementation of <tt>AbstractGraphics2D</tt> is a
  29. * simple help to programmers to get started with their own
  30. * implementation of <tt>Graphics2D</tt>.
  31. * <tt>DefaultGraphics2D</tt> implements all the abstract methods
  32. * is <tt>AbstractGraphics2D</tt> and makes it easy to start
  33. * implementing a <tt>Graphic2D</tt> piece-meal.
  34. *
  35. * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
  36. * @version $Id$
  37. * @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
  38. */
  39. public class PSGraphics2D extends AbstractGraphics2D {
  40. boolean standalone = false;
  41. /**
  42. * the PDF Document being created
  43. */
  44. protected PSRenderer psRenderer;
  45. protected FontState fontState;
  46. /**
  47. * the current (internal) font name
  48. */
  49. protected String currentFontName;
  50. /**
  51. * the current font size in millipoints
  52. */
  53. protected int currentFontSize;
  54. /**
  55. * the current vertical position in millipoints from bottom
  56. */
  57. protected int currentYPosition = 0;
  58. /**
  59. * the current horizontal position in millipoints from left
  60. */
  61. protected int currentXPosition = 0;
  62. /**
  63. * the current colour for use in svg
  64. */
  65. PDFColor currentColour = new PDFColor(0, 0, 0);
  66. FontInfo fontInfo;
  67. /**
  68. * Create a new PDFGraphics2D with the given pdf document info.
  69. * This is used to create a Graphics object for use inside an already
  70. * existing document.
  71. */
  72. public PSGraphics2D(boolean textAsShapes, FontState fs, PSRenderer ren,
  73. String font, int size, int xpos, int ypos) {
  74. super(textAsShapes);
  75. psRenderer = ren;
  76. currentFontName = font;
  77. currentFontSize = size;
  78. currentYPosition = ypos;
  79. currentXPosition = xpos;
  80. fontState = fs;
  81. }
  82. public PSGraphics2D(boolean textAsShapes) {
  83. super(textAsShapes);
  84. }
  85. public void setGraphicContext(GraphicContext c) {
  86. gc = c;
  87. }
  88. /**
  89. * This constructor supports the create method
  90. */
  91. public PSGraphics2D(PSGraphics2D g) {
  92. super(g);
  93. }
  94. /**
  95. * Creates a new <code>Graphics</code> object that is
  96. * a copy of this <code>Graphics</code> object.
  97. * @return a new graphics context that is a copy of
  98. * this graphics context.
  99. */
  100. public Graphics create() {
  101. return new PSGraphics2D(this);
  102. }
  103. /**
  104. * Draws as much of the specified image as is currently available.
  105. * The image is drawn with its top-left corner at
  106. * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
  107. * space. Transparent pixels in the image do not affect whatever
  108. * pixels are already there.
  109. * <p>
  110. * This method returns immediately in all cases, even if the
  111. * complete image has not yet been loaded, and it has not been dithered
  112. * and converted for the current output device.
  113. * <p>
  114. * If the image has not yet been completely loaded, then
  115. * <code>drawImage</code> returns <code>false</code>. As more of
  116. * the image becomes available, the process that draws the image notifies
  117. * the specified image observer.
  118. * @param img the specified image to be drawn.
  119. * @param x the <i>x</i> coordinate.
  120. * @param y the <i>y</i> coordinate.
  121. * @param observer object to be notified as more of
  122. * the image is converted.
  123. * @see java.awt.Image
  124. * @see java.awt.image.ImageObserver
  125. * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
  126. */
  127. public boolean drawImage(Image img, int x, int y,
  128. ImageObserver observer) {
  129. // System.err.println("drawImage:x, y");
  130. final int width = img.getWidth(observer);
  131. final int height = img.getHeight(observer);
  132. if (width == -1 || height == -1) {
  133. return false;
  134. }
  135. Dimension size = new Dimension(width, height);
  136. BufferedImage buf = buildBufferedImage(size);
  137. java.awt.Graphics2D g = buf.createGraphics();
  138. g.setComposite(AlphaComposite.SrcOver);
  139. g.setBackground(new Color(1, 1, 1, 0));
  140. g.setPaint(new Color(1, 1, 1, 0));
  141. g.fillRect(0, 0, width, height);
  142. g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
  143. if (!g.drawImage(img, 0, 0, observer)) {
  144. return false;
  145. }
  146. g.dispose();
  147. final byte[] result = new byte[buf.getWidth() * buf.getHeight() * 3];
  148. final byte[] mask = new byte[buf.getWidth() * buf.getHeight()];
  149. Raster raster = buf.getData();
  150. DataBuffer bd = raster.getDataBuffer();
  151. int count = 0;
  152. int maskpos = 0;
  153. switch (bd.getDataType()) {
  154. case DataBuffer.TYPE_INT:
  155. int[][] idata = ((DataBufferInt)bd).getBankData();
  156. for (int i = 0; i < idata.length; i++) {
  157. for (int j = 0; j < idata[i].length; j++) {
  158. // mask[maskpos++] = (byte)((idata[i][j] >> 24) & 0xFF);
  159. if (((idata[i][j] >> 24) & 0xFF) != 255) {
  160. result[count++] = (byte)0xFF;
  161. result[count++] = (byte)0xFF;
  162. result[count++] = (byte)0xFF;
  163. } else {
  164. result[count++] = (byte)((idata[i][j] >> 16) & 0xFF);
  165. result[count++] = (byte)((idata[i][j] >> 8) & 0xFF);
  166. result[count++] = (byte)((idata[i][j]) & 0xFF);
  167. }
  168. }
  169. }
  170. break;
  171. default:
  172. // error
  173. break;
  174. }
  175. try {
  176. FopImage fopimg = new TempImage(width, height, result, mask);
  177. AffineTransform at = getTransform();
  178. double[] matrix = new double[6];
  179. at.getMatrix(matrix);
  180. psRenderer.write("gsave");
  181. Shape imclip = getClip();
  182. writeClip(imclip);
  183. // psRenderer.write("" + matrix[0] + " " + matrix[1] +
  184. // " " + matrix[2] + " " + matrix[3] + " " +
  185. // matrix[4] + " " + matrix[5] + " cm\n");
  186. //psRenderer.renderBitmap(fopimg, x, y, width, height);
  187. psRenderer.write("grestore");
  188. } catch (Exception e) {
  189. e.printStackTrace();
  190. }
  191. return true;
  192. }
  193. public BufferedImage buildBufferedImage(Dimension size) {
  194. return new BufferedImage(size.width, size.height,
  195. BufferedImage.TYPE_INT_ARGB);
  196. }
  197. class TempImage implements FopImage {
  198. int m_height;
  199. int m_width;
  200. int m_bitsPerPixel;
  201. ColorSpace m_colorSpace;
  202. int m_bitmapSiye;
  203. byte[] m_bitmaps;
  204. byte[] m_mask;
  205. PDFColor transparent = new PDFColor(255, 255, 255);
  206. TempImage(int width, int height, byte[] result,
  207. byte[] mask) throws FopImageException {
  208. this.m_height = height;
  209. this.m_width = width;
  210. this.m_bitsPerPixel = 8;
  211. this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
  212. // this.m_isTransparent = false;
  213. // this.m_bitmapsSize = this.m_width * this.m_height * 3;
  214. this.m_bitmaps = result;
  215. this.m_mask = mask;
  216. }
  217. public String getURL() {
  218. return "" + m_bitmaps;
  219. }
  220. // image size
  221. public int getWidth() throws FopImageException {
  222. return m_width;
  223. }
  224. public int getHeight() throws FopImageException {
  225. return m_height;
  226. }
  227. // DeviceGray, DeviceRGB, or DeviceCMYK
  228. public ColorSpace getColorSpace() throws FopImageException {
  229. return m_colorSpace;
  230. }
  231. // bits per pixel
  232. public int getBitsPerPixel() throws FopImageException {
  233. return m_bitsPerPixel;
  234. }
  235. // For transparent images
  236. public boolean isTransparent() throws FopImageException {
  237. return transparent != null;
  238. }
  239. public PDFColor getTransparentColor() throws FopImageException {
  240. return transparent;
  241. }
  242. public byte[] getMask() throws FopImageException {
  243. return m_mask;
  244. }
  245. // get the image bytes, and bytes properties
  246. // get uncompressed image bytes
  247. public byte[] getBitmaps() throws FopImageException {
  248. return m_bitmaps;
  249. }
  250. // width * (bitsPerPixel / 8) * height, no ?
  251. public int getBitmapsSize() throws FopImageException {
  252. return m_width * m_height * 3;
  253. }
  254. // get compressed image bytes
  255. // I don't know if we really need it, nor if it
  256. // should be changed...
  257. public byte[] getRessourceBytes() throws FopImageException {
  258. return null;
  259. }
  260. public int getRessourceBytesSize() throws FopImageException {
  261. return 0;
  262. }
  263. // return null if no corresponding PDFFilter
  264. public PDFFilter getPDFFilter() throws FopImageException {
  265. return null;
  266. }
  267. // release memory
  268. public void close() {}
  269. }
  270. /**
  271. * Draws as much of the specified image as has already been scaled
  272. * to fit inside the specified rectangle.
  273. * <p>
  274. * The image is drawn inside the specified rectangle of this
  275. * graphics context's coordinate space, and is scaled if
  276. * necessary. Transparent pixels do not affect whatever pixels
  277. * are already there.
  278. * <p>
  279. * This method returns immediately in all cases, even if the
  280. * entire image has not yet been scaled, dithered, and converted
  281. * for the current output device.
  282. * If the current output representation is not yet complete, then
  283. * <code>drawImage</code> returns <code>false</code>. As more of
  284. * the image becomes available, the process that draws the image notifies
  285. * the image observer by calling its <code>imageUpdate</code> method.
  286. * <p>
  287. * A scaled version of an image will not necessarily be
  288. * available immediately just because an unscaled version of the
  289. * image has been constructed for this output device. Each size of
  290. * the image may be cached separately and generated from the original
  291. * data in a separate image production sequence.
  292. * @param img the specified image to be drawn.
  293. * @param x the <i>x</i> coordinate.
  294. * @param y the <i>y</i> coordinate.
  295. * @param width the width of the rectangle.
  296. * @param height the height of the rectangle.
  297. * @param observer object to be notified as more of
  298. * the image is converted.
  299. * @see java.awt.Image
  300. * @see java.awt.image.ImageObserver
  301. * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
  302. */
  303. public boolean drawImage(Image img, int x, int y, int width, int height,
  304. ImageObserver observer) {
  305. System.out.println("drawImage");
  306. return true;
  307. }
  308. /**
  309. * Disposes of this graphics context and releases
  310. * any system resources that it is using.
  311. * A <code>Graphics</code> object cannot be used after
  312. * <code>dispose</code>has been called.
  313. * <p>
  314. * When a Java program runs, a large number of <code>Graphics</code>
  315. * objects can be created within a short time frame.
  316. * Although the finalization process of the garbage collector
  317. * also disposes of the same system resources, it is preferable
  318. * to manually free the associated resources by calling this
  319. * method rather than to rely on a finalization process which
  320. * may not run to completion for a long period of time.
  321. * <p>
  322. * Graphics objects which are provided as arguments to the
  323. * <code>paint</code> and <code>update</code> methods
  324. * of components are automatically released by the system when
  325. * those methods return. For efficiency, programmers should
  326. * call <code>dispose</code> when finished using
  327. * a <code>Graphics</code> object only if it was created
  328. * directly from a component or another <code>Graphics</code> object.
  329. * @see java.awt.Graphics#finalize
  330. * @see java.awt.Component#paint
  331. * @see java.awt.Component#update
  332. * @see java.awt.Component#getGraphics
  333. * @see java.awt.Graphics#create
  334. */
  335. public void dispose() {
  336. // System.out.println("dispose");
  337. psRenderer = null;
  338. fontState = null;
  339. currentFontName = null;
  340. currentColour = null;
  341. fontInfo = null;
  342. }
  343. /**
  344. * Strokes the outline of a <code>Shape</code> using the settings of the
  345. * current <code>Graphics2D</code> context. The rendering attributes
  346. * applied include the <code>Clip</code>, <code>Transform</code>,
  347. * <code>Paint</code>, <code>Composite</code> and
  348. * <code>Stroke</code> attributes.
  349. * @param s the <code>Shape</code> to be rendered
  350. * @see #setStroke
  351. * @see #setPaint
  352. * @see java.awt.Graphics#setColor
  353. * @see #transform
  354. * @see #setTransform
  355. * @see #clip
  356. * @see #setClip
  357. * @see #setComposite
  358. */
  359. public void draw(Shape s) {
  360. // System.out.println("draw(Shape)");
  361. psRenderer.write("gsave");
  362. Shape imclip = getClip();
  363. writeClip(imclip);
  364. Color c = getColor();
  365. psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
  366. + " setrgbcolor");
  367. applyPaint(getPaint(), false);
  368. applyStroke(getStroke());
  369. psRenderer.write("newpath");
  370. PathIterator iter = s.getPathIterator(getTransform());
  371. while (!iter.isDone()) {
  372. double vals[] = new double[6];
  373. int type = iter.currentSegment(vals);
  374. switch (type) {
  375. case PathIterator.SEG_CUBICTO:
  376. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  377. + PDFNumber.doubleOut(1000 * vals[1]) + " "
  378. + PDFNumber.doubleOut(1000 * vals[2]) + " "
  379. + PDFNumber.doubleOut(1000 * vals[3]) + " "
  380. + PDFNumber.doubleOut(1000 * vals[4]) + " "
  381. + PDFNumber.doubleOut(1000 * vals[5])
  382. + " curveto");
  383. break;
  384. case PathIterator.SEG_LINETO:
  385. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  386. + PDFNumber.doubleOut(1000 * vals[1])
  387. + " lineto");
  388. break;
  389. case PathIterator.SEG_MOVETO:
  390. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  391. + PDFNumber.doubleOut(1000 * vals[1])
  392. + " M");
  393. break;
  394. case PathIterator.SEG_QUADTO:
  395. // psRenderer.write((1000 * PDFNumber.doubleOut(vals[0])) +
  396. // " " + (1000 * PDFNumber.doubleOut(vals[1])) + " " +
  397. // (1000 * PDFNumber.doubleOut(vals[2])) + " " +
  398. // (1000 * PDFNumber.doubleOut(vals[3])) + " y\n");
  399. break;
  400. case PathIterator.SEG_CLOSE:
  401. psRenderer.write("closepath");
  402. break;
  403. default:
  404. break;
  405. }
  406. iter.next();
  407. }
  408. doDrawing(false, true, false);
  409. psRenderer.write("grestore");
  410. }
  411. protected void writeClip(Shape s) {
  412. PathIterator iter = s.getPathIterator(getTransform());
  413. psRenderer.write("newpath");
  414. while (!iter.isDone()) {
  415. double vals[] = new double[6];
  416. int type = iter.currentSegment(vals);
  417. switch (type) {
  418. case PathIterator.SEG_CUBICTO:
  419. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  420. + PDFNumber.doubleOut(1000 * vals[1]) + " "
  421. + PDFNumber.doubleOut(1000 * vals[2]) + " "
  422. + PDFNumber.doubleOut(1000 * vals[3]) + " "
  423. + PDFNumber.doubleOut(1000 * vals[4]) + " "
  424. + PDFNumber.doubleOut(1000 * vals[5])
  425. + " curveto");
  426. break;
  427. case PathIterator.SEG_LINETO:
  428. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  429. + PDFNumber.doubleOut(1000 * vals[1])
  430. + " lineto");
  431. break;
  432. case PathIterator.SEG_MOVETO:
  433. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  434. + PDFNumber.doubleOut(1000 * vals[1])
  435. + " M");
  436. break;
  437. case PathIterator.SEG_QUADTO:
  438. // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
  439. // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
  440. // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
  441. // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
  442. break;
  443. case PathIterator.SEG_CLOSE:
  444. psRenderer.write("closepath");
  445. break;
  446. default:
  447. break;
  448. }
  449. iter.next();
  450. }
  451. // clip area
  452. psRenderer.write("clippath");
  453. }
  454. protected void applyPaint(Paint paint, boolean fill) {
  455. if (paint instanceof GradientPaint) {
  456. GradientPaint gp = (GradientPaint)paint;
  457. Color c1 = gp.getColor1();
  458. Color c2 = gp.getColor2();
  459. Point2D p1 = gp.getPoint1();
  460. Point2D p2 = gp.getPoint2();
  461. boolean cyclic = gp.isCyclic();
  462. Vector theCoords = new Vector();
  463. theCoords.addElement(new Double(p1.getX()));
  464. theCoords.addElement(new Double(p1.getY()));
  465. theCoords.addElement(new Double(p2.getX()));
  466. theCoords.addElement(new Double(p2.getY()));
  467. Vector theExtend = new Vector();
  468. theExtend.addElement(new Boolean(true));
  469. theExtend.addElement(new Boolean(true));
  470. Vector theDomain = new Vector();
  471. theDomain.addElement(new Double(0));
  472. theDomain.addElement(new Double(1));
  473. Vector theEncode = new Vector();
  474. theEncode.addElement(new Double(0));
  475. theEncode.addElement(new Double(1));
  476. theEncode.addElement(new Double(0));
  477. theEncode.addElement(new Double(1));
  478. Vector theBounds = new Vector();
  479. theBounds.addElement(new Double(0));
  480. theBounds.addElement(new Double(1));
  481. Vector theFunctions = new Vector();
  482. Vector someColors = new Vector();
  483. PDFColor color1 = new PDFColor(c1.getRed(), c1.getGreen(),
  484. c1.getBlue());
  485. someColors.addElement(color1);
  486. PDFColor color2 = new PDFColor(c2.getRed(), c2.getGreen(),
  487. c2.getBlue());
  488. someColors.addElement(color2);
  489. ColorSpace aColorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
  490. } else if (paint instanceof TexturePaint) {}
  491. }
  492. protected void applyStroke(Stroke stroke) {
  493. if (stroke instanceof BasicStroke) {
  494. BasicStroke bs = (BasicStroke)stroke;
  495. float[] da = bs.getDashArray();
  496. if (da != null) {
  497. psRenderer.write("[");
  498. for (int count = 0; count < da.length; count++) {
  499. psRenderer.write("" + (1000 * (int)da[count]));
  500. if (count < da.length - 1) {
  501. psRenderer.write(" ");
  502. }
  503. }
  504. psRenderer.write("] ");
  505. float offset = bs.getDashPhase();
  506. psRenderer.write((1000 * (int)offset) + " setdash");
  507. }
  508. int ec = bs.getEndCap();
  509. switch (ec) {
  510. case BasicStroke.CAP_BUTT:
  511. psRenderer.write(0 + " setlinecap");
  512. break;
  513. case BasicStroke.CAP_ROUND:
  514. psRenderer.write(1 + " setlinecap");
  515. break;
  516. case BasicStroke.CAP_SQUARE:
  517. psRenderer.write(2 + " setlinecap");
  518. break;
  519. }
  520. int lj = bs.getLineJoin();
  521. switch (lj) {
  522. case BasicStroke.JOIN_MITER:
  523. psRenderer.write(0 + " setlinejoin");
  524. break;
  525. case BasicStroke.JOIN_ROUND:
  526. psRenderer.write(1 + " setlinejoin");
  527. break;
  528. case BasicStroke.JOIN_BEVEL:
  529. psRenderer.write(2 + " setlinejoin");
  530. break;
  531. }
  532. float lw = bs.getLineWidth();
  533. psRenderer.write(PDFNumber.doubleOut(1000 * lw)
  534. + " setlinewidth");
  535. float ml = bs.getMiterLimit();
  536. psRenderer.write(PDFNumber.doubleOut(1000 * ml)
  537. + " setmiterlimit");
  538. }
  539. }
  540. /**
  541. * Renders a {@link RenderedImage},
  542. * applying a transform from image
  543. * space into user space before drawing.
  544. * The transformation from user space into device space is done with
  545. * the current <code>Transform</code> in the <code>Graphics2D</code>.
  546. * The specified transformation is applied to the image before the
  547. * transform attribute in the <code>Graphics2D</code> context is applied.
  548. * The rendering attributes applied include the <code>Clip</code>,
  549. * <code>Transform</code>, and <code>Composite</code> attributes. Note
  550. * that no rendering is done if the specified transform is
  551. * noninvertible.
  552. * @param img the image to be rendered
  553. * @param xform the transformation from image space into user space
  554. * @see #transform
  555. * @see #setTransform
  556. * @see #setComposite
  557. * @see #clip
  558. * @see #setClip
  559. */
  560. public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
  561. System.out.println("drawRenderedImage");
  562. }
  563. /**
  564. * Renders a
  565. * {@link RenderableImage},
  566. * applying a transform from image space into user space before drawing.
  567. * The transformation from user space into device space is done with
  568. * the current <code>Transform</code> in the <code>Graphics2D</code>.
  569. * The specified transformation is applied to the image before the
  570. * transform attribute in the <code>Graphics2D</code> context is applied.
  571. * The rendering attributes applied include the <code>Clip</code>,
  572. * <code>Transform</code>, and <code>Composite</code> attributes. Note
  573. * that no rendering is done if the specified transform is
  574. * noninvertible.
  575. * <p>
  576. * Rendering hints set on the <code>Graphics2D</code> object might
  577. * be used in rendering the <code>RenderableImage</code>.
  578. * If explicit control is required over specific hints recognized by a
  579. * specific <code>RenderableImage</code>, or if knowledge of which hints
  580. * are used is required, then a <code>RenderedImage</code> should be
  581. * obtained directly from the <code>RenderableImage</code>
  582. * and rendered using
  583. * {@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}.
  584. * @param img the image to be rendered
  585. * @param xform the transformation from image space into user space
  586. * @see #transform
  587. * @see #setTransform
  588. * @see #setComposite
  589. * @see #clip
  590. * @see #setClip
  591. * @see #drawRenderedImage
  592. */
  593. public void drawRenderableImage(RenderableImage img,
  594. AffineTransform xform) {
  595. System.out.println("drawRenderableImage");
  596. }
  597. /**
  598. * Renders the text specified by the specified <code>String</code>,
  599. * using the current <code>Font</code> and <code>Paint</code> attributes
  600. * in the <code>Graphics2D</code> context.
  601. * The baseline of the first character is at position
  602. * (<i>x</i>,&nbsp;<i>y</i>) in the User Space.
  603. * The rendering attributes applied include the <code>Clip</code>,
  604. * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
  605. * <code>Composite</code> attributes. For characters in script systems
  606. * such as Hebrew and Arabic, the glyphs can be rendered from right to
  607. * left, in which case the coordinate supplied is the location of the
  608. * leftmost character on the baseline.
  609. * @param s the <code>String</code> to be rendered
  610. * @param x,&nbsp;y the coordinates where the <code>String</code>
  611. * should be rendered
  612. * @see #setPaint
  613. * @see java.awt.Graphics#setColor
  614. * @see java.awt.Graphics#setFont
  615. * @see #setTransform
  616. * @see #setComposite
  617. * @see #setClip
  618. */
  619. public void drawString(String s, float x, float y) {
  620. System.out.println("drawString(String)");
  621. psRenderer.write("BT");
  622. Shape imclip = getClip();
  623. writeClip(imclip);
  624. Color c = getColor();
  625. psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
  626. + " setrgbcolor");
  627. AffineTransform trans = getTransform();
  628. trans.translate(x, y);
  629. double[] vals = new double[6];
  630. trans.getMatrix(vals);
  631. psRenderer.write(PDFNumber.doubleOut(vals[0]) + " "
  632. + PDFNumber.doubleOut(vals[1]) + " "
  633. + PDFNumber.doubleOut(vals[2]) + " "
  634. + PDFNumber.doubleOut(vals[3]) + " "
  635. + PDFNumber.doubleOut(vals[4]) + " "
  636. + PDFNumber.doubleOut(vals[5]) + " "
  637. + PDFNumber.doubleOut(vals[6]) + " Tm [" + s + "]");
  638. psRenderer.write("ET");
  639. }
  640. /**
  641. * Renders the text of the specified iterator, using the
  642. * <code>Graphics2D</code> context's current <code>Paint</code>. The
  643. * iterator must specify a font
  644. * for each character. The baseline of the
  645. * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in the
  646. * User Space.
  647. * The rendering attributes applied include the <code>Clip</code>,
  648. * <code>Transform</code>, <code>Paint</code>, and
  649. * <code>Composite</code> attributes.
  650. * For characters in script systems such as Hebrew and Arabic,
  651. * the glyphs can be rendered from right to left, in which case the
  652. * coordinate supplied is the location of the leftmost character
  653. * on the baseline.
  654. * @param iterator the iterator whose text is to be rendered
  655. * @param x,&nbsp;y the coordinates where the iterator's text is to be
  656. * rendered
  657. * @see #setPaint
  658. * @see java.awt.Graphics#setColor
  659. * @see #setTransform
  660. * @see #setComposite
  661. * @see #setClip
  662. */
  663. public void drawString(AttributedCharacterIterator iterator, float x,
  664. float y) {
  665. System.err.println("drawString(AttributedCharacterIterator)");
  666. psRenderer.write("BT");
  667. Shape imclip = getClip();
  668. writeClip(imclip);
  669. Color c = getColor();
  670. currentColour = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
  671. psRenderer.write(currentColour.getColorSpaceOut(true));
  672. c = getBackground();
  673. PDFColor col = new PDFColor(c.getRed(), c.getGreen(), c.getBlue());
  674. psRenderer.write(col.getColorSpaceOut(false));
  675. AffineTransform trans = getTransform();
  676. trans.translate(x, y);
  677. double[] vals = new double[6];
  678. trans.getMatrix(vals);
  679. for (char ch = iterator.first(); ch != CharacterIterator.DONE;
  680. ch = iterator.next()) {
  681. Map attr = iterator.getAttributes();
  682. psRenderer.write(PDFNumber.doubleOut(vals[0]) + " "
  683. + PDFNumber.doubleOut(vals[1]) + " "
  684. + PDFNumber.doubleOut(vals[2]) + " "
  685. + PDFNumber.doubleOut(vals[3]) + " "
  686. + PDFNumber.doubleOut(vals[4]) + " "
  687. + PDFNumber.doubleOut(vals[5]) + " "
  688. + PDFNumber.doubleOut(vals[6]) + " Tm [" + ch
  689. + "]");
  690. }
  691. psRenderer.write("ET");
  692. }
  693. /**
  694. * Fills the interior of a <code>Shape</code> using the settings of the
  695. * <code>Graphics2D</code> context. The rendering attributes applied
  696. * include the <code>Clip</code>, <code>Transform</code>,
  697. * <code>Paint</code>, and <code>Composite</code>.
  698. * @param s the <code>Shape</code> to be filled
  699. * @see #setPaint
  700. * @see java.awt.Graphics#setColor
  701. * @see #transform
  702. * @see #setTransform
  703. * @see #setComposite
  704. * @see #clip
  705. * @see #setClip
  706. */
  707. public void fill(Shape s) {
  708. // System.err.println("fill");
  709. psRenderer.write("gsave");
  710. Shape imclip = getClip();
  711. writeClip(imclip);
  712. Color c = getColor();
  713. psRenderer.write(c.getRed() + " " + c.getGreen() + " " + c.getBlue()
  714. + " setrgbcolor");
  715. applyPaint(getPaint(), true);
  716. psRenderer.write("newpath");
  717. PathIterator iter = s.getPathIterator(getTransform());
  718. while (!iter.isDone()) {
  719. double vals[] = new double[6];
  720. int type = iter.currentSegment(vals);
  721. switch (type) {
  722. case PathIterator.SEG_CUBICTO:
  723. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  724. + PDFNumber.doubleOut(1000 * vals[1]) + " "
  725. + PDFNumber.doubleOut(1000 * vals[2]) + " "
  726. + PDFNumber.doubleOut(1000 * vals[3]) + " "
  727. + PDFNumber.doubleOut(1000 * vals[4]) + " "
  728. + PDFNumber.doubleOut(1000 * vals[5])
  729. + " curveto");
  730. break;
  731. case PathIterator.SEG_LINETO:
  732. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  733. + PDFNumber.doubleOut(1000 * vals[1])
  734. + " lineto");
  735. break;
  736. case PathIterator.SEG_MOVETO:
  737. psRenderer.write(PDFNumber.doubleOut(1000 * vals[0]) + " "
  738. + PDFNumber.doubleOut(1000 * vals[1])
  739. + " M");
  740. break;
  741. case PathIterator.SEG_QUADTO:
  742. // psRenderer.write(1000 * PDFNumber.doubleOut(vals[0]) +
  743. // " " + 1000 * PDFNumber.doubleOut(vals[1]) + " " +
  744. // 1000 * PDFNumber.doubleOut(vals[2]) + " " +
  745. // 1000 * PDFNumber.doubleOut(vals[3]) + " y\n");
  746. break;
  747. case PathIterator.SEG_CLOSE:
  748. psRenderer.write("closepath");
  749. break;
  750. default:
  751. break;
  752. }
  753. iter.next();
  754. }
  755. doDrawing(true, false,
  756. iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
  757. psRenderer.write("grestore");
  758. }
  759. protected void doDrawing(boolean fill, boolean stroke, boolean nonzero) {
  760. if (fill) {
  761. if (stroke) {
  762. if (!nonzero)
  763. psRenderer.write("stroke");
  764. else
  765. psRenderer.write("stroke");
  766. } else {
  767. if (!nonzero)
  768. psRenderer.write("fill");
  769. else
  770. psRenderer.write("fill");
  771. }
  772. } else {
  773. // if(stroke)
  774. psRenderer.write("stroke");
  775. }
  776. }
  777. /**
  778. * Returns the device configuration associated with this
  779. * <code>Graphics2D</code>.
  780. */
  781. public GraphicsConfiguration getDeviceConfiguration() {
  782. // System.out.println("getDeviceConviguration");
  783. return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
  784. }
  785. /**
  786. * Used to create proper font metrics
  787. */
  788. private Graphics2D fmg;
  789. {
  790. BufferedImage bi = new BufferedImage(1, 1,
  791. BufferedImage.TYPE_INT_ARGB);
  792. fmg = bi.createGraphics();
  793. }
  794. /**
  795. * Gets the font metrics for the specified font.
  796. * @return the font metrics for the specified font.
  797. * @param f the specified font
  798. * @see java.awt.Graphics#getFont
  799. * @see java.awt.FontMetrics
  800. * @see java.awt.Graphics#getFontMetrics()
  801. */
  802. public FontMetrics getFontMetrics(Font f) {
  803. return fmg.getFontMetrics(f);
  804. }
  805. /**
  806. * Sets the paint mode of this graphics context to alternate between
  807. * this graphics context's current color and the new specified color.
  808. * This specifies that logical pixel operations are performed in the
  809. * XOR mode, which alternates pixels between the current color and
  810. * a specified XOR color.
  811. * <p>
  812. * When drawing operations are performed, pixels which are the
  813. * current color are changed to the specified color, and vice versa.
  814. * <p>
  815. * Pixels that are of colors other than those two colors are changed
  816. * in an unpredictable but reversible manner; if the same figure is
  817. * drawn twice, then all pixels are restored to their original values.
  818. * @param c1 the XOR alternation color
  819. */
  820. public void setXORMode(Color c1) {
  821. System.out.println("setXORMode");
  822. }
  823. /**
  824. * Copies an area of the component by a distance specified by
  825. * <code>dx</code> and <code>dy</code>. From the point specified
  826. * by <code>x</code> and <code>y</code>, this method
  827. * copies downwards and to the right. To copy an area of the
  828. * component to the left or upwards, specify a negative value for
  829. * <code>dx</code> or <code>dy</code>.
  830. * If a portion of the source rectangle lies outside the bounds
  831. * of the component, or is obscured by another window or component,
  832. * <code>copyArea</code> will be unable to copy the associated
  833. * pixels. The area that is omitted can be refreshed by calling
  834. * the component's <code>paint</code> method.
  835. * @param x the <i>x</i> coordinate of the source rectangle.
  836. * @param y the <i>y</i> coordinate of the source rectangle.
  837. * @param width the width of the source rectangle.
  838. * @param height the height of the source rectangle.
  839. * @param dx the horizontal distance to copy the pixels.
  840. * @param dy the vertical distance to copy the pixels.
  841. */
  842. public void copyArea(int x, int y, int width, int height, int dx,
  843. int dy) {
  844. System.out.println("copyArea");
  845. }
  846. }