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 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 * <p style="text-align:center"> 95 * <img src = "doc-files/LinearGradientPaint.png" 96 * alt="image showing the output of the example code"> 97 * 98 * @see java.awt.Paint 99 * @see java.awt.Graphics2D#setPaint 100 * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans 101 * @since 1.6 102 */ 103 public final class LinearGradientPaint extends MultipleGradientPaint { 104 105 /** Gradient start and end points. */ 106 private final Point2D start, end; 107 108 /** 109 * Constructs a {@code LinearGradientPaint} with a default 110 * {@code NO_CYCLE} repeating method and {@code SRGB} color space. 111 * 112 * @param startX the X coordinate of the gradient axis start point 113 * in user space 114 * @param startY the Y coordinate of the gradient axis start point 115 * in user space 116 * @param endX the X coordinate of the gradient axis end point 117 * in user space 118 * @param endY the Y coordinate of the gradient axis end point 119 * in user space 120 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 121 * distribution of colors along the gradient 122 * @param colors array of colors corresponding to each fractional value 123 * 124 * @throws NullPointerException 125 * if {@code fractions} array is null, 126 * or {@code colors} array is null, 127 * @throws IllegalArgumentException 128 * if start and end points are the same points, 129 * or {@code fractions.length != colors.length}, 130 * or {@code colors} is less than 2 in size, 131 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 132 * or the {@code fractions} are not provided in strictly increasing order 133 */ LinearGradientPaint(float startX, float startY, float endX, float endY, float[] fractions, Color[] colors)134 public LinearGradientPaint(float startX, float startY, 135 float endX, float endY, 136 float[] fractions, Color[] colors) 137 { 138 this(new Point2D.Float(startX, startY), 139 new Point2D.Float(endX, endY), 140 fractions, 141 colors, 142 CycleMethod.NO_CYCLE); 143 } 144 145 /** 146 * Constructs a {@code LinearGradientPaint} with a default {@code SRGB} 147 * color space. 148 * 149 * @param startX the X coordinate of the gradient axis start point 150 * in user space 151 * @param startY the Y coordinate of the gradient axis start point 152 * in user space 153 * @param endX the X coordinate of the gradient axis end point 154 * in user space 155 * @param endY the Y coordinate of the gradient axis end point 156 * in user space 157 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 158 * distribution of colors along the gradient 159 * @param colors array of colors corresponding to each fractional value 160 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT}, 161 * or {@code REPEAT} 162 * 163 * @throws NullPointerException 164 * if {@code fractions} array is null, 165 * or {@code colors} array is null, 166 * or {@code cycleMethod} is null 167 * @throws IllegalArgumentException 168 * if start and end points are the same points, 169 * or {@code fractions.length != colors.length}, 170 * or {@code colors} is less than 2 in size, 171 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 172 * or the {@code fractions} are not provided in strictly increasing order 173 */ LinearGradientPaint(float startX, float startY, float endX, float endY, float[] fractions, Color[] colors, CycleMethod cycleMethod)174 public LinearGradientPaint(float startX, float startY, 175 float endX, float endY, 176 float[] fractions, Color[] colors, 177 CycleMethod cycleMethod) 178 { 179 this(new Point2D.Float(startX, startY), 180 new Point2D.Float(endX, endY), 181 fractions, 182 colors, 183 cycleMethod); 184 } 185 186 /** 187 * Constructs a {@code LinearGradientPaint} with a default 188 * {@code NO_CYCLE} repeating method and {@code SRGB} color space. 189 * 190 * @param start the gradient axis start {@code Point2D} in user space 191 * @param end the gradient axis end {@code Point2D} in user space 192 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 193 * distribution of colors along the gradient 194 * @param colors array of colors corresponding to each fractional value 195 * 196 * @throws NullPointerException 197 * if one of the points is null, 198 * or {@code fractions} array is null, 199 * or {@code colors} array is null 200 * @throws IllegalArgumentException 201 * if start and end points are the same points, 202 * or {@code fractions.length != colors.length}, 203 * or {@code colors} is less than 2 in size, 204 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 205 * or the {@code fractions} are not provided in strictly increasing order 206 */ LinearGradientPaint(Point2D start, Point2D end, float[] fractions, Color[] colors)207 public LinearGradientPaint(Point2D start, Point2D end, 208 float[] fractions, Color[] colors) 209 { 210 this(start, end, 211 fractions, colors, 212 CycleMethod.NO_CYCLE); 213 } 214 215 /** 216 * Constructs a {@code LinearGradientPaint} with a default {@code SRGB} 217 * color space. 218 * 219 * @param start the gradient axis start {@code Point2D} in user space 220 * @param end the gradient axis end {@code Point2D} in user space 221 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 222 * distribution of colors along the gradient 223 * @param colors array of colors corresponding to each fractional value 224 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT}, 225 * or {@code REPEAT} 226 * 227 * @throws NullPointerException 228 * if one of the points is null, 229 * or {@code fractions} array is null, 230 * or {@code colors} array is null, 231 * or {@code cycleMethod} is null 232 * @throws IllegalArgumentException 233 * if start and end points are the same points, 234 * or {@code fractions.length != colors.length}, 235 * or {@code colors} is less than 2 in size, 236 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 237 * or the {@code fractions} are not provided in strictly increasing order 238 */ LinearGradientPaint(Point2D start, Point2D end, float[] fractions, Color[] colors, CycleMethod cycleMethod)239 public LinearGradientPaint(Point2D start, Point2D end, 240 float[] fractions, Color[] colors, 241 CycleMethod cycleMethod) 242 { 243 this(start, end, 244 fractions, colors, 245 cycleMethod, 246 ColorSpaceType.SRGB, 247 new AffineTransform()); 248 } 249 250 /** 251 * Constructs a {@code LinearGradientPaint}. 252 * 253 * @param start the gradient axis start {@code Point2D} in user space 254 * @param end the gradient axis end {@code Point2D} in user space 255 * @param fractions numbers ranging from 0.0 to 1.0 specifying the 256 * distribution of colors along the gradient 257 * @param colors array of colors corresponding to each fractional value 258 * @param cycleMethod either {@code NO_CYCLE}, {@code REFLECT}, 259 * or {@code REPEAT} 260 * @param colorSpace which color space to use for interpolation, 261 * either {@code SRGB} or {@code LINEAR_RGB} 262 * @param gradientTransform transform to apply to the gradient 263 * 264 * @throws NullPointerException 265 * if one of the points is null, 266 * or {@code fractions} array is null, 267 * or {@code colors} array is null, 268 * or {@code cycleMethod} is null, 269 * or {@code colorSpace} is null, 270 * or {@code gradientTransform} is null 271 * @throws IllegalArgumentException 272 * if start and end points are the same points, 273 * or {@code fractions.length != colors.length}, 274 * or {@code colors} is less than 2 in size, 275 * or a {@code fractions} value is less than 0.0 or greater than 1.0, 276 * or the {@code fractions} are not provided in strictly increasing order 277 */ 278 @ConstructorProperties({ "startPoint", "endPoint", "fractions", "colors", "cycleMethod", "colorSpace", "transform" }) LinearGradientPaint(Point2D start, Point2D end, float[] fractions, Color[] colors, CycleMethod cycleMethod, ColorSpaceType colorSpace, AffineTransform gradientTransform)279 public LinearGradientPaint(Point2D start, Point2D end, 280 float[] fractions, Color[] colors, 281 CycleMethod cycleMethod, 282 ColorSpaceType colorSpace, 283 AffineTransform gradientTransform) 284 { 285 super(fractions, colors, cycleMethod, colorSpace, gradientTransform); 286 287 // check input parameters 288 if (start == null || end == null) { 289 throw new NullPointerException("Start and end points must be" + 290 "non-null"); 291 } 292 293 if (start.equals(end)) { 294 throw new IllegalArgumentException("Start point cannot equal" + 295 "endpoint"); 296 } 297 298 // copy the points... 299 this.start = new Point2D.Double(start.getX(), start.getY()); 300 this.end = new Point2D.Double(end.getX(), end.getY()); 301 } 302 303 /** 304 * Creates and returns a {@link PaintContext} used to 305 * generate a linear color gradient pattern. 306 * See the {@link Paint#createContext specification} of the 307 * method in the {@link Paint} interface for information 308 * on null parameter handling. 309 * 310 * @param cm the preferred {@link ColorModel} which represents the most convenient 311 * format for the caller to receive the pixel data, or {@code null} 312 * if there is no preference. 313 * @param deviceBounds the device space bounding box 314 * of the graphics primitive being rendered. 315 * @param userBounds the user space bounding box 316 * of the graphics primitive being rendered. 317 * @param transform the {@link AffineTransform} from user 318 * space into device space. 319 * @param hints the set of hints that the context object can use to 320 * choose between rendering alternatives. 321 * @return the {@code PaintContext} for 322 * generating color patterns. 323 * @see Paint 324 * @see PaintContext 325 * @see ColorModel 326 * @see Rectangle 327 * @see Rectangle2D 328 * @see AffineTransform 329 * @see RenderingHints 330 */ createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform transform, RenderingHints hints)331 public PaintContext createContext(ColorModel cm, 332 Rectangle deviceBounds, 333 Rectangle2D userBounds, 334 AffineTransform transform, 335 RenderingHints hints) 336 { 337 // avoid modifying the user's transform... 338 transform = new AffineTransform(transform); 339 // incorporate the gradient transform 340 transform.concatenate(gradientTransform); 341 342 if ((fractions.length == 2) && 343 (cycleMethod != CycleMethod.REPEAT) && 344 (colorSpace == ColorSpaceType.SRGB)) 345 { 346 // faster to use the basic GradientPaintContext for this 347 // common case 348 boolean cyclic = (cycleMethod != CycleMethod.NO_CYCLE); 349 return new GradientPaintContext(cm, start, end, 350 transform, 351 colors[0], colors[1], 352 cyclic); 353 } else { 354 return new LinearGradientPaintContext(this, cm, 355 deviceBounds, userBounds, 356 transform, hints, 357 start, end, 358 fractions, colors, 359 cycleMethod, colorSpace); 360 } 361 } 362 363 /** 364 * Returns a copy of the start point of the gradient axis. 365 * 366 * @return a {@code Point2D} object that is a copy of the point 367 * that anchors the first color of this {@code LinearGradientPaint} 368 */ getStartPoint()369 public Point2D getStartPoint() { 370 return new Point2D.Double(start.getX(), start.getY()); 371 } 372 373 /** 374 * Returns a copy of the end point of the gradient axis. 375 * 376 * @return a {@code Point2D} object that is a copy of the point 377 * that anchors the last color of this {@code LinearGradientPaint} 378 */ getEndPoint()379 public Point2D getEndPoint() { 380 return new Point2D.Double(end.getX(), end.getY()); 381 } 382 } 383