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