1 /*
   2  * Copyright (c) 2006, 2013, 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 java.awt;
  27 
  28 import java.awt.geom.AffineTransform;
  29 import java.awt.geom.Point2D;
  30 import java.awt.geom.Rectangle2D;
  31 import java.awt.image.ColorModel;
  32 import java.beans.ConstructorProperties;
  33 
  34 /**
  35  * The {@code RadialGradientPaint} class provides a way to fill a shape with
  36  * a circular radial color gradient pattern. The user may specify 2 or more
  37  * gradient colors, and this paint will provide an interpolation between
  38  * each color.
  39  * <p>
  40  * The user must specify the circle controlling the gradient pattern,
  41  * which is described by a center point and a radius.  The user can also
  42  * specify a separate focus point within that circle, which controls the
  43  * location of the first color of the gradient.  By default the focus is
  44  * set to be the center of the circle.
  45  * <p>
  46  * This paint will map the first color of the gradient to the focus point,
  47  * and the last color to the perimeter of the circle, interpolating
  48  * smoothly for any in-between colors specified by the user.  Any line drawn
  49  * from the focus point to the circumference will thus span all the gradient
  50  * colors.
  51  * <p>
  52  * Specifying a focus point outside of the radius of the circle will cause
  53  * the rings of the gradient pattern to be centered on the point just inside
  54  * the edge of the circle in the direction of the focus point.
  55  * The rendering will internally use this modified location as if it were
  56  * the specified focus point.
  57  * <p>
  58  * The user must provide an array of floats specifying how to distribute the
  59  * colors along the gradient.  These values should range from 0.0 to 1.0 and
  60  * act like keyframes along the gradient (they mark where the gradient should
  61  * be exactly a particular color).
  62  * <p>
  63  * In the event that the user does not set the first keyframe value equal
  64  * to 0 and/or the last keyframe value equal to 1, keyframes will be created
  65  * at these positions and the first and last colors will be replicated there.
  66  * So, if a user specifies the following arrays to construct a gradient:<br>
  67  * <pre>
  68  *     {Color.BLUE, Color.RED}, {.3f, .7f}
  69  * </pre>
  70  * this will be converted to a gradient with the following keyframes:<br>
  71  * <pre>
  72  *     {Color.BLUE, Color.BLUE, Color.RED, Color.RED}, {0f, .3f, .7f, 1f}
  73  * </pre>
  74  *
  75  * <p>
  76  * The user may also select what action the {@code RadialGradientPaint} object
  77  * takes when it is filling the space outside the circle's radius by
  78  * setting {@code CycleMethod} to either {@code REFLECTION} or {@code REPEAT}.
  79  * The gradient color proportions are equal for any particular line drawn
  80  * from the focus point. The following figure shows that the distance AB
  81  * is equal to the distance BC, and the distance AD is equal to the distance DE.
  82  * <center>
  83  * <img src = "doc-files/RadialGradientPaint-3.png" alt="image showing the
  84  * distance AB=BC, and AD=DE">
  85  * </center>
  86  * If the gradient and graphics rendering transforms are uniformly scaled and
  87  * the user sets the focus so that it coincides with the center of the circle,
  88  * the gradient color proportions are equal for any line drawn from the center.
  89  * The following figure shows the distances AB, BC, AD, and DE. They are all equal.
  90  * <center>
  91  * <img src = "doc-files/RadialGradientPaint-4.png" alt="image showing the
  92  * distance of AB, BC, AD, and DE are all equal">
  93  * </center>
  94  * Note that some minor variations in distances may occur due to sampling at
  95  * the granularity of a pixel.
  96  * If no cycle method is specified, {@code NO_CYCLE} will be chosen by
  97  * default, which means the last keyframe color will be used to fill the
  98  * remaining area.
  99  * <p>
 100  * The colorSpace parameter allows the user to specify in which colorspace
 101  * the interpolation should be performed, default sRGB or linearized RGB.
 102  *
 103  * <p>
 104  * The following code demonstrates typical usage of
 105  * {@code RadialGradientPaint}, where the center and focus points are
 106  * the same:
 107  * <pre>
 108  *     Point2D center = new Point2D.Float(50, 50);
 109  *     float radius = 25;
 110  *     float[] dist = {0.0f, 0.2f, 1.0f};
 111  *     Color[] colors = {Color.RED, Color.WHITE, Color.BLUE};
 112  *     RadialGradientPaint p =
 113  *         new RadialGradientPaint(center, radius, dist, colors);
 114  * </pre>
 115  *
 116  * <p>
 117  * This image demonstrates the example code above, with default
 118  * (centered) focus for each of the three cycle methods:
 119  * <center>
 120  * <img src = "doc-files/RadialGradientPaint-1.png" alt="image showing the
 121  * output of the sameple code">
 122  * </center>
 123  *
 124  * <p>
 125  * It is also possible to specify a non-centered focus point, as
 126  * in the following code:
 127  * <pre>
 128  *     Point2D center = new Point2D.Float(50, 50);
 129  *     float radius = 25;
 130  *     Point2D focus = new Point2D.Float(40, 40);
 131  *     float[] dist = {0.0f, 0.2f, 1.0f};
 132  *     Color[] colors = {Color.RED, Color.WHITE, Color.BLUE};
 133  *     RadialGradientPaint p =
 134  *         new RadialGradientPaint(center, radius, focus,
 135  *                                 dist, colors,
 136  *                                 CycleMethod.NO_CYCLE);
 137  * </pre>
 138  *
 139  * <p>
 140  * This image demonstrates the previous example code, with non-centered
 141  * focus for each of the three cycle methods:
 142  * <center>
 143  * <img src = "doc-files/RadialGradientPaint-2.png" alt="image showing the
 144  * output of the sample code">
 145  * </center>
 146  *
 147  * @see java.awt.Paint
 148  * @see java.awt.Graphics2D#setPaint
 149  * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
 150  * @since 1.6
 151  */
 152 public final class RadialGradientPaint extends MultipleGradientPaint {
 153 
 154     /** Focus point which defines the 0% gradient stop X coordinate. */
 155     private final Point2D focus;
 156 
 157     /** Center of the circle defining the 100% gradient stop X coordinate. */
 158     private final Point2D center;
 159 
 160     /** Radius of the outermost circle defining the 100% gradient stop. */
 161     private final float radius;
 162 
 163     /**
 164      * Constructs a {@code RadialGradientPaint} with a default
 165      * {@code NO_CYCLE} repeating method and {@code SRGB} color space,
 166      * using the center as the focus point.
 167      *
 168      * @param cx the X coordinate in user space of the center point of the
 169      *           circle defining the gradient.  The last color of the
 170      *           gradient is mapped to the perimeter of this circle.
 171      * @param cy the Y coordinate in user space of the center point of the
 172      *           circle defining the gradient.  The last color of the
 173      *           gradient is mapped to the perimeter of this circle.
 174      * @param radius the radius of the circle defining the extents of the
 175      *               color gradient
 176      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 177      *                  distribution of colors along the gradient
 178      * @param colors array of colors to use in the gradient.  The first color
 179      *               is used at the focus point, the last color around the
 180      *               perimeter of the circle.
 181      *
 182      * @throws NullPointerException
 183      * if {@code fractions} array is null,
 184      * or {@code colors} array is null
 185      * @throws IllegalArgumentException
 186      * if {@code radius} is non-positive,
 187      * or {@code fractions.length != colors.length},
 188      * or {@code colors} is less than 2 in size,
 189      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 190      * or the {@code fractions} are not provided in strictly increasing order
 191      */
 192     public RadialGradientPaint(float cx, float cy, float radius,
 193                                float[] fractions, Color[] colors)
 194     {
 195         this(cx, cy,
 196              radius,
 197              cx, cy,
 198              fractions,
 199              colors,
 200              CycleMethod.NO_CYCLE);
 201     }
 202 
 203     /**
 204      * Constructs a {@code RadialGradientPaint} with a default
 205      * {@code NO_CYCLE} repeating method and {@code SRGB} color space,
 206      * using the center as the focus point.
 207      *
 208      * @param center the center point, in user space, of the circle defining
 209      *               the gradient
 210      * @param radius the radius of the circle defining the extents of the
 211      *               color gradient
 212      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 213      *                  distribution of colors along the gradient
 214      * @param colors array of colors to use in the gradient.  The first color
 215      *               is used at the focus point, the last color around the
 216      *               perimeter of the circle.
 217      *
 218      * @throws NullPointerException
 219      * if {@code center} point is null,
 220      * or {@code fractions} array is null,
 221      * or {@code colors} array is null
 222      * @throws IllegalArgumentException
 223      * if {@code radius} is non-positive,
 224      * or {@code fractions.length != colors.length},
 225      * or {@code colors} is less than 2 in size,
 226      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 227      * or the {@code fractions} are not provided in strictly increasing order
 228      */
 229     public RadialGradientPaint(Point2D center, float radius,
 230                                float[] fractions, Color[] colors)
 231     {
 232         this(center,
 233              radius,
 234              center,
 235              fractions,
 236              colors,
 237              CycleMethod.NO_CYCLE);
 238     }
 239 
 240     /**
 241      * Constructs a {@code RadialGradientPaint} with a default
 242      * {@code SRGB} color space, using the center as the focus point.
 243      *
 244      * @param cx the X coordinate in user space of the center point of the
 245      *           circle defining the gradient.  The last color of the
 246      *           gradient is mapped to the perimeter of this circle.
 247      * @param cy the Y coordinate in user space of the center point of the
 248      *           circle defining the gradient.  The last color of the
 249      *           gradient is mapped to the perimeter of this circle.
 250      * @param radius the radius of the circle defining the extents of the
 251      *               color gradient
 252      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 253      *                  distribution of colors along the gradient
 254      * @param colors array of colors to use in the gradient.  The first color
 255      *               is used at the focus point, the last color around the
 256      *               perimeter of the circle.
 257      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
 258      *                    or {@code REPEAT}
 259      *
 260      * @throws NullPointerException
 261      * if {@code fractions} array is null,
 262      * or {@code colors} array is null,
 263      * or {@code cycleMethod} is null
 264      * @throws IllegalArgumentException
 265      * if {@code radius} is non-positive,
 266      * or {@code fractions.length != colors.length},
 267      * or {@code colors} is less than 2 in size,
 268      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 269      * or the {@code fractions} are not provided in strictly increasing order
 270      */
 271     public RadialGradientPaint(float cx, float cy, float radius,
 272                                float[] fractions, Color[] colors,
 273                                CycleMethod cycleMethod)
 274     {
 275         this(cx, cy,
 276              radius,
 277              cx, cy,
 278              fractions,
 279              colors,
 280              cycleMethod);
 281     }
 282 
 283     /**
 284      * Constructs a {@code RadialGradientPaint} with a default
 285      * {@code SRGB} color space, using the center as the focus point.
 286      *
 287      * @param center the center point, in user space, of the circle defining
 288      *               the gradient
 289      * @param radius the radius of the circle defining the extents of the
 290      *               color gradient
 291      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 292      *                  distribution of colors along the gradient
 293      * @param colors array of colors to use in the gradient.  The first color
 294      *               is used at the focus point, the last color around the
 295      *               perimeter of the circle.
 296      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
 297      *                    or {@code REPEAT}
 298      *
 299      * @throws NullPointerException
 300      * if {@code center} point is null,
 301      * or {@code fractions} array is null,
 302      * or {@code colors} array is null,
 303      * or {@code cycleMethod} is null
 304      * @throws IllegalArgumentException
 305      * if {@code radius} is non-positive,
 306      * or {@code fractions.length != colors.length},
 307      * or {@code colors} is less than 2 in size,
 308      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 309      * or the {@code fractions} are not provided in strictly increasing order
 310      */
 311     public RadialGradientPaint(Point2D center, float radius,
 312                                float[] fractions, Color[] colors,
 313                                CycleMethod cycleMethod)
 314     {
 315         this(center,
 316              radius,
 317              center,
 318              fractions,
 319              colors,
 320              cycleMethod);
 321     }
 322 
 323     /**
 324      * Constructs a {@code RadialGradientPaint} with a default
 325      * {@code SRGB} color space.
 326      *
 327      * @param cx the X coordinate in user space of the center point of the
 328      *           circle defining the gradient.  The last color of the
 329      *           gradient is mapped to the perimeter of this circle.
 330      * @param cy the Y coordinate in user space of the center point of the
 331      *           circle defining the gradient.  The last color of the
 332      *           gradient is mapped to the perimeter of this circle.
 333      * @param radius the radius of the circle defining the extents of the
 334      *               color gradient
 335      * @param fx the X coordinate of the point in user space to which the
 336      *           first color is mapped
 337      * @param fy the Y coordinate of the point in user space to which the
 338      *           first color is mapped
 339      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 340      *                  distribution of colors along the gradient
 341      * @param colors array of colors to use in the gradient.  The first color
 342      *               is used at the focus point, the last color around the
 343      *               perimeter of the circle.
 344      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
 345      *                    or {@code REPEAT}
 346      *
 347      * @throws NullPointerException
 348      * if {@code fractions} array is null,
 349      * or {@code colors} array is null,
 350      * or {@code cycleMethod} is null
 351      * @throws IllegalArgumentException
 352      * if {@code radius} is non-positive,
 353      * or {@code fractions.length != colors.length},
 354      * or {@code colors} is less than 2 in size,
 355      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 356      * or the {@code fractions} are not provided in strictly increasing order
 357      */
 358     public RadialGradientPaint(float cx, float cy, float radius,
 359                                float fx, float fy,
 360                                float[] fractions, Color[] colors,
 361                                CycleMethod cycleMethod)
 362     {
 363         this(new Point2D.Float(cx, cy),
 364              radius,
 365              new Point2D.Float(fx, fy),
 366              fractions,
 367              colors,
 368              cycleMethod);
 369     }
 370 
 371     /**
 372      * Constructs a {@code RadialGradientPaint} with a default
 373      * {@code SRGB} color space.
 374      *
 375      * @param center the center point, in user space, of the circle defining
 376      *               the gradient.  The last color of the gradient is mapped
 377      *               to the perimeter of this circle.
 378      * @param radius the radius of the circle defining the extents of the color
 379      *               gradient
 380      * @param focus the point in user space to which the first color is mapped
 381      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 382      *                  distribution of colors along the gradient
 383      * @param colors array of colors to use in the gradient. The first color
 384      *               is used at the focus point, the last color around the
 385      *               perimeter of the circle.
 386      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
 387      *                    or {@code REPEAT}
 388      *
 389      * @throws NullPointerException
 390      * if one of the points is null,
 391      * or {@code fractions} array is null,
 392      * or {@code colors} array is null,
 393      * or {@code cycleMethod} is null
 394      * @throws IllegalArgumentException
 395      * if {@code radius} is non-positive,
 396      * or {@code fractions.length != colors.length},
 397      * or {@code colors} is less than 2 in size,
 398      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 399      * or the {@code fractions} are not provided in strictly increasing order
 400      */
 401     public RadialGradientPaint(Point2D center, float radius,
 402                                Point2D focus,
 403                                float[] fractions, Color[] colors,
 404                                CycleMethod cycleMethod)
 405     {
 406         this(center,
 407              radius,
 408              focus,
 409              fractions,
 410              colors,
 411              cycleMethod,
 412              ColorSpaceType.SRGB,
 413              new AffineTransform());
 414     }
 415 
 416     /**
 417      * Constructs a {@code RadialGradientPaint}.
 418      *
 419      * @param center the center point in user space of the circle defining the
 420      *               gradient.  The last color of the gradient is mapped to
 421      *               the perimeter of this circle.
 422      * @param radius the radius of the circle defining the extents of the
 423      *               color gradient
 424      * @param focus the point in user space to which the first color is mapped
 425      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 426      *                  distribution of colors along the gradient
 427      * @param colors array of colors to use in the gradient.  The first color
 428      *               is used at the focus point, the last color around the
 429      *               perimeter of the circle.
 430      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
 431      *                    or {@code REPEAT}
 432      * @param colorSpace which color space to use for interpolation,
 433      *                   either {@code SRGB} or {@code LINEAR_RGB}
 434      * @param gradientTransform transform to apply to the gradient
 435      *
 436      * @throws NullPointerException
 437      * if one of the points is null,
 438      * or {@code fractions} array is null,
 439      * or {@code colors} array is null,
 440      * or {@code cycleMethod} is null,
 441      * or {@code colorSpace} is null,
 442      * or {@code gradientTransform} is null
 443      * @throws IllegalArgumentException
 444      * if {@code radius} is non-positive,
 445      * or {@code fractions.length != colors.length},
 446      * or {@code colors} is less than 2 in size,
 447      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 448      * or the {@code fractions} are not provided in strictly increasing order
 449      */
 450     @ConstructorProperties({ "centerPoint", "radius", "focusPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" })
 451     public RadialGradientPaint(Point2D center,
 452                                float radius,
 453                                Point2D focus,
 454                                float[] fractions, Color[] colors,
 455                                CycleMethod cycleMethod,
 456                                ColorSpaceType colorSpace,
 457                                AffineTransform gradientTransform)
 458     {
 459         super(fractions, colors, cycleMethod, colorSpace, gradientTransform);
 460 
 461         // check input arguments
 462         if (center == null) {
 463             throw new NullPointerException("Center point must be non-null");
 464         }
 465 
 466         if (focus == null) {
 467             throw new NullPointerException("Focus point must be non-null");
 468         }
 469 
 470         if (radius <= 0) {
 471             throw new IllegalArgumentException("Radius must be greater " +
 472                                                "than zero");
 473         }
 474 
 475         // copy parameters
 476         this.center = new Point2D.Double(center.getX(), center.getY());
 477         this.focus = new Point2D.Double(focus.getX(), focus.getY());
 478         this.radius = radius;
 479     }
 480 
 481     /**
 482      * Constructs a {@code RadialGradientPaint} with a default
 483      * {@code SRGB} color space.
 484      * The gradient circle of the {@code RadialGradientPaint} is defined
 485      * by the given bounding box.
 486      * <p>
 487      * This constructor is a more convenient way to express the
 488      * following (equivalent) code:<br>
 489      *
 490      * <pre>
 491      *     double gw = gradientBounds.getWidth();
 492      *     double gh = gradientBounds.getHeight();
 493      *     double cx = gradientBounds.getCenterX();
 494      *     double cy = gradientBounds.getCenterY();
 495      *     Point2D center = new Point2D.Double(cx, cy);
 496      *
 497      *     AffineTransform gradientTransform = new AffineTransform();
 498      *     gradientTransform.translate(cx, cy);
 499      *     gradientTransform.scale(gw / 2, gh / 2);
 500      *     gradientTransform.translate(-cx, -cy);
 501      *
 502      *     RadialGradientPaint gp =
 503      *         new RadialGradientPaint(center, 1.0f, center,
 504      *                                 fractions, colors,
 505      *                                 cycleMethod,
 506      *                                 ColorSpaceType.SRGB,
 507      *                                 gradientTransform);
 508      * </pre>
 509      *
 510      * @param gradientBounds the bounding box, in user space, of the circle
 511      *                       defining the outermost extent of the gradient
 512      * @param fractions numbers ranging from 0.0 to 1.0 specifying the
 513      *                  distribution of colors along the gradient
 514      * @param colors array of colors to use in the gradient.  The first color
 515      *               is used at the focus point, the last color around the
 516      *               perimeter of the circle.
 517      * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
 518      *                    or {@code REPEAT}
 519      *
 520      * @throws NullPointerException
 521      * if {@code gradientBounds} is null,
 522      * or {@code fractions} array is null,
 523      * or {@code colors} array is null,
 524      * or {@code cycleMethod} is null
 525      * @throws IllegalArgumentException
 526      * if {@code gradientBounds} is empty,
 527      * or {@code fractions.length != colors.length},
 528      * or {@code colors} is less than 2 in size,
 529      * or a {@code fractions} value is less than 0.0 or greater than 1.0,
 530      * or the {@code fractions} are not provided in strictly increasing order
 531      */
 532     public RadialGradientPaint(Rectangle2D gradientBounds,
 533                                float[] fractions, Color[] colors,
 534                                CycleMethod cycleMethod)
 535     {
 536         // gradient center/focal point is the center of the bounding box,
 537         // radius is set to 1.0, and then we set a scale transform
 538         // to achieve an elliptical gradient defined by the bounding box
 539         this(new Point2D.Double(gradientBounds.getCenterX(),
 540                                 gradientBounds.getCenterY()),
 541              1.0f,
 542              new Point2D.Double(gradientBounds.getCenterX(),
 543                                 gradientBounds.getCenterY()),
 544              fractions,
 545              colors,
 546              cycleMethod,
 547              ColorSpaceType.SRGB,
 548              createGradientTransform(gradientBounds));
 549 
 550         if (gradientBounds.isEmpty()) {
 551             throw new IllegalArgumentException("Gradient bounds must be " +
 552                                                "non-empty");
 553         }
 554     }
 555 
 556     private static AffineTransform createGradientTransform(Rectangle2D r) {
 557         double cx = r.getCenterX();
 558         double cy = r.getCenterY();
 559         AffineTransform xform = AffineTransform.getTranslateInstance(cx, cy);
 560         xform.scale(r.getWidth()/2, r.getHeight()/2);
 561         xform.translate(-cx, -cy);
 562         return xform;
 563     }
 564 
 565     /**
 566      * Creates and returns a {@link PaintContext} used to
 567      * generate a circular radial color gradient pattern.
 568      * See the description of the {@link Paint#createContext createContext} method
 569      * for information on null parameter handling.
 570      *
 571      * @param cm the preferred {@link ColorModel} which represents the most convenient
 572      *           format for the caller to receive the pixel data, or {@code null}
 573      *           if there is no preference.
 574      * @param deviceBounds the device space bounding box
 575      *                     of the graphics primitive being rendered.
 576      * @param userBounds the user space bounding box
 577      *                   of the graphics primitive being rendered.
 578      * @param transform the {@link AffineTransform} from user
 579      *              space into device space.
 580      * @param hints the set of hints that the context object can use to
 581      *              choose between rendering alternatives.
 582      * @return the {@code PaintContext} for
 583      *         generating color patterns.
 584      * @see Paint
 585      * @see PaintContext
 586      * @see ColorModel
 587      * @see Rectangle
 588      * @see Rectangle2D
 589      * @see AffineTransform
 590      * @see RenderingHints
 591      */
 592     public PaintContext createContext(ColorModel cm,
 593                                       Rectangle deviceBounds,
 594                                       Rectangle2D userBounds,
 595                                       AffineTransform transform,
 596                                       RenderingHints hints)
 597     {
 598         // avoid modifying the user's transform...
 599         transform = new AffineTransform(transform);
 600         // incorporate the gradient transform
 601         transform.concatenate(gradientTransform);
 602 
 603         return new RadialGradientPaintContext(this, cm,
 604                                               deviceBounds, userBounds,
 605                                               transform, hints,
 606                                               (float)center.getX(),
 607                                               (float)center.getY(),
 608                                               radius,
 609                                               (float)focus.getX(),
 610                                               (float)focus.getY(),
 611                                               fractions, colors,
 612                                               cycleMethod, colorSpace);
 613     }
 614 
 615     /**
 616      * Returns a copy of the center point of the radial gradient.
 617      *
 618      * @return a {@code Point2D} object that is a copy of the center point
 619      */
 620     public Point2D getCenterPoint() {
 621         return new Point2D.Double(center.getX(), center.getY());
 622     }
 623 
 624     /**
 625      * Returns a copy of the focus point of the radial gradient.
 626      * Note that if the focus point specified when the radial gradient
 627      * was constructed lies outside of the radius of the circle, this
 628      * method will still return the original focus point even though
 629      * the rendering may center the rings of color on a different
 630      * point that lies inside the radius.
 631      *
 632      * @return a {@code Point2D} object that is a copy of the focus point
 633      */
 634     public Point2D getFocusPoint() {
 635         return new Point2D.Double(focus.getX(), focus.getY());
 636     }
 637 
 638     /**
 639      * Returns the radius of the circle defining the radial gradient.
 640      *
 641      * @return the radius of the circle defining the radial gradient
 642      */
 643     public float getRadius() {
 644         return radius;
 645     }
 646 }