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