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