001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: PSGraphics2D.java 548990 2007-06-20 08:28:52Z jeremias $ */
019:
020: package org.apache.xmlgraphics.java2d.ps;
021:
022: //Java
023: import java.awt.AlphaComposite;
024: import java.awt.BasicStroke;
025: import java.awt.Color;
026: import java.awt.Dimension; /* java.awt.Font is not imported to avoid confusion with
027: other classes called "Font" */
028: import java.awt.GradientPaint;
029: import java.awt.Graphics;
030: import java.awt.Graphics2D;
031: import java.awt.GraphicsConfiguration;
032: import java.awt.GraphicsEnvironment;
033: import java.awt.Image;
034: import java.awt.Paint;
035: import java.awt.Rectangle;
036: import java.awt.Shape;
037: import java.awt.Stroke;
038: import java.awt.TexturePaint;
039: import java.awt.color.ColorSpace;
040: import java.awt.geom.AffineTransform;
041: import java.awt.geom.PathIterator;
042: import java.awt.image.BufferedImage;
043: import java.awt.image.ImageObserver;
044: import java.awt.image.RenderedImage;
045: import java.awt.image.renderable.RenderableImage;
046: import java.io.IOException;
047:
048: import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
049: import org.apache.xmlgraphics.java2d.GraphicContext;
050: import org.apache.xmlgraphics.ps.PSGenerator;
051: import org.apache.xmlgraphics.ps.PSImageUtils;
052:
053: /**
054: * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and
055: * therefore of <tt>Graphics2D</tt>) which is able to generate PostScript
056: * code.
057: *
058: * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
059: * @version $Id: PSGraphics2D.java 548990 2007-06-20 08:28:52Z jeremias $
060: * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
061: */
062: public class PSGraphics2D extends AbstractGraphics2D {
063:
064: private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();
065:
066: private static final boolean DEBUG = false;
067:
068: /** the PostScript generator being created */
069: protected PSGenerator gen;
070:
071: private boolean clippingDisabled = false;
072:
073: /** Fallback text handler */
074: protected TextHandler fallbackTextHandler = new StrokingTextHandler(
075: this );
076:
077: /** Custom text handler */
078: protected TextHandler customTextHandler;
079:
080: /**
081: * the current colour for use in svg
082: */
083: protected Color currentColour = new Color(0, 0, 0);
084:
085: /**
086: * Create a new Graphics2D that generates PostScript code.
087: * @param textAsShapes True if text should be rendered as graphics
088: * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D#AbstractGraphics2D(boolean)
089: */
090: public PSGraphics2D(boolean textAsShapes) {
091: super (textAsShapes);
092: }
093:
094: /**
095: * Create a new Graphics2D that generates PostScript code.
096: * @param textAsShapes True if text should be rendered as graphics
097: * @param gen PostScript generator to use for output
098: * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D#AbstractGraphics2D(boolean)
099: */
100: public PSGraphics2D(boolean textAsShapes, PSGenerator gen) {
101: this (textAsShapes);
102: setPSGenerator(gen);
103: }
104:
105: /**
106: * Constructor for creating copies
107: * @param g parent PostScript Graphics2D
108: */
109: public PSGraphics2D(PSGraphics2D g) {
110: super (g);
111:
112: setPSGenerator(g.gen);
113: this .clippingDisabled = g.clippingDisabled;
114: this .fallbackTextHandler = g.fallbackTextHandler;
115: this .customTextHandler = g.customTextHandler;
116: this .currentColour = g.currentColour;
117: }
118:
119: /**
120: * Sets the PostScript generator
121: * @param gen the PostScript generator
122: */
123: public void setPSGenerator(PSGenerator gen) {
124: this .gen = gen;
125: }
126:
127: /** @return the PostScript generator used by this instance. */
128: public PSGenerator getPSGenerator() {
129: return this .gen;
130: }
131:
132: /**
133: * Sets the GraphicContext
134: * @param c GraphicContext to use
135: */
136: public void setGraphicContext(GraphicContext c) {
137: gc = c;
138: //setPrivateHints();
139: }
140:
141: /** @return the fallback TextHandler implementation */
142: public TextHandler getFallbackTextHandler() {
143: return this .fallbackTextHandler;
144: }
145:
146: /** @return the custom TextHandler implementation */
147: public TextHandler getCustomTextHandler() {
148: return this .customTextHandler;
149: }
150:
151: /**
152: * Sets a custom TextHandler implementation that is reponsible for painting text. The default
153: * TextHandler paints all text as shapes. A custom implementation can implement text painting
154: * using text painting operators.
155: * @param handler the custom TextHandler implementation
156: */
157: public void setCustomTextHandler(TextHandler handler) {
158: this .customTextHandler = handler;
159: }
160:
161: /* TODO Add me back at the right place!!!
162: private void setPrivateHints() {
163: setRenderingHint(RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING,
164: RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON);
165: }*/
166:
167: /**
168: * Creates a new <code>Graphics</code> object that is
169: * a copy of this <code>Graphics</code> object.
170: * @return a new graphics context that is a copy of
171: * this graphics context.
172: */
173: public Graphics create() {
174: return new PSGraphics2D(this );
175: }
176:
177: /**
178: * Central handler for IOExceptions for this class.
179: * @param ioe IOException to handle
180: */
181: public void handleIOException(IOException ioe) {
182: //TODO Surely, there's a better way to do this.
183: ioe.printStackTrace();
184: }
185:
186: /**
187: * This method is used by AbstractPSDocumentGraphics2D to prepare a new page if
188: * necessary.
189: */
190: public void preparePainting() {
191: //nop, used by AbstractPSDocumentGraphics2D
192: }
193:
194: /**
195: * Draws as much of the specified image as is currently available.
196: * The image is drawn with its top-left corner at
197: * (<i>x</i>, <i>y</i>) in this graphics context's coordinate
198: * space. Transparent pixels in the image do not affect whatever
199: * pixels are already there.
200: * <p>
201: * This method returns immediately in all cases, even if the
202: * complete image has not yet been loaded, and it has not been dithered
203: * and converted for the current output device.
204: * <p>
205: * If the image has not yet been completely loaded, then
206: * <code>drawImage</code> returns <code>false</code>. As more of
207: * the image becomes available, the process that draws the image notifies
208: * the specified image observer.
209: * @param img the specified image to be drawn.
210: * @param x the <i>x</i> coordinate.
211: * @param y the <i>y</i> coordinate.
212: * @param observer object to be notified as more of
213: * the image is converted.
214: * @return True if the image has been fully drawn/loaded
215: * @see java.awt.Image
216: * @see java.awt.image.ImageObserver
217: * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
218: */
219: public boolean drawImage(Image img, int x, int y,
220: ImageObserver observer) {
221: preparePainting();
222: if (DEBUG) {
223: System.out.println("drawImage: " + x + ", " + y + " "
224: + img.getClass().getName());
225: }
226:
227: final int width = img.getWidth(observer);
228: final int height = img.getHeight(observer);
229: if (width == -1 || height == -1) {
230: return false;
231: }
232:
233: Dimension size = new Dimension(width, height);
234: BufferedImage buf = buildBufferedImage(size);
235:
236: java.awt.Graphics2D g = buf.createGraphics();
237: g.setComposite(AlphaComposite.SrcOver);
238: g.setBackground(new Color(1, 1, 1, 0));
239: g.setPaint(new Color(1, 1, 1, 0));
240: g.fillRect(0, 0, width, height);
241: g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
242:
243: if (!g.drawImage(img, 0, 0, observer)) {
244: return false;
245: }
246: g.dispose();
247:
248: try {
249: AffineTransform at = getTransform();
250: gen.saveGraphicsState();
251: gen.concatMatrix(at);
252: Shape imclip = getClip();
253: writeClip(imclip);
254: PSImageUtils.renderBitmapImage(buf, x, y, width, height,
255: gen);
256: gen.restoreGraphicsState();
257: } catch (IOException ioe) {
258: handleIOException(ioe);
259: }
260:
261: return true;
262: }
263:
264: /**
265: * Creates a buffered image.
266: * @param size dimensions of the image to be created
267: * @return the buffered image
268: */
269: public BufferedImage buildBufferedImage(Dimension size) {
270: return new BufferedImage(size.width, size.height,
271: BufferedImage.TYPE_INT_ARGB);
272: }
273:
274: /**
275: * Draws as much of the specified image as has already been scaled
276: * to fit inside the specified rectangle.
277: * <p>
278: * The image is drawn inside the specified rectangle of this
279: * graphics context's coordinate space, and is scaled if
280: * necessary. Transparent pixels do not affect whatever pixels
281: * are already there.
282: * <p>
283: * This method returns immediately in all cases, even if the
284: * entire image has not yet been scaled, dithered, and converted
285: * for the current output device.
286: * If the current output representation is not yet complete, then
287: * <code>drawImage</code> returns <code>false</code>. As more of
288: * the image becomes available, the process that draws the image notifies
289: * the image observer by calling its <code>imageUpdate</code> method.
290: * <p>
291: * A scaled version of an image will not necessarily be
292: * available immediately just because an unscaled version of the
293: * image has been constructed for this output device. Each size of
294: * the image may be cached separately and generated from the original
295: * data in a separate image production sequence.
296: * @param img the specified image to be drawn.
297: * @param x the <i>x</i> coordinate.
298: * @param y the <i>y</i> coordinate.
299: * @param width the width of the rectangle.
300: * @param height the height of the rectangle.
301: * @param observer object to be notified as more of
302: * the image is converted.
303: * @return True if the image has been fully loaded/drawn
304: * @see java.awt.Image
305: * @see java.awt.image.ImageObserver
306: * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
307: */
308: public boolean drawImage(Image img, int x, int y, int width,
309: int height, ImageObserver observer) {
310: preparePainting();
311: System.err.println("NYI: drawImage");
312: return true;
313: }
314:
315: /**
316: * Disposes of this graphics context and releases
317: * any system resources that it is using.
318: * A <code>Graphics</code> object cannot be used after
319: * <code>dispose</code>has been called.
320: * <p>
321: * When a Java program runs, a large number of <code>Graphics</code>
322: * objects can be created within a short time frame.
323: * Although the finalization process of the garbage collector
324: * also disposes of the same system resources, it is preferable
325: * to manually free the associated resources by calling this
326: * method rather than to rely on a finalization process which
327: * may not run to completion for a long period of time.
328: * <p>
329: * Graphics objects which are provided as arguments to the
330: * <code>paint</code> and <code>update</code> methods
331: * of components are automatically released by the system when
332: * those methods return. For efficiency, programmers should
333: * call <code>dispose</code> when finished using
334: * a <code>Graphics</code> object only if it was created
335: * directly from a component or another <code>Graphics</code> object.
336: * @see java.awt.Graphics#finalize
337: * @see java.awt.Component#paint
338: * @see java.awt.Component#update
339: * @see java.awt.Component#getGraphics
340: * @see java.awt.Graphics#create
341: */
342: public void dispose() {
343: this .gen = null;
344: this .fallbackTextHandler = null;
345: this .customTextHandler = null;
346: this .currentColour = null;
347: }
348:
349: /**
350: * Processes a path iterator generating the nexessary painting operations.
351: * @param iter PathIterator to process
352: * @throws IOException In case of an I/O problem.
353: */
354: public void processPathIterator(PathIterator iter)
355: throws IOException {
356: double[] vals = new double[6];
357: while (!iter.isDone()) {
358: int type = iter.currentSegment(vals);
359: switch (type) {
360: case PathIterator.SEG_CUBICTO:
361: gen.writeln(gen.formatDouble(vals[0]) + " "
362: + gen.formatDouble(vals[1]) + " "
363: + gen.formatDouble(vals[2]) + " "
364: + gen.formatDouble(vals[3]) + " "
365: + gen.formatDouble(vals[4]) + " "
366: + gen.formatDouble(vals[5]) + " curveto");
367: break;
368: case PathIterator.SEG_LINETO:
369: gen.writeln(gen.formatDouble(vals[0]) + " "
370: + gen.formatDouble(vals[1]) + " lineto");
371: break;
372: case PathIterator.SEG_MOVETO:
373: gen.writeln(gen.formatDouble(vals[0]) + " "
374: + gen.formatDouble(vals[1]) + " M");
375: break;
376: case PathIterator.SEG_QUADTO:
377: gen.writeln(gen.formatDouble(vals[0]) + " "
378: + gen.formatDouble(vals[1]) + " "
379: + gen.formatDouble(vals[2]) + " "
380: + gen.formatDouble(vals[3]) + " QUADTO ");
381: break;
382: case PathIterator.SEG_CLOSE:
383: gen.writeln("closepath");
384: break;
385: default:
386: break;
387: }
388: iter.next();
389: }
390: }
391:
392: /**
393: * Strokes the outline of a <code>Shape</code> using the settings of the
394: * current <code>Graphics2D</code> context. The rendering attributes
395: * applied include the <code>Clip</code>, <code>Transform</code>,
396: * <code>Paint</code>, <code>Composite</code> and
397: * <code>Stroke</code> attributes.
398: * @param s the <code>Shape</code> to be rendered
399: * @see #setStroke
400: * @see #setPaint
401: * @see java.awt.Graphics#setColor
402: * @see #transform
403: * @see #setTransform
404: * @see #clip
405: * @see #setClip
406: * @see #setComposite
407: */
408: public void draw(Shape s) {
409: preparePainting();
410: try {
411: gen.saveGraphicsState();
412:
413: AffineTransform trans = getTransform();
414: boolean newTransform = gen.getCurrentState()
415: .checkTransform(trans)
416: && !trans.isIdentity();
417:
418: if (newTransform) {
419: gen.concatMatrix(trans);
420: }
421: Shape imclip = getClip();
422: writeClip(imclip);
423: establishColor(getColor());
424:
425: applyPaint(getPaint(), false);
426: applyStroke(getStroke());
427:
428: gen.writeln("newpath");
429: PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM);
430: processPathIterator(iter);
431: doDrawing(false, true, false);
432: gen.restoreGraphicsState();
433: } catch (IOException ioe) {
434: handleIOException(ioe);
435: }
436: }
437:
438: /**
439: * Establishes a clipping region
440: * @param s Shape defining the clipping region
441: */
442: public void writeClip(Shape s) {
443: if (s == null) {
444: return;
445: }
446: if (!this .clippingDisabled) {
447: preparePainting();
448: try {
449: gen.writeln("newpath");
450: PathIterator iter = s
451: .getPathIterator(IDENTITY_TRANSFORM);
452: processPathIterator(iter);
453: // clip area
454: gen.writeln("clip");
455: } catch (IOException ioe) {
456: handleIOException(ioe);
457: }
458: }
459: }
460:
461: /**
462: * Applies a new Paint object.
463: * @param paint Paint object to use
464: * @param fill True if to be applied for filling
465: */
466: protected void applyPaint(Paint paint, boolean fill) {
467: preparePainting();
468: if (paint instanceof GradientPaint) {
469: System.err.println("NYI: Gradient paint");
470: } else if (paint instanceof TexturePaint) {
471: System.err.println("NYI: texture paint");
472: }
473: }
474:
475: /**
476: * Applies a new Stroke object.
477: * @param stroke Stroke object to use
478: */
479: protected void applyStroke(Stroke stroke) {
480: preparePainting();
481: try {
482: if (stroke instanceof BasicStroke) {
483: BasicStroke bs = (BasicStroke) stroke;
484:
485: float[] da = bs.getDashArray();
486: if (da != null) {
487: gen.write("[");
488: for (int count = 0; count < da.length; count++) {
489: gen.write(gen.formatDouble(da[count]));
490: if (count < da.length - 1) {
491: gen.write(" ");
492: }
493: }
494: gen.write("] ");
495: float offset = bs.getDashPhase();
496: gen.writeln(gen.formatDouble(offset) + " setdash");
497: }
498: int ec = bs.getEndCap();
499: switch (ec) {
500: case BasicStroke.CAP_BUTT:
501: gen.writeln("0 setlinecap");
502: break;
503: case BasicStroke.CAP_ROUND:
504: gen.writeln("1 setlinecap");
505: break;
506: case BasicStroke.CAP_SQUARE:
507: gen.writeln("2 setlinecap");
508: break;
509: default:
510: System.err.println("Unsupported line cap: " + ec);
511: }
512:
513: int lj = bs.getLineJoin();
514: switch (lj) {
515: case BasicStroke.JOIN_MITER:
516: gen.writeln("0 setlinejoin");
517: float ml = bs.getMiterLimit();
518: gen.writeln(gen.formatDouble(ml >= -1 ? ml : 1)
519: + " setmiterlimit");
520: break;
521: case BasicStroke.JOIN_ROUND:
522: gen.writeln("1 setlinejoin");
523: break;
524: case BasicStroke.JOIN_BEVEL:
525: gen.writeln("2 setlinejoin");
526: break;
527: default:
528: System.err.println("Unsupported line join: " + lj);
529: }
530: float lw = bs.getLineWidth();
531: gen.writeln(gen.formatDouble(lw) + " setlinewidth");
532: }
533: } catch (IOException ioe) {
534: handleIOException(ioe);
535: }
536: }
537:
538: /**
539: * Renders a {@link RenderedImage},
540: * applying a transform from image
541: * space into user space before drawing.
542: * The transformation from user space into device space is done with
543: * the current <code>Transform</code> in the <code>Graphics2D</code>.
544: * The specified transformation is applied to the image before the
545: * transform attribute in the <code>Graphics2D</code> context is applied.
546: * The rendering attributes applied include the <code>Clip</code>,
547: * <code>Transform</code>, and <code>Composite</code> attributes. Note
548: * that no rendering is done if the specified transform is
549: * noninvertible.
550: * @param img the image to be rendered
551: * @param xform the transformation from image space into user space
552: * @see #transform
553: * @see #setTransform
554: * @see #setComposite
555: * @see #clip
556: * @see #setClip
557: */
558: public void drawRenderedImage(RenderedImage img,
559: AffineTransform xform) {
560: preparePainting();
561: System.err.println("NYI: drawRenderedImage");
562: }
563:
564: /**
565: * Renders a
566: * {@link RenderableImage},
567: * applying a transform from image space into user space before drawing.
568: * The transformation from user space into device space is done with
569: * the current <code>Transform</code> in the <code>Graphics2D</code>.
570: * The specified transformation is applied to the image before the
571: * transform attribute in the <code>Graphics2D</code> context is applied.
572: * The rendering attributes applied include the <code>Clip</code>,
573: * <code>Transform</code>, and <code>Composite</code> attributes. Note
574: * that no rendering is done if the specified transform is
575: * noninvertible.
576: * <p>
577: * Rendering hints set on the <code>Graphics2D</code> object might
578: * be used in rendering the <code>RenderableImage</code>.
579: * If explicit control is required over specific hints recognized by a
580: * specific <code>RenderableImage</code>, or if knowledge of which hints
581: * are used is required, then a <code>RenderedImage</code> should be
582: * obtained directly from the <code>RenderableImage</code>
583: * and rendered using
584: * {@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}.
585: * @param img the image to be rendered
586: * @param xform the transformation from image space into user space
587: * @see #transform
588: * @see #setTransform
589: * @see #setComposite
590: * @see #clip
591: * @see #setClip
592: * @see #drawRenderedImage
593: */
594: public void drawRenderableImage(RenderableImage img,
595: AffineTransform xform) {
596: preparePainting();
597: System.err.println("NYI: drawRenderableImage");
598: }
599:
600: /**
601: * Establishes the given color in the PostScript interpreter.
602: * @param c the color to set
603: * @throws IOException In case of an I/O problem
604: */
605: public void establishColor(Color c) throws IOException {
606: gen.useColor(c);
607: }
608:
609: /**
610: * Renders the text specified by the specified <code>String</code>,
611: * using the current <code>Font</code> and <code>Paint</code> attributes
612: * in the <code>Graphics2D</code> context.
613: * The baseline of the first character is at position
614: * (<i>x</i>, <i>y</i>) in the User Space.
615: * The rendering attributes applied include the <code>Clip</code>,
616: * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
617: * <code>Composite</code> attributes. For characters in script systems
618: * such as Hebrew and Arabic, the glyphs can be rendered from right to
619: * left, in which case the coordinate supplied is the location of the
620: * leftmost character on the baseline.
621: * @param s the <code>String</code> to be rendered
622: * @param x the x-coordinate where the <code>String</code>
623: * should be rendered
624: * @param y the y-coordinate where the <code>String</code>
625: * should be rendered
626: * @see #setPaint
627: * @see java.awt.Graphics#setColor
628: * @see java.awt.Graphics#setFont
629: * @see #setTransform
630: * @see #setComposite
631: * @see #setClip
632: */
633: public void drawString(String s, float x, float y) {
634: try {
635: if (customTextHandler != null && !textAsShapes) {
636: customTextHandler.drawString(s, x, y);
637: } else {
638: fallbackTextHandler.drawString(s, x, y);
639: }
640: } catch (IOException ioe) {
641: handleIOException(ioe);
642: }
643: }
644:
645: /**
646: * Fills the interior of a <code>Shape</code> using the settings of the
647: * <code>Graphics2D</code> context. The rendering attributes applied
648: * include the <code>Clip</code>, <code>Transform</code>,
649: * <code>Paint</code>, and <code>Composite</code>.
650: * @param s the <code>Shape</code> to be filled
651: * @see #setPaint
652: * @see java.awt.Graphics#setColor
653: * @see #transform
654: * @see #setTransform
655: * @see #setComposite
656: * @see #clip
657: * @see #setClip
658: */
659: public void fill(Shape s) {
660: preparePainting();
661: try {
662: gen.saveGraphicsState();
663:
664: AffineTransform trans = getTransform();
665: boolean newTransform = gen.getCurrentState()
666: .checkTransform(trans)
667: && !trans.isIdentity();
668:
669: if (newTransform) {
670: gen.concatMatrix(trans);
671: }
672: Shape imclip = getClip();
673: writeClip(imclip);
674:
675: establishColor(getColor());
676:
677: applyPaint(getPaint(), true);
678:
679: gen.writeln("newpath");
680: PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM);
681: processPathIterator(iter);
682: doDrawing(true, false,
683: iter.getWindingRule() == PathIterator.WIND_EVEN_ODD);
684: gen.restoreGraphicsState();
685: } catch (IOException ioe) {
686: handleIOException(ioe);
687: }
688: }
689:
690: /**
691: * Commits a painting operation.
692: * @param fill filling
693: * @param stroke stroking
694: * @param nonzero true if the non-zero winding rule should be used when filling
695: * @exception IOException In case of an I/O problem
696: */
697: protected void doDrawing(boolean fill, boolean stroke,
698: boolean nonzero) throws IOException {
699: preparePainting();
700: if (fill) {
701: if (stroke) {
702: if (!nonzero) {
703: gen.writeln("gsave fill grestore stroke");
704: } else {
705: gen.writeln("gsave eofill grestore stroke");
706: }
707: } else {
708: if (!nonzero) {
709: gen.writeln("fill");
710: } else {
711: gen.writeln("eofill");
712: }
713: }
714: } else {
715: // if(stroke)
716: gen.writeln("stroke");
717: }
718: }
719:
720: /**
721: * Returns the device configuration associated with this
722: * <code>Graphics2D</code>.
723: * @return the device configuration
724: */
725: public GraphicsConfiguration getDeviceConfiguration() {
726: return GraphicsEnvironment.getLocalGraphicsEnvironment()
727: .getDefaultScreenDevice().getDefaultConfiguration();
728: }
729:
730: /**
731: * Used to create proper font metrics
732: */
733: private Graphics2D fmg;
734:
735: {
736: BufferedImage bi = new BufferedImage(1, 1,
737: BufferedImage.TYPE_INT_ARGB);
738:
739: fmg = bi.createGraphics();
740: }
741:
742: /**
743: * Gets the font metrics for the specified font.
744: * @return the font metrics for the specified font.
745: * @param f the specified font
746: * @see java.awt.Graphics#getFont
747: * @see java.awt.FontMetrics
748: * @see java.awt.Graphics#getFontMetrics()
749: */
750: public java.awt.FontMetrics getFontMetrics(java.awt.Font f) {
751: return fmg.getFontMetrics(f);
752: }
753:
754: /**
755: * Sets the paint mode of this graphics context to alternate between
756: * this graphics context's current color and the new specified color.
757: * This specifies that logical pixel operations are performed in the
758: * XOR mode, which alternates pixels between the current color and
759: * a specified XOR color.
760: * <p>
761: * When drawing operations are performed, pixels which are the
762: * current color are changed to the specified color, and vice versa.
763: * <p>
764: * Pixels that are of colors other than those two colors are changed
765: * in an unpredictable but reversible manner; if the same figure is
766: * drawn twice, then all pixels are restored to their original values.
767: * @param c1 the XOR alternation color
768: */
769: public void setXORMode(Color c1) {
770: System.err.println("NYI: setXORMode");
771: }
772:
773: /**
774: * Copies an area of the component by a distance specified by
775: * <code>dx</code> and <code>dy</code>. From the point specified
776: * by <code>x</code> and <code>y</code>, this method
777: * copies downwards and to the right. To copy an area of the
778: * component to the left or upwards, specify a negative value for
779: * <code>dx</code> or <code>dy</code>.
780: * If a portion of the source rectangle lies outside the bounds
781: * of the component, or is obscured by another window or component,
782: * <code>copyArea</code> will be unable to copy the associated
783: * pixels. The area that is omitted can be refreshed by calling
784: * the component's <code>paint</code> method.
785: * @param x the <i>x</i> coordinate of the source rectangle.
786: * @param y the <i>y</i> coordinate of the source rectangle.
787: * @param width the width of the source rectangle.
788: * @param height the height of the source rectangle.
789: * @param dx the horizontal distance to copy the pixels.
790: * @param dy the vertical distance to copy the pixels.
791: */
792: public void copyArea(int x, int y, int width, int height, int dx,
793: int dy) {
794: System.err.println("NYI: copyArea");
795: }
796:
797: /* --- for debugging
798: public void transform(AffineTransform tx) {
799: System.out.println("transform(" + toArray(tx) + ")");
800: super.transform(zx);
801: }
802:
803: public void scale(double sx, double sy) {
804: System.out.println("scale(" + sx + ", " + sy + ")");
805: super.scale(sx, sy);
806: }
807:
808: public void translate(double tx, double ty) {
809: System.out.println("translate(double " + tx + ", " + ty + ")");
810: super.translate(tx, ty);
811: }
812:
813: public void translate(int tx, int ty) {
814: System.out.println("translate(int " + tx + ", " + ty + ")");
815: super.translate(tx, ty);
816: }
817: */
818:
819: }
|