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
35jfieldID pBandsArrayID;
36jfieldID pEndIndexID;
37jfieldID pRegionID;
38jfieldID pCurIndexID;
39jfieldID pNumXbandsID;
40
41JNIEXPORT void JNICALL
42Java_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
71static void
72fill(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
85static jboolean
86nextYRange(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
107static jboolean
108nextXBand(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
126JNIEXPORT void JNICALL
127Java_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
172JNIEXPORT void JNICALL
173Java_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