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 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      */
RadialGradientPaint(float cx, float cy, float radius, float[] fractions, Color[] colors)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      */
RadialGradientPaint(Point2D center, float radius, float[] fractions, Color[] colors)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      */
RadialGradientPaint(float cx, float cy, float radius, float[] fractions, Color[] colors, CycleMethod cycleMethod)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      */
RadialGradientPaint(Point2D center, float radius, float[] fractions, Color[] colors, CycleMethod cycleMethod)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      */
RadialGradientPaint(float cx, float cy, float radius, float fx, float fy, float[] fractions, Color[] colors, CycleMethod cycleMethod)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      */
RadialGradientPaint(Point2D center, float radius, Point2D focus, float[] fractions, Color[] colors, CycleMethod cycleMethod)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" })
RadialGradientPaint(Point2D center, float radius, Point2D focus, float[] fractions, Color[] colors, CycleMethod cycleMethod, ColorSpaceType colorSpace, AffineTransform gradientTransform)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      */
RadialGradientPaint(Rectangle2D gradientBounds, float[] fractions, Color[] colors, CycleMethod cycleMethod)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 
createGradientTransform(Rectangle2D r)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      */
createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform transform, RenderingHints hints)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      */
getCenterPoint()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      */
getFocusPoint()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      */
getRadius()643     public float getRadius() {
644         return radius;
645     }
646 }
647