blob: 9bb648f9bb2aeb1440f7bb4271270bd023f17bd3 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2007 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 sun.java2d.pisces;
27
28import sun.java2d.pipe.AATileGenerator;
29
30public class PiscesTileGenerator implements AATileGenerator {
31 public static final int TILE_SIZE = 32;
32
33 PiscesCache cache;
34 int x, y;
35 int maxalpha;
36 byte alphaMap[];
37
38 public PiscesTileGenerator(PiscesCache cache, int maxalpha) {
39 this.cache = cache;
40 this.x = cache.bboxX0;
41 this.y = cache.bboxY0;
42 this.alphaMap = getAlphaMap(maxalpha);
43 this.maxalpha = maxalpha;
44 }
45
46 static int prevMaxAlpha;
47 static byte prevAlphaMap[];
48
49 public synchronized static byte[] getAlphaMap(int maxalpha) {
50 if (maxalpha != prevMaxAlpha) {
51 prevAlphaMap = new byte[maxalpha+300];
52 int halfmaxalpha = maxalpha>>2;
53 for (int i = 0; i <= maxalpha; i++) {
54 prevAlphaMap[i] = (byte) ((i * 255 + halfmaxalpha) / maxalpha);
55 }
56 for (int i = maxalpha; i < prevAlphaMap.length; i++) {
57 prevAlphaMap[i] = (byte) 255;
58 }
59 prevMaxAlpha = maxalpha;
60 }
61 return prevAlphaMap;
62 }
63
64 public void getBbox(int bbox[]) {
65 bbox[0] = cache.bboxX0;
66 bbox[1] = cache.bboxY0;
67 bbox[2] = cache.bboxX1;
68 bbox[3] = cache.bboxY1;
69 //System.out.println("bbox["+bbox[0]+", "+bbox[1]+" => "+bbox[2]+", "+bbox[3]+"]");
70 }
71
72 /**
73 * Gets the width of the tiles that the generator batches output into.
74 * @return the width of the standard alpha tile
75 */
76 public int getTileWidth() {
77 return TILE_SIZE;
78 }
79
80 /**
81 * Gets the height of the tiles that the generator batches output into.
82 * @return the height of the standard alpha tile
83 */
84 public int getTileHeight() {
85 return TILE_SIZE;
86 }
87
88 /**
89 * Gets the typical alpha value that will characterize the current
90 * tile.
91 * The answer may be 0x00 to indicate that the current tile has
92 * no coverage in any of its pixels, or it may be 0xff to indicate
93 * that the current tile is completely covered by the path, or any
94 * other value to indicate non-trivial coverage cases.
95 * @return 0x00 for no coverage, 0xff for total coverage, or any other
96 * value for partial coverage of the tile
97 */
98 public int getTypicalAlpha() {
99 if (true) return 0x80;
100 // Decode run-length encoded alpha mask data
101 // The data for row j begins at cache.rowOffsetsRLE[j]
102 // and is encoded as a set of 2-byte pairs (val, runLen)
103 // terminated by a (0, 0) pair.
104
105 int x0 = this.x;
106 int x1 = x0 + TILE_SIZE;
107 int y0 = this.y;
108 int y1 = y0 + TILE_SIZE;
109 if (x1 > cache.bboxX1) x1 = cache.bboxX1;
110 if (y1 > cache.bboxY1) y1 = cache.bboxY1;
111 y0 -= cache.bboxY0;
112 y1 -= cache.bboxY0;
113
114 int ret = -1;
115 for (int cy = y0; cy < y1; cy++) {
116 int pos = cache.rowOffsetsRLE[cy];
117 int cx = cache.minTouched[cy];
118
119 if (cx > x0) {
120 if (ret > 0) return 0x80;
121 ret = 0x00;
122 }
123 while (cx < x1) {
124 int runLen = cache.rowAARLE[pos + 1] & 0xff;
125 if (runLen == 0) {
126 if (ret > 0) return 0x80;
127 ret = 0x00;
128 break;
129 }
130 cx += runLen;
131 if (cx > x0) {
132 int val = cache.rowAARLE[pos] & 0xff;
133 if (ret != val) {
134 if (ret < 0) {
135 if (val != 0x00 && val != maxalpha) return 0x80;
136 ret = val;
137 } else {
138 return 0x80;
139 }
140 }
141 }
142 pos += 2;
143 }
144 }
145 return ret;
146 }
147
148 /**
149 * Skips the current tile and moves on to the next tile.
150 * Either this method, or the getAlpha() method should be called
151 * once per tile, but not both.
152 */
153 public void nextTile() {
154 if ((x += TILE_SIZE) >= cache.bboxX1) {
155 x = cache.bboxX0;
156 y += TILE_SIZE;
157 }
158 }
159
160 /**
161 * Gets the alpha coverage values for the current tile.
162 * Either this method, or the nextTile() method should be called
163 * once per tile, but not both.
164 */
165 public void getAlpha(byte tile[], int offset, int rowstride) {
166 // Decode run-length encoded alpha mask data
167 // The data for row j begins at cache.rowOffsetsRLE[j]
168 // and is encoded as a set of 2-byte pairs (val, runLen)
169 // terminated by a (0, 0) pair.
170
171 int x0 = this.x;
172 int x1 = x0 + TILE_SIZE;
173 int y0 = this.y;
174 int y1 = y0 + TILE_SIZE;
175 if (x1 > cache.bboxX1) x1 = cache.bboxX1;
176 if (y1 > cache.bboxY1) y1 = cache.bboxY1;
177 y0 -= cache.bboxY0;
178 y1 -= cache.bboxY0;
179
180 int idx = offset;
181 for (int cy = y0; cy < y1; cy++) {
182 int pos = cache.rowOffsetsRLE[cy];
183 int cx = cache.minTouched[cy];
184 if (cx > x1) cx = x1;
185
186 if (cx > x0) {
187 //System.out.println("L["+(cx-x0)+"]");
188 for (int i = x0; i < cx; i++) {
189 tile[idx++] = 0x00;
190 }
191 }
192 while (cx < x1) {
193 byte val;
194 int runLen = 0;
195 try {
196 val = alphaMap[cache.rowAARLE[pos] & 0xff];
197 runLen = cache.rowAARLE[pos + 1] & 0xff;
198 } catch (RuntimeException e0) {
199 System.out.println("maxalpha = "+maxalpha);
200 System.out.println("tile["+x0+", "+y0+
201 " => "+x1+", "+y1+"]");
202 System.out.println("cx = "+cx+", cy = "+cy);
203 System.out.println("idx = "+idx+", pos = "+pos);
204 System.out.println("len = "+runLen);
205 cache.print(System.out);
206 e0.printStackTrace();
207 System.exit(1);
208 return;
209 }
210 if (runLen == 0) {
211 break;
212 }
213 int rx0 = cx;
214 cx += runLen;
215 int rx1 = cx;
216 if (rx0 < x0) rx0 = x0;
217 if (rx1 > x1) rx1 = x1;
218 runLen = rx1 - rx0;
219 //System.out.println("M["+runLen+"]");
220 while (--runLen >= 0) {
221 try {
222 tile[idx++] = val;
223 } catch (RuntimeException e) {
224 System.out.println("maxalpha = "+maxalpha);
225 System.out.println("tile["+x0+", "+y0+
226 " => "+x1+", "+y1+"]");
227 System.out.println("cx = "+cx+", cy = "+cy);
228 System.out.println("idx = "+idx+", pos = "+pos);
229 System.out.println("rx0 = "+rx0+", rx1 = "+rx1);
230 System.out.println("len = "+runLen);
231 cache.print(System.out);
232 e.printStackTrace();
233 System.exit(1);
234 return;
235 }
236 }
237 pos += 2;
238 }
239 if (cx < x0) { cx = x0; }
240 while (cx < x1) {
241 tile[idx++] = 0x00;
242 cx++;
243 }
244 /*
245 for (int i = idx - (x1-x0); i < idx; i++) {
246 System.out.print(hex(tile[i], 2));
247 }
248 System.out.println();
249 */
250 idx += (rowstride - (x1-x0));
251 }
252 nextTile();
253 }
254
255 static String hex(int v, int d) {
256 String s = Integer.toHexString(v);
257 while (s.length() < d) {
258 s = "0"+s;
259 }
260 return s.substring(0, d);
261 }
262
263 /**
264 * Disposes this tile generator.
265 * No further calls will be made on this instance.
266 */
267 public void dispose() {}
268}