KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > GradientPaintContext


1 /*
2  * @(#)GradientPaintContext.java 1.23 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt;
9
10 import java.awt.image.Raster JavaDoc;
11 import java.awt.image.WritableRaster JavaDoc;
12 import sun.awt.image.IntegerComponentRaster;
13 import java.awt.image.ColorModel JavaDoc;
14 import java.awt.image.DirectColorModel JavaDoc;
15 import java.awt.geom.Point2D JavaDoc;
16 import java.awt.geom.AffineTransform JavaDoc;
17 import java.awt.geom.NoninvertibleTransformException JavaDoc;
18 import java.lang.ref.WeakReference JavaDoc;
19
20 class GradientPaintContext implements PaintContext JavaDoc {
21     static ColorModel JavaDoc xrgbmodel =
22     new DirectColorModel JavaDoc(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
23     static ColorModel JavaDoc xbgrmodel =
24     new DirectColorModel JavaDoc(24, 0x000000ff, 0x0000ff00, 0x00ff0000);
25
26     static ColorModel JavaDoc cachedModel;
27     static WeakReference JavaDoc cached;
28
29     static synchronized Raster JavaDoc getCachedRaster(ColorModel JavaDoc cm, int w, int h) {
30     if (cm == cachedModel) {
31         if (cached != null) {
32         Raster JavaDoc ras = (Raster JavaDoc) cached.get();
33         if (ras != null &&
34             ras.getWidth() >= w &&
35             ras.getHeight() >= h)
36         {
37             cached = null;
38             return ras;
39         }
40         }
41     }
42     return cm.createCompatibleWritableRaster(w, h);
43     }
44
45     static synchronized void putCachedRaster(ColorModel JavaDoc cm, Raster JavaDoc ras) {
46     if (cached != null) {
47         Raster JavaDoc cras = (Raster JavaDoc) cached.get();
48         if (cras != null) {
49         int cw = cras.getWidth();
50         int ch = cras.getHeight();
51         int iw = ras.getWidth();
52         int ih = ras.getHeight();
53         if (cw >= iw && ch >= ih) {
54             return;
55         }
56         if (cw * ch >= iw * ih) {
57             return;
58         }
59         }
60     }
61     cachedModel = cm;
62     cached = new WeakReference JavaDoc(ras);
63     }
64
65     double x1;
66     double y1;
67     double dx;
68     double dy;
69     boolean cyclic;
70     int interp[];
71     Raster JavaDoc saved;
72     ColorModel JavaDoc model;
73
74     public GradientPaintContext(ColorModel JavaDoc cm,
75                 Point2D JavaDoc p1, Point2D JavaDoc p2, AffineTransform JavaDoc xform,
76                 Color JavaDoc c1, Color JavaDoc c2, boolean cyclic) {
77     // First calculate the distance moved in user space when
78
// we move a single unit along the X & Y axes in device space.
79
Point2D JavaDoc xvec = new Point2D.Double JavaDoc(1, 0);
80     Point2D JavaDoc yvec = new Point2D.Double JavaDoc(0, 1);
81     try {
82         AffineTransform JavaDoc inverse = xform.createInverse();
83         inverse.deltaTransform(xvec, xvec);
84         inverse.deltaTransform(yvec, yvec);
85     } catch (NoninvertibleTransformException JavaDoc e) {
86         xvec.setLocation(0, 0);
87         yvec.setLocation(0, 0);
88     }
89
90     // Now calculate the (square of the) user space distance
91
// between the anchor points. This value equals:
92
// (UserVec . UserVec)
93
double udx = p2.getX() - p1.getX();
94     double udy = p2.getY() - p1.getY();
95     double ulenSq = udx * udx + udy * udy;
96
97     if (ulenSq <= Double.MIN_VALUE) {
98         dx = 0;
99         dy = 0;
100     } else {
101         // Now calculate the proportional distance moved along the
102
// vector from p1 to p2 when we move a unit along X & Y in
103
// device space.
104
//
105
// The length of the projection of the Device Axis Vector is
106
// its dot product with the Unit User Vector:
107
// (DevAxisVec . (UserVec / Len(UserVec))
108
//
109
// The "proportional" length is that length divided again
110
// by the length of the User Vector:
111
// (DevAxisVec . (UserVec / Len(UserVec))) / Len(UserVec)
112
// which simplifies to:
113
// ((DevAxisVec . UserVec) / Len(UserVec)) / Len(UserVec)
114
// which simplifies to:
115
// (DevAxisVec . UserVec) / LenSquared(UserVec)
116
dx = (xvec.getX() * udx + xvec.getY() * udy) / ulenSq;
117         dy = (yvec.getX() * udx + yvec.getY() * udy) / ulenSq;
118
119         if (cyclic) {
120         dx = dx % 1.0;
121         dy = dy % 1.0;
122         } else {
123         // We are acyclic
124
if (dx < 0) {
125             // If we are using the acyclic form below, we need
126
// dx to be non-negative for simplicity of scanning
127
// across the scan lines for the transition points.
128
// To ensure that constraint, we negate the dx/dy
129
// values and swap the points and colors.
130
Point2D JavaDoc p = p1; p1 = p2; p2 = p;
131             Color JavaDoc c = c1; c1 = c2; c2 = c;
132             dx = -dx;
133             dy = -dy;
134         }
135         }
136     }
137
138     Point2D JavaDoc dp1 = xform.transform(p1, null);
139     this.x1 = dp1.getX();
140     this.y1 = dp1.getY();
141
142     this.cyclic = cyclic;
143     int rgb1 = c1.getRGB();
144     int rgb2 = c2.getRGB();
145     int a1 = (rgb1 >> 24) & 0xff;
146     int r1 = (rgb1 >> 16) & 0xff;
147     int g1 = (rgb1 >> 8) & 0xff;
148     int b1 = (rgb1 ) & 0xff;
149     int da = ((rgb2 >> 24) & 0xff) - a1;
150     int dr = ((rgb2 >> 16) & 0xff) - r1;
151     int dg = ((rgb2 >> 8) & 0xff) - g1;
152     int db = ((rgb2 ) & 0xff) - b1;
153     if (a1 == 0xff && da == 0) {
154         model = xrgbmodel;
155         if (cm instanceof DirectColorModel JavaDoc) {
156         DirectColorModel JavaDoc dcm = (DirectColorModel JavaDoc) cm;
157         int tmp = dcm.getAlphaMask();
158         if ((tmp == 0 || tmp == 0xff) &&
159             dcm.getRedMask() == 0xff &&
160             dcm.getGreenMask() == 0xff00 &&
161             dcm.getBlueMask() == 0xff0000)
162         {
163             model = xbgrmodel;
164             tmp = r1; r1 = b1; b1 = tmp;
165             tmp = dr; dr = db; db = tmp;
166         }
167         }
168     } else {
169         model = ColorModel.getRGBdefault();
170     }
171     interp = new int[cyclic ? 513 : 257];
172     for (int i = 0; i <= 256; i++) {
173         float rel = i / 256.0f;
174         int rgb =
175         (((int) (a1 + da * rel)) << 24) |
176         (((int) (r1 + dr * rel)) << 16) |
177         (((int) (g1 + dg * rel)) << 8) |
178         (((int) (b1 + db * rel)) );
179         interp[i] = rgb;
180         if (cyclic) {
181         interp[512 - i] = rgb;
182         }
183     }
184     }
185
186     /**
187      * Release the resources allocated for the operation.
188      */

