1 /* 2 * Copyright (c) 2011, 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 <PiscesUtil.h> 27 #include <PiscesRenderer.h> 28 29 #include <PiscesSysutils.h> 30 #include <PiscesMath.h> 31 32 #define NO_REPEAT_NO_INTERPOLATE 0 33 #define REPEAT_NO_INTERPOLATE 1 34 #define NO_REPEAT_INTERPOLATE_NO_ALPHA 2 35 #define NO_REPEAT_INTERPOLATE_ALPHA 3 36 #define REPEAT_INTERPOLATE_NO_ALPHA 4 37 #define REPEAT_INTERPOLATE_ALPHA 5 38 39 static jlong lmod(jlong x, jlong y) { 40 x = x % y; 41 if (x < 0) { 42 x += y; 43 } 44 return x; 45 } 46 47 48 #if defined(__arm__) && (defined(__GNUC__) && __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) 49 #define GCC_BUG_57967_WORKAROUND 50 #endif 51 52 #ifdef GCC_BUG_57967_WORKAROUND 53 #pragma GCC push_options 54 #pragma GCC optimize ("O1") 55 #endif 56 57 static INLINE jint interp(jint x0, jint x1, jint frac) { 58 return ((x0 << 16) + (x1 - x0) * frac + 0x8000) >> 16; 59 } 60 61 #ifdef GCC_BUG_57967_WORKAROUND 62 #pragma GCC pop_options 63 #endif 64 65 static INLINE jint 66 pad(jint ifrac, jint cycleMethod) { 67 switch (cycleMethod) { 68 case CYCLE_NONE: 69 if (ifrac < 0) { 70 ifrac = 0; 71 } else if (ifrac > 0xffff) { 72 ifrac = 0xffff; 73 } 74 break; 75 case CYCLE_REPEAT: 76 ifrac &= 0xffff; 77 break; 78 case CYCLE_REFLECT: 79 if (ifrac < 0) { 80 ifrac = -ifrac; 81 } 82 ifrac &= 0x1ffff; 83 if (ifrac > 0xffff) { 84 ifrac = 0x1ffff - ifrac; 85 } 86 break; 87 } 88 89 return ifrac; 90 } 91 92 void 93 genLinearGradientPaint(Renderer *rdr, jint height) { 94 jint paintOffset = 0; 95 jint width = rdr->_alphaWidth; 96 97 jint minX, maxX; 98 jfloat frac; 99 jint pidx; 100 101 jint x, y; 102 jint i, j; 103 104 jint cycleMethod = rdr->_gradient_cycleMethod; 105 jfloat mx = rdr->_lg_mx; 106 jfloat my = rdr->_lg_my; 107 jfloat b = rdr->_lg_b; 108 109 jint* paint = rdr->_paint; 110 jint* colors = rdr->_gradient_colors; 111 112 minX = rdr->_minTouched; 113 maxX = rdr->_maxTouched; 114 115 y = rdr->_currY; 116 for (j = 0; j < height; j++, y++) { 117 x = rdr->_currX; 118 pidx = paintOffset; 119 120 frac = x * mx + y * my + b; 121 for (i = 0; i < width; i++, pidx++) { 122 jint ifrac = pad((jint)frac, cycleMethod); 123 ifrac >>= 16 - LG_GRADIENT_MAP_SIZE; 124 paint[pidx] = colors[ifrac]; 125 126 frac += mx; 127 } 128 129 paintOffset += width; 130 } 131 } 132 133 void 134 genRadialGradientPaint(Renderer *rdr, jint height) { 135 jint cycleMethod = rdr->_gradient_cycleMethod; 136 jint width = rdr->_alphaWidth; 137 jint minX, maxX; 138 jint paintOffset = 0; 139 jint pidx; 140 jint i, j; 141 jint x, y; 142 143 jfloat a00, a01, a02, a10, a11, a12; 144 jfloat cx, cy, fx, fy, r, rsq; 145 jfloat cfxcfx, cfycfy, cfxcfy; 146 jfloat a00a00, a10a10, a00a10, sube; 147 148 float txx, tyy, fxx, fyy, cfx, cfy; 149 float A, B, B2, C, C2, U, dU, V, dV, ddV, tmp; 150 float _Csq, _C; 151 jint ifrac; 152 153 jint* paint = rdr->_paint; 154 jint* colors = rdr->_gradient_colors; 155 156 minX = rdr->_minTouched; 157 maxX = rdr->_maxTouched; 158 159 a00 = rdr->_rg_a00; 160 a01 = rdr->_rg_a01; 161 a02 = rdr->_rg_a02; 162 a10 = rdr->_rg_a10; 163 a11 = rdr->_rg_a11; 164 a12 = rdr->_rg_a12; 165 166 a00a00 = rdr->_rg_a00a00; 167 a10a10 = rdr->_rg_a10a10; 168 a00a10 = rdr->_rg_a00a10; 169 170 cx = rdr->_rg_cx; 171 cy = rdr->_rg_cy; 172 fx = rdr->_rg_fx; 173 fy = rdr->_rg_fy; 174 r = rdr->_rg_r; 175 rsq = rdr->_rg_rsq; 176 177 y = rdr->_currY; 178 for (j = 0; j < height; j++, y++) { 179 pidx = paintOffset; 180 x = rdr->_currX; 181 182 txx = x * a00 + y * a01 + a02; 183 tyy = x * a10 + y * a11 + a12; 184 185 fxx = fx - txx; 186 fyy = fy - tyy; 187 A = fxx * fxx + fyy * fyy; 188 cfx = cx - fx; 189 cfy = cy - fy; 190 cfxcfx = (jfloat)(cfx * cfx); 191 cfycfy = (jfloat)(cfy * cfy); 192 cfxcfy = (jfloat)(cfx * cfy); 193 B = (cfx * fxx + cfy * fyy); 194 B2 = -B * 2.0f; 195 C = cfxcfx + cfycfy - rsq; 196 C2 = 2.0f * C; 197 _C = 1.0f / C; 198 _Csq = _C * _C; 199 U = (-B * _C); 200 dU = (a00 * cfx + a10 * cfy) * _C; 201 V = ((B * B - A * C) * _Csq); 202 sube = 2.0f * a00a10 *cfxcfy; 203 dV = (sube + 204 (a00a00 * (cfxcfx - C) + a00 * (B2 * cfx + C2 * fxx)) + 205 (a10a10 * (cfycfy - C) + a10 * (B2 * cfy + C2 * fyy))) * _Csq; 206 tmp = a00a00*cfycfy - sube + a10a10*cfxcfx; 207 ddV = 2.0f * ((a00a00 + a10a10) * rsq - tmp) * _Csq; 208 209 U = (65536.0f * U); // 65536.0f to be in fixed-point level needed by "frac" 210 V = (65536.0f * 65536.0f * V); // 65536.0f * 65536.0f to stay in fixed point level after sqrt 211 dU = (65536.0f * dU); 212 dV = (65536.0f * 65536.0f * dV); 213 ddV = (65536.0f * 65536.0f * ddV); 214 for (i = 0; i < width; i++, pidx++) { 215 if (V < 0) { 216 V = 0; 217 } 218 219 ifrac = (jint)(U + PISCESsqrt(V)); 220 221 U += dU; 222 V += dV ; 223 dV += ddV; 224 225 ifrac = pad(ifrac, cycleMethod); 226 ifrac >>= (16 - LG_GRADIENT_MAP_SIZE); 227 paint[pidx] = colors[ifrac]; 228 } 229 230 paintOffset += width; 231 } 232 } 233 234 static INLINE jint interpolate2points(jint p0, jint p1, jint frac) { 235 jint a0 = (p0 >> 24) & 0xff; 236 jint r0 = (p0 >> 16) & 0xff; 237 jint g0 = (p0 >> 8) & 0xff; 238 jint b0 = p0 & 0xff; 239 240 jint a1 = (p1 >> 24) & 0xff; 241 jint r1 = (p1 >> 16) & 0xff; 242 jint g1 = (p1 >> 8) & 0xff; 243 jint b1 = p1 & 0xff; 244 245 jint aa = interp(a0, a1, frac); 246 jint rr = interp(r0, r1, frac); 247 jint gg = interp(g0, g1, frac); 248 jint bb = interp(b0, b1, frac); 249 250 return (aa << 24) | (rr << 16) | (gg << 8) | bb; 251 } 252 253 /** 254 * Function interpolate4points() takes color ARGB-value of pixel p00 and 255 * recalculates (using linear interpolation) it's color with ARGB values of 256 * neighbouring pixels. 257 * p01 - right neighbour of p00 258 * p10 - below p00 259 * p11 - below right 260 */ 261 262 static INLINE jint interpolate4points(jint p00, jint p01, jint p10, jint p11, 263 jint hfrac, jint vfrac) { 264 jint a00 = (p00 >> 24) & 0xff; 265 jint r00 = (p00 >> 16) & 0xff; 266 jint g00 = (p00 >> 8) & 0xff; 267 jint b00 = p00 & 0xff; 268 269 jint a01 = (p01 >> 24) & 0xff; 270 jint r01 = (p01 >> 16) & 0xff; 271 jint g01 = (p01 >> 8) & 0xff; 272 jint b01 = p01 & 0xff; 273 274 jint a0 = interp(a00, a01, hfrac); 275 jint r0 = interp(r00, r01, hfrac); 276 jint g0 = interp(g00, g01, hfrac); 277 jint b0 = interp(b00, b01, hfrac); 278 279 jint a10 = (p10 >> 24) & 0xff; 280 jint r10 = (p10 >> 16) & 0xff; 281 jint g10 = (p10 >> 8) & 0xff; 282 jint b10 = p10 & 0xff; 283 284 jint a11 = (p11 >> 24) & 0xff; 285 jint r11 = (p11 >> 16) & 0xff; 286 jint g11 = (p11 >> 8) & 0xff; 287 jint b11 = p11 & 0xff; 288 289 jint a1 = interp(a10, a11, hfrac); 290 jint r1 = interp(r10, r11, hfrac); 291 jint g1 = interp(g10, g11, hfrac); 292 jint b1 = interp(b10, b11, hfrac); 293 294 jint aa = interp(a0, a1, vfrac); 295 jint rr = interp(r0, r1, vfrac); 296 jint gg = interp(g0, g1, vfrac); 297 jint bb = interp(b0, b1, vfrac); 298 299 return (aa << 24) | (rr << 16) | (gg << 8) | bb; 300 } 301 302 static INLINE jint interpolate2pointsNoAlpha(jint p0, jint p1, jint frac) { 303 jint r0 = (p0 >> 16) & 0xff; 304 jint g0 = (p0 >> 8) & 0xff; 305 jint b0 = p0 & 0xff; 306 307 jint r1 = (p1 >> 16) & 0xff; 308 jint g1 = (p1 >> 8) & 0xff; 309 jint b1 = p1 & 0xff; 310 311 jint rr = interp(r0, r1, frac); 312 jint gg = interp(g0, g1, frac); 313 jint bb = interp(b0, b1, frac); 314 315 return (0xff000000) | (rr << 16) | (gg << 8) | bb; 316 } 317 318 static INLINE jint interpolate4pointsNoAlpha(jint p00, jint p01, jint p10, jint p11, 319 jint hfrac, jint vfrac) { 320 jint r00 = (p00 >> 16) & 0xff; 321 jint g00 = (p00 >> 8) & 0xff; 322 jint b00 = p00 & 0xff; 323 324 jint r01 = (p01 >> 16) & 0xff; 325 jint g01 = (p01 >> 8) & 0xff; 326 jint b01 = p01 & 0xff; 327 328 jint r0 = interp(r00, r01, hfrac); 329 jint g0 = interp(g00, g01, hfrac); 330 jint b0 = interp(b00, b01, hfrac); 331 332 jint r10 = (p10 >> 16) & 0xff; 333 jint g10 = (p10 >> 8) & 0xff; 334 jint b10 = p10 & 0xff; 335 336 jint r11 = (p11 >> 16) & 0xff; 337 jint g11 = (p11 >> 8) & 0xff; 338 jint b11 = p11 & 0xff; 339 340 jint r1 = interp(r10, r11, hfrac); 341 jint g1 = interp(g10, g11, hfrac); 342 jint b1 = interp(b10, b11, hfrac); 343 344 jint rr = interp(r0, r1, vfrac); 345 jint gg = interp(g0, g1, vfrac); 346 jint bb = interp(b0, b1, vfrac); 347 348 return (0xff000000) | (rr << 16) | (gg << 8) | bb; 349 } 350 351 static INLINE jboolean isInBoundsNoRepeat(jint *a, jlong *la, jint min, jint max) { 352 jboolean inBounds = XNI_TRUE; 353 jint aval = *a; 354 if (aval < min || aval > max) { 355 inBounds = XNI_FALSE; 356 } 357 return inBounds; 358 } 359 360 // 361 // this function is called when transform is translate or scale 362 // because the bounding box will be always fully filled 363 // 364 static INLINE void checkBoundsRepeat(jint *a, jlong *la, jint min, jint max) { 365 jint aval = *a; 366 if (aval < min || aval > max) { 367 if (max >= 0) { 368 *la = lmod(*la, (max+1) << 16); 369 *a = (jint)(*la >> 16); 370 } else { 371 *la = 0; 372 *a = 0; 373 } 374 } 375 } 376 377 static INLINE void checkBoundsNoRepeat(jint *a, jlong *la, jint min, jint max) { 378 jint aval = *a; 379 if (aval < min) { 380 *a = min; 381 } else if (aval > max) { 382 *a = max; 383 } 384 } 385 386 static INLINE void getPointsToInterpolate(jint *pts, jint *data, jint sidx, jint stride, jint p00, 387 jint tx, jint txMax, jint ty, jint tyMax) 388 { 389 jint sidx2 = (ty >= tyMax) ? sidx : sidx + stride; 390 jboolean isXin = (tx < txMax); 391 pts[0] = (isXin) ? data[sidx + 1] : p00; 392 pts[1] = data[sidx2]; 393 pts[2] = (isXin) ? data[sidx2 + 1] : data[sidx2]; 394 } 395 396 static INLINE void getPointsToInterpolateRepeat(jint *pts, jint *data, jint sidx, jint stride, jint p00, 397 jint tx, jint txMax, jint ty, jint tyMax) 398 { 399 jint sidx2 = (ty >= tyMax) ? MAX(tx,0) : sidx + stride; 400 jboolean isXin = (tx < txMax); 401 pts[0] = (isXin) ? data[sidx + 1] : data[sidx - MAX(tx,0)]; 402 pts[1] = data[sidx2]; 403 pts[2] = (isXin) ? data[sidx2 + 1] : data[sidx2 - MAX(tx,0)]; 404 } 405 406 void 407 genTexturePaintTarget(Renderer *rdr, jint *paint, jint height) { 408 jint j; 409 jint paintStride = rdr->_alphaWidth; 410 411 jint x, y; 412 jint* txtData = rdr->_texture_intData; 413 jint txtWidth = rdr->_texture_imageWidth; 414 jint txtHeight = rdr->_texture_imageHeight; 415 jint txtStride = rdr->_texture_stride; 416 jint txMin = rdr->_texture_txMin; 417 jint tyMin = rdr->_texture_tyMin; 418 jint txMax = rdr->_texture_txMax; 419 jint tyMax = rdr->_texture_tyMax; 420 jint repeatInterpolateMode; 421 422 if (rdr->_texture_interpolate) { 423 if (rdr->_texture_hasAlpha) { 424 repeatInterpolateMode = (rdr->_texture_repeat) ? 425 REPEAT_INTERPOLATE_ALPHA : NO_REPEAT_INTERPOLATE_ALPHA; 426 } else { 427 repeatInterpolateMode = (rdr->_texture_repeat) ? 428 REPEAT_INTERPOLATE_NO_ALPHA : NO_REPEAT_INTERPOLATE_NO_ALPHA; 429 } 430 } else { 431 repeatInterpolateMode = (rdr->_texture_repeat) ? 432 REPEAT_NO_INTERPOLATE : NO_REPEAT_NO_INTERPOLATE; 433 } 434 435 switch (rdr->_texture_transformType) { 436 case TEXTURE_TRANSFORM_IDENTITY: 437 // There used to be special case code for IDENTITY, but it had a number 438 // of bugs where it punted on some calculations which turned out to be 439 // necessary. It was also rarely used because it relied on no 440 // translations to be set and/or no sub-textures to be used, which 441 // almost never happens in a scene graph, so this code was largely 442 // untested (witness the bugs mentioned above). The decision was made 443 // to just have this case fall through to the translate case which is 444 // reasonably optimal and the code that was being used 99% of the 445 // time when there was no scale anyway. 446 /* NO BREAK */ 447 448 // just TRANSLATION 449 case TEXTURE_TRANSFORM_TRANSLATE: 450 { 451 jint cval, pidx; 452 jint *a, *am; 453 jlong ltx, lty; 454 jint tx, ty, vfrac, hfrac; 455 jint paintOffset = 0; 456 jint pts[3]; 457 jint sidx, p00; 458 459 y = rdr->_currY; 460 461 for (j = 0; j < height; j++, y++) { 462 pidx = paintOffset; 463 464 x = rdr->_currX; 465 466 ltx = (x << 16) + rdr->_texture_m02; 467 lty = (y << 16) + rdr->_texture_m12; 468 469 // we can compute here since (m00 == 65536) && (m10 == 0) 470 tx = (jint)(ltx >> 16); 471 ty = (jint)(lty >> 16); 472 hfrac = (jint)(ltx & 0xffff); 473 vfrac = (jint)(lty & 0xffff); 474 475 if (rdr->_texture_repeat) { 476 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 477 } else { 478 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 479 } 480 481 a = paint + pidx; 482 am = a + paintStride; 483 484 PISCES_DEBUG("TRANSLATE, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax); 485 486 switch (repeatInterpolateMode) { 487 case NO_REPEAT_NO_INTERPOLATE: 488 { 489 jint *txtRow = txtData + (MAX(0, ty) * txtStride); 490 jint len; 491 tx = (jint)(ltx >> 16); 492 while (tx < txMin && a < am) { 493 *a++ = txtRow[txMin]; 494 ++tx; 495 } 496 len = MIN(am-a, txMax-tx+1); 497 if (len > 0) { 498 memcpy(a, txtRow + tx, sizeof(jint) * len); 499 a += len; 500 } 501 while (a < am) { 502 *a++ = txtRow[txMax]; 503 } 504 break; 505 } 506 case REPEAT_NO_INTERPOLATE: 507 while (a < am) { 508 tx = (jint)(ltx >> 16); 509 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 510 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 511 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 512 assert(pidx >= 0); 513 assert(pidx < rdr->_paint_length); 514 paint[pidx] = txtData[sidx]; 515 ++a; 516 ++pidx; 517 ltx += 0x10000; 518 } // while (a < am) 519 break; 520 case NO_REPEAT_INTERPOLATE_ALPHA: 521 while (a < am) { 522 tx = (jint)(ltx >> 16); 523 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 524 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 525 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 526 p00 = txtData[sidx]; 527 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 528 tx, txtWidth-1, ty, txtHeight-1); 529 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 530 if (hfrac && vfrac) { 531 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 532 } else if (hfrac) { 533 cval = interpolate2points(p00, pts[0], hfrac); 534 } else if (vfrac) { 535 cval = interpolate2points(p00, pts[1], vfrac); 536 } else { 537 cval = p00; 538 } 539 assert(pidx >= 0); 540 assert(pidx < rdr->_paint_length); 541 paint[pidx] = cval; 542 ++a; 543 ++pidx; 544 ltx += 0x10000; 545 } // while (a < am) 546 break; 547 case REPEAT_INTERPOLATE_ALPHA: 548 while (a < am) { 549 tx = (jint)(ltx >> 16); 550 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 551 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 552 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 553 p00 = txtData[sidx]; 554 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 555 tx, txtWidth-1, ty, txtHeight-1); 556 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 557 if (hfrac && vfrac) { 558 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 559 } else if (hfrac) { 560 cval = interpolate2points(p00, pts[0], hfrac); 561 } else if (vfrac) { 562 cval = interpolate2points(p00, pts[1], vfrac); 563 } else { 564 cval = p00; 565 } 566 assert(pidx >= 0); 567 assert(pidx < rdr->_paint_length); 568 paint[pidx] = cval; 569 ++a; 570 ++pidx; 571 ltx += 0x10000; 572 } // while (a < am) 573 break; 574 case NO_REPEAT_INTERPOLATE_NO_ALPHA: 575 while (a < am) { 576 tx = (jint)(ltx >> 16); 577 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 578 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 579 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 580 p00 = txtData[sidx]; 581 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 582 tx, txtWidth-1, ty, txtHeight-1); 583 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 584 if (hfrac && vfrac) { 585 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 586 } else if (hfrac) { 587 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 588 } else if (vfrac) { 589 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 590 } else { 591 cval = p00; 592 } 593 assert(pidx >= 0); 594 assert(pidx < rdr->_paint_length); 595 paint[pidx] = cval; 596 ++a; 597 ++pidx; 598 ltx += 0x10000; 599 } // while (a < am) 600 break; 601 case REPEAT_INTERPOLATE_NO_ALPHA: 602 while (a < am) { 603 tx = (jint)(ltx >> 16); 604 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 605 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 606 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 607 p00 = txtData[sidx]; 608 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 609 tx, txtWidth-1, ty, txtHeight-1); 610 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 611 if (hfrac && vfrac) { 612 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 613 } else if (hfrac) { 614 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 615 } else if (vfrac) { 616 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 617 } else { 618 cval = p00; 619 } 620 assert(pidx >= 0); 621 assert(pidx < rdr->_paint_length); 622 paint[pidx] = cval; 623 ++a; 624 ++pidx; 625 ltx += 0x10000; 626 } // while (a < am) 627 break; 628 } 629 PISCES_DEBUG("\n"); 630 paintOffset += paintStride; 631 } // for 632 } 633 break; 634 635 // scale transform 636 case TEXTURE_TRANSFORM_SCALE_TRANSLATE: 637 { 638 jint cval, pidx; 639 jint *a, *am; 640 jlong ltx, lty; 641 jint tx, ty, vfrac, hfrac; 642 jint paintOffset = 0; 643 jint pts[3]; 644 jint sidx, p00; 645 646 y = rdr->_currY; 647 648 for (j = 0; j < height; j++, y++) { 649 pidx = paintOffset; 650 651 x = rdr->_currX; 652 653 ltx = x * rdr->_texture_m00 + y * rdr->_texture_m01 + rdr->_texture_m02; 654 lty = x * rdr->_texture_m10 + y * rdr->_texture_m11 + rdr->_texture_m12; 655 656 a = paint + pidx; 657 am = a + paintStride; 658 659 PISCES_DEBUG("SCALE, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax); 660 661 switch (repeatInterpolateMode) { 662 case NO_REPEAT_NO_INTERPOLATE: 663 while (a < am) { 664 tx = (jint)(ltx >> 16); 665 ty = (jint)(lty >> 16); 666 hfrac = (jint)(ltx & 0xffff); 667 vfrac = (jint)(lty & 0xffff); 668 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 669 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 670 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 671 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 672 assert(pidx >= 0); 673 assert(pidx < rdr->_paint_length); 674 paint[pidx] = txtData[sidx]; 675 ++a; 676 ++pidx; 677 ltx += rdr->_texture_m00; 678 lty += rdr->_texture_m10; 679 } // while (a < am)b 680 break; 681 case REPEAT_NO_INTERPOLATE: 682 while (a < am) { 683 tx = (jint)(ltx >> 16); 684 ty = (jint)(lty >> 16); 685 hfrac = (jint)(ltx & 0xffff); 686 vfrac = (jint)(lty & 0xffff); 687 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 688 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 689 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 690 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 691 assert(pidx >= 0); 692 assert(pidx < rdr->_paint_length); 693 paint[pidx] = txtData[sidx]; 694 ++a; 695 ++pidx; 696 ltx += rdr->_texture_m00; 697 lty += rdr->_texture_m10; 698 } // while (a < am)b 699 break; 700 case NO_REPEAT_INTERPOLATE_ALPHA: 701 while (a < am) { 702 tx = (jint)(ltx >> 16); 703 ty = (jint)(lty >> 16); 704 hfrac = (jint)(ltx & 0xffff); 705 vfrac = (jint)(lty & 0xffff); 706 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 707 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 708 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 709 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 710 p00 = txtData[sidx]; 711 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 712 tx, txtWidth-1, ty, txtHeight-1); 713 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 714 if (hfrac && vfrac) { 715 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 716 } else if (hfrac) { 717 cval = interpolate2points(p00, pts[0], hfrac); 718 } else if (vfrac) { 719 cval = interpolate2points(p00, pts[1], vfrac); 720 } else { 721 cval = p00; 722 } 723 assert(pidx >= 0); 724 assert(pidx < rdr->_paint_length); 725 paint[pidx] = cval; 726 727 ++a; 728 ++pidx; 729 ltx += rdr->_texture_m00; 730 lty += rdr->_texture_m10; 731 } // while (a < am)b 732 break; 733 case REPEAT_INTERPOLATE_ALPHA: 734 while (a < am) { 735 tx = (jint)(ltx >> 16); 736 ty = (jint)(lty >> 16); 737 hfrac = (jint)(ltx & 0xffff); 738 vfrac = (jint)(lty & 0xffff); 739 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 740 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 741 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 742 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 743 p00 = txtData[sidx]; 744 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 745 tx, txtWidth-1, ty, txtHeight-1); 746 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 747 if (hfrac && vfrac) { 748 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 749 } else if (hfrac) { 750 cval = interpolate2points(p00, pts[0], hfrac); 751 } else if (vfrac) { 752 cval = interpolate2points(p00, pts[1], vfrac); 753 } else { 754 cval = p00; 755 } 756 assert(pidx >= 0); 757 assert(pidx < rdr->_paint_length); 758 paint[pidx] = cval; 759 760 ++a; 761 ++pidx; 762 ltx += rdr->_texture_m00; 763 lty += rdr->_texture_m10; 764 } // while (a < am)b 765 break; 766 case NO_REPEAT_INTERPOLATE_NO_ALPHA: 767 while (a < am) { 768 tx = (jint)(ltx >> 16); 769 ty = (jint)(lty >> 16); 770 hfrac = (jint)(ltx & 0xffff); 771 vfrac = (jint)(lty & 0xffff); 772 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 773 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 774 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 775 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 776 p00 = txtData[sidx]; 777 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 778 tx, txtWidth-1, ty, txtHeight-1); 779 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 780 if (hfrac && vfrac) { 781 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 782 } else if (hfrac) { 783 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 784 } else if (vfrac) { 785 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 786 } else { 787 cval = p00; 788 } 789 assert(pidx >= 0); 790 assert(pidx < rdr->_paint_length); 791 paint[pidx] = cval; 792 793 ++a; 794 ++pidx; 795 ltx += rdr->_texture_m00; 796 lty += rdr->_texture_m10; 797 } // while (a < am)b 798 break; 799 case REPEAT_INTERPOLATE_NO_ALPHA: 800 while (a < am) { 801 tx = (jint)(ltx >> 16); 802 ty = (jint)(lty >> 16); 803 hfrac = (jint)(ltx & 0xffff); 804 vfrac = (jint)(lty & 0xffff); 805 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 806 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 807 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 808 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 809 p00 = txtData[sidx]; 810 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 811 tx, txtWidth-1, ty, txtHeight-1); 812 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 813 if (hfrac && vfrac) { 814 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 815 } else if (hfrac) { 816 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 817 } else if (vfrac) { 818 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 819 } else { 820 cval = p00; 821 } 822 assert(pidx >= 0); 823 assert(pidx < rdr->_paint_length); 824 paint[pidx] = cval; 825 826 ++a; 827 ++pidx; 828 ltx += rdr->_texture_m00; 829 lty += rdr->_texture_m10; 830 } // while (a < am)b 831 break; 832 } 833 PISCES_DEBUG("\n"); 834 paintOffset += paintStride; 835 }//for 836 } 837 break; 838 839 // generic transform 840 case TEXTURE_TRANSFORM_GENERIC: 841 { 842 jint cval, pidx; 843 jint *a, *am; 844 jlong ltx, lty; 845 jint tx, ty, vfrac, hfrac; 846 jint paintOffset = 0; 847 jint pts[3]; 848 jint sidx, p00; 849 jboolean inBounds; 850 851 y = rdr->_currY; 852 853 for (j = 0; j < height; j++, y++) { 854 pidx = paintOffset; 855 856 x = rdr->_currX; 857 858 ltx = x * rdr->_texture_m00 + y * rdr->_texture_m01 + rdr->_texture_m02; 859 lty = x * rdr->_texture_m10 + y * rdr->_texture_m11 + rdr->_texture_m12; 860 861 a = paint + pidx; 862 am = a + paintStride; 863 864 PISCES_DEBUG("GENERIC, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax); 865 866 switch (repeatInterpolateMode) { 867 case NO_REPEAT_NO_INTERPOLATE: 868 while (a < am) { 869 tx = (jint)(ltx >> 16); 870 ty = (jint)(lty >> 16); 871 hfrac = (jint)(ltx & 0xffff); 872 vfrac = (jint)(lty & 0xffff); 873 874 inBounds = 875 isInBoundsNoRepeat(&tx, <x, txMin-1, txMax) && 876 isInBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 877 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 878 if (inBounds) { 879 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 880 p00 = txtData[sidx]; 881 assert(pidx >= 0); 882 assert(pidx < rdr->_paint_length); 883 paint[pidx] = p00; 884 } else { 885 assert(pidx >= 0); 886 assert(pidx < rdr->_paint_length); 887 paint[pidx] = 0x00000000; 888 } 889 ++a; 890 ++pidx; 891 ltx += rdr->_texture_m00; 892 lty += rdr->_texture_m10; 893 } // while (a < am)b 894 break; 895 case REPEAT_NO_INTERPOLATE: 896 while (a < am) { 897 tx = (jint)(ltx >> 16); 898 ty = (jint)(lty >> 16); 899 hfrac = (jint)(ltx & 0xffff); 900 vfrac = (jint)(lty & 0xffff); 901 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 902 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 903 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 904 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 905 p00 = txtData[sidx]; 906 assert(pidx >= 0); 907 assert(pidx < rdr->_paint_length); 908 paint[pidx] = p00; 909 ++a; 910 ++pidx; 911 ltx += rdr->_texture_m00; 912 lty += rdr->_texture_m10; 913 } // while (a < am)b 914 break; 915 case NO_REPEAT_INTERPOLATE_ALPHA: 916 while (a < am) { 917 tx = (jint)(ltx >> 16); 918 ty = (jint)(lty >> 16); 919 hfrac = (jint)(ltx & 0xffff); 920 vfrac = (jint)(lty & 0xffff); 921 922 inBounds = 923 isInBoundsNoRepeat(&tx, <x, txMin-1, txMax) && 924 isInBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 925 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 926 if (inBounds) { 927 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 928 p00 = txtData[sidx]; 929 930 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 931 tx, txtWidth-1, ty, txtHeight-1); 932 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 933 if (hfrac && vfrac) { 934 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 935 } else if (hfrac) { 936 cval = interpolate2points(p00, pts[0], hfrac); 937 } else if (vfrac) { 938 cval = interpolate2points(p00, pts[1], vfrac); 939 } else { 940 cval = p00; 941 } 942 assert(pidx >= 0); 943 assert(pidx < rdr->_paint_length); 944 paint[pidx] = cval; 945 } else { 946 assert(pidx >= 0); 947 assert(pidx < rdr->_paint_length); 948 paint[pidx] = 0x00000000; 949 } 950 ++a; 951 ++pidx; 952 ltx += rdr->_texture_m00; 953 lty += rdr->_texture_m10; 954 } // while (a < am)b 955 break; 956 case REPEAT_INTERPOLATE_ALPHA: 957 while (a < am) { 958 tx = (jint)(ltx >> 16); 959 ty = (jint)(lty >> 16); 960 hfrac = (jint)(ltx & 0xffff); 961 vfrac = (jint)(lty & 0xffff); 962 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 963 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 964 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 965 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 966 p00 = txtData[sidx]; 967 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 968 tx, txtWidth-1, ty, txtHeight-1); 969 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 970 if (hfrac && vfrac) { 971 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 972 } else if (hfrac) { 973 cval = interpolate2points(p00, pts[0], hfrac); 974 } else if (vfrac) { 975 cval = interpolate2points(p00, pts[1], vfrac); 976 } else { 977 cval = p00; 978 } 979 assert(pidx >= 0); 980 assert(pidx < rdr->_paint_length); 981 paint[pidx] = cval; 982 ++a; 983 ++pidx; 984 ltx += rdr->_texture_m00; 985 lty += rdr->_texture_m10; 986 } // while (a < am)b 987 break; 988 case NO_REPEAT_INTERPOLATE_NO_ALPHA: 989 while (a < am) { 990 tx = (jint)(ltx >> 16); 991 ty = (jint)(lty >> 16); 992 hfrac = (jint)(ltx & 0xffff); 993 vfrac = (jint)(lty & 0xffff); 994 995 inBounds = 996 isInBoundsNoRepeat(&tx, <x, txMin-1, txMax) && 997 isInBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 998 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 999 if (inBounds) { 1000 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 1001 p00 = txtData[sidx]; 1002 1003 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 1004 tx, txtWidth-1, ty, txtHeight-1); 1005 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 1006 if (hfrac && vfrac) { 1007 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 1008 } else if (hfrac) { 1009 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 1010 } else if (vfrac) { 1011 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 1012 } else { 1013 cval = p00; 1014 } 1015 assert(pidx >= 0); 1016 assert(pidx < rdr->_paint_length); 1017 paint[pidx] = cval; 1018 } else { 1019 assert(pidx >= 0); 1020 assert(pidx < rdr->_paint_length); 1021 paint[pidx] = 0x00000000; 1022 } 1023 ++a; 1024 ++pidx; 1025 ltx += rdr->_texture_m00; 1026 lty += rdr->_texture_m10; 1027 } // while (a < am)b 1028 break; 1029 case REPEAT_INTERPOLATE_NO_ALPHA: 1030 while (a < am) { 1031 tx = (jint)(ltx >> 16); 1032 ty = (jint)(lty >> 16); 1033 hfrac = (jint)(ltx & 0xffff); 1034 vfrac = (jint)(lty & 0xffff); 1035 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 1036 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 1037 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 1038 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 1039 p00 = txtData[sidx]; 1040 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 1041 tx, txtWidth-1, ty, txtHeight-1); 1042 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 1043 if (hfrac && vfrac) { 1044 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 1045 } else if (hfrac) { 1046 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 1047 } else if (vfrac) { 1048 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 1049 } else { 1050 cval = p00; 1051 } 1052 assert(pidx >= 0); 1053 assert(pidx < rdr->_paint_length); 1054 paint[pidx] = cval; 1055 ++a; 1056 ++pidx; 1057 ltx += rdr->_texture_m00; 1058 lty += rdr->_texture_m10; 1059 } // while (a < am)b 1060 break; 1061 } 1062 PISCES_DEBUG("\n"); 1063 paintOffset += paintStride; 1064 }//for 1065 } 1066 break; 1067 } 1068 } 1069 1070 void 1071 genTexturePaint(Renderer *rdr, jint height) { 1072 genTexturePaintTarget(rdr, rdr->_paint, height); 1073 } 1074 1075 void 1076 genTexturePaintMultiply(Renderer *rdr, jint height) { 1077 jint i, j, idx; 1078 jint x_from = rdr->_minTouched; 1079 jint x_to = rdr->_maxTouched; 1080 jint w = (x_to - x_from + 1); 1081 jint *paint = rdr->_paint; 1082 jint paintStride = rdr->_alphaWidth; 1083 jint pval, tval, palpha_1; 1084 jint calpha = rdr->_calpha; 1085 jint cred = rdr->_cred; 1086 jint cgreen = rdr->_cgreen; 1087 jint cblue = rdr->_cblue; 1088 jint oalpha, ored, ogreen, oblue; 1089 1090 switch (rdr->_prevPaintMode) { 1091 case PAINT_FLAT_COLOR: 1092 genTexturePaintTarget(rdr, paint, height); 1093 palpha_1 = calpha + 1; 1094 if (cred == 0xFF && cgreen == 0xFF && cblue == 0xFF) { 1095 if (calpha < 0xFF) { 1096 for (i = 0; i < height; i++) { 1097 idx = i * paintStride; 1098 for (j = 0; j < w; j++) { 1099 tval = paint[idx + j]; 1100 oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8; 1101 ored = (palpha_1 * ((tval >> 16) & 0xFF)) >> 8; 1102 ogreen = (palpha_1 * ((tval >> 8) & 0xFF)) >> 8; 1103 oblue = (palpha_1 * (tval & 0xFF)) >> 8; 1104 paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue; 1105 } 1106 } 1107 } 1108 } else { 1109 for (i = 0; i < height; i++) { 1110 idx = i * paintStride; 1111 for (j = 0; j < w; j++) { 1112 tval = paint[idx + j]; 1113 oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8; 1114 ored = ((((cred + 1) * ((tval >> 16) & 0xFF)) >> 8) * palpha_1) >> 8; 1115 ogreen = ((((cgreen + 1) * ((tval >> 8) & 0xFF)) >> 8) * palpha_1) >> 8; 1116 oblue = ((((cblue + 1) * (tval & 0xFF)) >> 8) * palpha_1) >> 8; 1117 paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue; 1118 } 1119 } 1120 } 1121 break; 1122 case PAINT_LINEAR_GRADIENT: 1123 case PAINT_RADIAL_GRADIENT: 1124 { 1125 jint *imagePaint = my_malloc(jint, w * height); 1126 if (imagePaint != NULL) { 1127 if (rdr->_prevPaintMode == PAINT_LINEAR_GRADIENT) { 1128 genLinearGradientPaint(rdr, height); 1129 } else { 1130 genRadialGradientPaint(rdr, height); 1131 } 1132 genTexturePaintTarget(rdr, imagePaint, height); 1133 for (i = 0; i < height; i++) { 1134 idx = i * paintStride; 1135 for (j = 0; j < w; j++) { 1136 pval = paint[idx + j]; 1137 tval = imagePaint[idx + j]; 1138 palpha_1 = ((pval >> 24) & 0xFF) + 1; 1139 oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8; 1140 ored = ((((((pval >> 16) & 0xFF) + 1) * ((tval >> 16) & 0xFF)) >> 8) * palpha_1) >> 8; 1141 ogreen = ((((((pval >> 8) & 0xFF) + 1) * ((tval >> 8) & 0xFF)) >> 8) * palpha_1) >> 8; 1142 oblue = (((((pval & 0xFF) + 1) * (tval & 0xFF)) >> 8) * palpha_1) >> 8; 1143 paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue; 1144 } 1145 } 1146 my_free(imagePaint); 1147 } 1148 } 1149 break; 1150 } 1151 } 1152