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 LinearGradientPaint} class provides a way to fill 36 * a {@link java.awt.Shape} with a linear color gradient pattern. The user 37 * may specify two or more gradient colors, and this paint will provide an 38 * interpolation between each color. The user also specifies start and end 39 * points which define where in user space the color gradient should begin 40 * and end. 41 * <p> 42 * The user must provide an array of floats specifying how to distribute the 43 * colors along the gradient. These values should range from 0.0 to 1.0 and 44 * act like keyframes along the gradient (they mark where the gradient should 45 * be exactly a particular color). 46 * <p> 47 * In the event that the user does not set the first keyframe value equal 48 * to 0 and/or the last keyframe value equal to 1, keyframes will be created 49 * at these positions and the first and last colors will be replicated there. 50 * So, if a user specifies the following arrays to construct a gradient:<br> 51 * <pre> 52 * {Color.BLUE, Color.RED}, {.3f, .7f} 53 * </pre> 54 * this will be converted to a gradient with the following keyframes:<br> 55 * <pre> 56 * {Color.BLUE, Color.BLUE, Color.RED, Color.RED}, {0f, .3f, .7f, 1f} 57 * </pre> 58 * 59 * <p> 60 * The user may also select what action the {@code LinearGradientPaint} object 61 * takes when it is filling the space outside the start and end points by 62 * setting {@code CycleMethod} to either {@code REFLECTION} or {@code REPEAT}. 63 * The distances between any two colors in any of the reflected or repeated 64 * copies of the gradient are the same as the distance between those same two 65 * colors between the start and end points. 66 * Note that some minor variations in distances may occur due to sampling at 67 * the granularity of a pixel. 68 * If no cycle method is specified, {@code NO_CYCLE} will be chosen by 69 * default, which means the endpoint colors will be used to fill the 70 * remaining area. 71 * <p> 72 * The colorSpace parameter allows the user to specify in which colorspace 73 * the interpolation should be performed, default sRGB or linearized RGB. 74 * 75 * <p> 76 * The following code demonstrates typical usage of 77 * {@code LinearGradientPaint}: 78 * <pre> 79 * Point2D start = new Point2D.Float(0, 0); 80 * Point2D end = new Point2D.Float(50, 50); 81 * float[] dist = {0.0f, 0.2f, 1.0f}; 82 * Color[] colors = {Color.RED, Color.WHITE, Color.BLUE}; 83 * LinearGradientPaint p = 84 * new LinearGradientPaint(start, end, dist, colors); 85 * </pre> 86 * <p> 87 * This code will create a {@code LinearGradientPaint} which interpolates 88 * between red and white for the first 20% of the gradient and between white 89 * and blue for the remaining 80%. 90 * 91 * <p> 92 * This image demonstrates the example code above for each 93 * of the three cycle methods: 94 * <center> 95 * <img src = "doc-files/LinearGradientPaint.png" 96 * alt="image showing the output of the example code"> 97 * </center> 98 * 99 * @see java.awt.Paint 100 * @see java.awt.Graphics2D#setPaint 101 * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans 102 * @since 1.6 103 */ 104 public final class LinearGradientPaint extends MultipleGradientPaint { 105 106 /** Gradient start and end points. */ 107 private final Point2D start, end; 108 109 /** 110 * Constructs a {@code LinearGradientPaint} with a default 111 * {@code NO_CYCLE} repeating method and {@code SRGB} color space. 112 * 113 * @param startX the X coordinate of the gradient axis start point 114 * in user space 115 * @param startY the Y coordinate of the gradient axis start point 116 * in user space 117 * @param endX the X coordinate of the gradient axis end point 118 * in user space 119 * @param endY the Y coordinate of the gradient axis end point 120 * in user space 121 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 122 * distribution of colors along the gradient 123 * @param colors array of colors corresponding to each fractional value 124 * 125 * @throws NullPointerException 126 * if {@code fractions} array is null, 127 * or {@code colors} array is null, 128 * @throws IllegalArgumentException 129 * if start and end points are the same points, 130 * or {@code fractions.length != colors.length}, 131 * or {@code colors} is less than 2 in size, 132 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 133 * or the {@code fractions} are not provided in strictly increasing order 134 */ 135 public LinearGradientPaint(float startX, float startY, 136 float endX, float endY, 137 float[] fractions, Color[] colors) 138 { 139 this(new Point2D.Float(startX, startY), 140 new Point2D.Float(endX, endY), 141 fractions, 142 colors, 143 CycleMethod.NO_CYCLE); 144 } 145 146 /** 147 * Constructs a {@code LinearGradientPaint} with a default {@code SRGB} 148 * color space. 149 * 150 * @param startX the X coordinate of the gradient axis start point 151 * in user space 152 * @param startY the Y coordinate of the gradient axis start point 153 * in user space 154 * @param endX the X coordinate of the gradient axis end point 155 * in user space 156 * @param endY the Y coordinate of the gradient axis end point 157 * in user space 158 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 159 * distribution of colors along the gradient 160 * @param colors array of colors corresponding to each fractional value 161 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT}, 162 * or {@code REPEAT} 163 * 164 * @throws NullPointerException 165 * if {@code fractions} array is null, 166 * or {@code colors} array is null, 167 * or {@code cycleMethod} is null 168 * @throws IllegalArgumentException 169 * if start and end points are the same points, 170 * or {@code fractions.length != colors.length}, 171 * or {@code colors} is less than 2 in size, 172 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 173 * or the {@code fractions} are not provided in strictly increasing order 174 */ 175 public LinearGradientPaint(float startX, float startY, 176 float endX, float endY, 177 float[] fractions, Color[] colors, 178 CycleMethod cycleMethod) 179 { 180 this(new Point2D.Float(startX, startY), 181 new Point2D.Float(endX, endY), 182 fractions, 183 colors, 184 cycleMethod); 185 } 186 187 /** 188 * Constructs a {@code LinearGradientPaint} with a default 189 * {@code NO_CYCLE} repeating method and {@code SRGB} color space. 190 * 191 * @param start the gradient axis start {@code Point2D} in user space 192 * @param end the gradient axis end {@code Point2D} in user space 193 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 194 * distribution of colors along the gradient 195 * @param colors array of colors corresponding to each fractional value 196 * 197 * @throws NullPointerException 198 * if one of the points is null, 199 * or {@code fractions} array is null, 200 * or {@code colors} array is null 201 * @throws IllegalArgumentException 202 * if start and end points are the same points, 203 * or {@code fractions.length != colors.length}, 204 * or {@code colors} is less than 2 in size, 205 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 206 * or the {@code fractions} are not provided in strictly increasing order 207 */ 208 public LinearGradientPaint(Point2D start, Point2D end, 209 float[] fractions, Color[] colors) 210 { 211 this(start, end, 212 fractions, colors, 213 CycleMethod.NO_CYCLE); 214 } 215 216 /** 217 * Constructs a {@code LinearGradientPaint} with a default {@code SRGB} 218 * color space. 219 * 220 * @param start the gradient axis start {@code Point2D} in user space 221 * @param end the gradient axis end {@code Point2D} in user space 222 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 223 * distribution of colors along the gradient 224 * @param colors array of colors corresponding to each fractional value 225 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT}, 226 * or {@code REPEAT} 227 * 228 * @throws NullPointerException 229 * if one of the points is null, 230 * or {@code fractions} array is null, 231 * or {@code colors} array is null, 232 * or {@code cycleMethod} is null 233 * @throws IllegalArgumentException 234 * if start and end points are the same points, 235 * or {@code fractions.length != colors.length}, 236 * or {@code colors} is less than 2 in size, 237 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 238 * or the {@code fractions} are not provided in strictly increasing order 239 */ 240 public LinearGradientPaint(Point2D start, Point2D end, 241 float[] fractions, Color[] colors, 242 CycleMethod cycleMethod) 243 { 244 this(start, end, 245 fractions, colors, 246 cycleMethod, 247 ColorSpaceType.SRGB, 248 new AffineTransform()); 249 } 250 251 /** 252 * Constructs a {@code LinearGradientPaint}. 253 * 254 * @param start the gradient axis start {@code Point2D} in user space 255 * @param end the gradient axis end {@code Point2D} in user space 256 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 257 * distribution of colors along the gradient 258 * @param colors array of colors corresponding to each fractional value 259 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT}, 260 * or {@code REPEAT} 261 * @param colorSpace which color space to use for interpolation, 262 * either {@code SRGB} or {@code LINEAR_RGB} 263 * @param gradientTransform transform to apply to the gradient 264 * 265 * @throws NullPointerException 266 * if one of the points is null, 267 * or {@code fractions} array is null, 268 * or {@code colors} array is null, 269 * or {@code cycleMethod} is null, 270 * or {@code colorSpace} is null, 271 * or {@code gradientTransform} is null 272 * @throws IllegalArgumentException 273 * if start and end points are the same points, 274 * or {@code fractions.length != colors.length}, 275 * or {@code colors} is less than 2 in size, 276 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 277 * or the {@code fractions} are not provided in strictly increasing order 278 */ 279 @ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" }) 280 public LinearGradientPaint(Point2D start, Point2D end, 281 float[] fractions, Color[] colors, 282 CycleMethod cycleMethod, 283 ColorSpaceType colorSpace, 284 AffineTransform gradientTransform) 285 { 286 super(fractions, colors, cycleMethod, colorSpace, gradientTransform); 287 288 // check input parameters 289 if (start == null || end == null) { 290 throw new NullPointerException("Start and end points must be" + 291 "non-null"); 292 } 293 294 if (start.equals(end)) { 295 throw new IllegalArgumentException("Start point cannot equal" + 296 "endpoint"); 297 } 298 299 // copy the points... 300 this.start = new Point2D.Double(start.getX(), start.getY()); 301 this.end = new Point2D.Double(end.getX(), end.getY()); 302 } 303 304 /** 305 * Creates and returns a {@link PaintContext} used to 306 * generate a linear color gradient pattern. 307 * See the {@link Paint#createContext specification} of the 308 * method in the {@link Paint} interface for information 309 * on null parameter handling. 310 * 311 * @param cm the preferred {@link ColorModel} which represents the most convenient 312 * format for the caller to receive the pixel data, or {@code null} 313 * if there is no preference. 314 * @param deviceBounds the device space bounding box 315 * of the graphics primitive being rendered. 316 * @param userBounds the user space bounding box 317 * of the graphics primitive being rendered. 318 * @param transform the {@link AffineTransform} from user 319 * space into device space. 320 * @param hints the set of hints that the context object can use to 321 * choose between rendering alternatives. 322 * @return the {@code PaintContext} for 323 * generating color patterns. 324 * @see Paint 325 * @see PaintContext 326 * @see ColorModel 327 * @see Rectangle 328 * @see Rectangle2D 329 * @see AffineTransform 330 * @see RenderingHints 331 */ 332 public PaintContext createContext(ColorModel cm, 333 Rectangle deviceBounds, 334 Rectangle2D userBounds, 335 AffineTransform transform, 336 RenderingHints hints) 337 { 338 // avoid modifying the user's transform... 339 transform = new AffineTransform(transform); 340 // incorporate the gradient transform 341 transform.concatenate(gradientTransform); 342 343 if ((fractions.length == 2) && 344 (cycleMethod != CycleMethod.REPEAT) && 345 (colorSpace == ColorSpaceType.SRGB)) 346 { 347 // faster to use the basic GradientPaintContext for this 348 // common case 349 boolean cyclic = (cycleMethod != CycleMethod.NO_CYCLE); 350 return new GradientPaintContext(cm, start, end, 351 transform, 352 colors[0], colors[1], 353 cyclic); 354 } else { 355 return new LinearGradientPaintContext(this, cm, 356 deviceBounds, userBounds, 357 transform, hints, 358 start, end, 359 fractions, colors, 360 cycleMethod, colorSpace); 361 } 362 } 363 364 /** 365 * Returns a copy of the start point of the gradient axis. 366 * 367 * @return a {@code Point2D} object that is a copy of the point 368 * that anchors the first color of this {@code LinearGradientPaint} 369 */ 370 public Point2D getStartPoint() { 371 return new Point2D.Double(start.getX(), start.getY()); 372 } 373 374 /** 375 * Returns a copy of the end point of the gradient axis. 376 * 377 * @return a {@code Point2D} object that is a copy of the point 378 * that anchors the last color of this {@code LinearGradientPaint} 379 */ 380 public Point2D getEndPoint() { 381 return new Point2D.Double(end.getX(), end.getY()); 382 } 383 }