189     public void dispose() {
190     if (saved != null) {
191         putCachedRaster(model, saved);
192         saved = null;
193     }
194     }
195
196     /**
197      * Return the ColorModel of the output.
198      */

199     public ColorModel JavaDoc getColorModel() {
200         return model;
201     }
202
203     /**
204      * Return a Raster containing the colors generated for the graphics
205      * operation.
206      * @param x,y,w,h The area in device space for which colors are
207      * generated.
208      */

209     public Raster JavaDoc getRaster(int x, int y, int w, int h) {
210     double rowrel = (x - x1) * dx + (y - y1) * dy;
211
212     Raster JavaDoc rast = saved;
213     if (rast == null || rast.getWidth() < w || rast.getHeight() < h) {
214         rast = getCachedRaster(model, w, h);
215         saved = rast;
216     }
217     IntegerComponentRaster irast = (IntegerComponentRaster) rast;
218     int off = irast.getDataOffset(0);
219     int adjust = irast.getScanlineStride() - w;
220     int[] pixels = irast.getDataStorage();
221
222     if (cyclic) {
223         cycleFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
224     } else {
225         clipFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
226     }
227
228     return rast;
229     }
230
231     void cycleFillRaster(int[] pixels, int off, int adjust, int w, int h,
232              double rowrel, double dx, double dy) {
233     rowrel = rowrel % 2.0;
234     int irowrel = ((int) (rowrel * (1 << 30))) << 1;
235     int idx = (int) (-dx * (1 << 31));
236     int idy = (int) (-dy * (1 << 31));
237     while (--h >= 0) {
238         int icolrel = irowrel;
239         for (int j = w; j > 0; j--) {
240         pixels[off++] = interp[icolrel >>> 23];
241         icolrel += idx;
242         }
243
244         off += adjust;
245         irowrel += idy;
246         }
247     }
248
249     void clipFillRaster(int[] pixels, int off, int adjust, int w, int h,
250             double rowrel, double dx, double dy) {
251     while (--h >= 0) {
252         double colrel = rowrel;
253         int j = w;
254         if (colrel <= 0.0) {
255         int rgb = interp[0];
256         do {
257             pixels[off++] = rgb;
258             colrel += dx;
259         } while (--j > 0 && colrel <= 0.0);
260         }
261         while (colrel < 1.0 && --j >= 0) {
262         pixels[off++] = interp[(int) (colrel * 256)];
263         colrel += dx;
264         }
265         if (j > 0) {
266         int rgb = interp[256];
267         do {
268             pixels[off++] = rgb;
269         } while (--j > 0);
270         }
271
272         off += adjust;
273         rowrel += dy;
274         }
275     }
276 }
277
Popular Tags