blob: 32f69686cb51ec9139a4f5e9ccafe04a4cbefd4f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package java.awt;
27
28import java.awt.MultipleGradientPaint.CycleMethod;
29import java.awt.MultipleGradientPaint.ColorSpaceType;
30import java.awt.geom.AffineTransform;
31import java.awt.geom.Point2D;
32import java.awt.geom.Rectangle2D;
33import java.awt.image.ColorModel;
34
35/**
36 * Provides the actual implementation for the LinearGradientPaint.
37 * This is where the pixel processing is done.
38 *
39 * @see java.awt.LinearGradientPaint
40 * @see java.awt.PaintContext
41 * @see java.awt.Paint
42 * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
43 */
44final class LinearGradientPaintContext extends MultipleGradientPaintContext {
45
46 /**
47 * The following invariants are used to process the gradient value from
48 * a device space coordinate, (X, Y):
49 * g(X, Y) = dgdX*X + dgdY*Y + gc
50 */
51 private float dgdX, dgdY, gc;
52
53 /**
54 * Constructor for LinearGradientPaintContext.
55 *
56 * @param paint the {@code LinearGradientPaint} from which this context
57 * is created
58 * @param cm {@code ColorModel} that receives
59 * the <code>Paint</code> data. This is used only as a hint.
60 * @param deviceBounds the device space bounding box of the
61 * graphics primitive being rendered
62 * @param userBounds the user space bounding box of the
63 * graphics primitive being rendered
64 * @param t the {@code AffineTransform} from user
65 * space into device space (gradientTransform should be
66 * concatenated with this)
67 * @param hints the hints that the context object uses to choose
68 * between rendering alternatives
69 * @param dStart gradient start point, in user space
70 * @param dEnd gradient end point, in user space
71 * @param fractions the fractions specifying the gradient distribution
72 * @param colors the gradient colors
73 * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
74 * @param colorSpace which colorspace to use for interpolation,
75 * either SRGB or LINEAR_RGB
76 */
77 LinearGradientPaintContext(LinearGradientPaint paint,
78 ColorModel cm,
79 Rectangle deviceBounds,
80 Rectangle2D userBounds,
81 AffineTransform t,
82 RenderingHints hints,
83 Point2D start,
84 Point2D end,
85 float[] fractions,
86 Color[] colors,
87 CycleMethod cycleMethod,
88 ColorSpaceType colorSpace)
89 {
90 super(paint, cm, deviceBounds, userBounds, t, hints, fractions,
91 colors, cycleMethod, colorSpace);
92
93 // A given point in the raster should take on the same color as its
94 // projection onto the gradient vector.
95 // Thus, we want the projection of the current position vector
96 // onto the gradient vector, then normalized with respect to the
97 // length of the gradient vector, giving a value which can be mapped
98 // into the range 0-1.
99 // projection =
100 // currentVector dot gradientVector / length(gradientVector)
101 // normalized = projection / length(gradientVector)
102
103 float startx = (float)start.getX();
104 float starty = (float)start.getY();
105 float endx = (float)end.getX();
106 float endy = (float)end.getY();
107
108 float dx = endx - startx; // change in x from start to end
109 float dy = endy - starty; // change in y from start to end
110 float dSq = dx*dx + dy*dy; // total distance squared
111
112 // avoid repeated calculations by doing these divides once
113 float constX = dx/dSq;
114 float constY = dy/dSq;
115
116 // incremental change along gradient for +x
117 dgdX = a00*constX + a10*constY;
118 // incremental change along gradient for +y
119 dgdY = a01*constX + a11*constY;
120
121 // constant, incorporates the translation components from the matrix
122 gc = (a02-startx)*constX + (a12-starty)*constY;
123 }
124
125 /**
126 * Return a Raster containing the colors generated for the graphics
127 * operation. This is where the area is filled with colors distributed
128 * linearly.
129 *
130 * @param x,y,w,h the area in device space for which colors are
131 * generated.
132 */
133 protected void fillRaster(int[] pixels, int off, int adjust,
134 int x, int y, int w, int h)
135 {
136 // current value for row gradients
137 float g = 0;
138
139 // used to end iteration on rows
140 int rowLimit = off + w;
141
142 // constant which can be pulled out of the inner loop
143 float initConst = (dgdX*x) + gc;
144
145 for (int i = 0; i < h; i++) { // for every row
146
147 // initialize current value to be start
148 g = initConst + dgdY*(y+i);
149
150 while (off < rowLimit) { // for every pixel in this row
151 // get the color
152 pixels[off++] = indexIntoGradientsArrays(g);
153
154 // incremental change in g
155 g += dgdX;
156 }
157
158 // change in off from row to row
159 off += adjust;
160
161 //rowlimit is width + offset
162 rowLimit = off + w;
163 }
164 }
165}