1 /*
   2  * Copyright (c) 1998, 2018, 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 
  26 package sun.print;
  27 
  28 import java.util.Map;
  29 
  30 import java.awt.Color;
  31 import java.awt.Composite;
  32 import java.awt.Graphics;
  33 import java.awt.Graphics2D;
  34 import java.awt.Font;
  35 import java.awt.FontMetrics;
  36 import java.awt.font.FontRenderContext;
  37 import java.awt.Graphics;
  38 import java.awt.GraphicsConfiguration;
  39 import java.awt.Image;
  40 import java.awt.Paint;
  41 import java.awt.Rectangle;
  42 import java.awt.Shape;
  43 import java.awt.Stroke;
  44 import java.awt.RenderingHints;
  45 import java.awt.RenderingHints.Key;
  46 
  47 import java.awt.font.GlyphVector;
  48 
  49 import java.awt.geom.AffineTransform;
  50 import java.awt.geom.Rectangle2D;
  51 import java.awt.geom.NoninvertibleTransformException;
  52 import java.awt.image.BufferedImage;
  53 import java.awt.image.BufferedImageOp;
  54 import java.awt.image.ImageObserver;
  55 import java.awt.image.RenderedImage;
  56 import java.awt.image.renderable.RenderContext;
  57 import java.awt.image.renderable.RenderableImage;
  58 import java.awt.print.PrinterGraphics;
  59 import java.awt.print.PrinterJob;
  60 
  61 import java.text.AttributedCharacterIterator;
  62 
  63 public class ProxyGraphics2D extends Graphics2D implements PrinterGraphics {
  64 
  65     /**
  66      * Drawing methods will be forwarded to this object.
  67      */
  68     Graphics2D mGraphics;
  69 
  70     /**
  71      * The PrinterJob controlling the current printing.
  72      */
  73     PrinterJob mPrinterJob;
  74 
  75     /**
  76      * The new ProxyGraphics2D will forward all graphics
  77      * calls to 'graphics'.
  78      */
  79     public ProxyGraphics2D(Graphics2D graphics, PrinterJob printerJob) {
  80         mGraphics = graphics;
  81         mPrinterJob = printerJob;
  82     }
  83 
  84     /**
  85      * Return the Graphics2D object that does the drawing
  86      * for this instance.
  87      */
  88     public Graphics2D getDelegate() {
  89         return mGraphics;
  90     }
  91 
  92     /**
  93      * Set the Graphics2D instance which will do the
  94      * drawing.
  95      */
  96     public void setDelegate(Graphics2D graphics) {
  97         mGraphics = graphics;
  98     }
  99 
 100     public PrinterJob getPrinterJob() {
 101         return mPrinterJob;
 102     }
 103 
 104     /**
 105      * Returns the device configuration associated with this Graphics2D.
 106      */
 107     public GraphicsConfiguration getDeviceConfiguration() {
 108         return ((RasterPrinterJob)mPrinterJob).getPrinterGraphicsConfig();
 109     }
 110 
 111 /* The Delegated Graphics Methods */
 112 
 113     /**
 114      * Creates a new {@code Graphics} object that is
 115      * a copy of this {@code Graphics} object.
 116      * @return     a new graphics context that is a copy of
 117      *                       this graphics context.
 118      * @since      1.0
 119      */
 120     public Graphics create() {
 121         return new ProxyGraphics2D((Graphics2D) mGraphics.create(),
 122                                    mPrinterJob);
 123     }
 124 
 125     /**
 126      * Translates the origin of the graphics context to the point
 127      * (<i>x</i>,&nbsp;<i>y</i>) in the current coordinate system.
 128      * Modifies this graphics context so that its new origin corresponds
 129      * to the point (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's
 130      * original coordinate system.  All coordinates used in subsequent
 131      * rendering operations on this graphics context will be relative
 132      * to this new origin.
 133      * @param  x   the <i>x</i> coordinate.
 134      * @param  y   the <i>y</i> coordinate.
 135      * @since   1.0
 136      */
 137     public void translate(int x, int y) {
 138         mGraphics.translate(x, y);
 139     }
 140 
 141     /**
 142      * Concatenates the current transform of this Graphics2D with a
 143      * translation transformation.
 144      * This is equivalent to calling transform(T), where T is an
 145      * AffineTransform represented by the following matrix:
 146      * <pre>
 147      *          [   1    0    tx  ]
 148      *          [   0    1    ty  ]
 149      *          [   0    0    1   ]
 150      * </pre>
 151      */
 152     public void translate(double tx, double ty) {
 153         mGraphics.translate(tx, ty);
 154     }
 155 
 156     /**
 157      * Concatenates the current transform of this Graphics2D with a
 158      * rotation transformation.
 159      * This is equivalent to calling transform(R), where R is an
 160      * AffineTransform represented by the following matrix:
 161      * <pre>
 162      *          [   cos(theta)    -sin(theta)    0   ]
 163      *          [   sin(theta)     cos(theta)    0   ]
 164      *          [       0              0         1   ]
 165      * </pre>
 166      * Rotating with a positive angle theta rotates points on the positive
 167      * x axis toward the positive y axis.
 168      * @param theta The angle of rotation in radians.
 169      */
 170     public void rotate(double theta) {
 171         mGraphics.rotate(theta);
 172     }
 173 
 174     /**
 175      * Concatenates the current transform of this Graphics2D with a
 176      * translated rotation transformation.
 177      * This is equivalent to the following sequence of calls:
 178      * <pre>
 179      *          translate(x, y);
 180      *          rotate(theta);
 181      *          translate(-x, -y);
 182      * </pre>
 183      * Rotating with a positive angle theta rotates points on the positive
 184      * x axis toward the positive y axis.
 185      * @param theta The angle of rotation in radians.
 186      * @param x The x coordinate of the origin of the rotation
 187      * @param y The x coordinate of the origin of the rotation
 188      */
 189     public void rotate(double theta, double x, double y) {
 190         mGraphics.rotate(theta, x, y);
 191     }
 192 
 193     /**
 194      * Concatenates the current transform of this Graphics2D with a
 195      * scaling transformation.
 196      * This is equivalent to calling transform(S), where S is an
 197      * AffineTransform represented by the following matrix:
 198      * <pre>
 199      *          [   sx   0    0   ]
 200      *          [   0    sy   0   ]
 201      *          [   0    0    1   ]
 202      * </pre>
 203      */
 204     public void scale(double sx, double sy) {
 205         mGraphics.scale(sx, sy);
 206     }
 207 
 208     /**
 209      * Concatenates the current transform of this Graphics2D with a
 210      * shearing transformation.
 211      * This is equivalent to calling transform(SH), where SH is an
 212      * AffineTransform represented by the following matrix:
 213      * <pre>
 214      *          [   1   shx   0   ]
 215      *          [  shy   1    0   ]
 216      *          [   0    0    1   ]
 217      * </pre>
 218      * @param shx The factor by which coordinates are shifted towards the
 219      * positive X axis direction according to their Y coordinate
 220      * @param shy The factor by which coordinates are shifted towards the
 221      * positive Y axis direction according to their X coordinate
 222      */
 223     public void shear(double shx, double shy) {
 224         mGraphics.shear(shx, shy);
 225     }
 226 
 227     /**
 228      * Gets this graphics context's current color.
 229      * @return    this graphics context's current color.
 230      * @see       java.awt.Color
 231      * @see       java.awt.Graphics#setColor
 232      * @since     1.0
 233      */
 234     public Color getColor() {
 235         return mGraphics.getColor();
 236     }
 237 
 238     /**
 239      * Sets this graphics context's current color to the specified
 240      * color. All subsequent graphics operations using this graphics
 241      * context use this specified color.
 242      * @param     c   the new rendering color.
 243      * @see       java.awt.Color
 244      * @see       java.awt.Graphics#getColor
 245      * @since     1.0
 246      */
 247     public void setColor(Color c) {
 248         mGraphics.setColor(c);
 249     }
 250 
 251     /**
 252      * Sets the paint mode of this graphics context to overwrite the
 253      * destination with this graphics context's current color.
 254      * This sets the logical pixel operation function to the paint or
 255      * overwrite mode.  All subsequent rendering operations will
 256      * overwrite the destination with the current color.
 257      * @since   1.0
 258      */
 259     public void setPaintMode() {
 260         mGraphics.setPaintMode();
 261     }
 262 
 263     /**
 264      * Sets the paint mode of this graphics context to alternate between
 265      * this graphics context's current color and the new specified color.
 266      * This specifies that logical pixel operations are performed in the
 267      * XOR mode, which alternates pixels between the current color and
 268      * a specified XOR color.
 269      * <p>
 270      * When drawing operations are performed, pixels which are the
 271      * current color are changed to the specified color, and vice versa.
 272      * <p>
 273      * Pixels that are of colors other than those two colors are changed
 274      * in an unpredictable but reversible manner; if the same figure is
 275      * drawn twice, then all pixels are restored to their original values.
 276      * @param     c1 the XOR alternation color
 277      * @since     1.0
 278      */
 279     public void setXORMode(Color c1) {
 280         mGraphics.setXORMode(c1);
 281     }
 282 
 283     /**
 284      * Gets the current font.
 285      * @return    this graphics context's current font.
 286      * @see       java.awt.Font
 287      * @see       java.awt.Graphics#setFont
 288      * @since     1.0
 289      */
 290     public Font getFont() {
 291         return mGraphics.getFont();
 292     }
 293 
 294     /**
 295      * Sets this graphics context's font to the specified font.
 296      * All subsequent text operations using this graphics context
 297      * use this font.
 298      * @param  font   the font.
 299      * @see     java.awt.Graphics#getFont
 300      * @see     java.awt.Graphics#drawChars(char[], int, int, int, int)
 301      * @see     java.awt.Graphics#drawString(String, int, int)
 302      * @see     java.awt.Graphics#drawBytes(byte[], int, int, int, int)
 303      * @since   1.0
 304     */
 305     public void setFont(Font font) {
 306         mGraphics.setFont(font);
 307     }
 308 
 309     /**
 310      * Gets the font metrics for the specified font.
 311      * @return    the font metrics for the specified font.
 312      * @param     f the specified font
 313      * @see       java.awt.Graphics#getFont
 314      * @see       java.awt.FontMetrics
 315      * @see       java.awt.Graphics#getFontMetrics()
 316      * @since     1.0
 317      */
 318     public FontMetrics getFontMetrics(Font f) {
 319         return mGraphics.getFontMetrics(f);
 320     }
 321 
 322     /**
 323     * Get the rendering context of the font
 324     * within this Graphics2D context.
 325     */
 326     public FontRenderContext getFontRenderContext() {
 327         return mGraphics.getFontRenderContext();
 328     }
 329 
 330     /**
 331      * Returns the bounding rectangle of the current clipping area.
 332      * The coordinates in the rectangle are relative to the coordinate
 333      * system origin of this graphics context.
 334      * @return      the bounding rectangle of the current clipping area.
 335      * @see         java.awt.Graphics#getClip
 336      * @see         java.awt.Graphics#clipRect
 337      * @see         java.awt.Graphics#setClip(int, int, int, int)
 338      * @see         java.awt.Graphics#setClip(Shape)
 339      * @since       1.1
 340      */
 341     public Rectangle getClipBounds() {
 342         return mGraphics.getClipBounds();
 343     }
 344 
 345 
 346     /**
 347      * Intersects the current clip with the specified rectangle.
 348      * The resulting clipping area is the intersection of the current
 349      * clipping area and the specified rectangle.
 350      * This method can only be used to make the current clip smaller.
 351      * To set the current clip larger, use any of the setClip methods.
 352      * Rendering operations have no effect outside of the clipping area.
 353      * @param x the x coordinate of the rectangle to intersect the clip with
 354      * @param y the y coordinate of the rectangle to intersect the clip with
 355      * @param width the width of the rectangle to intersect the clip with
 356      * @param height the height of the rectangle to intersect the clip with
 357      * @see #setClip(int, int, int, int)
 358      * @see #setClip(Shape)
 359      */
 360     public void clipRect(int x, int y, int width, int height) {
 361         mGraphics.clipRect(x, y, width, height);
 362     }
 363 
 364 
 365     /**
 366      * Sets the current clip to the rectangle specified by the given
 367      * coordinates.
 368      * Rendering operations have no effect outside of the clipping area.
 369      * @param       x the <i>x</i> coordinate of the new clip rectangle.
 370      * @param       y the <i>y</i> coordinate of the new clip rectangle.
 371      * @param       width the width of the new clip rectangle.
 372      * @param       height the height of the new clip rectangle.
 373      * @see         java.awt.Graphics#clipRect
 374      * @see         java.awt.Graphics#setClip(Shape)
 375      * @since       1.1
 376      */
 377     public void setClip(int x, int y, int width, int height) {
 378         mGraphics.setClip(x, y, width, height);
 379     }
 380 
 381     /**
 382      * Gets the current clipping area.
 383      * @return      a {@code Shape} object representing the
 384      *                      current clipping area.
 385      * @see         java.awt.Graphics#getClipBounds
 386      * @see         java.awt.Graphics#clipRect
 387      * @see         java.awt.Graphics#setClip(int, int, int, int)
 388      * @see         java.awt.Graphics#setClip(Shape)
 389      * @since       1.1
 390      */
 391     public Shape getClip() {
 392         return mGraphics.getClip();
 393     }
 394 
 395 
 396     /**
 397      * Sets the current clipping area to an arbitrary clip shape.
 398      * Not all objects which implement the {@code Shape}
 399      * interface can be used to set the clip.  The only
 400      * {@code Shape} objects which are guaranteed to be
 401      * supported are {@code Shape} objects which are
 402      * obtained via the {@code getClip} method and via
 403      * {@code Rectangle} objects.
 404      * @see         java.awt.Graphics#getClip()
 405      * @see         java.awt.Graphics#clipRect
 406      * @see         java.awt.Graphics#setClip(int, int, int, int)
 407      * @since       1.1
 408      */
 409     public void setClip(Shape clip) {
 410         mGraphics.setClip(clip);
 411     }
 412 
 413 
 414     /**
 415      * Copies an area of the component by a distance specified by
 416      * {@code dx} and {@code dy}. From the point specified
 417      * by {@code x} and {@code y}, this method
 418      * copies downwards and to the right.  To copy an area of the
 419      * component to the left or upwards, specify a negative value for
 420      * {@code dx} or {@code dy}.
 421      * If a portion of the source rectangle lies outside the bounds
 422      * of the component, or is obscured by another window or component,
 423      * {@code copyArea} will be unable to copy the associated
 424      * pixels. The area that is omitted can be refreshed by calling
 425      * the component's {@code paint} method.
 426      * @param       x the <i>x</i> coordinate of the source rectangle.
 427      * @param       y the <i>y</i> coordinate of the source rectangle.
 428      * @param       width the width of the source rectangle.
 429      * @param       height the height of the source rectangle.
 430      * @param       dx the horizontal distance to copy the pixels.
 431      * @param       dy the vertical distance to copy the pixels.
 432      * @since       1.0
 433      */
 434     public void copyArea(int x, int y, int width, int height,
 435                          int dx, int dy) {
 436         mGraphics.copyArea(x, y, width, height, dx, dy);
 437     }
 438 
 439     /**
 440      * Draws a line, using the current color, between the points
 441      * <code>(x1,&nbsp;y1)</code> and <code>(x2,&nbsp;y2)</code>
 442      * in this graphics context's coordinate system.
 443      * @param   x1  the first point's <i>x</i> coordinate.
 444      * @param   y1  the first point's <i>y</i> coordinate.
 445      * @param   x2  the second point's <i>x</i> coordinate.
 446      * @param   y2  the second point's <i>y</i> coordinate.
 447      * @since   1.0
 448      */
 449     public void drawLine(int x1, int y1, int x2, int y2) {
 450         mGraphics.drawLine(x1, y1, x2, y2);
 451     }
 452 
 453 
 454     /**
 455      * Fills the specified rectangle.
 456      * The left and right edges of the rectangle are at
 457      * {@code x} and <code>x&nbsp;+&nbsp;width&nbsp;-&nbsp;1</code>.
 458      * The top and bottom edges are at
 459      * {@code y} and <code>y&nbsp;+&nbsp;height&nbsp;-&nbsp;1</code>.
 460      * The resulting rectangle covers an area
 461      * {@code width} pixels wide by
 462      * {@code height} pixels tall.
 463      * The rectangle is filled using the graphics context's current color.
 464      * @param         x   the <i>x</i> coordinate
 465      *                         of the rectangle to be filled.
 466      * @param         y   the <i>y</i> coordinate
 467      *                         of the rectangle to be filled.
 468      * @param         width   the width of the rectangle to be filled.
 469      * @param         height   the height of the rectangle to be filled.
 470      * @see           java.awt.Graphics#fillRect
 471      * @see           java.awt.Graphics#clearRect
 472      * @since         1.0
 473      */
 474     public void fillRect(int x, int y, int width, int height) {
 475         mGraphics.fillRect(x, y, width, height);
 476     }
 477 
 478     /**
 479      * Clears the specified rectangle by filling it with the background
 480      * color of the current drawing surface. This operation does not
 481      * use the current paint mode.
 482      * <p>
 483      * Beginning with Java&nbsp;1.1, the background color
 484      * of offscreen images may be system dependent. Applications should
 485      * use {@code setColor} followed by {@code fillRect} to
 486      * ensure that an offscreen image is cleared to a specific color.
 487      * @param       x the <i>x</i> coordinate of the rectangle to clear.
 488      * @param       y the <i>y</i> coordinate of the rectangle to clear.
 489      * @param       width the width of the rectangle to clear.
 490      * @param       height the height of the rectangle to clear.
 491      * @see         java.awt.Graphics#fillRect(int, int, int, int)
 492      * @see         java.awt.Graphics#drawRect
 493      * @see         java.awt.Graphics#setColor(java.awt.Color)
 494      * @see         java.awt.Graphics#setPaintMode
 495      * @see         java.awt.Graphics#setXORMode(java.awt.Color)
 496      * @since       1.0
 497      */
 498     public void clearRect(int x, int y, int width, int height) {
 499         mGraphics.clearRect(x, y, width, height);
 500     }
 501 
 502     /**
 503      * Draws an outlined round-cornered rectangle using this graphics
 504      * context's current color. The left and right edges of the rectangle
 505      * are at {@code x} and <code>x&nbsp;+&nbsp;width</code>,
 506      * respectively. The top and bottom edges of the rectangle are at
 507      * {@code y} and <code>y&nbsp;+&nbsp;height</code>.
 508      * @param      x the <i>x</i> coordinate of the rectangle to be drawn.
 509      * @param      y the <i>y</i> coordinate of the rectangle to be drawn.
 510      * @param      width the width of the rectangle to be drawn.
 511      * @param      height the height of the rectangle to be drawn.
 512      * @param      arcWidth the horizontal diameter of the arc
 513      *                    at the four corners.
 514      * @param      arcHeight the vertical diameter of the arc
 515      *                    at the four corners.
 516      * @see        java.awt.Graphics#fillRoundRect
 517      * @since      1.0
 518      */
 519     public void drawRoundRect(int x, int y, int width, int height,
 520                               int arcWidth, int arcHeight) {
 521         mGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
 522     }
 523 
 524     /**
 525      * Fills the specified rounded corner rectangle with the current color.
 526      * The left and right edges of the rectangle
 527      * are at {@code x} and <code>x&nbsp;+&nbsp;width&nbsp;-&nbsp;1</code>,
 528      * respectively. The top and bottom edges of the rectangle are at
 529      * {@code y} and <code>y&nbsp;+&nbsp;height&nbsp;-&nbsp;1</code>.
 530      * @param       x the <i>x</i> coordinate of the rectangle to be filled.
 531      * @param       y the <i>y</i> coordinate of the rectangle to be filled.
 532      * @param       width the width of the rectangle to be filled.
 533      * @param       height the height of the rectangle to be filled.
 534      * @param       arcWidth the horizontal diameter
 535      *                     of the arc at the four corners.
 536      * @param       arcHeight the vertical diameter
 537      *                     of the arc at the four corners.
 538      * @see         java.awt.Graphics#drawRoundRect
 539      * @since       1.0
 540      */
 541     public void fillRoundRect(int x, int y, int width, int height,
 542                                        int arcWidth, int arcHeight) {
 543         mGraphics.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
 544     }
 545 
 546     /**
 547      * Draws the outline of an oval.
 548      * The result is a circle or ellipse that fits within the
 549      * rectangle specified by the {@code x}, {@code y},
 550      * {@code width}, and {@code height} arguments.
 551      * <p>
 552      * The oval covers an area that is
 553      * <code>width&nbsp;+&nbsp;1</code> pixels wide
 554      * and <code>height&nbsp;+&nbsp;1</code> pixels tall.
 555      * @param       x the <i>x</i> coordinate of the upper left
 556      *                     corner of the oval to be drawn.
 557      * @param       y the <i>y</i> coordinate of the upper left
 558      *                     corner of the oval to be drawn.
 559      * @param       width the width of the oval to be drawn.
 560      * @param       height the height of the oval to be drawn.
 561      * @see         java.awt.Graphics#fillOval
 562      * @since       1.0
 563      */
 564     public void drawOval(int x, int y, int width, int height) {
 565         mGraphics.drawOval(x, y, width, height);
 566     }
 567 
 568     /**
 569      * Fills an oval bounded by the specified rectangle with the
 570      * current color.
 571      * @param       x the <i>x</i> coordinate of the upper left corner
 572      *                     of the oval to be filled.
 573      * @param       y the <i>y</i> coordinate of the upper left corner
 574      *                     of the oval to be filled.
 575      * @param       width the width of the oval to be filled.
 576      * @param       height the height of the oval to be filled.
 577      * @see         java.awt.Graphics#drawOval
 578      * @since       1.0
 579      */
 580     public void fillOval(int x, int y, int width, int height) {
 581         mGraphics.fillOval(x, y, width, height);
 582     }
 583 
 584     /**
 585      * Draws the outline of a circular or elliptical arc
 586      * covering the specified rectangle.
 587      * <p>
 588      * The resulting arc begins at {@code startAngle} and extends
 589      * for {@code arcAngle} degrees, using the current color.
 590      * Angles are interpreted such that 0&nbsp;degrees
 591      * is at the 3&nbsp;o'clock position.
 592      * A positive value indicates a counter-clockwise rotation
 593      * while a negative value indicates a clockwise rotation.
 594      * <p>
 595      * The center of the arc is the center of the rectangle whose origin
 596      * is (<i>x</i>,&nbsp;<i>y</i>) and whose size is specified by the
 597      * {@code width} and {@code height} arguments.
 598      * <p>
 599      * The resulting arc covers an area
 600      * <code>width&nbsp;+&nbsp;1</code> pixels wide
 601      * by <code>height&nbsp;+&nbsp;1</code> pixels tall.
 602      * @param        x the <i>x</i> coordinate of the
 603      *                    upper-left corner of the arc to be drawn.
 604      * @param        y the <i>y</i>  coordinate of the
 605      *                    upper-left corner of the arc to be drawn.
 606      * @param        width the width of the arc to be drawn.
 607      * @param        height the height of the arc to be drawn.
 608      * @param        startAngle the beginning angle.
 609      * @param        arcAngle the angular extent of the arc,
 610      *                    relative to the start angle.
 611      * @see         java.awt.Graphics#fillArc
 612      * @since       1.0
 613      */
 614     public void drawArc(int x, int y, int width, int height,
 615                                  int startAngle, int arcAngle) {
 616         mGraphics.drawArc(x, y, width, height, startAngle, arcAngle);
 617     }
 618 
 619     /**
 620      * Fills a circular or elliptical arc covering the specified rectangle.
 621      * <p>
 622      * The resulting arc begins at {@code startAngle} and extends
 623      * for {@code arcAngle} degrees.
 624      * Angles are interpreted such that 0&nbsp;degrees
 625      * is at the 3&nbsp;o'clock position.
 626      * A positive value indicates a counter-clockwise rotation
 627      * while a negative value indicates a clockwise rotation.
 628      * <p>
 629      * The center of the arc is the center of the rectangle whose origin
 630      * is (<i>x</i>,&nbsp;<i>y</i>) and whose size is specified by the
 631      * {@code width} and {@code height} arguments.
 632      * <p>
 633      * The resulting arc covers an area
 634      * <code>width&nbsp;+&nbsp;1</code> pixels wide
 635      * by <code>height&nbsp;+&nbsp;1</code> pixels tall.
 636      * @param        x the <i>x</i> coordinate of the
 637      *                    upper-left corner of the arc to be filled.
 638      * @param        y the <i>y</i>  coordinate of the
 639      *                    upper-left corner of the arc to be filled.
 640      * @param        width the width of the arc to be filled.
 641      * @param        height the height of the arc to be filled.
 642      * @param        startAngle the beginning angle.
 643      * @param        arcAngle the angular extent of the arc,
 644      *                    relative to the start angle.
 645      * @see         java.awt.Graphics#drawArc
 646      * @since       1.0
 647      */
 648     public void fillArc(int x, int y, int width, int height,
 649                         int startAngle, int arcAngle) {
 650         mGraphics.fillArc(x, y, width, height, startAngle, arcAngle);
 651     }
 652 
 653     /**
 654      * Draws a sequence of connected lines defined by
 655      * arrays of <i>x</i> and <i>y</i> coordinates.
 656      * Each pair of (<i>x</i>,&nbsp;<i>y</i>) coordinates defines a point.
 657      * The figure is not closed if the first point
 658      * differs from the last point.
 659      * @param       xPoints an array of <i>x</i> points
 660      * @param       yPoints an array of <i>y</i> points
 661      * @param       nPoints the total number of points
 662      * @see         java.awt.Graphics#drawPolygon(int[], int[], int)
 663      * @since       1.1
 664      */
 665     public void drawPolyline(int[] xPoints, int[] yPoints,
 666                              int nPoints) {
 667         mGraphics.drawPolyline(xPoints, yPoints, nPoints);
 668     }
 669 
 670     /**
 671      * Draws a closed polygon defined by
 672      * arrays of <i>x</i> and <i>y</i> coordinates.
 673      * Each pair of (<i>x</i>,&nbsp;<i>y</i>) coordinates defines a point.
 674      * <p>
 675      * This method draws the polygon defined by {@code nPoint} line
 676      * segments, where the first <code>nPoint&nbsp;-&nbsp;1</code>
 677      * line segments are line segments from
 678      * <code>(xPoints[i&nbsp;-&nbsp;1],&nbsp;yPoints[i&nbsp;-&nbsp;1])</code>
 679      * to <code>(xPoints[i],&nbsp;yPoints[i])</code>, for
 680      * 1&nbsp;&le;&nbsp;<i>i</i>&nbsp;&le;&nbsp;{@code nPoints}.
 681      * The figure is automatically closed by drawing a line connecting
 682      * the final point to the first point, if those points are different.
 683      * @param        xPoints   a an array of {@code x} coordinates.
 684      * @param        yPoints   a an array of {@code y} coordinates.
 685      * @param        nPoints   a the total number of points.
 686      * @see          java.awt.Graphics#fillPolygon
 687      * @see          java.awt.Graphics#drawPolyline
 688      * @since        1.0
 689      */
 690     public void drawPolygon(int[] xPoints, int[] yPoints,
 691                             int nPoints) {
 692         mGraphics.drawPolygon(xPoints, yPoints, nPoints);
 693     }
 694 
 695     /**
 696      * Fills a closed polygon defined by
 697      * arrays of <i>x</i> and <i>y</i> coordinates.
 698      * <p>
 699      * This method draws the polygon defined by {@code nPoint} line
 700      * segments, where the first <code>nPoint&nbsp;-&nbsp;1</code>
 701      * line segments are line segments from
 702      * <code>(xPoints[i&nbsp;-&nbsp;1],&nbsp;yPoints[i&nbsp;-&nbsp;1])</code>
 703      * to <code>(xPoints[i],&nbsp;yPoints[i])</code>, for
 704      * 1&nbsp;&le;&nbsp;<i>i</i>&nbsp;&le;&nbsp;{@code nPoints}.
 705      * The figure is automatically closed by drawing a line connecting
 706      * the final point to the first point, if those points are different.
 707      * <p>
 708      * The area inside the polygon is defined using an
 709      * even-odd fill rule, also known as the alternating rule.
 710      * @param        xPoints   a an array of {@code x} coordinates.
 711      * @param        yPoints   a an array of {@code y} coordinates.
 712      * @param        nPoints   a the total number of points.
 713      * @see          java.awt.Graphics#drawPolygon(int[], int[], int)
 714      * @since        1.0
 715      */
 716     public void fillPolygon(int[] xPoints, int[] yPoints,
 717                             int nPoints) {
 718         mGraphics.fillPolygon(xPoints, yPoints, nPoints);
 719     }
 720 
 721     /**
 722      * Draws the text given by the specified string, using this
 723      * graphics context's current font and color. The baseline of the
 724      * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this
 725      * graphics context's coordinate system.
 726      * @param       str      the string to be drawn.
 727      * @param       x        the <i>x</i> coordinate.
 728      * @param       y        the <i>y</i> coordinate.
 729      * @see         java.awt.Graphics#drawBytes
 730      * @see         java.awt.Graphics#drawChars
 731      * @since       1.0
 732      */
 733     public void drawString(String str, int x, int y) {
 734         mGraphics.drawString(str, x, y);
 735     }
 736 
 737     /**
 738      * Draws the text given by the specified iterator, using this
 739      * graphics context's current color. The iterator has to specify a font
 740      * for each character. The baseline of the
 741      * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this
 742      * graphics context's coordinate system.
 743      * The rendering attributes applied include the clip, transform,
 744      * paint or color, and composite attributes.
 745      * For characters in script systems such as Hebrew and Arabic,
 746      * the glyphs may be draw from right to left, in which case the
 747      * coordinate supplied is the location of the leftmost character
 748      * on the baseline.
 749      * @param iterator the iterator whose text is to be drawn
 750      * @param x,y the coordinates where the iterator's text should be drawn.
 751      * @see #setPaint
 752      * @see java.awt.Graphics#setColor
 753      * @see #setTransform
 754      * @see #setComposite
 755      * @see #setClip
 756      */
 757     public void drawString(AttributedCharacterIterator iterator,
 758                                     int x, int y) {
 759         mGraphics.drawString(iterator, x, y);
 760     }
 761 
 762     /**
 763      * Draws the text given by the specified iterator, using this
 764      * graphics context's current color. The iterator has to specify a font
 765      * for each character. The baseline of the
 766      * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this
 767      * graphics context's coordinate system.
 768      * The rendering attributes applied include the clip, transform,
 769      * paint or color, and composite attributes.
 770      * For characters in script systems such as Hebrew and Arabic,
 771      * the glyphs may be draw from right to left, in which case the
 772      * coordinate supplied is the location of the leftmost character
 773      * on the baseline.
 774      * @param iterator the iterator whose text is to be drawn
 775      * @param x,y the coordinates where the iterator's text should be drawn.
 776      * @see #setPaint
 777      * @see java.awt.Graphics#setColor
 778      * @see #setTransform
 779      * @see #setComposite
 780      * @see #setClip
 781      */
 782     public void drawString(AttributedCharacterIterator iterator,
 783                                     float x, float y) {
 784         mGraphics.drawString(iterator, x, y);
 785     }
 786 
 787     /**
 788      * Draws as much of the specified image as is currently available.
 789      * The image is drawn with its top-left corner at
 790      * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
 791      * space. Transparent pixels in the image do not affect whatever
 792      * pixels are already there.
 793      * <p>
 794      * This method returns immediately in all cases, even if the
 795      * complete image has not yet been loaded, and it has not been dithered
 796      * and converted for the current output device.
 797      * <p>
 798      * If the image has not yet been completely loaded, then
 799      * {@code drawImage} returns {@code false}. As more of
 800      * the image becomes available, the process that draws the image notifies
 801      * the specified image observer.
 802      * @param    img the specified image to be drawn.
 803      * @param    x   the <i>x</i> coordinate.
 804      * @param    y   the <i>y</i> coordinate.
 805      * @param    observer    object to be notified as more of
 806      *                          the image is converted.
 807      * @see      java.awt.Image
 808      * @see      java.awt.image.ImageObserver
 809      * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
 810      * @since    1.0
 811      */
 812     public boolean drawImage(Image img, int x, int y,
 813                              ImageObserver observer) {
 814 
 815         return mGraphics.drawImage(img, x, y, observer);
 816     }
 817 
 818     /**
 819      * Draws as much of the specified image as has already been scaled
 820      * to fit inside the specified rectangle.
 821      * <p>
 822      * The image is drawn inside the specified rectangle of this
 823      * graphics context's coordinate space, and is scaled if
 824      * necessary. Transparent pixels do not affect whatever pixels
 825      * are already there.
 826      * <p>
 827      * This method returns immediately in all cases, even if the
 828      * entire image has not yet been scaled, dithered, and converted
 829      * for the current output device.
 830      * If the current output representation is not yet complete, then
 831      * {@code drawImage} returns {@code false}. As more of
 832      * the image becomes available, the process that draws the image notifies
 833      * the image observer by calling its {@code imageUpdate} method.
 834      * <p>
 835      * A scaled version of an image will not necessarily be
 836      * available immediately just because an unscaled version of the
 837      * image has been constructed for this output device.  Each size of
 838      * the image may be cached separately and generated from the original
 839      * data in a separate image production sequence.
 840      * @param    img    the specified image to be drawn.
 841      * @param    x      the <i>x</i> coordinate.
 842      * @param    y      the <i>y</i> coordinate.
 843      * @param    width  the width of the rectangle.
 844      * @param    height the height of the rectangle.
 845      * @param    observer    object to be notified as more of
 846      *                          the image is converted.
 847      * @see      java.awt.Image
 848      * @see      java.awt.image.ImageObserver
 849      * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
 850      * @since    1.0
 851      */
 852     public boolean drawImage(Image img, int x, int y,
 853                              int width, int height,
 854                              ImageObserver observer) {
 855 
 856         return mGraphics.drawImage(img, x, y, width, height, observer);
 857     }
 858 
 859     /**
 860      * Draws as much of the specified image as is currently available.
 861      * The image is drawn with its top-left corner at
 862      * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
 863      * space.  Transparent pixels are drawn in the specified
 864      * background color.
 865      * <p>
 866      * This operation is equivalent to filling a rectangle of the
 867      * width and height of the specified image with the given color and then
 868      * drawing the image on top of it, but possibly more efficient.
 869      * <p>
 870      * This method returns immediately in all cases, even if the
 871      * complete image has not yet been loaded, and it has not been dithered
 872      * and converted for the current output device.
 873      * <p>
 874      * If the image has not yet been completely loaded, then
 875      * {@code drawImage} returns {@code false}. As more of
 876      * the image becomes available, the process that draws the image notifies
 877      * the specified image observer.
 878      * @param    img    the specified image to be drawn.
 879      * @param    x      the <i>x</i> coordinate.
 880      * @param    y      the <i>y</i> coordinate.
 881      * @param    bgcolor the background color to paint under the
 882      *                         non-opaque portions of the image.
 883      * @param    observer    object to be notified as more of
 884      *                          the image is converted.
 885      * @see      java.awt.Image
 886      * @see      java.awt.image.ImageObserver
 887      * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
 888      * @since    1.0
 889      */
 890     public boolean drawImage(Image img, int x, int y,
 891                              Color bgcolor,
 892                              ImageObserver observer) {
 893 
 894         if (img == null) {
 895             return true;
 896         }
 897 
 898         boolean result;
 899 
 900         if (needToCopyBgColorImage(img)) {
 901             BufferedImage imageCopy = getBufferedImageCopy(img, bgcolor);
 902             result = mGraphics.drawImage(imageCopy, x, y, null);
 903         } else {
 904             result = mGraphics.drawImage(img, x, y, bgcolor, observer);
 905         }
 906 
 907         return result;
 908     }
 909 
 910     /**
 911      * Draws as much of the specified image as has already been scaled
 912      * to fit inside the specified rectangle.
 913      * <p>
 914      * The image is drawn inside the specified rectangle of this
 915      * graphics context's coordinate space, and is scaled if
 916      * necessary. Transparent pixels are drawn in the specified
 917      * background color.
 918      * This operation is equivalent to filling a rectangle of the
 919      * width and height of the specified image with the given color and then
 920      * drawing the image on top of it, but possibly more efficient.
 921      * <p>
 922      * This method returns immediately in all cases, even if the
 923      * entire image has not yet been scaled, dithered, and converted
 924      * for the current output device.
 925      * If the current output representation is not yet complete then
 926      * {@code drawImage} returns {@code false}. As more of
 927      * the image becomes available, the process that draws the image notifies
 928      * the specified image observer.
 929      * <p>
 930      * A scaled version of an image will not necessarily be
 931      * available immediately just because an unscaled version of the
 932      * image has been constructed for this output device.  Each size of
 933      * the image may be cached separately and generated from the original
 934      * data in a separate image production sequence.
 935      * @param    img       the specified image to be drawn.
 936      * @param    x         the <i>x</i> coordinate.
 937      * @param    y         the <i>y</i> coordinate.
 938      * @param    width     the width of the rectangle.
 939      * @param    height    the height of the rectangle.
 940      * @param    bgcolor   the background color to paint under the
 941      *                         non-opaque portions of the image.
 942      * @param    observer    object to be notified as more of
 943      *                          the image is converted.
 944      * @see      java.awt.Image
 945      * @see      java.awt.image.ImageObserver
 946      * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
 947      * @since    1.0
 948      */
 949     public boolean drawImage(Image img, int x, int y,
 950                              int width, int height,
 951                              Color bgcolor,
 952                              ImageObserver observer) {
 953 
 954         if (img == null) {
 955             return true;
 956         }
 957 
 958         boolean result;
 959 
 960         if (needToCopyBgColorImage(img)) {
 961             BufferedImage imageCopy = getBufferedImageCopy(img, bgcolor);
 962             result = mGraphics.drawImage(imageCopy, x, y, width, height, null);
 963         } else {
 964             result = mGraphics.drawImage(img, x, y, width, height,
 965                                          bgcolor, observer);
 966         }
 967 
 968         return result;
 969     }
 970 
 971     /**
 972      * Draws as much of the specified area of the specified image as is
 973      * currently available, scaling it on the fly to fit inside the
 974      * specified area of the destination drawable surface. Transparent pixels
 975      * do not affect whatever pixels are already there.
 976      * <p>
 977      * This method returns immediately in all cases, even if the
 978      * image area to be drawn has not yet been scaled, dithered, and converted
 979      * for the current output device.
 980      * If the current output representation is not yet complete then
 981      * {@code drawImage} returns {@code false}. As more of
 982      * the image becomes available, the process that draws the image notifies
 983      * the specified image observer.
 984      * <p>
 985      * This method always uses the unscaled version of the image
 986      * to render the scaled rectangle and performs the required
 987      * scaling on the fly. It does not use a cached, scaled version
 988      * of the image for this operation. Scaling of the image from source
 989      * to destination is performed such that the first coordinate
 990      * of the source rectangle is mapped to the first coordinate of
 991      * the destination rectangle, and the second source coordinate is
 992      * mapped to the second destination coordinate. The subimage is
 993      * scaled and flipped as needed to preserve those mappings.
 994      * @param       img the specified image to be drawn
 995      * @param       dx1 the <i>x</i> coordinate of the first corner of the
 996      *                    destination rectangle.
 997      * @param       dy1 the <i>y</i> coordinate of the first corner of the
 998      *                    destination rectangle.
 999      * @param       dx2 the <i>x</i> coordinate of the second corner of the
1000      *                    destination rectangle.
1001      * @param       dy2 the <i>y</i> coordinate of the second corner of the
1002      *                    destination rectangle.
1003      * @param       sx1 the <i>x</i> coordinate of the first corner of the
1004      *                    source rectangle.
1005      * @param       sy1 the <i>y</i> coordinate of the first corner of the
1006      *                    source rectangle.
1007      * @param       sx2 the <i>x</i> coordinate of the second corner of the
1008      *                    source rectangle.
1009      * @param       sy2 the <i>y</i> coordinate of the second corner of the
1010      *                    source rectangle.
1011      * @param       observer object to be notified as more of the image is
1012      *                    scaled and converted.
1013      * @see         java.awt.Image
1014      * @see         java.awt.image.ImageObserver
1015      * @see         java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1016      * @since       1.1
1017      */
1018     public boolean drawImage(Image img,
1019                                       int dx1, int dy1, int dx2, int dy2,
1020                                       int sx1, int sy1, int sx2, int sy2,
1021                                       ImageObserver observer) {
1022         return mGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1023                                    sx1, sy1, sx2, sy2,
1024                                    observer);
1025     }
1026 
1027     /**
1028      * Draws as much of the specified area of the specified image as is
1029      * currently available, scaling it on the fly to fit inside the
1030      * specified area of the destination drawable surface.
1031      * <p>
1032      * Transparent pixels are drawn in the specified background color.
1033      * This operation is equivalent to filling a rectangle of the
1034      * width and height of the specified image with the given color and then
1035      * drawing the image on top of it, but possibly more efficient.
1036      * <p>
1037      * This method returns immediately in all cases, even if the
1038      * image area to be drawn has not yet been scaled, dithered, and converted
1039      * for the current output device.
1040      * If the current output representation is not yet complete then
1041      * {@code drawImage} returns {@code false}. As more of
1042      * the image becomes available, the process that draws the image notifies
1043      * the specified image observer.
1044      * <p>
1045      * This method always uses the unscaled version of the image
1046      * to render the scaled rectangle and performs the required
1047      * scaling on the fly. It does not use a cached, scaled version
1048      * of the image for this operation. Scaling of the image from source
1049      * to destination is performed such that the first coordinate
1050      * of the source rectangle is mapped to the first coordinate of
1051      * the destination rectangle, and the second source coordinate is
1052      * mapped to the second destination coordinate. The subimage is
1053      * scaled and flipped as needed to preserve those mappings.
1054      * @param       img the specified image to be drawn
1055      * @param       dx1 the <i>x</i> coordinate of the first corner of the
1056      *                    destination rectangle.
1057      * @param       dy1 the <i>y</i> coordinate of the first corner of the
1058      *                    destination rectangle.
1059      * @param       dx2 the <i>x</i> coordinate of the second corner of the
1060      *                    destination rectangle.
1061      * @param       dy2 the <i>y</i> coordinate of the second corner of the
1062      *                    destination rectangle.
1063      * @param       sx1 the <i>x</i> coordinate of the first corner of the
1064      *                    source rectangle.
1065      * @param       sy1 the <i>y</i> coordinate of the first corner of the
1066      *                    source rectangle.
1067      * @param       sx2 the <i>x</i> coordinate of the second corner of the
1068      *                    source rectangle.
1069      * @param       sy2 the <i>y</i> coordinate of the second corner of the
1070      *                    source rectangle.
1071      * @param       bgcolor the background color to paint under the
1072      *                    non-opaque portions of the image.
1073      * @param       observer object to be notified as more of the image is
1074      *                    scaled and converted.
1075      * @see         java.awt.Image
1076      * @see         java.awt.image.ImageObserver
1077      * @see         java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1078      * @since       1.1
1079      */
1080     public boolean drawImage(Image img,
1081                              int dx1, int dy1, int dx2, int dy2,
1082                              int sx1, int sy1, int sx2, int sy2,
1083                              Color bgcolor,
1084                              ImageObserver observer) {
1085 
1086         if (img == null) {
1087             return true;
1088         }
1089 
1090         boolean result;
1091         if (needToCopyBgColorImage(img)) {
1092             BufferedImage imageCopy = getBufferedImageCopy(img, bgcolor);
1093             result = mGraphics.drawImage(imageCopy,
1094                                          dx1, dy1, dx2, dy2,
1095                                          sy1, sy1, sx2, sy2,
1096                                          null);
1097         } else {
1098             result = mGraphics.drawImage(img,
1099                                          dx1, dy1, dx2, dy2,
1100                                          sy1, sy1, sx2, sy2,
1101                                          bgcolor,
1102                                          observer);
1103         }
1104 
1105         return result;
1106     }
1107 
1108     /**
1109      * Return true if drawing {@code img} will
1110      * invoke a Java2D bug (#4258675). The bug in question
1111      * occurs when a draw image call with a background color
1112      * parameter tries to render a sheared
1113      * or rotated image. The portions of the bounding
1114      * rectangle not covered by the sheared image
1115      * are incorrectly drawn with the background color.
1116      */
1117     private boolean needToCopyBgColorImage(Image img) {
1118 
1119         boolean needToCopy;
1120 
1121         AffineTransform transform = getTransform();
1122 
1123         return (transform.getType()
1124                 & (AffineTransform.TYPE_GENERAL_ROTATION
1125                    | AffineTransform.TYPE_GENERAL_TRANSFORM)) != 0;
1126     }
1127 
1128     /**
1129      * Return a new {@code BufferedImage}
1130      * that contains a copy of the provided
1131      * {@code Image} where its
1132      * transparent pixels have been replaced by
1133      * {@code bgcolor}. If the new
1134      * {@code BufferedImage} can not be created,
1135      * probably because the original image has not
1136      * finished loading, then {@code null} is
1137      * returned.
1138      */
1139     private BufferedImage getBufferedImageCopy(Image img, Color bgcolor) {
1140 
1141         BufferedImage imageCopy = null;
1142 
1143         int width = img.getWidth(null);
1144         int height = img.getHeight(null);
1145 
1146         if (width > 0 && height > 0) {
1147 
1148             int imageType;
1149 
1150             /* Try to minimize the depth of the BufferedImage
1151              * we are about to create by, if possible, making
1152              * it the same depth as the original image.
1153              */
1154             if (img instanceof BufferedImage) {
1155                 BufferedImage bufImage = (BufferedImage) img;
1156                 imageType = bufImage.getType();
1157             } else {
1158                 imageType = BufferedImage.TYPE_INT_ARGB;
1159             }
1160 
1161             imageCopy = new BufferedImage(width, height, imageType);
1162 
1163             /* Copy the original image into the new buffer
1164              * without any transformations.
1165              * This will replace the transparent pixels
1166              * in the original with background color.
1167              */
1168             Graphics g = imageCopy.createGraphics();
1169             g.drawImage(img, 0, 0, bgcolor, null);
1170             g.dispose();
1171 
1172         /* We couldn't get the width or height of the image
1173          * so just return null.
1174          */
1175         } else {
1176             imageCopy = null;
1177         }
1178 
1179         return imageCopy;
1180     }
1181 
1182     /**
1183      * Draws an image, applying a transform from image space into user space
1184      * before drawing.
1185      * The transformation from user space into device space is done with
1186      * the current transform in the Graphics2D.
1187      * The given transformation is applied to the image before the
1188      * transform attribute in the Graphics2D state is applied.
1189      * The rendering attributes applied include the clip, transform,
1190      * and composite attributes. Note that the result is
1191      * undefined, if the given transform is noninvertible.
1192      * @param img The image to be drawn.
1193      * @param xform The transformation from image space into user space.
1194      * @see #transform
1195      * @see #setTransform
1196      * @see #setComposite
1197      * @see #clip
1198      * @see #setClip
1199      */
1200     public void drawRenderedImage(RenderedImage img,
1201                                   AffineTransform xform) {
1202         mGraphics.drawRenderedImage(img, xform);
1203     }
1204 
1205 
1206 
1207     public void drawRenderableImage(RenderableImage img,
1208                                     AffineTransform xform) {
1209 
1210         if (img == null) {
1211             return;
1212         }
1213 
1214         AffineTransform pipeTransform = getTransform();
1215         AffineTransform concatTransform = new AffineTransform(xform);
1216         concatTransform.concatenate(pipeTransform);
1217         AffineTransform reverseTransform;
1218 
1219         RenderContext rc = new RenderContext(concatTransform);
1220 
1221         try {
1222             reverseTransform = pipeTransform.createInverse();
1223         } catch (NoninvertibleTransformException nte) {
1224             rc = new RenderContext(pipeTransform);
1225             reverseTransform = new AffineTransform();
1226         }
1227 
1228         RenderedImage rendering = img.createRendering(rc);
1229         drawRenderedImage(rendering,reverseTransform);
1230     }
1231 
1232     /**
1233      * Disposes of this graphics context and releases
1234      * any system resources that it is using.
1235      * A {@code Graphics} object cannot be used after
1236      * {@code dispose} has been called.
1237      * <p>
1238      * When a Java program runs, a large number of {@code Graphics}
1239      * objects can be created within a short time frame.
1240      * Although the finalization process of the garbage collector
1241      * also disposes of the same system resources, it is preferable
1242      * to manually free the associated resources by calling this
1243      * method rather than to rely on a finalization process which
1244      * may not run to completion for a long period of time.
1245      * <p>
1246      * Graphics objects which are provided as arguments to the
1247      * {@code paint} and {@code update} methods
1248      * of components are automatically released by the system when
1249      * those methods return. For efficiency, programmers should
1250      * call {@code dispose} when finished using
1251      * a {@code Graphics} object only if it was created
1252      * directly from a component or another {@code Graphics} object.
1253      * @see         java.awt.Graphics#finalize
1254      * @see         java.awt.Component#paint
1255      * @see         java.awt.Component#update
1256      * @see         java.awt.Component#getGraphics
1257      * @see         java.awt.Graphics#create
1258      * @since       1.0
1259      */
1260     public void dispose() {
1261         mGraphics.dispose();
1262     }
1263 
1264     /**
1265      * Empty finalizer as no clean up needed here.
1266      */
1267     @SuppressWarnings("deprecation")
1268     public void finalize() {
1269     }
1270 
1271 
1272 /* The Delegated Graphics2D Methods */
1273 
1274     /**
1275      * Strokes the outline of a Shape using the settings of the current
1276      * graphics state.  The rendering attributes applied include the
1277      * clip, transform, paint or color, composite and stroke attributes.
1278      * @param s The shape to be drawn.
1279      * @see #setStroke
1280      * @see #setPaint
1281      * @see java.awt.Graphics#setColor
1282      * @see #transform
1283      * @see #setTransform
1284      * @see #clip
1285      * @see #setClip
1286      * @see #setComposite
1287      */
1288     public void draw(Shape s) {
1289         mGraphics.draw(s);
1290     }
1291 
1292     /**
1293      * Draws an image, applying a transform from image space into user space
1294      * before drawing.
1295      * The transformation from user space into device space is done with
1296      * the current transform in the Graphics2D.
1297      * The given transformation is applied to the image before the
1298      * transform attribute in the Graphics2D state is applied.
1299      * The rendering attributes applied include the clip, transform,
1300      * and composite attributes. Note that the result is
1301      * undefined, if the given transform is noninvertible.
1302      * @param img The image to be drawn.
1303      * @param xform The transformation from image space into user space.
1304      * @param obs The image observer to be notified as more of the image
1305      * is converted.
1306      * @see #transform
1307      * @see #setTransform
1308      * @see #setComposite
1309      * @see #clip
1310      * @see #setClip
1311      */
1312     public boolean drawImage(Image img,
1313                              AffineTransform xform,
1314                              ImageObserver obs) {
1315 
1316         return mGraphics.drawImage(img, xform, obs);
1317     }
1318 
1319     /**
1320      * Draws a BufferedImage that is filtered with a BufferedImageOp.
1321      * The rendering attributes applied include the clip, transform
1322      * and composite attributes.  This is equivalent to:
1323      * <pre>
1324      * img1 = op.filter(img, null);
1325      * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
1326      * </pre>
1327      * @param op The filter to be applied to the image before drawing.
1328      * @param img The BufferedImage to be drawn.
1329      * @param x,y The location in user space where the image should be drawn.
1330      * @see #transform
1331      * @see #setTransform
1332      * @see #setComposite
1333      * @see #clip
1334      * @see #setClip
1335      */
1336     public void drawImage(BufferedImage img,
1337                           BufferedImageOp op,
1338                           int x,
1339                           int y) {
1340 
1341         mGraphics.drawImage(img, op, x, y);
1342     }
1343 
1344 
1345     /**
1346      * Draws a string of text.
1347      * The rendering attributes applied include the clip, transform,
1348      * paint or color, font and composite attributes.
1349      * @param str The string to be drawn.
1350      * @param x,y The coordinates where the string should be drawn.
1351      * @see #setPaint
1352      * @see java.awt.Graphics#setColor
1353      * @see java.awt.Graphics#setFont
1354      * @see #transform
1355      * @see #setTransform
1356      * @see #setComposite
1357      * @see #clip
1358      * @see #setClip
1359      */
1360     public void drawString(String str,
1361                            float x,
1362                            float y) {
1363         mGraphics.drawString(str, x, y);
1364     }
1365 
1366     /**
1367      * Draws a GlyphVector.
1368      * The rendering attributes applied include the clip, transform,
1369      * paint or color, and composite attributes.  The GlyphVector specifies
1370      * individual glyphs from a Font.
1371      * @param g The GlyphVector to be drawn.
1372      * @param x,y The coordinates where the glyphs should be drawn.
1373      * @see #setPaint
1374      * @see java.awt.Graphics#setColor
1375      * @see #transform
1376      * @see #setTransform
1377      * @see #setComposite
1378      * @see #clip
1379      * @see #setClip
1380      */
1381     public void drawGlyphVector(GlyphVector g,
1382                                 float x,
1383                                 float y) {
1384         mGraphics.drawGlyphVector(g, x, y);
1385     }
1386 
1387     /**
1388      * Fills the interior of a Shape using the settings of the current
1389      * graphics state. The rendering attributes applied include the
1390      * clip, transform, paint or color, and composite.
1391      * @see #setPaint
1392      * @see java.awt.Graphics#setColor
1393      * @see #transform
1394      * @see #setTransform
1395      * @see #setComposite
1396      * @see #clip
1397      * @see #setClip
1398      */
1399     public void fill(Shape s) {
1400         mGraphics.fill(s);
1401     }
1402 
1403     /**
1404      * Checks to see if the outline of a Shape intersects the specified
1405      * Rectangle in device space.
1406      * The rendering attributes taken into account include the
1407      * clip, transform, and stroke attributes.
1408      * @param rect The area in device space to check for a hit.
1409      * @param s The shape to check for a hit.
1410      * @param onStroke Flag to choose between testing the stroked or
1411      * the filled shape.
1412      * @return True if there is a hit, false otherwise.
1413      * @see #setStroke
1414      * @see #fill
1415      * @see #draw
1416      * @see #transform
1417      * @see #setTransform
1418      * @see #clip
1419      * @see #setClip
1420      */
1421     public boolean hit(Rectangle rect,
1422                        Shape s,
1423                        boolean onStroke) {
1424 
1425         return mGraphics.hit(rect, s, onStroke);
1426     }
1427 
1428     /**
1429      * Sets the Composite in the current graphics state. Composite is used
1430      * in all drawing methods such as drawImage, drawString, draw,
1431      * and fill.  It specifies how new pixels are to be combined with
1432      * the existing pixels on the graphics device in the rendering process.
1433      * @param comp The Composite object to be used for drawing.
1434      * @see java.awt.Graphics#setXORMode
1435      * @see java.awt.Graphics#setPaintMode
1436      * @see java.awt.AlphaComposite
1437      */
1438     public void setComposite(Composite comp) {
1439         mGraphics.setComposite(comp);
1440     }
1441 
1442 
1443     /**
1444      * Sets the Paint in the current graphics state.
1445      * @param paint The Paint object to be used to generate color in
1446      * the rendering process.
1447      * @see java.awt.Graphics#setColor
1448      * @see java.awt.GradientPaint
1449      * @see java.awt.TexturePaint
1450      */
1451     public void setPaint(Paint paint) {
1452         mGraphics.setPaint(paint);
1453     }
1454 
1455     /**
1456      * Sets the Stroke in the current graphics state.
1457      * @param s The Stroke object to be used to stroke a Shape in
1458      * the rendering process.
1459      * @see java.awt.BasicStroke
1460      */
1461     public void setStroke(Stroke s) {
1462         mGraphics.setStroke(s);
1463     }
1464 
1465     /**
1466      * Sets the preferences for the rendering algorithms.
1467      * Hint categories include controls for rendering quality and
1468      * overall time/quality trade-off in the rendering process.
1469      * @param hintCategory The category of hint to be set.
1470      * @param hintValue The value indicating preferences for the specified
1471      * hint category.
1472      * @see RenderingHints
1473      */
1474     public void setRenderingHint(Key hintCategory, Object hintValue) {
1475         mGraphics.setRenderingHint(hintCategory, hintValue);
1476     }
1477 
1478     /**
1479      * Returns the preferences for the rendering algorithms.
1480      * @param hintCategory The category of hint to be set.
1481      * @return The preferences for rendering algorithms.
1482      * @see RenderingHints
1483      */
1484     public Object getRenderingHint(Key hintCategory) {
1485         return mGraphics.getRenderingHint(hintCategory);
1486     }
1487 
1488     /**
1489      * Sets the preferences for the rendering algorithms.
1490      * Hint categories include controls for rendering quality and
1491      * overall time/quality trade-off in the rendering process.
1492      * @param hints The rendering hints to be set
1493      * @see RenderingHints
1494      */
1495     public void setRenderingHints(Map<?,?> hints) {
1496         mGraphics.setRenderingHints(hints);
1497     }
1498 
1499     /**
1500      * Adds a number of preferences for the rendering algorithms.
1501      * Hint categories include controls for rendering quality and
1502      * overall time/quality trade-off in the rendering process.
1503      * @param hints The rendering hints to be set
1504      * @see RenderingHints
1505      */
1506     public void addRenderingHints(Map<?,?> hints) {
1507         mGraphics.addRenderingHints(hints);
1508     }
1509 
1510     /**
1511      * Gets the preferences for the rendering algorithms.
1512      * Hint categories include controls for rendering quality and
1513      * overall time/quality trade-off in the rendering process.
1514      * @see RenderingHints
1515      */
1516     public RenderingHints getRenderingHints() {
1517         return mGraphics.getRenderingHints();
1518     }
1519 
1520     /**
1521      * Composes a Transform object with the transform in this
1522      * Graphics2D according to the rule last-specified-first-applied.
1523      * If the currrent transform is Cx, the result of composition
1524      * with Tx is a new transform Cx'.  Cx' becomes the current
1525      * transform for this Graphics2D.
1526      * Transforming a point p by the updated transform Cx' is
1527      * equivalent to first transforming p by Tx and then transforming
1528      * the result by the original transform Cx.  In other words,
1529      * Cx'(p) = Cx(Tx(p)).
1530      * A copy of the Tx is made, if necessary, so further
1531      * modifications to Tx do not affect rendering.
1532      * @param Tx The Transform object to be composed with the current
1533      * transform.
1534      * @see #setTransform
1535      * @see AffineTransform
1536      */
1537     public void transform(AffineTransform Tx) {
1538         mGraphics.transform(Tx);
1539     }
1540 
1541     /**
1542      * Sets the Transform in the current graphics state.
1543      * @param Tx The Transform object to be used in the rendering process.
1544      * @see #transform
1545      * @see AffineTransform
1546      */
1547     public void setTransform(AffineTransform Tx) {
1548         mGraphics.setTransform(Tx);
1549     }
1550 
1551     /**
1552      * Returns the current Transform in the Graphics2D state.
1553      * @see #transform
1554      * @see #setTransform
1555      */
1556     public AffineTransform getTransform() {
1557         return mGraphics.getTransform();
1558     }
1559 
1560     /**
1561      * Returns the current Paint in the Graphics2D state.
1562      * @see #setPaint
1563      * @see java.awt.Graphics#setColor
1564      */
1565     public Paint getPaint() {
1566         return mGraphics.getPaint();
1567     }
1568 
1569     /**
1570      * Returns the current Composite in the Graphics2D state.
1571      * @see #setComposite
1572      */
1573     public Composite getComposite() {
1574         return mGraphics.getComposite();
1575     }
1576 
1577     /**
1578      * Sets the background color in this context used for clearing a region.
1579      * When Graphics2D is constructed for a component, the backgroung color is
1580      * inherited from the component. Setting the background color in the
1581      * Graphics2D context only affects the subsequent clearRect() calls and
1582      * not the background color of the component. To change the background
1583      * of the component, use appropriate methods of the component.
1584      * @param color The background color that should be used in
1585      * subsequent calls to clearRect().
1586      * @see #getBackground
1587      * @see Graphics#clearRect
1588      */
1589     public void setBackground(Color color) {
1590         mGraphics.setBackground(color);
1591     }
1592 
1593     /**
1594      * Returns the background color used for clearing a region.
1595      * @see #setBackground
1596      */
1597     public Color getBackground() {
1598         return mGraphics.getBackground();
1599     }
1600 
1601     /**
1602      * Returns the current Stroke in the Graphics2D state.
1603      * @see #setStroke
1604      */
1605     public Stroke getStroke() {
1606         return mGraphics.getStroke();
1607     }
1608 
1609     /**
1610      * Intersects the current clip with the interior of the specified Shape
1611      * and sets the current clip to the resulting intersection.
1612      * The indicated shape is transformed with the current transform in the
1613      * Graphics2D state before being intersected with the current clip.
1614      * This method is used to make the current clip smaller.
1615      * To make the clip larger, use any setClip method.
1616      * @param s The Shape to be intersected with the current clip.
1617      */
1618      public void clip(Shape s) {
1619         mGraphics.clip(s);
1620      }
1621 }