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