1 /* 2 * Copyright (c) 2011, 2018, 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 <JNIUtil.h> 27 28 #include <JAbstractSurface.h> 29 #include <JPiscesRenderer.h> 30 #include <JTransform.h> 31 32 #include <PiscesBlit.h> 33 #include <PiscesSysutils.h> 34 35 #include <PiscesRenderer.inl> 36 37 #define RENDERER_NATIVE_PTR 0 38 #define RENDERER_SURFACE 1 39 #define RENDERER_LAST RENDERER_SURFACE 40 41 #define SURFACE_FROM_RENDERER(surface, env, surfaceHandle, rendererHandle) \ 42 (surfaceHandle) = (*(env))->GetObjectField((env), (rendererHandle), \ 43 fieldIds[RENDERER_SURFACE] \ 44 ); \ 45 (surface) = &surface_get((env), (surfaceHandle))->super; 46 47 static jfieldID fieldIds[RENDERER_LAST + 1]; 48 static jboolean fieldIdsInitialized = JNI_FALSE; 49 static jboolean initializeRendererFieldIds(JNIEnv *env, jobject objectHandle); 50 51 static int toPiscesCoords(unsigned int ff); 52 static void renderer_finalize(JNIEnv *env, jobject objectHandle); 53 static void fillAlphaMask(Renderer* rdr, jint minX, jint minY, jint maxX, jint maxY, 54 JNIEnv *env, jobject this, jint maskType, jbyteArray jmask, jint x, jint y, 55 jint maskWidth, jint maskHeight, jint offset, jint stride); 56 57 JNIEXPORT void JNICALL 58 Java_com_sun_pisces_PiscesRenderer_initialize(JNIEnv* env, jobject objectHandle) 59 { 60 Renderer* rdr; 61 Surface* surface; 62 jboolean sfieldsOK; 63 64 sfieldsOK = initializeRendererFieldIds(env, objectHandle); 65 if (sfieldsOK) { 66 jobject surfaceHandle = (*env)->GetObjectField(env, objectHandle, 67 fieldIds[RENDERER_SURFACE]); 68 surface = &surface_get(env, surfaceHandle)->super; 69 70 rdr = renderer_create(surface); 71 72 (*env)->SetLongField(env, objectHandle, fieldIds[RENDERER_NATIVE_PTR], 73 PointerToJLong(rdr)); 74 if (JNI_TRUE == readAndClearMemErrorFlag()) { 75 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 76 "Allocation of internal renderer buffer failed!!!"); 77 } 78 79 } else { 80 JNI_ThrowNew(env, "java/lang/IllegalStateException", ""); 81 } 82 } 83 84 JNIEXPORT void JNICALL 85 Java_com_sun_pisces_PiscesRenderer_nativeFinalize(JNIEnv* env, 86 jobject objectHandle) 87 { 88 renderer_finalize(env, objectHandle); 89 90 if (JNI_TRUE == readAndClearMemErrorFlag()) { 91 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 92 "Allocation of internal renderer buffer failed."); 93 } 94 } 95 96 JNIEXPORT void JNICALL 97 Java_com_sun_pisces_PiscesRenderer_setClipImpl(JNIEnv* env, jobject objectHandle, 98 jint minX, jint minY, jint width, jint height) { 99 Renderer* rdr; 100 rdr = (Renderer*)JLongToPointer( 101 (*env)->GetLongField(env, objectHandle, 102 fieldIds[RENDERER_NATIVE_PTR])); 103 104 renderer_setClip(rdr, minX, minY, width, height); 105 106 if (JNI_TRUE == readAndClearMemErrorFlag()) { 107 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 108 "Allocation of internal renderer buffer failed."); 109 } 110 } 111 112 JNIEXPORT void JNICALL 113 Java_com_sun_pisces_PiscesRenderer_setColorImpl(JNIEnv* env, jobject objectHandle, 114 jint red, jint green, jint blue, jint alpha) { 115 Renderer* rdr; 116 rdr = (Renderer*)JLongToPointer( 117 (*env)->GetLongField(env, objectHandle, 118 fieldIds[RENDERER_NATIVE_PTR])); 119 120 renderer_setColor(rdr, red, green, blue, alpha); 121 122 if (JNI_TRUE == readAndClearMemErrorFlag()) { 123 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 124 "Allocation of internal renderer buffer failed."); 125 } 126 } 127 128 JNIEXPORT void JNICALL 129 Java_com_sun_pisces_PiscesRenderer_setCompositeRuleImpl(JNIEnv* env, 130 jobject objectHandle, 131 jint compositeRule) 132 { 133 Renderer* rdr; 134 rdr = (Renderer*)JLongToPointer( 135 (*env)->GetLongField(env, objectHandle, 136 fieldIds[RENDERER_NATIVE_PTR])); 137 138 renderer_setCompositeRule(rdr, compositeRule); 139 140 if (JNI_TRUE == readAndClearMemErrorFlag()) { 141 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 142 "Allocation of internal renderer buffer failed."); 143 } 144 } 145 146 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_clearRectImpl(JNIEnv* env, jobject objectHandle, 147 jint x, jint y, jint w, jint h) { 148 Renderer* rdr; 149 Surface* surface; 150 jobject surfaceHandle; 151 152 rdr = (Renderer*)JLongToPointer( 153 (*env)->GetLongField(env, objectHandle, 154 fieldIds[RENDERER_NATIVE_PTR])); 155 156 SURFACE_FROM_RENDERER(surface, env, surfaceHandle, objectHandle); 157 ACQUIRE_SURFACE(surface, env, surfaceHandle); 158 INVALIDATE_RENDERER_SURFACE(rdr); 159 160 rdr->_imagePixelStride = 1; 161 rdr->_imageScanlineStride = surface->width; 162 renderer_clearRect(rdr, x, y, w, h); 163 164 RELEASE_SURFACE(surface, env, surfaceHandle); 165 166 if (JNI_TRUE == readAndClearMemErrorFlag()) { 167 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 168 "Allocation of internal renderer buffer failed."); 169 } 170 } 171 172 /* 173 * Class: com_sun_pisces_PiscesRenderer 174 * Method: setLinearGradientImpl 175 * Signature: (IIII[IILcom/sun/pisces/Transform6;)V 176 */ 177 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_setLinearGradientImpl( 178 JNIEnv *env, jobject this, jint x0, jint y0, jint x1, jint y1, 179 jintArray jramp, jint cycleMethod, jobject jTransform) 180 { 181 Renderer* rdr; 182 Transform6 gradientTransform; 183 jint *ramp; 184 185 transform_get6(&gradientTransform, env, jTransform); 186 187 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, 188 fieldIds[RENDERER_NATIVE_PTR])); 189 190 ramp = (*env)->GetIntArrayElements(env, jramp, NULL); 191 if (ramp != NULL) { 192 rdr->_gradient_cycleMethod = cycleMethod; 193 renderer_setLinearGradient(rdr, x0, y0, x1, y1, 194 ramp, &gradientTransform); 195 (*env)->ReleaseIntArrayElements(env, jramp, ramp, 0); 196 } else { 197 setMemErrorFlag(); 198 } 199 200 if (JNI_TRUE == readAndClearMemErrorFlag()) { 201 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 202 "Allocation of internal renderer buffer failed."); 203 } 204 } 205 206 /* 207 * Class: com_sun_pisces_PiscesRenderer 208 * Method: setRadialGradientImpl 209 * Signature: (IIIII[IILcom/sun/pisces/Transform6;)V 210 */ 211 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_setRadialGradientImpl( 212 JNIEnv *env, jobject this, jint cx, jint cy, jint fx, jint fy, jint radius, 213 jintArray jramp, jint cycleMethod, jobject jTransform) 214 { 215 Renderer* rdr; 216 Transform6 gradientTransform; 217 218 jint *ramp; 219 220 transform_get6(&gradientTransform, env, jTransform); 221 222 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, 223 fieldIds[RENDERER_NATIVE_PTR])); 224 225 ramp = (*env)->GetIntArrayElements(env, jramp, NULL); 226 if (ramp != NULL) { 227 rdr->_gradient_cycleMethod = cycleMethod; 228 renderer_setRadialGradient(rdr, cx, cy, fx, fy, radius, 229 ramp, &gradientTransform); 230 (*env)->ReleaseIntArrayElements(env, jramp, ramp, 0); 231 } else { 232 setMemErrorFlag(); 233 } 234 235 if (JNI_TRUE == readAndClearMemErrorFlag()) { 236 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 237 "Allocation of internal renderer buffer failed."); 238 } 239 } 240 241 /* 242 * Class: com_sun_pisces_PiscesRenderer 243 * Method: setTextureImpl 244 * Signature: (I[IIILcom/sun/pisces/Transform6;Z)V 245 */ 246 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_setTextureImpl 247 (JNIEnv *env, jobject this, jint imageType, jintArray dataArray, 248 jint width, jint height, jint stride, 249 jobject jTransform, jboolean repeat, jboolean linearFiltering, jboolean hasAlpha) 250 { 251 Renderer* rdr; 252 Transform6 textureTransform; 253 jint *data; 254 255 transform_get6(&textureTransform, env, jTransform); 256 257 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR])); 258 259 data = (jint*)(*env)->GetPrimitiveArrayCritical(env, dataArray, NULL); 260 if (data != NULL) { 261 jint *alloc_data = my_malloc(jint, width * height); 262 if (alloc_data != NULL) { 263 if (stride == width) { 264 memcpy(alloc_data, data, sizeof(jint) * width * height); 265 } else { 266 jint i; 267 for (i = 0; i < height; i++) { 268 memcpy(alloc_data + (i*width), data + (i*stride), sizeof(jint) * width); 269 } 270 } 271 renderer_setTexture(rdr, IMAGE_MODE_NORMAL, 272 alloc_data, width, height, width, repeat, linearFiltering, 273 &textureTransform, JNI_TRUE, hasAlpha, 274 0, 0, width-1, height-1); 275 } else { 276 setMemErrorFlag(); 277 } 278 (*env)->ReleasePrimitiveArrayCritical(env, dataArray, data, 0); 279 } else { 280 setMemErrorFlag(); 281 } 282 283 if (JNI_TRUE == readAndClearMemErrorFlag()) { 284 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 285 "Allocation of internal renderer buffer failed."); 286 } 287 } 288 289 Renderer* 290 renderer_get(JNIEnv* env, jobject objectHandle) { 291 return (Renderer*)JLongToPointer( 292 (*env)->GetLongField(env, objectHandle, 293 fieldIds[RENDERER_NATIVE_PTR])); 294 } 295 296 static void 297 renderer_finalize(JNIEnv *env, jobject objectHandle) { 298 Renderer* rdr; 299 300 if (!fieldIdsInitialized) { 301 return; 302 } 303 304 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, objectHandle, 305 fieldIds[RENDERER_NATIVE_PTR])); 306 307 if (rdr != (Renderer*)0) { 308 renderer_dispose(rdr); 309 (*env)->SetLongField(env, objectHandle, fieldIds[RENDERER_NATIVE_PTR], 310 (jlong)0); 311 } 312 } 313 314 static jboolean 315 initializeObjectFieldIds(JNIEnv *env, 316 jobject objectHandle, 317 const char * className, 318 FieldDesc * fieldDesc, 319 jfieldID * fieldIds, 320 jboolean * initializedField) 321 { 322 jboolean retVal; 323 jclass classHandle; 324 325 if (*initializedField) { 326 return JNI_TRUE; 327 } 328 329 retVal = JNI_FALSE; 330 331 if (objectHandle != 0) { 332 classHandle = (*env)->GetObjectClass(env, objectHandle); 333 } else if (className != 0) { 334 classHandle = (*env)->FindClass(env, className); 335 if (checkAndClearException(env)) return JNI_FALSE; 336 } else { 337 return JNI_FALSE; 338 } 339 340 if (initializeFieldIds(fieldIds, env, classHandle, fieldDesc)) { 341 retVal = JNI_TRUE; 342 *initializedField = JNI_TRUE; 343 } 344 345 return retVal; 346 } 347 348 static jboolean 349 initializeRendererFieldIds(JNIEnv *env, jobject objectHandle) { 350 static FieldDesc rendererFieldDesc[] = { 351 { "nativePtr", "J" }, 352 { "surface", "Lcom/sun/pisces/AbstractSurface;" }, 353 { NULL, NULL } 354 }; 355 356 return initializeObjectFieldIds(env, objectHandle, 0, rendererFieldDesc, 357 fieldIds, &fieldIdsInitialized); 358 } 359 360 /** 361 * Converts floating point number into S15.16 format 362 * [= (int)(f * 65536.0f)]. Doesn't correctly handle INF, NaN and -0. 363 * 364 * @param ff number encoded as sign [1 bit], exponent + 127 [8 bits], mantisa 365 * without the implicit 1 at the beginning [23 bits] 366 * @return ff in S15.16 format 367 */ 368 static int 369 toPiscesCoords(unsigned int ff) { 370 int shift; 371 unsigned int gg; 372 373 /* get mantisa */ 374 gg = ((ff & 0xffffff) | 0x800000); 375 /* calculate shift from exponent */ 376 shift = 134 - ((ff >> 23) & 0xff); 377 /* do left or right shift to get value to S15.16 format */ 378 gg = (shift < 0) ? (gg << -shift) : (gg >> shift); 379 /* fix sign */ 380 gg = (gg ^ -(int)(ff >> 31)) + (ff >> 31); 381 /* handle zero */ 382 gg &= -(ff != 0); 383 384 return (int)gg; 385 } 386 387 static void 388 fillRect(JNIEnv *env, jobject this, Renderer* rdr, 389 jint x, jint y, jint w, jint h, 390 jint lEdge, jint rEdge, jint tEdge, jint bEdge) 391 { 392 Surface* surface; 393 jobject surfaceHandle; 394 jint x_from, x_to, y_from, y_to; 395 jint lfrac, rfrac, tfrac, bfrac; 396 jint rows_to_render_by_loop, rows_being_rendered; 397 398 lfrac = (0x10000 - (x & 0xFFFF)) & 0xFFFF; 399 rfrac = (x + w) & 0xFFFF; 400 tfrac = (0x10000 - (y & 0xFFFF)) & 0xFFFF; 401 bfrac = (y + h) & 0xFFFF; 402 403 x_from = x >> 16; 404 x_to = x + w; 405 x_to = (rfrac) ? x_to >> 16 : (x_to >> 16) - 1; 406 y_from = y >> 16; 407 y_to = y + h; 408 y_to = (bfrac) ? y_to >> 16 : (y_to >> 16) - 1; 409 410 rdr->_rectX = x_from; 411 rdr->_rectY = y_from; 412 413 switch (lEdge) { 414 case IMAGE_FRAC_EDGE_PAD: 415 lfrac = 0; 416 break; 417 case IMAGE_FRAC_EDGE_TRIM: 418 if (lfrac) { x_from++; } 419 lfrac = 0; 420 break; 421 } 422 423 switch (rEdge) { 424 case IMAGE_FRAC_EDGE_PAD: 425 rfrac = 0; 426 break; 427 case IMAGE_FRAC_EDGE_TRIM: 428 if (rfrac) { x_to--; } 429 rfrac = 0; 430 break; 431 } 432 433 switch (tEdge) { 434 case IMAGE_FRAC_EDGE_PAD: 435 tfrac = 0; 436 break; 437 case IMAGE_FRAC_EDGE_TRIM: 438 if (tfrac) { y_from++; } 439 tfrac = 0; 440 break; 441 } 442 443 switch (bEdge) { 444 case IMAGE_FRAC_EDGE_PAD: 445 bfrac = 0; 446 break; 447 case IMAGE_FRAC_EDGE_TRIM: 448 if (bfrac) { y_to--; } 449 bfrac = 0; 450 break; 451 } 452 453 // apply clip 454 if (x_from < rdr->_clip_bbMinX) { 455 x_from = rdr->_clip_bbMinX; 456 lfrac = 0; 457 } 458 if (y_from < rdr->_clip_bbMinY) { 459 y_from = rdr->_clip_bbMinY; 460 tfrac = 0; 461 } 462 if (x_to > rdr->_clip_bbMaxX) { 463 x_to = rdr->_clip_bbMaxX; 464 rfrac = 0; 465 } 466 if (y_to > rdr->_clip_bbMaxY) { 467 y_to = rdr->_clip_bbMaxY; 468 bfrac = 0; 469 } 470 471 if ((x_from <= x_to) && (y_from <= y_to)) { 472 rows_to_render_by_loop = y_to - y_from + 1; 473 474 SURFACE_FROM_RENDERER(surface, env, surfaceHandle, this); 475 ACQUIRE_SURFACE(surface, env, surfaceHandle); 476 INVALIDATE_RENDERER_SURFACE(rdr); 477 VALIDATE_BLITTING(rdr); 478 479 rdr->_minTouched = x_from; 480 rdr->_maxTouched = x_to; 481 rdr->_currX = x_from; 482 rdr->_currY = y_from; 483 484 rdr->_alphaWidth = x_to - x_from + 1; 485 486 rdr->_currImageOffset = y_from * surface->width; 487 rdr->_imageScanlineStride = surface->width; 488 rdr->_imagePixelStride = 1; 489 rdr->_rowNum = 0; 490 491 if (y_from == y_to && (tfrac | bfrac)) { 492 // rendering single horizontal fractional line bfrac > (y & 0xFFFF) 493 tfrac = (bfrac - 0x10000 + tfrac) & 0xFFFF; 494 bfrac = 0; 495 } 496 if (x_from == x_to && (lfrac | rfrac)) { 497 // rendering single vertival fractional line rfrac > (x & 0xFFFF) 498 lfrac = (rfrac - 0x10000 + lfrac) & 0xFFFF; 499 rfrac = 0; 500 } 501 502 rdr->_el_lfrac = lfrac; 503 rdr->_el_rfrac = rfrac; 504 505 if (bfrac) { 506 // one "full" line less -> will be rendered at the end 507 rows_to_render_by_loop--; 508 } 509 510 // emit fractional top line 511 if (tfrac) { 512 if (rdr->_genPaint) { 513 size_t l = (x_to - x_from + 1); 514 ALLOC3(rdr->_paint, jint, l); 515 rdr->_genPaint(rdr, 1); 516 } 517 rdr->_emitLine(rdr, 1, tfrac); 518 rows_to_render_by_loop--; 519 rdr->_currX = x_from; 520 rdr->_currY++; 521 rdr->_currImageOffset = rdr->_currY * surface->width; 522 rdr->_rowNum++; 523 } 524 525 // emit "full" lines that are in the middle 526 while (rows_to_render_by_loop > 0) { 527 rows_being_rendered = MIN(rows_to_render_by_loop, NUM_ALPHA_ROWS); 528 529 if (rdr->_genPaint) { 530 size_t l = (x_to - x_from + 1) * rows_being_rendered; 531 ALLOC3(rdr->_paint, jint, l); 532 rdr->_genPaint(rdr, rows_being_rendered); 533 } 534 rdr->_emitLine(rdr, rows_being_rendered, 0x10000); 535 536 rows_to_render_by_loop -= rows_being_rendered; 537 rdr->_currX = x_from; 538 rdr->_currY += rows_being_rendered; 539 rdr->_currImageOffset = rdr->_currY * surface->width; 540 rdr->_rowNum += rows_being_rendered; 541 } 542 543 // emit fractional bottom line 544 if (bfrac) { 545 if (rdr->_genPaint) { 546 size_t l = (x_to - x_from + 1); 547 ALLOC3(rdr->_paint, jint, l); 548 rdr->_genPaint(rdr, 1); 549 } 550 rdr->_emitLine(rdr, 1, bfrac); 551 } 552 RELEASE_SURFACE(surface, env, surfaceHandle); 553 554 if (JNI_TRUE == readAndClearMemErrorFlag()) { 555 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 556 "Allocation of internal renderer buffer failed."); 557 } 558 } 559 } 560 561 /* 562 * Class: com_sun_pisces_PiscesRenderer 563 * Method: fillRect 564 * Signature: (IIII)V 565 * x, y, w, h are already transformed (is surface coordinates) 566 * and rectangle is in an up-right position ie. no rotate or shear 567 */ 568 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_fillRectImpl 569 (JNIEnv *env, jobject this, jint x, jint y, jint w, jint h) 570 { 571 Renderer* rdr; 572 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR])); 573 fillRect(env, this, rdr, x, y, w, h, 574 IMAGE_FRAC_EDGE_KEEP, IMAGE_FRAC_EDGE_KEEP, 575 IMAGE_FRAC_EDGE_KEEP, IMAGE_FRAC_EDGE_KEEP); 576 } 577 578 /* 579 * Class: com_sun_pisces_PiscesRenderer 580 * Method: emitAndClearAlphaRowImpl 581 * Signature: ([B[IIII)V 582 */ 583 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_emitAndClearAlphaRowImpl 584 (JNIEnv *env, jobject this, jbyteArray jAlphaMap, jintArray jAlphaDeltas, jint y, jint x_from, jint x_to, 585 jint x_off, jint rowNum) 586 { 587 Renderer* rdr; 588 Surface* surface; 589 jobject surfaceHandle; 590 jbyte* alphaMap; 591 592 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR])); 593 594 SURFACE_FROM_RENDERER(surface, env, surfaceHandle, this); 595 ACQUIRE_SURFACE(surface, env, surfaceHandle); 596 INVALIDATE_RENDERER_SURFACE(rdr); 597 VALIDATE_BLITTING(rdr); 598 599 alphaMap = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, jAlphaMap, NULL); 600 if (alphaMap != NULL) 601 { 602 jint* alphaRow = (jint*)(*env)->GetPrimitiveArrayCritical(env, jAlphaDeltas, NULL); 603 if (alphaRow != NULL) 604 { 605 x_from = MAX(x_from, rdr->_clip_bbMinX); 606 x_to = MIN(x_to, rdr->_clip_bbMaxX); 607 608 if (x_to >= x_from && 609 y >= rdr->_clip_bbMinY && 610 y <= rdr->_clip_bbMaxY) 611 { 612 rdr->_minTouched = x_from; 613 rdr->_maxTouched = x_to; 614 rdr->_currX = x_from; 615 rdr->_currY = y; 616 617 rdr->_rowNum = rowNum; 618 619 rdr->alphaMap = alphaMap; 620 rdr->_rowAAInt = alphaRow + x_off; /* add offset in alpha buffer */ 621 rdr->_alphaWidth = x_to - x_from + 1; 622 623 rdr->_currImageOffset = y * surface->width; 624 rdr->_imageScanlineStride = surface->width; 625 rdr->_imagePixelStride = 1; 626 627 if (rdr->_genPaint) { 628 size_t l = (x_to - x_from + 1); 629 ALLOC3(rdr->_paint, jint, l); 630 rdr->_genPaint(rdr, 1); 631 } 632 rdr->_emitRows(rdr, 1); 633 rdr->_rowAAInt = NULL; 634 } 635 (*env)->ReleasePrimitiveArrayCritical(env, jAlphaDeltas, alphaRow, 0); 636 } else { 637 setMemErrorFlag(); 638 } 639 (*env)->ReleasePrimitiveArrayCritical(env, jAlphaMap, alphaMap, 0); 640 } else { 641 setMemErrorFlag(); 642 } 643 644 RELEASE_SURFACE(surface, env, surfaceHandle); 645 646 if (JNI_TRUE == readAndClearMemErrorFlag()) { 647 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 648 "Allocation of internal renderer buffer failed."); 649 } 650 } 651 652 /* 653 * Class: com_sun_pisces_PiscesRenderer 654 * Method: drawImageImpl 655 * Signature: (I[IIIIILcom/sun/pisces/Transform6;ZIIII)V 656 */ 657 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_drawImageImpl 658 (JNIEnv *env, jobject this, jint imageType, jint imageMode, 659 jintArray dataArray, jint width, jint height, jint offset, jint stride, 660 jobject jTransform, jboolean repeat, jboolean linearFiltering, 661 jint bboxX, jint bboxY, jint bboxW, jint bboxH, 662 jint lEdge, jint rEdge, jint tEdge, jint bEdge, 663 jint txMin, jint tyMin, jint txMax, jint tyMax, 664 jboolean hasAlpha) 665 { 666 Renderer* rdr; 667 jint* data; 668 669 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR])); 670 data = (jint*)(*env)->GetPrimitiveArrayCritical(env, dataArray, NULL); 671 if (data != NULL) { 672 Transform6 textureTransform; 673 674 transform_get6(&textureTransform, env, jTransform); 675 renderer_setTexture(rdr, imageMode, data + offset, width, height, stride, 676 repeat, linearFiltering, &textureTransform, JNI_FALSE, hasAlpha, 677 txMin, tyMin, txMax, tyMax); 678 679 fillRect(env, this, rdr, 680 bboxX, bboxY, bboxW, bboxH, 681 lEdge, rEdge, tEdge, bEdge); 682 683 rdr->_texture_intData = NULL; 684 (*env)->ReleasePrimitiveArrayCritical(env, dataArray, data, 0); 685 } else { 686 setMemErrorFlag(); 687 } 688 689 if (JNI_TRUE == readAndClearMemErrorFlag()) { 690 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 691 "Allocation of internal renderer buffer failed."); 692 } 693 PISCES_DEBUG_FLUSH(stdout); 694 } 695 696 /* 697 * Class: com_sun_pisces_PiscesRenderer 698 * Method: fillAlphaMaskImpl 699 * Signature: ([BIIIIII)V 700 */ 701 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_fillAlphaMaskImpl 702 (JNIEnv *env, jobject this, jbyteArray jmask, jint x, jint y, jint maskWidth, jint maskHeight, jint offset, jint stride) 703 { 704 Renderer* rdr; 705 jint minX, minY, maxX, maxY; 706 jint maskOffset; 707 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR])); 708 709 minX = MAX(x, rdr->_clip_bbMinX); 710 minY = MAX(y, rdr->_clip_bbMinY); 711 maxX = MIN(x + maskWidth - 1, rdr->_clip_bbMaxX); 712 maxY = MIN(y + maskHeight - 1, rdr->_clip_bbMaxY); 713 714 maskOffset = offset + (minY - y) * maskWidth + minX - x; 715 716 fillAlphaMask(rdr, minX, minY, maxX, maxY, env, this, ALPHA_MASK, jmask, 717 x, y, maskWidth, maskHeight, maskOffset, stride); 718 } 719 720 /* 721 * Class: com_sun_pisces_PiscesRenderer 722 * Method: setLCDGammaCorrection 723 * Signature: (F)V 724 */ 725 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_setLCDGammaCorrectionImpl 726 (JNIEnv *env, jobject this, jfloat gamma) 727 { 728 initGammaArrays(gamma); 729 } 730 731 /* 732 * Class: com_sun_pisces_PiscesRenderer 733 * Method: fillLCDAlphaMaskImpl 734 * Signature: ([BIIIIII)V 735 */ 736 JNIEXPORT void JNICALL Java_com_sun_pisces_PiscesRenderer_fillLCDAlphaMaskImpl 737 (JNIEnv *env, jobject this, jbyteArray jmask, jint x, jint y, 738 jint maskWidth, jint maskHeight, 739 jint offset, jint stride) 740 { 741 Renderer* rdr; 742 jint minX, minY, maxX, maxY; 743 jint maskOffset; 744 rdr = (Renderer*)JLongToPointer((*env)->GetLongField(env, this, fieldIds[RENDERER_NATIVE_PTR])); 745 746 minX = MAX(x, rdr->_clip_bbMinX); 747 minY = MAX(y, rdr->_clip_bbMinY); 748 maxX = MIN(x + (maskWidth/3) - 1, rdr->_clip_bbMaxX); 749 maxY = MIN(y + maskHeight - 1, rdr->_clip_bbMaxY); 750 751 maskOffset = offset + (minY - y) * maskWidth + (minX - x) * 3; 752 753 fillAlphaMask(rdr, minX, minY, maxX, maxY, env, this, LCD_ALPHA_MASK, jmask, 754 x, y, maskWidth, maskHeight, maskOffset, stride); 755 } 756 757 static void fillAlphaMask(Renderer* rdr, jint minX, jint minY, jint maxX, jint maxY, 758 JNIEnv *env, jobject this, jint maskType, jbyteArray jmask, 759 jint x, jint y, jint maskWidth, jint maskHeight, jint offset, jint stride) 760 { 761 jint rowsToBeRendered, rowsBeingRendered; 762 763 Surface* surface; 764 jobject surfaceHandle; 765 766 if (maxX >= minX && maxY >= minY) 767 { 768 jbyte* mask; 769 770 SURFACE_FROM_RENDERER(surface, env, surfaceHandle, this); 771 ACQUIRE_SURFACE(surface, env, surfaceHandle); 772 773 mask = (jbyte*)(*env)->GetPrimitiveArrayCritical(env, jmask, NULL); 774 if (mask != NULL) { 775 jint width = maxX - minX + 1; 776 jint height = maxY - minY + 1; 777 778 renderer_setMask(rdr, maskType, mask, maskWidth, maskHeight, JNI_FALSE); 779 780 INVALIDATE_RENDERER_SURFACE(rdr); 781 VALIDATE_BLITTING(rdr); 782 783 rdr->_minTouched = minX; 784 rdr->_maxTouched = maxX; 785 rdr->_currX = minX; 786 rdr->_currY = minY; 787 788 rdr->_alphaWidth = width; 789 790 rdr->_imageScanlineStride = surface->width; 791 rdr->_imagePixelStride = 1; 792 rdr->_rowNum = 0; 793 rdr->_maskOffset = offset; 794 795 rowsToBeRendered = height; 796 797 while (rowsToBeRendered > 0) { 798 rowsBeingRendered = 1; //MIN(rowsToBeRendered, NUM_ALPHA_ROWS); 799 800 rdr->_currImageOffset = rdr->_currY * surface->width; 801 if (rdr->_genPaint) { 802 size_t l = (width * rowsBeingRendered); 803 ALLOC3(rdr->_paint, jint, l); 804 rdr->_genPaint(rdr, rowsBeingRendered); 805 } 806 rdr->_emitRows(rdr, rowsBeingRendered); 807 808 rdr->_maskOffset += maskWidth; 809 rdr->_rowNum += rowsBeingRendered; 810 rowsToBeRendered -= rowsBeingRendered; 811 rdr->_currX = x; 812 rdr->_currY += rowsBeingRendered; 813 } 814 815 renderer_removeMask(rdr); 816 (*env)->ReleasePrimitiveArrayCritical(env, jmask, mask, 0); 817 } else { 818 setMemErrorFlag(); 819 } 820 821 RELEASE_SURFACE(surface, env, surfaceHandle); 822 823 if (JNI_TRUE == readAndClearMemErrorFlag()) { 824 JNI_ThrowNew(env, "java/lang/OutOfMemoryError", 825 "Allocation of internal renderer buffer failed."); 826 } 827 } 828 } 829