1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing;
27
28import java.awt.*;
29import java.awt.image.*;
30import java.text.AttributedCharacterIterator;
31
32/**
33 * Graphics subclass supporting graphics debugging. Overrides most methods
34 * from Graphics.  DebugGraphics objects are rarely created by hand.  They
35 * are most frequently created automatically when a JComponent's
36 * debugGraphicsOptions are changed using the setDebugGraphicsOptions()
37 * method.
38 * <p>
39 * NOTE: You must turn off double buffering to use DebugGraphics:
40 *       RepaintManager repaintManager = RepaintManager.currentManager(component);
41 *       repaintManager.setDoubleBufferingEnabled(false);
42 *
43 * @see JComponent#setDebugGraphicsOptions
44 * @see RepaintManager#currentManager
45 * @see RepaintManager#setDoubleBufferingEnabled
46 *
47 * @author Dave Karlton
48 * @since 1.2
49 */
50public class DebugGraphics extends Graphics {
51    Graphics                    graphics;
52    Image                       buffer;
53    int                         debugOptions;
54    int                         graphicsID = graphicsCount++;
55    int                         xOffset, yOffset;
56    private static int          graphicsCount = 0;
57    private static ImageIcon    imageLoadingIcon = new ImageIcon();
58
59    /** Log graphics operations. */
60    public static final int     LOG_OPTION   = 1 << 0;
61    /** Flash graphics operations. */
62    public static final int     FLASH_OPTION = 1 << 1;
63    /** Show buffered operations in a separate <code>Frame</code>. */
64    public static final int     BUFFERED_OPTION = 1 << 2;
65    /** Don't debug graphics operations. */
66    public static final int     NONE_OPTION = -1;
67
68    static {
69        JComponent.DEBUG_GRAPHICS_LOADED = true;
70    }
71
72    /**
73     * Constructs a new debug graphics context that supports slowed
74     * down drawing.
75     */
76    public DebugGraphics() {
77        super();
78        buffer = null;
79        xOffset = yOffset = 0;
80    }
81
82    /**
83     * Constructs a debug graphics context from an existing graphics
84     * context that slows down drawing for the specified component.
85     *
86     * @param graphics  the Graphics context to slow down
87     * @param component the JComponent to draw slowly
88     */
89    public DebugGraphics(Graphics graphics, JComponent component) {
90        this(graphics);
91        setDebugOptions(component.shouldDebugGraphics());
92    }
93
94    /**
95     * Constructs a debug graphics context from an existing graphics
96     * context that supports slowed down drawing.
97     *
98     * @param graphics  the Graphics context to slow down
99     */
100    public DebugGraphics(Graphics graphics) {
101        this();
102        this.graphics = graphics;
103    }
104
105    /**
106     * Overrides <code>Graphics.create</code> to return a DebugGraphics object.
107     */
108    public Graphics create() {
109        DebugGraphics debugGraphics;
110
111        debugGraphics = new DebugGraphics();
112        debugGraphics.graphics = graphics.create();
113        debugGraphics.debugOptions = debugOptions;
114        debugGraphics.buffer = buffer;
115
116        return debugGraphics;
117    }
118
119    /**
120     * Overrides <code>Graphics.create</code> to return a DebugGraphics object.
121     */
122    public Graphics create(int x, int y, int width, int height) {
123        DebugGraphics debugGraphics;
124
125        debugGraphics = new DebugGraphics();
126        debugGraphics.graphics = graphics.create(x, y, width, height);
127        debugGraphics.debugOptions = debugOptions;
128        debugGraphics.buffer = buffer;
129        debugGraphics.xOffset = xOffset + x;
130        debugGraphics.yOffset = yOffset + y;
131
132        return debugGraphics;
133    }
134
135
136    //------------------------------------------------
137    //  NEW METHODS
138    //------------------------------------------------
139
140    /**
141     * Sets the Color used to flash drawing operations.
142     *
143     * @param flashColor the Color used to flash drawing operations
144     */
145    public static void setFlashColor(Color flashColor) {
146        info().flashColor = flashColor;
147    }
148
149    /**
150     * Returns the Color used to flash drawing operations.
151     *
152     * @return the Color used to flash drawing operations
153     * @see #setFlashColor
154     */
155    public static Color flashColor() {
156        return info().flashColor;
157    }
158
159    /**
160     * Sets the time delay of drawing operation flashing.
161     *
162     * @param flashTime the time delay of drawing operation flashing
163     */
164    public static void setFlashTime(int flashTime) {
165        info().flashTime = flashTime;
166    }
167
168    /**
169     * Returns the time delay of drawing operation flashing.
170     *
171     * @return the time delay of drawing operation flashing
172     * @see #setFlashTime
173     */
174    public static int flashTime() {
175        return info().flashTime;
176    }
177
178    /**
179     * Sets the number of times that drawing operations will flash.
180     *
181     * @param flashCount number of times that drawing operations will flash
182     */
183    public static void setFlashCount(int flashCount) {
184        info().flashCount = flashCount;
185    }
186
187    /**
188     * Returns the number of times that drawing operations will flash.
189     *
190     * @return the number of times that drawing operations will flash
191     * @see #setFlashCount
192     */
193    public static int flashCount() {
194        return info().flashCount;
195    }
196
197    /**
198     * Sets the stream to which the DebugGraphics logs drawing operations.
199     *
200     * @param stream the stream to which the DebugGraphics logs drawing operations
201     */
202    public static void setLogStream(java.io.PrintStream stream) {
203        info().stream = stream;
204    }
205
206    /**
207     * Returns the stream to which the DebugGraphics logs drawing operations.
208     *
209     * @return the stream to which the DebugGraphics logs drawing operations
210     * @see #setLogStream
211     */
212    public static java.io.PrintStream logStream() {
213        return info().stream;
214    }
215
216    /** Sets the Font used for text drawing operations.
217      */
218    public void setFont(Font aFont) {
219        if (debugLog()) {
220            info().log(toShortString() + " Setting font: " + aFont);
221        }
222        graphics.setFont(aFont);
223    }
224
225    /** Returns the Font used for text drawing operations.
226      * @see #setFont
227      */
228    public Font getFont() {
229        return graphics.getFont();
230    }
231
232    /** Sets the color to be used for drawing and filling lines and shapes.
233      */
234    public void setColor(Color aColor) {
235        if (debugLog()) {
236            info().log(toShortString() + " Setting color: " + aColor);
237        }
238        graphics.setColor(aColor);
239    }
240
241    /** Returns the Color used for text drawing operations.
242      * @see #setColor
243      */
244    public Color getColor() {
245        return graphics.getColor();
246    }
247
248
249    //-----------------------------------------------
250    // OVERRIDDEN METHODS
251    //------------------------------------------------
252
253    /**
254     * Overrides <code>Graphics.getFontMetrics</code>.
255     */
256    public FontMetrics getFontMetrics() {
257        return graphics.getFontMetrics();
258    }
259
260    /**
261     * Overrides <code>Graphics.getFontMetrics</code>.
262     */
263    public FontMetrics getFontMetrics(Font f) {
264        return graphics.getFontMetrics(f);
265    }
266
267    /**
268     * Overrides <code>Graphics.translate</code>.
269     */
270    public void translate(int x, int y) {
271        if (debugLog()) {
272            info().log(toShortString() +
273                " Translating by: " + new Point(x, y));
274        }
275        xOffset += x;
276        yOffset += y;
277        graphics.translate(x, y);
278    }
279
280    /**
281     * Overrides <code>Graphics.setPaintMode</code>.
282     */
283    public void setPaintMode() {
284        if (debugLog()) {
285            info().log(toShortString() + " Setting paint mode");
286        }
287        graphics.setPaintMode();
288    }
289
290    /**
291     * Overrides <code>Graphics.setXORMode</code>.
292     */
293    public void setXORMode(Color aColor) {
294        if (debugLog()) {
295            info().log(toShortString() + " Setting XOR mode: " + aColor);
296        }
297        graphics.setXORMode(aColor);
298    }
299
300    /**
301     * Overrides <code>Graphics.getClipBounds</code>.
302     */
303    public Rectangle getClipBounds() {
304        return graphics.getClipBounds();
305    }
306
307    /**
308     * Overrides <code>Graphics.clipRect</code>.
309     */
310    public void clipRect(int x, int y, int width, int height) {
311        graphics.clipRect(x, y, width, height);
312        if (debugLog()) {
313            info().log(toShortString() +
314                " Setting clipRect: " + (new Rectangle(x, y, width, height)) +
315                " New clipRect: " + graphics.getClip());
316        }
317    }
318
319    /**
320     * Overrides <code>Graphics.setClip</code>.
321     */
322    public void setClip(int x, int y, int width, int height) {
323        graphics.setClip(x, y, width, height);
324        if (debugLog()) {
325            info().log(toShortString() +
326                        " Setting new clipRect: " + graphics.getClip());
327        }
328    }
329
330    /**
331     * Overrides <code>Graphics.getClip</code>.
332     */
333    public Shape getClip() {
334        return graphics.getClip();
335    }
336
337    /**
338     * Overrides <code>Graphics.setClip</code>.
339     */
340    public void setClip(Shape clip) {
341        graphics.setClip(clip);
342        if (debugLog()) {
343            info().log(toShortString() +
344                       " Setting new clipRect: " +  graphics.getClip());
345        }
346    }
347
348    /**
349     * Overrides <code>Graphics.drawRect</code>.
350     */
351    public void drawRect(int x, int y, int width, int height) {
352        DebugGraphicsInfo info = info();
353
354        if (debugLog()) {
355            info().log(toShortString() +
356                      " Drawing rect: " +
357                      new Rectangle(x, y, width, height));
358        }
359
360        if (isDrawingBuffer()) {
361            if (debugBuffered()) {
362                Graphics debugGraphics = debugGraphics();
363
364                debugGraphics.drawRect(x, y, width, height);
365                debugGraphics.dispose();
366            }
367        } else if (debugFlash()) {
368            Color oldColor = getColor();
369            int i, count = (info.flashCount * 2) - 1;
370
371            for (i = 0; i < count; i++) {
372                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
373                graphics.drawRect(x, y, width, height);
374                Toolkit.getDefaultToolkit().sync();
375                sleep(info.flashTime);
376            }
377            graphics.setColor(oldColor);
378        }
379        graphics.drawRect(x, y, width, height);
380    }
381
382    /**
383     * Overrides <code>Graphics.fillRect</code>.
384     */
385    public void fillRect(int x, int y, int width, int height) {
386        DebugGraphicsInfo info = info();
387
388        if (debugLog()) {
389            info().log(toShortString() +
390                      " Filling rect: " +
391                      new Rectangle(x, y, width, height));
392        }
393
394        if (isDrawingBuffer()) {
395            if (debugBuffered()) {
396                Graphics debugGraphics = debugGraphics();
397
398                debugGraphics.fillRect(x, y, width, height);
399                debugGraphics.dispose();
400            }
401        } else if (debugFlash()) {
402            Color oldColor = getColor();
403            int i, count = (info.flashCount * 2) - 1;
404
405            for (i = 0; i < count; i++) {
406                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
407                graphics.fillRect(x, y, width, height);
408                Toolkit.getDefaultToolkit().sync();
409                sleep(info.flashTime);
410            }
411            graphics.setColor(oldColor);
412        }
413        graphics.fillRect(x, y, width, height);
414    }
415
416    /**
417     * Overrides <code>Graphics.clearRect</code>.
418     */
419    public void clearRect(int x, int y, int width, int height) {
420        DebugGraphicsInfo info = info();
421
422        if (debugLog()) {
423            info().log(toShortString() +
424                      " Clearing rect: " +
425                      new Rectangle(x, y, width, height));
426        }
427
428        if (isDrawingBuffer()) {
429            if (debugBuffered()) {
430                Graphics debugGraphics = debugGraphics();
431
432                debugGraphics.clearRect(x, y, width, height);
433                debugGraphics.dispose();
434            }
435        } else if (debugFlash()) {
436            Color oldColor = getColor();
437            int i, count = (info.flashCount * 2) - 1;
438
439            for (i = 0; i < count; i++) {
440                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
441                graphics.clearRect(x, y, width, height);
442                Toolkit.getDefaultToolkit().sync();
443                sleep(info.flashTime);
444            }
445            graphics.setColor(oldColor);
446        }
447        graphics.clearRect(x, y, width, height);
448    }
449
450    /**
451     * Overrides <code>Graphics.drawRoundRect</code>.
452     */
453    public void drawRoundRect(int x, int y, int width, int height,
454                              int arcWidth, int arcHeight) {
455        DebugGraphicsInfo info = info();
456
457        if (debugLog()) {
458            info().log(toShortString() +
459                      " Drawing round rect: " +
460                      new Rectangle(x, y, width, height) +
461                      " arcWidth: " + arcWidth +
462                      " archHeight: " + arcHeight);
463        }
464        if (isDrawingBuffer()) {
465            if (debugBuffered()) {
466                Graphics debugGraphics = debugGraphics();
467
468                debugGraphics.drawRoundRect(x, y, width, height,
469                                            arcWidth, arcHeight);
470                debugGraphics.dispose();
471            }
472        } else if (debugFlash()) {
473            Color oldColor = getColor();
474            int i, count = (info.flashCount * 2) - 1;
475
476            for (i = 0; i < count; i++) {
477                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
478                graphics.drawRoundRect(x, y, width, height,
479                                       arcWidth, arcHeight);
480                Toolkit.getDefaultToolkit().sync();
481                sleep(info.flashTime);
482            }
483            graphics.setColor(oldColor);
484        }
485        graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
486    }
487
488    /**
489     * Overrides <code>Graphics.fillRoundRect</code>.
490     */
491    public void fillRoundRect(int x, int y, int width, int height,
492                              int arcWidth, int arcHeight) {
493        DebugGraphicsInfo info = info();
494
495        if (debugLog()) {
496            info().log(toShortString() +
497                      " Filling round rect: " +
498                      new Rectangle(x, y, width, height) +
499                      " arcWidth: " + arcWidth +
500                      " archHeight: " + arcHeight);
501        }
502        if (isDrawingBuffer()) {
503            if (debugBuffered()) {
504                Graphics debugGraphics = debugGraphics();
505
506                debugGraphics.fillRoundRect(x, y, width, height,
507                                            arcWidth, arcHeight);
508                debugGraphics.dispose();
509            }
510        } else if (debugFlash()) {
511            Color oldColor = getColor();
512            int i, count = (info.flashCount * 2) - 1;
513
514            for (i = 0; i < count; i++) {
515                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
516                graphics.fillRoundRect(x, y, width, height,
517                                       arcWidth, arcHeight);
518                Toolkit.getDefaultToolkit().sync();
519                sleep(info.flashTime);
520            }
521            graphics.setColor(oldColor);
522        }
523        graphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
524    }
525
526    /**
527     * Overrides <code>Graphics.drawLine</code>.
528     */
529    public void drawLine(int x1, int y1, int x2, int y2) {
530        DebugGraphicsInfo info = info();
531
532        if (debugLog()) {
533            info().log(toShortString() +
534                       " Drawing line: from " + pointToString(x1, y1) +
535                       " to " +  pointToString(x2, y2));
536        }
537
538        if (isDrawingBuffer()) {
539            if (debugBuffered()) {
540                Graphics debugGraphics = debugGraphics();
541
542                debugGraphics.drawLine(x1, y1, x2, y2);
543                debugGraphics.dispose();
544            }
545        } else if (debugFlash()) {
546            Color oldColor = getColor();
547            int i, count = (info.flashCount * 2) - 1;
548
549            for (i = 0; i < count; i++) {
550                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
551                graphics.drawLine(x1, y1, x2, y2);
552                Toolkit.getDefaultToolkit().sync();
553                sleep(info.flashTime);
554            }
555            graphics.setColor(oldColor);
556        }
557        graphics.drawLine(x1, y1, x2, y2);
558    }
559
560    /**
561     * Overrides <code>Graphics.draw3DRect</code>.
562     */
563    public void draw3DRect(int x, int y, int width, int height,
564                           boolean raised) {
565        DebugGraphicsInfo info = info();
566
567        if (debugLog()) {
568            info().log(toShortString() +
569                       " Drawing 3D rect: " +
570                       new Rectangle(x, y, width, height) +
571                       " Raised bezel: " + raised);
572        }
573        if (isDrawingBuffer()) {
574            if (debugBuffered()) {
575                Graphics debugGraphics = debugGraphics();
576
577                debugGraphics.draw3DRect(x, y, width, height, raised);
578                debugGraphics.dispose();
579            }
580        } else if (debugFlash()) {
581            Color oldColor = getColor();
582            int i, count = (info.flashCount * 2) - 1;
583
584            for (i = 0; i < count; i++) {
585                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
586                graphics.draw3DRect(x, y, width, height, raised);
587                Toolkit.getDefaultToolkit().sync();
588                sleep(info.flashTime);
589            }
590            graphics.setColor(oldColor);
591        }
592        graphics.draw3DRect(x, y, width, height, raised);
593    }
594
595    /**
596     * Overrides <code>Graphics.fill3DRect</code>.
597     */
598    public void fill3DRect(int x, int y, int width, int height,
599                           boolean raised) {
600        DebugGraphicsInfo info = info();
601
602        if (debugLog()) {
603            info().log(toShortString() +
604                       " Filling 3D rect: " +
605                       new Rectangle(x, y, width, height) +
606                       " Raised bezel: " + raised);
607        }
608        if (isDrawingBuffer()) {
609            if (debugBuffered()) {
610                Graphics debugGraphics = debugGraphics();
611
612                debugGraphics.fill3DRect(x, y, width, height, raised);
613                debugGraphics.dispose();
614            }
615        } else if (debugFlash()) {
616            Color oldColor = getColor();
617            int i, count = (info.flashCount * 2) - 1;
618
619            for (i = 0; i < count; i++) {
620                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
621                graphics.fill3DRect(x, y, width, height, raised);
622                Toolkit.getDefaultToolkit().sync();
623                sleep(info.flashTime);
624            }
625            graphics.setColor(oldColor);
626        }
627        graphics.fill3DRect(x, y, width, height, raised);
628    }
629
630    /**
631     * Overrides <code>Graphics.drawOval</code>.
632     */
633    public void drawOval(int x, int y, int width, int height) {
634        DebugGraphicsInfo info = info();
635
636        if (debugLog()) {
637            info().log(toShortString() +
638                      " Drawing oval: " +
639                      new Rectangle(x, y, width, height));
640        }
641        if (isDrawingBuffer()) {
642            if (debugBuffered()) {
643                Graphics debugGraphics = debugGraphics();
644
645                debugGraphics.drawOval(x, y, width, height);
646                debugGraphics.dispose();
647            }
648        } else if (debugFlash()) {
649            Color oldColor = getColor();
650            int i, count = (info.flashCount * 2) - 1;
651
652            for (i = 0; i < count; i++) {
653                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
654                graphics.drawOval(x, y, width, height);
655                Toolkit.getDefaultToolkit().sync();
656                sleep(info.flashTime);
657            }
658            graphics.setColor(oldColor);
659        }
660        graphics.drawOval(x, y, width, height);
661    }
662
663    /**
664     * Overrides <code>Graphics.fillOval</code>.
665     */
666    public void fillOval(int x, int y, int width, int height) {
667        DebugGraphicsInfo info = info();
668
669        if (debugLog()) {
670            info().log(toShortString() +
671                      " Filling oval: " +
672                      new Rectangle(x, y, width, height));
673        }
674        if (isDrawingBuffer()) {
675            if (debugBuffered()) {
676                Graphics debugGraphics = debugGraphics();
677
678                debugGraphics.fillOval(x, y, width, height);
679                debugGraphics.dispose();
680            }
681        } else if (debugFlash()) {
682            Color oldColor = getColor();
683            int i, count = (info.flashCount * 2) - 1;
684
685            for (i = 0; i < count; i++) {
686                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
687                graphics.fillOval(x, y, width, height);
688                Toolkit.getDefaultToolkit().sync();
689                sleep(info.flashTime);
690            }
691            graphics.setColor(oldColor);
692        }
693        graphics.fillOval(x, y, width, height);
694    }
695
696    /**
697     * Overrides <code>Graphics.drawArc</code>.
698     */
699    public void drawArc(int x, int y, int width, int height,
700                        int startAngle, int arcAngle) {
701        DebugGraphicsInfo info = info();
702
703        if (debugLog()) {
704            info().log(toShortString() +
705                      " Drawing arc: " +
706                      new Rectangle(x, y, width, height) +
707                      " startAngle: " + startAngle +
708                      " arcAngle: " + arcAngle);
709        }
710        if (isDrawingBuffer()) {
711            if (debugBuffered()) {
712                Graphics debugGraphics = debugGraphics();
713
714                debugGraphics.drawArc(x, y, width, height,
715                                      startAngle, arcAngle);
716                debugGraphics.dispose();
717            }
718        } else if (debugFlash()) {
719            Color oldColor = getColor();
720            int i, count = (info.flashCount * 2) - 1;
721
722            for (i = 0; i < count; i++) {
723                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
724                graphics.drawArc(x, y, width, height, startAngle, arcAngle);
725                Toolkit.getDefaultToolkit().sync();
726                sleep(info.flashTime);
727            }
728            graphics.setColor(oldColor);
729        }
730        graphics.drawArc(x, y, width, height, startAngle, arcAngle);
731    }
732
733    /**
734     * Overrides <code>Graphics.fillArc</code>.
735     */
736    public void fillArc(int x, int y, int width, int height,
737                        int startAngle, int arcAngle) {
738        DebugGraphicsInfo info = info();
739
740        if (debugLog()) {
741            info().log(toShortString() +
742                      " Filling arc: " +
743                      new Rectangle(x, y, width, height) +
744                      " startAngle: " + startAngle +
745                      " arcAngle: " + arcAngle);
746        }
747        if (isDrawingBuffer()) {
748            if (debugBuffered()) {
749                Graphics debugGraphics = debugGraphics();
750
751                debugGraphics.fillArc(x, y, width, height,
752                                      startAngle, arcAngle);
753                debugGraphics.dispose();
754            }
755        } else if (debugFlash()) {
756            Color oldColor = getColor();
757            int i, count = (info.flashCount * 2) - 1;
758
759            for (i = 0; i < count; i++) {
760                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
761                graphics.fillArc(x, y, width, height, startAngle, arcAngle);
762                Toolkit.getDefaultToolkit().sync();
763                sleep(info.flashTime);
764            }
765            graphics.setColor(oldColor);
766        }
767        graphics.fillArc(x, y, width, height, startAngle, arcAngle);
768    }
769
770    /**
771     * Overrides <code>Graphics.drawPolyline</code>.
772     */
773    public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
774        DebugGraphicsInfo info = info();
775
776        if (debugLog()) {
777            info().log(toShortString() +
778                      " Drawing polyline: " +
779                      " nPoints: " + nPoints +
780                      " X's: " + xPoints +
781                      " Y's: " + yPoints);
782        }
783        if (isDrawingBuffer()) {
784            if (debugBuffered()) {
785                Graphics debugGraphics = debugGraphics();
786
787                debugGraphics.drawPolyline(xPoints, yPoints, nPoints);
788                debugGraphics.dispose();
789            }
790        } else if (debugFlash()) {
791            Color oldColor = getColor();
792            int i, count = (info.flashCount * 2) - 1;
793
794            for (i = 0; i < count; i++) {
795                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
796                graphics.drawPolyline(xPoints, yPoints, nPoints);
797                Toolkit.getDefaultToolkit().sync();
798                sleep(info.flashTime);
799            }
800            graphics.setColor(oldColor);
801        }
802        graphics.drawPolyline(xPoints, yPoints, nPoints);
803    }
804
805    /**
806     * Overrides <code>Graphics.drawPolygon</code>.
807     */
808    public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
809        DebugGraphicsInfo info = info();
810
811        if (debugLog()) {
812            info().log(toShortString() +
813                      " Drawing polygon: " +
814                      " nPoints: " + nPoints +
815                      " X's: " + xPoints +
816                      " Y's: " + yPoints);
817        }
818        if (isDrawingBuffer()) {
819            if (debugBuffered()) {
820                Graphics debugGraphics = debugGraphics();
821
822                debugGraphics.drawPolygon(xPoints, yPoints, nPoints);
823                debugGraphics.dispose();
824            }
825        } else if (debugFlash()) {
826            Color oldColor = getColor();
827            int i, count = (info.flashCount * 2) - 1;
828
829            for (i = 0; i < count; i++) {
830                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
831                graphics.drawPolygon(xPoints, yPoints, nPoints);
832                Toolkit.getDefaultToolkit().sync();
833                sleep(info.flashTime);
834            }
835            graphics.setColor(oldColor);
836        }
837        graphics.drawPolygon(xPoints, yPoints, nPoints);
838    }
839
840    /**
841     * Overrides <code>Graphics.fillPolygon</code>.
842     */
843    public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
844        DebugGraphicsInfo info = info();
845
846        if (debugLog()) {
847            info().log(toShortString() +
848                      " Filling polygon: " +
849                      " nPoints: " + nPoints +
850                      " X's: " + xPoints +
851                      " Y's: " + yPoints);
852        }
853        if (isDrawingBuffer()) {
854            if (debugBuffered()) {
855                Graphics debugGraphics = debugGraphics();
856
857                debugGraphics.fillPolygon(xPoints, yPoints, nPoints);
858                debugGraphics.dispose();
859            }
860        } else if (debugFlash()) {
861            Color oldColor = getColor();
862            int i, count = (info.flashCount * 2) - 1;
863
864            for (i = 0; i < count; i++) {
865                graphics.setColor((i % 2) == 0 ? info.flashColor : oldColor);
866                graphics.fillPolygon(xPoints, yPoints, nPoints);
867                Toolkit.getDefaultToolkit().sync();
868                sleep(info.flashTime);
869            }
870            graphics.setColor(oldColor);
871        }
872        graphics.fillPolygon(xPoints, yPoints, nPoints);
873    }
874
875    /**
876     * Overrides <code>Graphics.drawString</code>.
877     */
878    public void drawString(String aString, int x, int y) {
879        DebugGraphicsInfo info = info();
880
881        if (debugLog()) {
882            info().log(toShortString() +
883                       " Drawing string: \"" + aString +
884                       "\" at: " + new Point(x, y));
885        }
886
887        if (isDrawingBuffer()) {
888            if (debugBuffered()) {
889                Graphics debugGraphics = debugGraphics();
890
891                debugGraphics.drawString(aString, x, y);
892                debugGraphics.dispose();
893            }
894        } else if (debugFlash()) {
895            Color oldColor = getColor();
896            int i, count = (info.flashCount * 2) - 1;
897
898            for (i = 0; i < count; i++) {
899                graphics.setColor((i % 2) == 0 ? info.flashColor
900                                  : oldColor);
901                graphics.drawString(aString, x, y);
902                Toolkit.getDefaultToolkit().sync();
903                sleep(info.flashTime);
904            }
905            graphics.setColor(oldColor);
906        }
907        graphics.drawString(aString, x, y);
908    }
909
910    /**
911     * Overrides <code>Graphics.drawString</code>.
912     */
913    public void drawString(AttributedCharacterIterator iterator, int x, int y) {
914        DebugGraphicsInfo info = info();
915
916        if (debugLog()) {
917            info().log(toShortString() +
918                       " Drawing text: \"" + iterator +
919                       "\" at: " + new Point(x, y));
920        }
921
922        if (isDrawingBuffer()) {
923            if (debugBuffered()) {
924                Graphics debugGraphics = debugGraphics();
925
926                debugGraphics.drawString(iterator, x, y);
927                debugGraphics.dispose();
928            }
929        } else if (debugFlash()) {
930            Color oldColor = getColor();
931            int i, count = (info.flashCount * 2) - 1;
932
933            for (i = 0; i < count; i++) {
934                graphics.setColor((i % 2) == 0 ? info.flashColor
935                                  : oldColor);
936                graphics.drawString(iterator, x, y);
937                Toolkit.getDefaultToolkit().sync();
938                sleep(info.flashTime);
939            }
940            graphics.setColor(oldColor);
941        }
942        graphics.drawString(iterator, x, y);
943    }
944
945    /**
946     * Overrides <code>Graphics.drawBytes</code>.
947     */
948    public void drawBytes(byte data[], int offset, int length, int x, int y) {
949        DebugGraphicsInfo info = info();
950
951        Font font = graphics.getFont();
952
953        if (debugLog()) {
954            info().log(toShortString() +
955                       " Drawing bytes at: " + new Point(x, y));
956        }
957
958        if (isDrawingBuffer()) {
959            if (debugBuffered()) {
960                Graphics debugGraphics = debugGraphics();
961
962                debugGraphics.drawBytes(data, offset, length, x, y);
963                debugGraphics.dispose();
964            }
965        } else if (debugFlash()) {
966            Color oldColor = getColor();
967            int i, count = (info.flashCount * 2) - 1;
968
969            for (i = 0; i < count; i++) {
970                graphics.setColor((i % 2) == 0 ? info.flashColor
971                                  : oldColor);
972                graphics.drawBytes(data, offset, length, x, y);
973                Toolkit.getDefaultToolkit().sync();
974                sleep(info.flashTime);
975            }
976            graphics.setColor(oldColor);
977        }
978        graphics.drawBytes(data, offset, length, x, y);
979    }
980
981    /**
982     * Overrides <code>Graphics.drawChars</code>.
983     */
984    public void drawChars(char data[], int offset, int length, int x, int y) {
985        DebugGraphicsInfo info = info();
986
987        Font font = graphics.getFont();
988
989        if (debugLog()) {
990            info().log(toShortString() +
991                       " Drawing chars at " +  new Point(x, y));
992        }
993
994        if (isDrawingBuffer()) {
995            if (debugBuffered()) {
996                Graphics debugGraphics = debugGraphics();
997
998                debugGraphics.drawChars(data, offset, length, x, y);
999                debugGraphics.dispose();
1000            }
1001        } else if (debugFlash()) {
1002            Color oldColor = getColor();
1003            int i, count = (info.flashCount * 2) - 1;
1004
1005            for (i = 0; i < count; i++) {
1006                graphics.setColor((i % 2) == 0 ? info.flashColor
1007                                  : oldColor);
1008                graphics.drawChars(data, offset, length, x, y);
1009                Toolkit.getDefaultToolkit().sync();
1010                sleep(info.flashTime);
1011            }
1012            graphics.setColor(oldColor);
1013        }
1014        graphics.drawChars(data, offset, length, x, y);
1015    }
1016
1017    /**
1018     * Overrides <code>Graphics.drawImage</code>.
1019     */
1020    public boolean drawImage(Image img, int x, int y,
1021                             ImageObserver observer) {
1022        DebugGraphicsInfo info = info();
1023
1024        if (debugLog()) {
1025            info.log(toShortString() +
1026                     " Drawing image: " + img +
1027                     " at: " + new Point(x, y));
1028        }
1029
1030        if (isDrawingBuffer()) {
1031            if (debugBuffered()) {
1032                Graphics debugGraphics = debugGraphics();
1033
1034                debugGraphics.drawImage(img, x, y, observer);
1035                debugGraphics.dispose();
1036            }
1037        } else if (debugFlash()) {
1038            int i, count = (info.flashCount * 2) - 1;
1039            ImageProducer oldProducer = img.getSource();
1040            ImageProducer newProducer
1041                = new FilteredImageSource(oldProducer,
1042                                new DebugGraphicsFilter(info.flashColor));
1043            Image newImage
1044                = Toolkit.getDefaultToolkit().createImage(newProducer);
1045            DebugGraphicsObserver imageObserver
1046                = new DebugGraphicsObserver();
1047
1048            Image imageToDraw;
1049            for (i = 0; i < count; i++) {
1050                imageToDraw = (i % 2) == 0 ? newImage : img;
1051                loadImage(imageToDraw);
1052                graphics.drawImage(imageToDraw, x, y,
1053                                   imageObserver);
1054                Toolkit.getDefaultToolkit().sync();
1055                sleep(info.flashTime);
1056            }
1057        }
1058        return graphics.drawImage(img, x, y, observer);
1059    }
1060
1061    /**
1062     * Overrides <code>Graphics.drawImage</code>.
1063     */
1064    public boolean drawImage(Image img, int x, int y, int width, int height,
1065                             ImageObserver observer) {
1066        DebugGraphicsInfo info = info();
1067
1068        if (debugLog()) {
1069            info.log(toShortString() +
1070                     " Drawing image: " + img +
1071                     " at: " + new Rectangle(x, y, width, height));
1072        }
1073
1074        if (isDrawingBuffer()) {
1075            if (debugBuffered()) {
1076                Graphics debugGraphics = debugGraphics();
1077
1078                debugGraphics.drawImage(img, x, y, width, height, observer);
1079                debugGraphics.dispose();
1080            }
1081        } else if (debugFlash()) {
1082            int i, count = (info.flashCount * 2) - 1;
1083            ImageProducer oldProducer = img.getSource();
1084            ImageProducer newProducer
1085                = new FilteredImageSource(oldProducer,
1086                                new DebugGraphicsFilter(info.flashColor));
1087            Image newImage
1088                = Toolkit.getDefaultToolkit().createImage(newProducer);
1089            DebugGraphicsObserver imageObserver
1090                = new DebugGraphicsObserver();
1091
1092            Image imageToDraw;
1093            for (i = 0; i < count; i++) {
1094                imageToDraw = (i % 2) == 0 ? newImage : img;
1095                loadImage(imageToDraw);
1096                graphics.drawImage(imageToDraw, x, y,
1097                                   width, height, imageObserver);
1098                Toolkit.getDefaultToolkit().sync();
1099                sleep(info.flashTime);
1100            }
1101        }
1102        return graphics.drawImage(img, x, y, width, height, observer);
1103    }
1104
1105    /**
1106     * Overrides <code>Graphics.drawImage</code>.
1107     */
1108    public boolean drawImage(Image img, int x, int y,
1109                             Color bgcolor,
1110                             ImageObserver observer) {
1111        DebugGraphicsInfo info = info();
1112
1113        if (debugLog()) {
1114            info.log(toShortString() +
1115                     " Drawing image: " + img +
1116                     " at: " + new Point(x, y) +
1117                     ", bgcolor: " + bgcolor);
1118        }
1119
1120        if (isDrawingBuffer()) {
1121            if (debugBuffered()) {
1122                Graphics debugGraphics = debugGraphics();
1123
1124                debugGraphics.drawImage(img, x, y, bgcolor, observer);
1125                debugGraphics.dispose();
1126            }
1127        } else if (debugFlash()) {
1128            int i, count = (info.flashCount * 2) - 1;
1129            ImageProducer oldProducer = img.getSource();
1130            ImageProducer newProducer
1131                = new FilteredImageSource(oldProducer,
1132                                new DebugGraphicsFilter(info.flashColor));
1133            Image newImage
1134                = Toolkit.getDefaultToolkit().createImage(newProducer);
1135            DebugGraphicsObserver imageObserver
1136                = new DebugGraphicsObserver();
1137
1138            Image imageToDraw;
1139            for (i = 0; i < count; i++) {
1140                imageToDraw = (i % 2) == 0 ? newImage : img;
1141                loadImage(imageToDraw);
1142                graphics.drawImage(imageToDraw, x, y,
1143                                   bgcolor, imageObserver);
1144                Toolkit.getDefaultToolkit().sync();
1145                sleep(info.flashTime);
1146            }
1147        }
1148        return graphics.drawImage(img, x, y, bgcolor, observer);
1149    }
1150
1151    /**
1152     * Overrides <code>Graphics.drawImage</code>.
1153     */
1154    public boolean drawImage(Image img, int x, int y,int width, int height,
1155                             Color bgcolor,
1156                             ImageObserver observer) {
1157        DebugGraphicsInfo info = info();
1158
1159        if (debugLog()) {
1160            info.log(toShortString() +
1161                     " Drawing image: " + img +
1162                     " at: " + new Rectangle(x, y, width, height) +
1163                     ", bgcolor: " + bgcolor);
1164        }
1165
1166        if (isDrawingBuffer()) {
1167            if (debugBuffered()) {
1168                Graphics debugGraphics = debugGraphics();
1169
1170                debugGraphics.drawImage(img, x, y, width, height,
1171                                        bgcolor, observer);
1172                debugGraphics.dispose();
1173            }
1174        } else if (debugFlash()) {
1175            int i, count = (info.flashCount * 2) - 1;
1176            ImageProducer oldProducer = img.getSource();
1177            ImageProducer newProducer
1178                = new FilteredImageSource(oldProducer,
1179                                new DebugGraphicsFilter(info.flashColor));
1180            Image newImage
1181                = Toolkit.getDefaultToolkit().createImage(newProducer);
1182            DebugGraphicsObserver imageObserver
1183                = new DebugGraphicsObserver();
1184
1185            Image imageToDraw;
1186            for (i = 0; i < count; i++) {
1187                imageToDraw = (i % 2) == 0 ? newImage : img;
1188                loadImage(imageToDraw);
1189                graphics.drawImage(imageToDraw, x, y,
1190                                   width, height, bgcolor, imageObserver);
1191                Toolkit.getDefaultToolkit().sync();
1192                sleep(info.flashTime);
1193            }
1194        }
1195        return graphics.drawImage(img, x, y, width, height, bgcolor, observer);
1196    }
1197
1198    /**
1199     * Overrides <code>Graphics.drawImage</code>.
1200     */
1201    public boolean drawImage(Image img,
1202                             int dx1, int dy1, int dx2, int dy2,
1203                             int sx1, int sy1, int sx2, int sy2,
1204                             ImageObserver observer) {
1205        DebugGraphicsInfo info = info();
1206
1207        if (debugLog()) {
1208            info.log(toShortString() +
1209                     " Drawing image: " + img +
1210                     " destination: " + new Rectangle(dx1, dy1, dx2, dy2) +
1211                     " source: " + new Rectangle(sx1, sy1, sx2, sy2));
1212        }
1213
1214        if (isDrawingBuffer()) {
1215            if (debugBuffered()) {
1216                Graphics debugGraphics = debugGraphics();
1217
1218                debugGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1219                                        sx1, sy1, sx2, sy2, observer);
1220                debugGraphics.dispose();
1221            }
1222        } else if (debugFlash()) {
1223            int i, count = (info.flashCount * 2) - 1;
1224            ImageProducer oldProducer = img.getSource();
1225            ImageProducer newProducer
1226                = new FilteredImageSource(oldProducer,
1227                                new DebugGraphicsFilter(info.flashColor));
1228            Image newImage
1229                = Toolkit.getDefaultToolkit().createImage(newProducer);
1230            DebugGraphicsObserver imageObserver
1231                = new DebugGraphicsObserver();
1232
1233            Image imageToDraw;
1234            for (i = 0; i < count; i++) {
1235                imageToDraw = (i % 2) == 0 ? newImage : img;
1236                loadImage(imageToDraw);
1237                graphics.drawImage(imageToDraw,
1238                                   dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1239                                   imageObserver);
1240                Toolkit.getDefaultToolkit().sync();
1241                sleep(info.flashTime);
1242            }
1243        }
1244        return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1245                                  observer);
1246    }
1247
1248    /**
1249     * Overrides <code>Graphics.drawImage</code>.
1250     */
1251    public boolean drawImage(Image img,
1252                             int dx1, int dy1, int dx2, int dy2,
1253                             int sx1, int sy1, int sx2, int sy2,
1254                             Color bgcolor,
1255                             ImageObserver observer) {
1256        DebugGraphicsInfo info = info();
1257
1258        if (debugLog()) {
1259            info.log(toShortString() +
1260                     " Drawing image: " + img +
1261                     " destination: " + new Rectangle(dx1, dy1, dx2, dy2) +
1262                     " source: " + new Rectangle(sx1, sy1, sx2, sy2) +
1263                     ", bgcolor: " + bgcolor);
1264        }
1265
1266        if (isDrawingBuffer()) {
1267            if (debugBuffered()) {
1268                Graphics debugGraphics = debugGraphics();
1269
1270                debugGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1271                                        sx1, sy1, sx2, sy2, bgcolor, observer);
1272                debugGraphics.dispose();
1273            }
1274        } else if (debugFlash()) {
1275            int i, count = (info.flashCount * 2) - 1;
1276            ImageProducer oldProducer = img.getSource();
1277            ImageProducer newProducer
1278                = new FilteredImageSource(oldProducer,
1279                                new DebugGraphicsFilter(info.flashColor));
1280            Image newImage
1281                = Toolkit.getDefaultToolkit().createImage(newProducer);
1282            DebugGraphicsObserver imageObserver
1283                = new DebugGraphicsObserver();
1284
1285            Image imageToDraw;
1286            for (i = 0; i < count; i++) {
1287                imageToDraw = (i % 2) == 0 ? newImage : img;
1288                loadImage(imageToDraw);
1289                graphics.drawImage(imageToDraw,
1290                                   dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1291                                   bgcolor, imageObserver);
1292                Toolkit.getDefaultToolkit().sync();
1293                sleep(info.flashTime);
1294            }
1295        }
1296        return graphics.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1297                                  bgcolor, observer);
1298    }
1299
1300    static void loadImage(Image img) {
1301        imageLoadingIcon.loadImage(img);
1302    }
1303
1304
1305    /**
1306     * Overrides <code>Graphics.copyArea</code>.
1307     */
1308    public void copyArea(int x, int y, int width, int height,
1309                         int destX, int destY) {
1310        if (debugLog()) {
1311            info().log(toShortString() +
1312                      " Copying area from: " +
1313                      new Rectangle(x, y, width, height) +
1314                      " to: " + new Point(destX, destY));
1315        }
1316        graphics.copyArea(x, y, width, height, destX, destY);
1317    }
1318
1319    final void sleep(int mSecs) {
1320        try {
1321            Thread.sleep(mSecs);
1322        } catch (Exception e) {
1323        }
1324    }
1325
1326    /**
1327     * Overrides <code>Graphics.dispose</code>.
1328     */
1329    public void dispose() {
1330        graphics.dispose();
1331        graphics = null;
1332    }
1333
1334    // ALERT!
1335    /**
1336     * Returns the drawingBuffer value.
1337     *
1338     * @return true if this object is drawing from a Buffer
1339     */
1340    public boolean isDrawingBuffer() {
1341        return buffer != null;
1342    }
1343
1344    String toShortString() {
1345        return "Graphics" + (isDrawingBuffer() ? "<B>" : "") + "(" + graphicsID + "-" + debugOptions + ")";
1346    }
1347
1348    String pointToString(int x, int y) {
1349        return "(" + x + ", " + y + ")";
1350    }
1351
1352    /** Enables/disables diagnostic information about every graphics
1353      * operation. The value of <b>options</b> indicates how this information
1354      * should be displayed. LOG_OPTION causes a text message to be printed.
1355      * FLASH_OPTION causes the drawing to flash several times. BUFFERED_OPTION
1356      * creates a new Frame that shows each operation on an
1357      * offscreen buffer. The value of <b>options</b> is bitwise OR'd into
1358      * the current value. To disable debugging use NONE_OPTION.
1359      *
1360      * @param options indicates how diagnostic information should be displayed
1361      */
1362    public void setDebugOptions(int options) {
1363        if (options != 0) {
1364            if (options == NONE_OPTION) {
1365                if (debugOptions != 0) {
1366                    System.err.println(toShortString() + " Disabling debug");
1367                    debugOptions = 0;
1368                }
1369            } else {
1370                if (debugOptions != options) {
1371                    debugOptions |= options;
1372                    if (debugLog()) {
1373                        System.err.println(toShortString() + " Enabling debug");
1374                    }
1375                }
1376            }
1377        }
1378    }
1379
1380    /**
1381     * Returns the current debugging options for this DebugGraphics.
1382     *
1383     * @return the current debugging options for this DebugGraphics
1384     * @see #setDebugOptions
1385     */
1386    public int getDebugOptions() {
1387        return debugOptions;
1388    }
1389
1390    /** Static wrapper method for DebugGraphicsInfo.setDebugOptions(). Stores
1391      * options on a per component basis.
1392      */
1393    static void setDebugOptions(JComponent component, int options) {
1394        info().setDebugOptions(component, options);
1395    }
1396
1397    /** Static wrapper method for DebugGraphicsInfo.getDebugOptions().
1398      */
1399    static int getDebugOptions(JComponent component) {
1400        DebugGraphicsInfo debugGraphicsInfo = info();
1401        if (debugGraphicsInfo == null) {
1402            return 0;
1403        } else {
1404            return debugGraphicsInfo.getDebugOptions(component);
1405        }
1406    }
1407
1408    /** Returns non-zero if <b>component</b> should display with DebugGraphics,
1409      * zero otherwise. Walks the JComponent's parent tree to determine if
1410      * any debugging options have been set.
1411      */
1412    static int shouldComponentDebug(JComponent component) {
1413        DebugGraphicsInfo info = info();
1414        if (info == null) {
1415            return 0;
1416        } else {
1417            Container container = (Container)component;
1418            int debugOptions = 0;
1419
1420            while (container != null && (container instanceof JComponent)) {
1421                debugOptions |= info.getDebugOptions((JComponent)container);
1422                container = container.getParent();
1423            }
1424
1425            return debugOptions;
1426        }
1427    }
1428
1429    /** Returns the number of JComponents that have debugging options turned
1430      * on.
1431      */
1432    static int debugComponentCount() {
1433        DebugGraphicsInfo debugGraphicsInfo = info();
1434        if (debugGraphicsInfo != null &&
1435                    debugGraphicsInfo.componentToDebug != null) {
1436            return debugGraphicsInfo.componentToDebug.size();
1437        } else {
1438            return 0;
1439        }
1440    }
1441
1442    boolean debugLog() {
1443        return (debugOptions & LOG_OPTION) == LOG_OPTION;
1444    }
1445
1446    boolean debugFlash() {
1447        return (debugOptions & FLASH_OPTION) == FLASH_OPTION;
1448    }
1449
1450    boolean debugBuffered() {
1451        return (debugOptions & BUFFERED_OPTION) == BUFFERED_OPTION;
1452    }
1453
1454    /** Returns a DebugGraphics for use in buffering window.
1455      */
1456    @SuppressWarnings("deprecation")
1457    private Graphics debugGraphics() {
1458        DebugGraphics        debugGraphics;
1459        DebugGraphicsInfo    info = info();
1460        JFrame               debugFrame;
1461
1462        if (info.debugFrame == null) {
1463            info.debugFrame = new JFrame();
1464            info.debugFrame.setSize(500, 500);
1465        }
1466        debugFrame = info.debugFrame;
1467        debugFrame.show();
1468        debugGraphics = new DebugGraphics(debugFrame.getGraphics());
1469        debugGraphics.setFont(getFont());
1470        debugGraphics.setColor(getColor());
1471        debugGraphics.translate(xOffset, yOffset);
1472        debugGraphics.setClip(getClipBounds());
1473        if (debugFlash()) {
1474            debugGraphics.setDebugOptions(FLASH_OPTION);
1475        }
1476        return debugGraphics;
1477    }
1478
1479    /** Returns DebugGraphicsInfo, or creates one if none exists.
1480      */
1481    static DebugGraphicsInfo info() {
1482        DebugGraphicsInfo debugGraphicsInfo = (DebugGraphicsInfo)
1483            SwingUtilities.appContextGet(debugGraphicsInfoKey);
1484        if (debugGraphicsInfo == null) {
1485            debugGraphicsInfo = new DebugGraphicsInfo();
1486            SwingUtilities.appContextPut(debugGraphicsInfoKey,
1487                                         debugGraphicsInfo);
1488        }
1489        return debugGraphicsInfo;
1490    }
1491    private static final Class<DebugGraphicsInfo> debugGraphicsInfoKey = DebugGraphicsInfo.class;
1492}
1493