1 | /* |
2 | * Copyright (c) 1998, 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 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <math.h> |
29 | |
30 | #include "jni.h" |
31 | #include "jni_util.h" |
32 | |
33 | #include "sun_java2d_pipe_SpanClipRenderer.h" |
34 | |
35 | jfieldID pBandsArrayID; |
36 | jfieldID pEndIndexID; |
37 | jfieldID pRegionID; |
38 | jfieldID pCurIndexID; |
39 | jfieldID pNumXbandsID; |
40 | |
41 | JNIEXPORT void JNICALL |
42 | Java_sun_java2d_pipe_SpanClipRenderer_initIDs |
43 | (JNIEnv *env, jclass src, jclass rc, jclass ric) |
44 | { |
45 | /* Region fields */ |
46 | pBandsArrayID = (*env)->GetFieldID(env, rc, "bands" , "[I" ); |
47 | if (pBandsArrayID == NULL) { |
48 | return; |
49 | } |
50 | pEndIndexID = (*env)->GetFieldID(env, rc, "endIndex" , "I" ); |
51 | if (pEndIndexID == NULL) { |
52 | return; |
53 | } |
54 | |
55 | /* RegionIterator fields */ |
56 | pRegionID = (*env)->GetFieldID(env, ric, "region" , |
57 | "Lsun/java2d/pipe/Region;" ); |
58 | if (pRegionID == NULL) { |
59 | return; |
60 | } |
61 | pCurIndexID = (*env)->GetFieldID(env, ric, "curIndex" , "I" ); |
62 | if (pCurIndexID == NULL) { |
63 | return; |
64 | } |
65 | pNumXbandsID = (*env)->GetFieldID(env, ric, "numXbands" , "I" ); |
66 | if (pNumXbandsID == NULL) { |
67 | return; |
68 | } |
69 | } |
70 | |
71 | static void |
72 | fill(jbyte *alpha, jint offset, jint tsize, |
73 | jint x, jint y, jint w, jint h, jbyte value) |
74 | { |
75 | alpha += offset + y * tsize + x; |
76 | tsize -= w; |
77 | while (--h >= 0) { |
78 | for (x = 0; x < w; x++) { |
79 | *alpha++ = value; |
80 | } |
81 | alpha += tsize; |
82 | } |
83 | } |
84 | |
85 | static jboolean |
86 | nextYRange(jint *box, jint *bands, jint endIndex, |
87 | jint *pCurIndex, jint *pNumXbands) |
88 | { |
89 | jint curIndex = *pCurIndex; |
90 | jint numXbands = *pNumXbands; |
91 | jboolean ret; |
92 | |
93 | curIndex += numXbands * 2; |
94 | ret = (curIndex + 3 < endIndex); |
95 | if (ret) { |
96 | box[1] = bands[curIndex++]; |
97 | box[3] = bands[curIndex++]; |
98 | numXbands = bands[curIndex++]; |
99 | } else { |
100 | numXbands = 0; |
101 | } |
102 | *pCurIndex = curIndex; |
103 | *pNumXbands = numXbands; |
104 | return ret; |
105 | } |
106 | |
107 | static jboolean |
108 | nextXBand(jint *box, jint *bands, jint endIndex, |
109 | jint *pCurIndex, jint *pNumXbands) |
110 | { |
111 | jint curIndex = *pCurIndex; |
112 | jint numXbands = *pNumXbands; |
113 | |
114 | if (numXbands <= 0 || curIndex + 2 > endIndex) { |
115 | return JNI_FALSE; |
116 | } |
117 | numXbands--; |
118 | box[0] = bands[curIndex++]; |
119 | box[2] = bands[curIndex++]; |
120 | |
121 | *pCurIndex = curIndex; |
122 | *pNumXbands = numXbands; |
123 | return JNI_TRUE; |
124 | } |
125 | |
126 | JNIEXPORT void JNICALL |
127 | Java_sun_java2d_pipe_SpanClipRenderer_fillTile |
128 | (JNIEnv *env, jobject sr, jobject ri, |
129 | jbyteArray alphaTile, jint offset, jint tsize, jintArray boxArray) |
130 | { |
131 | jbyte *alpha; |
132 | jint *box; |
133 | jint w, h; |
134 | jsize alphalen; |
135 | |
136 | if ((*env)->GetArrayLength(env, boxArray) < 4) { |
137 | JNU_ThrowArrayIndexOutOfBoundsException(env, "band array" ); |
138 | return; |
139 | } |
140 | alphalen = (*env)->GetArrayLength(env, alphaTile); |
141 | |
142 | box = (*env)->GetPrimitiveArrayCritical(env, boxArray, 0); |
143 | if (box == NULL) { |
144 | return; |
145 | } |
146 | |
147 | w = box[2] - box[0]; |
148 | h = box[3] - box[1]; |
149 | |
150 | if (alphalen < offset || (alphalen - offset) / tsize < h) { |
151 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
152 | JNU_ThrowArrayIndexOutOfBoundsException(env, "alpha tile array" ); |
153 | return; |
154 | } |
155 | |
156 | alpha = (*env)->GetPrimitiveArrayCritical(env, alphaTile, 0); |
157 | if (alpha == NULL) { |
158 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
159 | return; |
160 | } |
161 | |
162 | fill(alpha, offset, tsize, 0, 0, w, h, (jbyte) 0xff); |
163 | |
164 | (*env)->ReleasePrimitiveArrayCritical(env, alphaTile, alpha, 0); |
165 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
166 | |
167 | Java_sun_java2d_pipe_SpanClipRenderer_eraseTile(env, sr, ri, |
168 | alphaTile, offset, tsize, |
169 | boxArray); |
170 | } |
171 | |
172 | JNIEXPORT void JNICALL |
173 | Java_sun_java2d_pipe_SpanClipRenderer_eraseTile |
174 | (JNIEnv *env, jobject sr, jobject ri, |
175 | jbyteArray alphaTile, jint offset, jint tsize, jintArray boxArray) |
176 | { |
177 | jobject region; |
178 | jintArray bandsArray; |
179 | jint *bands; |
180 | jbyte *alpha; |
181 | jint *box; |
182 | jint endIndex; |
183 | jint curIndex; |
184 | jint saveCurIndex; |
185 | jint numXbands; |
186 | jint saveNumXbands; |
187 | jint lox; |
188 | jint loy; |
189 | jint hix; |
190 | jint hiy; |
191 | jint firstx; |
192 | jint firsty; |
193 | jint lastx; |
194 | jint lasty; |
195 | jint curx; |
196 | jsize alphalen; |
197 | |
198 | if ((*env)->GetArrayLength(env, boxArray) < 4) { |
199 | JNU_ThrowArrayIndexOutOfBoundsException(env, "band array" ); |
200 | return; |
201 | } |
202 | alphalen = (*env)->GetArrayLength(env, alphaTile); |
203 | |
204 | saveCurIndex = (*env)->GetIntField(env, ri, pCurIndexID); |
205 | saveNumXbands = (*env)->GetIntField(env, ri, pNumXbandsID); |
206 | region = (*env)->GetObjectField(env, ri, pRegionID); |
207 | bandsArray = (*env)->GetObjectField(env, region, pBandsArrayID); |
208 | endIndex = (*env)->GetIntField(env, region, pEndIndexID); |
209 | |
210 | if (endIndex > (*env)->GetArrayLength(env, bandsArray)) { |
211 | endIndex = (*env)->GetArrayLength(env, bandsArray); |
212 | } |
213 | |
214 | box = (*env)->GetPrimitiveArrayCritical(env, boxArray, 0); |
215 | if (box == NULL) { |
216 | return; |
217 | } |
218 | |
219 | lox = box[0]; |
220 | loy = box[1]; |
221 | hix = box[2]; |
222 | hiy = box[3]; |
223 | |
224 | if (alphalen < offset || |
225 | alphalen < offset + (hix-lox) || |
226 | (alphalen - offset - (hix-lox)) / tsize < (hiy - loy - 1)) { |
227 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
228 | JNU_ThrowArrayIndexOutOfBoundsException(env, "alpha tile array" ); |
229 | return; |
230 | } |
231 | |
232 | bands = (*env)->GetPrimitiveArrayCritical(env, bandsArray, 0); |
233 | if (bands == NULL) { |
234 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
235 | return; |
236 | } |
237 | alpha = (*env)->GetPrimitiveArrayCritical(env, alphaTile, 0); |
238 | if (alpha == NULL) { |
239 | (*env)->ReleasePrimitiveArrayCritical(env, bandsArray, bands, 0); |
240 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
241 | return; |
242 | } |
243 | |
244 | curIndex = saveCurIndex; |
245 | numXbands = saveNumXbands; |
246 | firsty = hiy; |
247 | lasty = hiy; |
248 | firstx = hix; |
249 | lastx = lox; |
250 | |
251 | while (nextYRange(box, bands, endIndex, &curIndex, &numXbands)) { |
252 | if (box[3] <= loy) { |
253 | saveNumXbands = numXbands; |
254 | saveCurIndex = curIndex; |
255 | continue; |
256 | } |
257 | if (box[1] >= hiy) { |
258 | break; |
259 | } |
260 | if (box[1] < loy) { |
261 | box[1] = loy; |
262 | } |
263 | if (box[3] > hiy) { |
264 | box[3] = hiy; |
265 | } |
266 | curx = lox; |
267 | while (nextXBand(box, bands, endIndex, &curIndex, &numXbands)) { |
268 | if (box[2] <= lox) { |
269 | continue; |
270 | } |
271 | if (box[0] >= hix) { |
272 | break; |
273 | } |
274 | if (box[0] < lox) { |
275 | box[0] = lox; |
276 | } |
277 | if (lasty < box[1]) { |
278 | fill(alpha, offset, tsize, |
279 | 0, lasty - loy, |
280 | hix - lox, box[1] - lasty, 0); |
281 | } |
282 | lasty = box[3]; |
283 | if (firstx > box[0]) { |
284 | firstx = box[0]; |
285 | } |
286 | if (curx < box[0]) { |
287 | fill(alpha, offset, tsize, |
288 | curx - lox, box[1] - loy, |
289 | box[0] - curx, box[3] - box[1], 0); |
290 | } |
291 | curx = box[2]; |
292 | if (curx >= hix) { |
293 | curx = hix; |
294 | break; |
295 | } |
296 | } |
297 | if (curx > lox) { |
298 | if (curx < hix) { |
299 | fill(alpha, offset, tsize, |
300 | curx - lox, box[1] - loy, |
301 | hix - curx, box[3] - box[1], 0); |
302 | } |
303 | if (firsty > box[1]) { |
304 | firsty = box[1]; |
305 | } |
306 | } |
307 | if (lastx < curx) { |
308 | lastx = curx; |
309 | } |
310 | } |
311 | |
312 | box[0] = firstx; |
313 | box[1] = firsty; |
314 | box[2] = lastx; |
315 | box[3] = lasty; |
316 | |
317 | (*env)->ReleasePrimitiveArrayCritical(env, alphaTile, alpha, 0); |
318 | (*env)->ReleasePrimitiveArrayCritical(env, bandsArray, bands, 0); |
319 | (*env)->ReleasePrimitiveArrayCritical(env, boxArray, box, 0); |
320 | |
321 | (*env)->SetIntField(env, ri, pCurIndexID, saveCurIndex); |
322 | (*env)->SetIntField(env, ri, pNumXbandsID, saveNumXbands); |
323 | } |
324 | |