001 /*
002 * Copyright 2006-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.awt;
027
028 import java.awt.geom.AffineTransform;
029 import java.awt.geom.NoninvertibleTransformException;
030 import java.awt.geom.Point2D;
031 import java.awt.geom.Rectangle2D;
032 import java.awt.image.ColorModel;
033
034 /**
035 * The {@code LinearGradientPaint} class provides a way to fill
036 * a {@link java.awt.Shape} with a linear color gradient pattern. The user
037 * may specify two or more gradient colors, and this paint will provide an
038 * interpolation between each color. The user also specifies start and end
039 * points which define where in user space the color gradient should begin
040 * and end.
041 * <p>
042 * The user must provide an array of floats specifying how to distribute the
043 * colors along the gradient. These values should range from 0.0 to 1.0 and
044 * act like keyframes along the gradient (they mark where the gradient should
045 * be exactly a particular color).
046 * <p>
047 * In the event that the user does not set the first keyframe value equal
048 * to 0 and/or the last keyframe value equal to 1, keyframes will be created
049 * at these positions and the first and last colors will be replicated there.
050 * So, if a user specifies the following arrays to construct a gradient:<br>
051 * <pre>
052 * {Color.BLUE, Color.RED}, {.3f, .7f}
053 * </pre>
054 * this will be converted to a gradient with the following keyframes:<br>
055 * <pre>
056 * {Color.BLUE, Color.BLUE, Color.RED, Color.RED}, {0f, .3f, .7f, 1f}
057 * </pre>
058 *
059 * <p>
060 * The user may also select what action the {@code LinearGradientPaint}
061 * should take when filling color outside the start and end points.
062 * If no cycle method is specified, {@code NO_CYCLE} will be chosen by
063 * default, which means the endpoint colors will be used to fill the
064 * remaining area.
065 * <p>
066 * The colorSpace parameter allows the user to specify in which colorspace
067 * the interpolation should be performed, default sRGB or linearized RGB.
068 *
069 * <p>
070 * The following code demonstrates typical usage of
071 * {@code LinearGradientPaint}:
072 * <p>
073 * <pre>
074 * Point2D start = new Point2D.Float(0, 0);
075 * Point2D end = new Point2D.Float(50, 50);
076 * float[] dist = {0.0f, 0.2f, 1.0f};
077 * Color[] colors = {Color.RED, Color.WHITE, Color.BLUE};
078 * LinearGradientPaint p =
079 * new LinearGradientPaint(start, end, dist, colors);
080 * </pre>
081 * <p>
082 * This code will create a {@code LinearGradientPaint} which interpolates
083 * between red and white for the first 20% of the gradient and between white
084 * and blue for the remaining 80%.
085 *
086 * <p>
087 * This image demonstrates the example code above for each
088 * of the three cycle methods:
089 * <p>
090 * <center>
091 * <img src = "doc-files/LinearGradientPaint.png">
092 * </center>
093 *
094 * @see java.awt.Paint
095 * @see java.awt.Graphics2D#setPaint
096 * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
097 * @since 1.6
098 */
099 public final class LinearGradientPaint extends MultipleGradientPaint {
100
101 /** Gradient start and end points. */
102 private final Point2D start, end;
103
104 /**
105 * Constructs a {@code LinearGradientPaint} with a default
106 * {@code NO_CYCLE} repeating method and {@code SRGB} color space.
107 *
108 * @param startX the X coordinate of the gradient axis start point
109 * in user space
110 * @param startY the Y coordinate of the gradient axis start point
111 * in user space
112 * @param endX the X coordinate of the gradient axis end point
113 * in user space
114 * @param endY the Y coordinate of the gradient axis end point
115 * in user space
116 * @param fractions numbers ranging from 0.0 to 1.0 specifying the
117 * distribution of colors along the gradient
118 * @param colors array of colors corresponding to each fractional value
119 *
120 * @throws NullPointerException
121 * if {@code fractions} array is null,
122 * or {@code colors} array is null,
123 * @throws IllegalArgumentException
124 * if start and end points are the same points,
125 * or {@code fractions.length != colors.length},
126 * or {@code colors} is less than 2 in size,
127 * or a {@code fractions} value is less than 0.0 or greater than 1.0,
128 * or the {@code fractions} are not provided in strictly increasing order
129 */
130 public LinearGradientPaint(float startX, float startY, float endX,
131 float endY, float[] fractions, Color[] colors) {
132 this (new Point2D.Float(startX, startY), new Point2D.Float(endX,
133 endY), fractions, colors, CycleMethod.NO_CYCLE);
134 }
135
136 /**
137 * Constructs a {@code LinearGradientPaint} with a default {@code SRGB}
138 * color space.
139 *
140 * @param startX the X coordinate of the gradient axis start point
141 * in user space
142 * @param startY the Y coordinate of the gradient axis start point
143 * in user space
144 * @param endX the X coordinate of the gradient axis end point
145 * in user space
146 * @param endY the Y coordinate of the gradient axis end point
147 * in user space
148 * @param fractions numbers ranging from 0.0 to 1.0 specifying the
149 * distribution of colors along the gradient
150 * @param colors array of colors corresponding to each fractional value
151 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
152 * or {@code REPEAT}
153 *
154 * @throws NullPointerException
155 * if {@code fractions} array is null,
156 * or {@code colors} array is null,
157 * or {@code cycleMethod} is null
158 * @throws IllegalArgumentException
159 * if start and end points are the same points,
160 * or {@code fractions.length != colors.length},
161 * or {@code colors} is less than 2 in size,
162 * or a {@code fractions} value is less than 0.0 or greater than 1.0,
163 * or the {@code fractions} are not provided in strictly increasing order
164 */
165 public LinearGradientPaint(float startX, float startY, float endX,
166 float endY, float[] fractions, Color[] colors,
167 CycleMethod cycleMethod) {
168 this (new Point2D.Float(startX, startY), new Point2D.Float(endX,
169 endY), fractions, colors, cycleMethod);
170 }
171
172 /**
173 * Constructs a {@code LinearGradientPaint} with a default
174 * {@code NO_CYCLE} repeating method and {@code SRGB} color space.
175 *
176 * @param start the gradient axis start {@code Point2D} in user space
177 * @param end the gradient axis end {@code Point2D} in user space
178 * @param fractions numbers ranging from 0.0 to 1.0 specifying the
179 * distribution of colors along the gradient
180 * @param colors array of colors corresponding to each fractional value
181 *
182 * @throws NullPointerException
183 * if one of the points is null,
184 * or {@code fractions} array is null,
185 * or {@code colors} array is null
186 * @throws IllegalArgumentException
187 * if start and end points are the same points,
188 * or {@code fractions.length != colors.length},
189 * or {@code colors} is less than 2 in size,
190 * or a {@code fractions} value is less than 0.0 or greater than 1.0,
191 * or the {@code fractions} are not provided in strictly increasing order
192 */
193 public LinearGradientPaint(Point2D start, Point2D end,
194 float[] fractions, Color[] colors) {
195 this (start, end, fractions, colors, CycleMethod.NO_CYCLE);
196 }
197
198 /**
199 * Constructs a {@code LinearGradientPaint} with a default {@code SRGB}
200 * color space.
201 *
202 * @param start the gradient axis start {@code Point2D} in user space
203 * @param end the gradient axis end {@code Point2D} in user space
204 * @param fractions numbers ranging from 0.0 to 1.0 specifying the
205 * distribution of colors along the gradient
206 * @param colors array of colors corresponding to each fractional value
207 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
208 * or {@code REPEAT}
209 *
210 * @throws NullPointerException
211 * if one of the points is null,
212 * or {@code fractions} array is null,
213 * or {@code colors} array is null,
214 * or {@code cycleMethod} is null
215 * @throws IllegalArgumentException
216 * if start and end points are the same points,
217 * or {@code fractions.length != colors.length},
218 * or {@code colors} is less than 2 in size,
219 * or a {@code fractions} value is less than 0.0 or greater than 1.0,
220 * or the {@code fractions} are not provided in strictly increasing order
221 */
222 public LinearGradientPaint(Point2D start, Point2D end,
223 float[] fractions, Color[] colors, CycleMethod cycleMethod) {
224 this (start, end, fractions, colors, cycleMethod,
225 ColorSpaceType.SRGB, new AffineTransform());
226 }
227
228 /**
229 * Constructs a {@code LinearGradientPaint}.
230 *
231 * @param start the gradient axis start {@code Point2D} in user space
232 * @param end the gradient axis end {@code Point2D} in user space
233 * @param fractions numbers ranging from 0.0 to 1.0 specifying the
234 * distribution of colors along the gradient
235 * @param colors array of colors corresponding to each fractional value
236 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT},
237 * or {@code REPEAT}
238 * @param colorSpace which color space to use for interpolation,
239 * either {@code SRGB} or {@code LINEAR_RGB}
240 * @param gradientTransform transform to apply to the gradient
241 *
242 * @throws NullPointerException
243 * if one of the points is null,
244 * or {@code fractions} array is null,
245 * or {@code colors} array is null,
246 * or {@code cycleMethod} is null,
247 * or {@code colorSpace} is null,
248 * or {@code gradientTransform} is null
249 * @throws IllegalArgumentException
250 * if start and end points are the same points,
251 * or {@code fractions.length != colors.length},
252 * or {@code colors} is less than 2 in size,
253 * or a {@code fractions} value is less than 0.0 or greater than 1.0,
254 * or the {@code fractions} are not provided in strictly increasing order
255 */
256 public LinearGradientPaint(Point2D start, Point2D end,
257 float[] fractions, Color[] colors, CycleMethod cycleMethod,
258 ColorSpaceType colorSpace, AffineTransform gradientTransform) {
259 super (fractions, colors, cycleMethod, colorSpace,
260 gradientTransform);
261
262 // check input parameters
263 if (start == null || end == null) {
264 throw new NullPointerException(
265 "Start and end points must be" + "non-null");
266 }
267
268 if (start.equals(end)) {
269 throw new IllegalArgumentException(
270 "Start point cannot equal" + "endpoint");
271 }
272
273 // copy the points...
274 this .start = new Point2D.Double(start.getX(), start.getY());
275 this .end = new Point2D.Double(end.getX(), end.getY());
276 }
277
278 /**
279 * {@inheritDoc}
280 */
281 public PaintContext createContext(ColorModel cm,
282 Rectangle deviceBounds, Rectangle2D userBounds,
283 AffineTransform transform, RenderingHints hints) {
284 // avoid modifying the user's transform...
285 transform = new AffineTransform(transform);
286 // incorporate the gradient transform
287 transform.concatenate(gradientTransform);
288
289 if ((fractions.length == 2)
290 && (cycleMethod != CycleMethod.REPEAT)
291 && (colorSpace == ColorSpaceType.SRGB)) {
292 // faster to use the basic GradientPaintContext for this
293 // common case
294 boolean cyclic = (cycleMethod != CycleMethod.NO_CYCLE);
295 return new GradientPaintContext(cm, start, end, transform,
296 colors[0], colors[1], cyclic);
297 } else {
298 return new LinearGradientPaintContext(this , cm,
299 deviceBounds, userBounds, transform, hints, start,
300 end, fractions, colors, cycleMethod, colorSpace);
301 }
302 }
303
304 /**
305 * Returns a copy of the start point of the gradient axis.
306 *
307 * @return a {@code Point2D} object that is a copy of the point
308 * that anchors the first color of this {@code LinearGradientPaint}
309 */
310 public Point2D getStartPoint() {
311 return new Point2D.Double(start.getX(), start.getY());
312 }
313
314 /**
315 * Returns a copy of the end point of the gradient axis.
316 *
317 * @return a {@code Point2D} object that is a copy of the point
318 * that anchors the last color of this {@code LinearGradientPaint}
319 */
320 public Point2D getEndPoint() {
321 return new Point2D.Double(end.getX(), end.getY());
322 }
323 }
|