001/* DebugGraphics.java --
002   Copyright (C) 2002, 2004, 2005  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package javax.swing;
039
040import java.awt.Color;
041import java.awt.Font;
042import java.awt.FontMetrics;
043import java.awt.Graphics;
044import java.awt.Image;
045import java.awt.Point;
046import java.awt.Rectangle;
047import java.awt.Shape;
048import java.awt.image.ImageObserver;
049import java.io.PrintStream;
050import java.text.AttributedCharacterIterator;
051
052
053/**
054 * An extension of {@link Graphics} that can be used for debugging
055 * custom Swing widgets. <code>DebugGraphics</code> has the ability to
056 * draw slowly and can log drawing actions.
057 *
058 * @author Andrew Selkirk
059 */
060public class DebugGraphics extends Graphics
061{
062  /**
063   * LOG_OPTION
064   */
065  public static final int LOG_OPTION = 1;
066
067  /**
068   * FLASH_OPTION
069   */
070  public static final int FLASH_OPTION = 2;
071
072  /**
073   * BUFFERED_OPTION
074   */
075  public static final int BUFFERED_OPTION = 4;
076
077  /**
078   * NONE_OPTION
079   */
080  public static final int NONE_OPTION = -1;
081
082  static Color debugFlashColor = Color.RED;
083  static int debugFlashCount = 10;
084  static int debugFlashTime = 1000;
085  static PrintStream debugLogStream = System.out;
086
087  /**
088   * Counts the created DebugGraphics objects. This is used by the
089   * logging facility.
090   */
091  static int counter = 0;
092
093  /**
094   * graphics
095   */
096  Graphics graphics;
097
098  /**
099   * buffer
100   */
101  Image buffer;
102
103  /**
104   * debugOptions
105   */
106  int debugOptions;
107
108  /**
109   * graphicsID
110   */
111  int graphicsID;
112
113  /**
114   * xOffset
115   */
116  int xOffset;
117
118  /**
119   * yOffset
120   */
121  int yOffset;
122
123  /**
124   * Creates a <code>DebugGraphics</code> object.
125   */
126  public DebugGraphics()
127  {
128    counter++;
129  }
130
131  /**
132   * Creates a <code>DebugGraphics</code> object.
133   *
134   * @param graphics The <code>Graphics</code> object to wrap
135   * @param component TODO
136   */
137  public DebugGraphics(Graphics graphics, JComponent component)
138  {
139    this(graphics);
140    // FIXME: What shall we do with component ?
141  }
142
143  /**
144   * Creates a <code>DebugGraphics</code> object.
145   *
146   * @param graphics The <code>Graphics</code> object to wrap
147   */
148  public DebugGraphics(Graphics graphics)
149  {
150    this();
151    this.graphics = graphics;
152  }
153
154  /**
155   * Sets the color to draw stuff with.
156   *
157   * @param color The color
158   */
159  public void setColor(Color color)
160  {
161    if ((debugOptions & LOG_OPTION) != 0)
162      logStream().println(prefix() + " Setting color: " + color);
163
164    graphics.setColor(color);
165  }
166
167  /**
168   * Creates a overrides <code>Graphics.create</code> to create a
169   * <code>DebugGraphics</code> object.
170   *
171   * @return a new <code>DebugGraphics</code> object.
172   */
173  public Graphics create()
174  {
175    DebugGraphics copy = new DebugGraphics(graphics.create());
176    copy.debugOptions = debugOptions;
177    return copy;
178  }
179
180  /**
181   * Creates a overrides <code>Graphics.create</code> to create a
182   * <code>DebugGraphics</code> object.
183   *
184   * @param x the x coordinate
185   * @param y the y coordinate
186   * @param width the width
187   * @param height the height
188   *
189   * @return a new <code>DebugGraphics</code> object.
190   */
191  public Graphics create(int x, int y, int width, int height)
192  {
193    DebugGraphics copy = new DebugGraphics(graphics.create(x, y, width,
194                                                           height));
195    copy.debugOptions = debugOptions;
196    return copy;
197  }
198
199  /**
200   * flashColor
201   *
202   * @return Color
203   */
204  public static Color flashColor()
205  {
206    return debugFlashColor;
207  }
208
209  /**
210   * setFlashColor
211   *
212   * @param color the color to use for flashing
213   */
214  public static void setFlashColor(Color color)
215  {
216    debugFlashColor = color;
217  }
218
219  /**
220   * flashTime
221   *
222   * @return The time in milliseconds
223   */
224  public static int flashTime()
225  {
226    return debugFlashTime;
227  }
228
229  /**
230   * setFlashTime
231   *
232   * @param time The time in milliseconds
233   */
234  public static void setFlashTime(int time)
235  {
236    debugFlashTime = time;
237  }
238
239  /**
240   * flashCount
241   *
242   * @return The number of flashes
243   */
244  public static int flashCount()
245  {
246    return debugFlashCount;
247  }
248
249  /**
250   * setFlashCount
251   *
252   * @param count The number of flashes
253   */
254  public static void setFlashCount(int count)
255  {
256    debugFlashCount = count;
257  }
258
259  /**
260   * logStream
261   *
262   * @return The <code>PrintStream</code> to write logging messages to
263   */
264  public static PrintStream logStream()
265  {
266    return debugLogStream;
267  }
268
269  /**
270   * setLogStream
271   *
272   * @param stream The currently set <code>PrintStream</code>.
273   */
274  public static void setLogStream(PrintStream stream)
275  {
276    debugLogStream = stream;
277  }
278
279  /**
280   * getFont
281   *
282   * @return The font
283   */
284  public Font getFont()
285  {
286    return graphics.getFont();
287  }
288
289  /**
290   * setFont
291   *
292   * @param font The font to use for drawing text
293   */
294  public void setFont(Font font)
295  {
296    if ((debugOptions & LOG_OPTION) != 0)
297      logStream().println(prefix() + " Setting font: " + font);
298
299    graphics.setFont(font);
300  }
301
302  /**
303   * Returns the color used for drawing.
304   *
305   * @return The color.
306   */
307  public Color getColor()
308  {
309    return graphics.getColor();
310  }
311
312  /**
313   * Returns the font metrics of the current font.
314   *
315   * @return a <code>FontMetrics</code> object
316   */
317  public FontMetrics getFontMetrics()
318  {
319    return graphics.getFontMetrics();
320  }
321
322  /**
323   * Returns the font metrics for a given font.
324   *
325   * @param font the font to get the metrics for
326   *
327   * @return a <code>FontMetrics</code> object
328   */
329  public FontMetrics getFontMetrics(Font font)
330  {
331    return graphics.getFontMetrics(font);
332  }
333
334  /**
335   * translate
336   *
337   * @param x the x coordinate
338   * @param y the y coordinate
339   */
340  public void translate(int x, int y)
341  {
342    if ((debugOptions & LOG_OPTION) != 0)
343      logStream().println(prefix() + " Translating by: " + new Point(x, y));
344
345    graphics.translate(x, y);
346  }
347
348  /**
349   * setPaintMode
350   */
351  public void setPaintMode()
352  {
353    if ((debugOptions & LOG_OPTION) != 0)
354      logStream().println(prefix() + " Setting paint mode");
355
356    graphics.setPaintMode();
357  }
358
359  /**
360   * setXORMode
361   *
362   * @param color the color
363   */
364  public void setXORMode(Color color)
365  {
366    if ((debugOptions & LOG_OPTION) != 0)
367      logStream().println(prefix() + " Setting XOR mode: " + color);
368
369    graphics.setXORMode(color);
370  }
371
372  /**
373   * getClipBounds
374   *
375   * @return Rectangle
376   */
377  public Rectangle getClipBounds()
378  {
379    return graphics.getClipBounds();
380  }
381
382  /**
383   * Intersects the current clip region with the given region.
384   *
385   * @param x The x-position of the region
386   * @param y The y-position of the region
387   * @param width The width of the region
388   * @param height The height of the region
389   */
390  public void clipRect(int x, int y, int width, int height)
391  {
392    if ((debugOptions & LOG_OPTION) != 0)
393      {
394        logStream().print(prefix() + " Setting clipRect: "
395                          + new Rectangle(x, y, width, height));
396      }
397
398    graphics.clipRect(x, y, width, height);
399
400    if ((debugOptions & LOG_OPTION) != 0)
401      logStream().println(" Netting clipRect: " + graphics.getClipBounds());
402  }
403
404  /**
405   * Sets the clipping region.
406   *
407   * @param x The x-position of the region
408   * @param y The y-position of the region
409   * @param width The width of the region
410   * @param height The height of the region
411   */
412  public void setClip(int x, int y, int width, int height)
413  {
414    if ((debugOptions & LOG_OPTION) != 0)
415      {
416        logStream().println(prefix() + " Setting new clipRect: "
417                            + new Rectangle(x, y, width, height));
418      }
419
420    graphics.setClip(x, y, width, height);
421  }
422
423  /**
424   * Returns the current clipping region.
425   *
426   * @return Shape
427   */
428  public Shape getClip()
429  {
430    return graphics.getClip();
431  }
432
433  /**
434   * Sets the current clipping region
435   *
436   * @param shape The clippin region
437   */
438  public void setClip(Shape shape)
439  {
440    if ((debugOptions & LOG_OPTION) != 0)
441      logStream().println(prefix() + " Setting new clipRect: " + shape);
442
443    graphics.setClip(shape);
444  }
445
446  private void sleep(int milliseconds)
447  {
448    try
449      {
450        Thread.sleep(milliseconds);
451      }
452    catch (InterruptedException e)
453      {
454        // Ignore this.
455      }
456  }
457
458  /**
459   * Draws a rectangle.
460   *
461   * @param x The x-position of the rectangle
462   * @param y The y-position of the rectangle
463   * @param width The width of the rectangle
464   * @param height The height of the rectangle
465   */
466  public void drawRect(int x, int y, int width, int height)
467  {
468    if ((debugOptions & LOG_OPTION) != 0)
469      {
470        logStream().println(prefix() + " Drawing rect: "
471                            + new Rectangle(x, y, width, height));
472      }
473
474    if ((debugOptions & FLASH_OPTION) != 0)
475      {
476        Color color = graphics.getColor();
477        for (int index = 0; index < (debugFlashCount - 1); ++index)
478          {
479            graphics.setColor(color);
480            graphics.drawRect(x, y, width, height);
481            sleep(debugFlashTime);
482            graphics.setColor(debugFlashColor);
483            graphics.drawRect(x, y, width, height);
484            sleep(debugFlashTime);
485          }
486        graphics.setColor(color);
487      }
488
489    graphics.drawRect(x, y, width, height);
490  }
491
492  /**
493   * Draws a filled rectangle.
494   *
495   * @param x The x-position of the rectangle
496   * @param y The y-position of the rectangle
497   * @param width The width of the rectangle
498   * @param height The height of the rectangle
499   */
500  public void fillRect(int x, int y, int width, int height)
501  {
502    if ((debugOptions & LOG_OPTION) != 0)
503      {
504        logStream().println(prefix() + " Filling rect: "
505                            + new Rectangle(x, y, width, height));
506      }
507
508    if ((debugOptions & FLASH_OPTION) != 0)
509      {
510        Color color = graphics.getColor();
511        for (int index = 0; index < (debugFlashCount - 1); ++index)
512          {
513            graphics.setColor(color);
514            graphics.fillRect(x, y, width, height);
515            sleep(debugFlashTime);
516            graphics.setColor(debugFlashColor);
517            graphics.fillRect(x, y, width, height);
518            sleep(debugFlashTime);
519          }
520        graphics.setColor(color);
521      }
522
523    graphics.fillRect(x, y, width, height);
524  }
525
526  /**
527   * clearRect
528   *
529   * @param x The x-position of the rectangle
530   * @param y The y-position of the rectangle
531   * @param width The width of the rectangle
532   * @param height The height of the rectangle
533   */
534  public void clearRect(int x, int y, int width, int height)
535  {
536    if ((debugOptions & LOG_OPTION) != 0)
537      {
538        logStream().println(prefix() + " Clearing rect: "
539                            + new Rectangle(x, y, width, height));
540      }
541
542    graphics.clearRect(x, y, width, height);
543  }
544
545  /**
546   * drawRoundRect
547   *
548   * @param x The x-position of the rectangle
549   * @param y The y-position of the rectangle
550   * @param width The width of the rectangle
551   * @param height The height of the rectangle
552   * @param arcWidth TODO
553   * @param arcHeight TODO
554   */
555  public void drawRoundRect(int x, int y, int width, int height,
556                            int arcWidth, int arcHeight)
557  {
558    if ((debugOptions & LOG_OPTION) != 0)
559      {
560        logStream().println(prefix() + " Drawing round rect: "
561                            + new Rectangle(x, y, width, height)
562                            + " arcWidth: " + arcWidth
563                            + " arcHeight: " + arcHeight);
564      }
565
566    graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
567  }
568
569  /**
570   * fillRoundRect
571   *
572   * @param x The x-position of the rectangle
573   * @param y The y-position of the rectangle
574   * @param width The width of the rectangle
575   * @param height The height of the rectangle
576   * @param arcWidth TODO
577   * @param arcHeight TODO
578   */
579  public void fillRoundRect(int x, int y, int width, int height,
580                            int arcWidth, int arcHeight)
581  {
582    if ((debugOptions & LOG_OPTION) != 0)
583      {
584        logStream().println(prefix() + " Filling round rect: "
585                            + new Rectangle(x, y, width, height)
586                            + " arcWidth: " + arcWidth
587                            + " arcHeight: " + arcHeight);
588      }
589
590    graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
591  }
592
593  /**
594   * drawLine
595   *
596   * @param x1 The x-position of the start
597   * @param y1 The y-position of the start
598   * @param x2 The x-position of the end
599   * @param y2 The y-position of the end
600   */
601  public void drawLine(int x1, int y1, int x2, int y2)
602  {
603    if ((debugOptions & LOG_OPTION) != 0)
604      {
605        logStream().println(prefix() + " Drawing line: from (" + x1 + ", "
606                            + y1 + ") to (" + x2 + ", " + y2 + ")");
607      }
608
609    graphics.drawLine(x1, y1, x2, y2);
610  }
611
612  /**
613   * draw3DRect
614   *
615   * @param x The x-position of the rectangle
616   * @param y The y-position of the rectangle
617   * @param width The width of the rectangle
618   * @param height The height of the rectangle
619   * @param raised TODO
620   */
621  public void draw3DRect(int x, int y, int width, int height, boolean raised)
622  {
623    if ((debugOptions & LOG_OPTION) != 0)
624      {
625        logStream().println(prefix() + " Drawing 3D rect: "
626                            + new Rectangle(x, y, width, height)
627                            + "Raised bezel: " + raised);
628      }
629
630    graphics.draw3DRect(x, y, width, height, raised);
631  }
632
633  /**
634   * fill3DRect
635   *
636   * @param x The x-position of the rectangle
637   * @param y The y-position of the rectangle
638   * @param width The width of the rectangle
639   * @param height The height of the rectangle
640   * @param raised TODO
641   */
642  public void fill3DRect(int x, int y, int width, int height, boolean raised)
643  {
644    if ((debugOptions & LOG_OPTION) != 0)
645      {
646        logStream().println(prefix() + " Filling 3D rect: "
647                            + new Rectangle(x, y, width, height)
648                            + "Raised bezel: " + raised);
649      }
650
651    graphics.fill3DRect(x, y, width, height, raised);
652  }
653
654  /**
655   * drawOval
656   *
657   * @param x the x coordinate
658   * @param y the y coordiante
659   * @param width the width
660   * @param height the height
661   */
662  public void drawOval(int x, int y, int width, int height)
663  {
664    if ((debugOptions & LOG_OPTION) != 0)
665      {
666        logStream().println(prefix() + " Drawing oval: "
667                            + new Rectangle(x, y, width, height));
668      }
669
670    graphics.drawOval(x, y, width, height);
671  }
672
673  /**
674   * fillOval
675   *
676   * @param x the x coordinate
677   * @param y the y coordinate
678   * @param width the width
679   * @param height the height
680   */
681  public void fillOval(int x, int y, int width, int height)
682  {
683    if ((debugOptions & LOG_OPTION) != 0)
684      {
685        logStream().println(prefix() + " Filling oval: "
686                            + new Rectangle(x, y, width, height));
687      }
688
689    graphics.fillOval(x, y, width, height);
690  }
691
692  /**
693   * drawArc
694   *
695   * @param x the x coordinate
696   * @param y the y coordinate
697   * @param width the width
698   * @param height the height
699   * @param startAngle TODO
700   * @param arcAngle TODO
701   */
702  public void drawArc(int x, int y, int width, int height,
703                      int startAngle, int arcAngle)
704  {
705    if ((debugOptions & LOG_OPTION) != 0)
706      {
707        logStream().println(prefix() + " Drawing arc: "
708                            + new Rectangle(x, y, width, height)
709                            + " startAngle: " + startAngle
710                            + " arcAngle: " + arcAngle);
711      }
712
713    graphics.drawArc(x, y, width, height, startAngle, arcAngle);
714  }
715
716  /**
717   * fillArc
718   *
719   * @param x the coordinate
720   * @param y the y coordinate
721   * @param width the width
722   * @param height the height
723   * @param startAngle TODO
724   * @param arcAngle TODO
725   */
726  public void fillArc(int x, int y, int width, int height,
727                      int startAngle, int arcAngle)
728  {
729    if ((debugOptions & LOG_OPTION) != 0)
730      {
731        logStream().println(prefix() + " Filling arc: "
732                            + new Rectangle(x, y, width, height)
733                            + " startAngle: " + startAngle
734                            + " arcAngle: " + arcAngle);
735      }
736
737    graphics.fillArc(x, y, width, height, startAngle, arcAngle);
738  }
739
740  /**
741   * drawPolyline
742   *
743   * @param xpoints TODO
744   * @param ypoints TODO
745   * @param npoints TODO
746   */
747  public void drawPolyline(int[] xpoints, int[] ypoints, int npoints)
748  {
749    if ((debugOptions & LOG_OPTION) != 0)
750      {
751        logStream().println(prefix() + " Drawing polyline: nPoints: " + npoints
752                            + " X's: " + xpoints + " Y's: " + ypoints);
753      }
754
755    graphics.drawPolyline(xpoints, ypoints, npoints);
756  }
757
758  /**
759   * drawPolygon
760   *
761   * @param xpoints TODO
762   * @param ypoints TODO
763   * @param npoints TODO
764   */
765  public void drawPolygon(int[] xpoints, int[] ypoints, int npoints)
766  {
767    if ((debugOptions & LOG_OPTION) != 0)
768      {
769        logStream().println(prefix() + " Drawing polygon: nPoints: " + npoints
770                            + " X's: " + xpoints + " Y's: " + ypoints);
771      }
772
773    graphics.drawPolygon(xpoints, ypoints, npoints);
774  }
775
776  /**
777   * fillPolygon
778   *
779   * @param xpoints TODO
780   * @param ypoints TODO
781   * @param npoints TODO
782   */
783  public void fillPolygon(int[] xpoints, int[] ypoints, int npoints)
784  {
785    if ((debugOptions & LOG_OPTION) != 0)
786      {
787        logStream().println(prefix() + " Drawing polygon: nPoints: " + npoints
788                            + " X's: " + xpoints + " Y's: " + ypoints);
789      }
790
791    graphics.fillPolygon(xpoints, ypoints, npoints);
792  }
793
794  /**
795   * drawString
796   *
797   * @param string the string
798   * @param x the x coordinate
799   * @param y the y coordinate
800   */
801  public void drawString(String string, int x, int y)
802  {
803    if ((debugOptions & LOG_OPTION) != 0)
804      {
805        logStream().println(prefix() + " Drawing string: \"" + string
806                            + "\" at: " + new Point(x, y));
807      }
808
809    graphics.drawString(string, x, y);
810  }
811
812  /**
813   * drawString
814   *
815   * @param iterator TODO
816   * @param x the x coordinate
817   * @param y the y coordinate
818   */
819  public void drawString(AttributedCharacterIterator iterator,
820                         int x, int y)
821  {
822    if ((debugOptions & LOG_OPTION) != 0)
823      {
824        logStream().println(prefix() + " Drawing string: \"" + iterator
825                            + "\" at: " + new Point(x, y));
826      }
827
828    graphics.drawString(iterator, x, y);
829  }
830
831  /**
832   * drawBytes
833   *
834   * @param data TODO
835   * @param offset TODO
836   * @param length TODO
837   * @param x the x coordinate
838   * @param y the y coordinate
839   */
840  public void drawBytes(byte[] data, int offset, int length,
841                        int x, int y)
842  {
843    if ((debugOptions & LOG_OPTION) != 0)
844      logStream().println(prefix() + " Drawing bytes at: " + new Point(x, y));
845
846    graphics.drawBytes(data, offset, length, x, y);
847  }
848
849  /**
850   * drawChars
851   *
852   * @param data array of characters to draw
853   * @param offset offset in array
854   * @param length number of characters in array to draw
855   * @param x x-position
856   * @param y y-position
857   */
858  public void drawChars(char[] data, int offset, int length,
859                        int x, int y)
860  {
861    if ((debugOptions & LOG_OPTION) != 0)
862      logStream().println(prefix() + " Drawing chars at: " + new Point(x, y));
863
864    if ((debugOptions & FLASH_OPTION) != 0)
865      {
866        Color color = graphics.getColor();
867        for (int index = 0; index < (debugFlashCount - 1); ++index)
868          {
869            graphics.setColor(color);
870            graphics.drawChars(data, offset, length, x, y);
871            sleep(debugFlashTime);
872            graphics.setColor(debugFlashColor);
873            graphics.drawChars(data, offset, length, x, y);
874            sleep(debugFlashTime);
875          }
876        graphics.setColor(color);
877      }
878
879    graphics.drawChars(data, offset, length, x, y);
880  }
881
882  /**
883   * drawImage
884   *
885   * @param image The image to draw
886   * @param x The x position
887   * @param y The y position
888   * @param observer The image observer
889   * @return boolean
890   */
891  public boolean drawImage(Image image, int x, int y,
892                           ImageObserver observer)
893  {
894    if ((debugOptions & LOG_OPTION) != 0)
895      {
896        logStream().println(prefix() + " Drawing image: " + image + " at: "
897                          + new Point(x, y));
898      }
899
900    return graphics.drawImage(image, x, y, observer);
901  }
902
903  /**
904   * drawImage
905   *
906   * @param image The image to draw
907   * @param x The x position
908   * @param y The y position
909   * @param width The width of the area to draw the image
910   * @param height The height of the area to draw the image
911   * @param observer The image observer
912   *
913   * @return boolean
914   */
915  public boolean drawImage(Image image, int x, int y, int width,
916                           int height, ImageObserver observer)
917  {
918    if ((debugOptions & LOG_OPTION) != 0)
919      {
920        logStream().println(prefix() + " Drawing image: " + image
921                            + " at: " + new Rectangle(x, y, width, height));
922      }
923
924    return graphics.drawImage(image, x, y, width, height, observer);
925  }
926
927  /**
928   * drawImage
929   *
930   * @param image The image to draw
931   * @param x The x position
932   * @param y The y position
933   * @param background The color for the background in the opaque regions
934   * of the image
935   * @param observer The image observer
936   *
937   * @return boolean
938   */
939  public boolean drawImage(Image image, int x, int y,
940                           Color background, ImageObserver observer)
941  {
942    if ((debugOptions & LOG_OPTION) != 0)
943      {
944        logStream().println(prefix() + " Drawing image: " + image
945                            + " at: " + new Point(x, y)
946                            + ", bgcolor: " + background);
947      }
948
949    return graphics.drawImage(image, x, y, background, observer);
950  }
951
952  /**
953   * drawImage
954   *
955   * @param image The image to draw
956   * @param x The x position
957   * @param y The y position
958   * @param width The width of the area to draw the image
959   * @param height The height of the area to draw the image
960   * @param background The color for the background in the opaque regions
961   * of the image
962   * @param observer The image observer
963   *
964   * @return boolean
965   */
966  public boolean drawImage(Image image, int x, int y, int width, int height,
967                           Color background, ImageObserver observer)
968  {
969    if ((debugOptions & LOG_OPTION) != 0)
970      {
971        logStream().println(prefix() + " Drawing image: " + image
972                            + " at: " + new Rectangle(x, y, width, height)
973                            + ", bgcolor: " + background);
974      }
975
976    return graphics.drawImage(image, x, y, width, height, background, observer);
977  }
978
979  /**
980   * drawImage
981   *
982   * @param image The image to draw
983   * @param dx1 TODO
984   * @param dy1 TODO
985   * @param dx2 TODO
986   * @param dy2 TODO
987   * @param sx1 TODO
988   * @param sy1 TODO
989   * @param sx2 TODO
990   * @param sy2 TODO
991   * @param observer The image observer
992   *
993   * @return boolean
994   */
995  public boolean drawImage(Image image, int dx1, int dy1,
996                           int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
997                           ImageObserver observer)
998  {
999    if ((debugOptions & LOG_OPTION) != 0)
1000      {
1001        logStream().println(prefix() + " Drawing image: " + image
1002                         + " destination: " + new Rectangle(dx1, dy1, dx2, dy2)
1003                         + " source: " + new Rectangle(sx1, sy1, sx2, sy2));
1004      }
1005
1006    return graphics.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
1007  }
1008
1009  /**
1010   * drawImage
1011   *
1012   * @param image The image to draw
1013   * @param dx1 TODO
1014   * @param dy1 TODO
1015   * @param dx2 TODO
1016   * @param dy2 TODO
1017   * @param sx1 TODO
1018   * @param sy1 TODO
1019   * @param sx2 TODO
1020   * @param sy2 TODO
1021   * @param background The color for the background in the opaque regions
1022   * of the image
1023   * @param observer The image observer
1024   *
1025   * @return boolean
1026   */
1027  public boolean drawImage(Image image, int dx1, int dy1,
1028                           int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
1029                           Color background, ImageObserver observer)
1030  {
1031    if ((debugOptions & LOG_OPTION) != 0)
1032      {
1033        logStream().println(prefix() + " Drawing image: " + image
1034                         + " destination: " + new Rectangle(dx1, dy1, dx2, dy2)
1035                         + " source: " + new Rectangle(sx1, sy1, sx2, sy2)
1036                         + ", bgcolor: " + background);
1037      }
1038
1039    return graphics.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, background, observer);
1040  }
1041
1042  /**
1043   * copyArea
1044   *
1045   * @param x The x position of the source area
1046   * @param y The y position of the source area
1047   * @param width The width of the area
1048   * @param height The height of the area
1049   * @param destx The x position of the destination area
1050   * @param desty The y posiiton of the destination area
1051   */
1052  public void copyArea(int x, int y, int width, int height,
1053                       int destx, int desty)
1054  {
1055    if ((debugOptions & LOG_OPTION) != 0)
1056      {
1057        logStream().println(prefix() + " Copying area from: "
1058                            +  new Rectangle(x, y, width, height)
1059                            + " to: " + new Point(destx, desty));
1060      }
1061
1062    graphics.copyArea(x, y, width, height, destx, desty);
1063  }
1064
1065  /**
1066   * Releases all system resources that this <code>Graphics</code> is using.
1067   */
1068  public void dispose()
1069  {
1070    graphics.dispose();
1071    graphics = null;
1072  }
1073
1074  /**
1075   * isDrawingBuffer
1076   *
1077   * @return boolean
1078   */
1079  public boolean isDrawingBuffer()
1080  {
1081    return false; // TODO
1082  }
1083
1084  /**
1085   * setDebugOptions
1086   *
1087   * @param options the debug options
1088   */
1089  public void setDebugOptions(int options)
1090  {
1091    debugOptions = options;
1092    if ((debugOptions & LOG_OPTION) != 0)
1093      if (options == NONE_OPTION)
1094        logStream().println(prefix() + "Disabling debug");
1095      else
1096        logStream().println(prefix() + "Enabling debug");
1097  }
1098
1099  /**
1100   * getDebugOptions
1101   *
1102   * @return the debug options
1103   */
1104  public int getDebugOptions()
1105  {
1106    return debugOptions;
1107  }
1108
1109  /**
1110   * Creates and returns the prefix that should be prepended to all logging
1111   * messages. The prefix is made up like this:
1112   *
1113   * <code>Graphics(<counter>-1)</code> where counter is an integer number
1114   * saying how many DebugGraphics objects have been created so far. The second
1115   * number always seem to be 1 on Sun's JDK, this has to be investigated a
1116   * little more.
1117   *
1118   * @return the prefix that should be prepended to all logging
1119   *         messages
1120   */
1121  private String prefix()
1122  {
1123    return "Graphics(" + counter + "-1)";
1124  }
1125}