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 while (a < am) { 489 tx = (jint)(ltx >> 16); 490 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 491 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 492 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 493 assert(pidx >= 0); 494 assert(pidx < rdr->_paint_length); 495 paint[pidx] = txtData[sidx]; 496 ++a; 497 ++pidx; 498 ltx += 0x10000; 499 } // while (a < am) 500 break; 501 case REPEAT_NO_INTERPOLATE: 502 while (a < am) { 503 tx = (jint)(ltx >> 16); 504 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 505 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 506 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 507 assert(pidx >= 0); 508 assert(pidx < rdr->_paint_length); 509 paint[pidx] = txtData[sidx]; 510 ++a; 511 ++pidx; 512 ltx += 0x10000; 513 } // while (a < am) 514 break; 515 case NO_REPEAT_INTERPOLATE_ALPHA: 516 while (a < am) { 517 tx = (jint)(ltx >> 16); 518 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 519 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 520 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 521 p00 = txtData[sidx]; 522 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 523 tx, txtWidth-1, ty, txtHeight-1); 524 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 525 if (hfrac && vfrac) { 526 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 527 } else if (hfrac) { 528 cval = interpolate2points(p00, pts[0], hfrac); 529 } else if (vfrac) { 530 cval = interpolate2points(p00, pts[1], vfrac); 531 } else { 532 cval = p00; 533 } 534 assert(pidx >= 0); 535 assert(pidx < rdr->_paint_length); 536 paint[pidx] = cval; 537 ++a; 538 ++pidx; 539 ltx += 0x10000; 540 } // while (a < am) 541 break; 542 case REPEAT_INTERPOLATE_ALPHA: 543 while (a < am) { 544 tx = (jint)(ltx >> 16); 545 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 546 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 547 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 548 p00 = txtData[sidx]; 549 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 550 tx, txtWidth-1, ty, txtHeight-1); 551 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 552 if (hfrac && vfrac) { 553 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 554 } else if (hfrac) { 555 cval = interpolate2points(p00, pts[0], hfrac); 556 } else if (vfrac) { 557 cval = interpolate2points(p00, pts[1], vfrac); 558 } else { 559 cval = p00; 560 } 561 assert(pidx >= 0); 562 assert(pidx < rdr->_paint_length); 563 paint[pidx] = cval; 564 ++a; 565 ++pidx; 566 ltx += 0x10000; 567 } // while (a < am) 568 break; 569 case NO_REPEAT_INTERPOLATE_NO_ALPHA: 570 while (a < am) { 571 tx = (jint)(ltx >> 16); 572 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 573 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 574 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 575 p00 = txtData[sidx]; 576 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 577 tx, txtWidth-1, ty, txtHeight-1); 578 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 579 if (hfrac && vfrac) { 580 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 581 } else if (hfrac) { 582 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 583 } else if (vfrac) { 584 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 585 } else { 586 cval = p00; 587 } 588 assert(pidx >= 0); 589 assert(pidx < rdr->_paint_length); 590 paint[pidx] = cval; 591 ++a; 592 ++pidx; 593 ltx += 0x10000; 594 } // while (a < am) 595 break; 596 case REPEAT_INTERPOLATE_NO_ALPHA: 597 while (a < am) { 598 tx = (jint)(ltx >> 16); 599 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 600 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 601 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 602 p00 = txtData[sidx]; 603 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 604 tx, txtWidth-1, ty, txtHeight-1); 605 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 606 if (hfrac && vfrac) { 607 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 608 } else if (hfrac) { 609 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 610 } else if (vfrac) { 611 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 612 } else { 613 cval = p00; 614 } 615 assert(pidx >= 0); 616 assert(pidx < rdr->_paint_length); 617 paint[pidx] = cval; 618 ++a; 619 ++pidx; 620 ltx += 0x10000; 621 } // while (a < am) 622 break; 623 } 624 PISCES_DEBUG("\n"); 625 paintOffset += paintStride; 626 } // for 627 } 628 break; 629 630 // scale transform 631 case TEXTURE_TRANSFORM_SCALE_TRANSLATE: 632 { 633 jint cval, pidx; 634 jint *a, *am; 635 jlong ltx, lty; 636 jint tx, ty, vfrac, hfrac; 637 jint paintOffset = 0; 638 jint pts[3]; 639 jint sidx, p00; 640 641 y = rdr->_currY; 642 643 for (j = 0; j < height; j++, y++) { 644 pidx = paintOffset; 645 646 x = rdr->_currX; 647 648 ltx = x * rdr->_texture_m00 + y * rdr->_texture_m01 + rdr->_texture_m02; 649 lty = x * rdr->_texture_m10 + y * rdr->_texture_m11 + rdr->_texture_m12; 650 651 a = paint + pidx; 652 am = a + paintStride; 653 654 PISCES_DEBUG("SCALE, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax); 655 656 switch (repeatInterpolateMode) { 657 case NO_REPEAT_NO_INTERPOLATE: 658 while (a < am) { 659 tx = (jint)(ltx >> 16); 660 ty = (jint)(lty >> 16); 661 hfrac = (jint)(ltx & 0xffff); 662 vfrac = (jint)(lty & 0xffff); 663 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 664 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 665 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 666 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 667 assert(pidx >= 0); 668 assert(pidx < rdr->_paint_length); 669 paint[pidx] = txtData[sidx]; 670 ++a; 671 ++pidx; 672 ltx += rdr->_texture_m00; 673 lty += rdr->_texture_m10; 674 } // while (a < am)b 675 break; 676 case REPEAT_NO_INTERPOLATE: 677 while (a < am) { 678 tx = (jint)(ltx >> 16); 679 ty = (jint)(lty >> 16); 680 hfrac = (jint)(ltx & 0xffff); 681 vfrac = (jint)(lty & 0xffff); 682 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 683 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 684 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 685 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 686 assert(pidx >= 0); 687 assert(pidx < rdr->_paint_length); 688 paint[pidx] = txtData[sidx]; 689 ++a; 690 ++pidx; 691 ltx += rdr->_texture_m00; 692 lty += rdr->_texture_m10; 693 } // while (a < am)b 694 break; 695 case NO_REPEAT_INTERPOLATE_ALPHA: 696 while (a < am) { 697 tx = (jint)(ltx >> 16); 698 ty = (jint)(lty >> 16); 699 hfrac = (jint)(ltx & 0xffff); 700 vfrac = (jint)(lty & 0xffff); 701 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 702 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 703 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 704 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 705 p00 = txtData[sidx]; 706 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 707 tx, txtWidth-1, ty, txtHeight-1); 708 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 709 if (hfrac && vfrac) { 710 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 711 } else if (hfrac) { 712 cval = interpolate2points(p00, pts[0], hfrac); 713 } else if (vfrac) { 714 cval = interpolate2points(p00, pts[1], vfrac); 715 } else { 716 cval = p00; 717 } 718 assert(pidx >= 0); 719 assert(pidx < rdr->_paint_length); 720 paint[pidx] = cval; 721 722 ++a; 723 ++pidx; 724 ltx += rdr->_texture_m00; 725 lty += rdr->_texture_m10; 726 } // while (a < am)b 727 break; 728 case REPEAT_INTERPOLATE_ALPHA: 729 while (a < am) { 730 tx = (jint)(ltx >> 16); 731 ty = (jint)(lty >> 16); 732 hfrac = (jint)(ltx & 0xffff); 733 vfrac = (jint)(lty & 0xffff); 734 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 735 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 736 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 737 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 738 p00 = txtData[sidx]; 739 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 740 tx, txtWidth-1, ty, txtHeight-1); 741 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 742 if (hfrac && vfrac) { 743 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 744 } else if (hfrac) { 745 cval = interpolate2points(p00, pts[0], hfrac); 746 } else if (vfrac) { 747 cval = interpolate2points(p00, pts[1], vfrac); 748 } else { 749 cval = p00; 750 } 751 assert(pidx >= 0); 752 assert(pidx < rdr->_paint_length); 753 paint[pidx] = cval; 754 755 ++a; 756 ++pidx; 757 ltx += rdr->_texture_m00; 758 lty += rdr->_texture_m10; 759 } // while (a < am)b 760 break; 761 case NO_REPEAT_INTERPOLATE_NO_ALPHA: 762 while (a < am) { 763 tx = (jint)(ltx >> 16); 764 ty = (jint)(lty >> 16); 765 hfrac = (jint)(ltx & 0xffff); 766 vfrac = (jint)(lty & 0xffff); 767 checkBoundsNoRepeat(&tx, <x, txMin-1, txMax); 768 checkBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 769 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 770 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 771 p00 = txtData[sidx]; 772 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 773 tx, txtWidth-1, ty, txtHeight-1); 774 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 775 if (hfrac && vfrac) { 776 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 777 } else if (hfrac) { 778 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 779 } else if (vfrac) { 780 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 781 } else { 782 cval = p00; 783 } 784 assert(pidx >= 0); 785 assert(pidx < rdr->_paint_length); 786 paint[pidx] = cval; 787 788 ++a; 789 ++pidx; 790 ltx += rdr->_texture_m00; 791 lty += rdr->_texture_m10; 792 } // while (a < am)b 793 break; 794 case REPEAT_INTERPOLATE_NO_ALPHA: 795 while (a < am) { 796 tx = (jint)(ltx >> 16); 797 ty = (jint)(lty >> 16); 798 hfrac = (jint)(ltx & 0xffff); 799 vfrac = (jint)(lty & 0xffff); 800 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 801 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 802 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 803 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 804 p00 = txtData[sidx]; 805 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 806 tx, txtWidth-1, ty, txtHeight-1); 807 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 808 if (hfrac && vfrac) { 809 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 810 } else if (hfrac) { 811 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 812 } else if (vfrac) { 813 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 814 } else { 815 cval = p00; 816 } 817 assert(pidx >= 0); 818 assert(pidx < rdr->_paint_length); 819 paint[pidx] = cval; 820 821 ++a; 822 ++pidx; 823 ltx += rdr->_texture_m00; 824 lty += rdr->_texture_m10; 825 } // while (a < am)b 826 break; 827 } 828 PISCES_DEBUG("\n"); 829 paintOffset += paintStride; 830 }//for 831 } 832 break; 833 834 // generic transform 835 case TEXTURE_TRANSFORM_GENERIC: 836 { 837 jint cval, pidx; 838 jint *a, *am; 839 jlong ltx, lty; 840 jint tx, ty, vfrac, hfrac; 841 jint paintOffset = 0; 842 jint pts[3]; 843 jint sidx, p00; 844 jboolean inBounds; 845 846 y = rdr->_currY; 847 848 for (j = 0; j < height; j++, y++) { 849 pidx = paintOffset; 850 851 x = rdr->_currX; 852 853 ltx = x * rdr->_texture_m00 + y * rdr->_texture_m01 + rdr->_texture_m02; 854 lty = x * rdr->_texture_m10 + y * rdr->_texture_m11 + rdr->_texture_m12; 855 856 a = paint + pidx; 857 am = a + paintStride; 858 859 PISCES_DEBUG("GENERIC, txMin: %d, txMax: %d, tyMin: %d, tyMax: %d\n", txMin, txMax, tyMin, tyMax); 860 861 switch (repeatInterpolateMode) { 862 case NO_REPEAT_NO_INTERPOLATE: 863 while (a < am) { 864 tx = (jint)(ltx >> 16); 865 ty = (jint)(lty >> 16); 866 hfrac = (jint)(ltx & 0xffff); 867 vfrac = (jint)(lty & 0xffff); 868 869 inBounds = 870 isInBoundsNoRepeat(&tx, <x, txMin-1, txMax) && 871 isInBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 872 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 873 if (inBounds) { 874 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 875 p00 = txtData[sidx]; 876 assert(pidx >= 0); 877 assert(pidx < rdr->_paint_length); 878 paint[pidx] = p00; 879 } else { 880 assert(pidx >= 0); 881 assert(pidx < rdr->_paint_length); 882 paint[pidx] = 0x00000000; 883 } 884 ++a; 885 ++pidx; 886 ltx += rdr->_texture_m00; 887 lty += rdr->_texture_m10; 888 } // while (a < am)b 889 break; 890 case REPEAT_NO_INTERPOLATE: 891 while (a < am) { 892 tx = (jint)(ltx >> 16); 893 ty = (jint)(lty >> 16); 894 hfrac = (jint)(ltx & 0xffff); 895 vfrac = (jint)(lty & 0xffff); 896 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 897 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 898 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 899 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 900 p00 = txtData[sidx]; 901 assert(pidx >= 0); 902 assert(pidx < rdr->_paint_length); 903 paint[pidx] = p00; 904 ++a; 905 ++pidx; 906 ltx += rdr->_texture_m00; 907 lty += rdr->_texture_m10; 908 } // while (a < am)b 909 break; 910 case NO_REPEAT_INTERPOLATE_ALPHA: 911 while (a < am) { 912 tx = (jint)(ltx >> 16); 913 ty = (jint)(lty >> 16); 914 hfrac = (jint)(ltx & 0xffff); 915 vfrac = (jint)(lty & 0xffff); 916 917 inBounds = 918 isInBoundsNoRepeat(&tx, <x, txMin-1, txMax) && 919 isInBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 920 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 921 if (inBounds) { 922 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 923 p00 = txtData[sidx]; 924 925 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 926 tx, txtWidth-1, ty, txtHeight-1); 927 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 928 if (hfrac && vfrac) { 929 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 930 } else if (hfrac) { 931 cval = interpolate2points(p00, pts[0], hfrac); 932 } else if (vfrac) { 933 cval = interpolate2points(p00, pts[1], vfrac); 934 } else { 935 cval = p00; 936 } 937 assert(pidx >= 0); 938 assert(pidx < rdr->_paint_length); 939 paint[pidx] = cval; 940 } else { 941 assert(pidx >= 0); 942 assert(pidx < rdr->_paint_length); 943 paint[pidx] = 0x00000000; 944 } 945 ++a; 946 ++pidx; 947 ltx += rdr->_texture_m00; 948 lty += rdr->_texture_m10; 949 } // while (a < am)b 950 break; 951 case REPEAT_INTERPOLATE_ALPHA: 952 while (a < am) { 953 tx = (jint)(ltx >> 16); 954 ty = (jint)(lty >> 16); 955 hfrac = (jint)(ltx & 0xffff); 956 vfrac = (jint)(lty & 0xffff); 957 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 958 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 959 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 960 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 961 p00 = txtData[sidx]; 962 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 963 tx, txtWidth-1, ty, txtHeight-1); 964 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 965 if (hfrac && vfrac) { 966 cval = interpolate4points(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 967 } else if (hfrac) { 968 cval = interpolate2points(p00, pts[0], hfrac); 969 } else if (vfrac) { 970 cval = interpolate2points(p00, pts[1], vfrac); 971 } else { 972 cval = p00; 973 } 974 assert(pidx >= 0); 975 assert(pidx < rdr->_paint_length); 976 paint[pidx] = cval; 977 ++a; 978 ++pidx; 979 ltx += rdr->_texture_m00; 980 lty += rdr->_texture_m10; 981 } // while (a < am)b 982 break; 983 case NO_REPEAT_INTERPOLATE_NO_ALPHA: 984 while (a < am) { 985 tx = (jint)(ltx >> 16); 986 ty = (jint)(lty >> 16); 987 hfrac = (jint)(ltx & 0xffff); 988 vfrac = (jint)(lty & 0xffff); 989 990 inBounds = 991 isInBoundsNoRepeat(&tx, <x, txMin-1, txMax) && 992 isInBoundsNoRepeat(&ty, <y, tyMin-1, tyMax); 993 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 994 if (inBounds) { 995 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 996 p00 = txtData[sidx]; 997 998 getPointsToInterpolate(pts, txtData, sidx, txtStride, p00, 999 tx, txtWidth-1, ty, txtHeight-1); 1000 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 1001 if (hfrac && vfrac) { 1002 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 1003 } else if (hfrac) { 1004 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 1005 } else if (vfrac) { 1006 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 1007 } else { 1008 cval = p00; 1009 } 1010 assert(pidx >= 0); 1011 assert(pidx < rdr->_paint_length); 1012 paint[pidx] = cval; 1013 } else { 1014 assert(pidx >= 0); 1015 assert(pidx < rdr->_paint_length); 1016 paint[pidx] = 0x00000000; 1017 } 1018 ++a; 1019 ++pidx; 1020 ltx += rdr->_texture_m00; 1021 lty += rdr->_texture_m10; 1022 } // while (a < am)b 1023 break; 1024 case REPEAT_INTERPOLATE_NO_ALPHA: 1025 while (a < am) { 1026 tx = (jint)(ltx >> 16); 1027 ty = (jint)(lty >> 16); 1028 hfrac = (jint)(ltx & 0xffff); 1029 vfrac = (jint)(lty & 0xffff); 1030 checkBoundsRepeat(&tx, <x, txMin-1, txMax); 1031 checkBoundsRepeat(&ty, <y, tyMin-1, tyMax); 1032 PISCES_DEBUG("[%d, %d, h:%d, v:%d] ", tx, ty, hfrac, vfrac); 1033 sidx = MAX(0, ty) * txtStride + MAX(0, tx); 1034 p00 = txtData[sidx]; 1035 getPointsToInterpolateRepeat(pts, txtData, sidx, txtStride, p00, 1036 tx, txtWidth-1, ty, txtHeight-1); 1037 PISCES_DEBUG("cols[%x, %x, %x, %x] ", p00, pts[0], pts[1], pts[2]); 1038 if (hfrac && vfrac) { 1039 cval = interpolate4pointsNoAlpha(p00, pts[0], pts[1], pts[2], hfrac, vfrac); 1040 } else if (hfrac) { 1041 cval = interpolate2pointsNoAlpha(p00, pts[0], hfrac); 1042 } else if (vfrac) { 1043 cval = interpolate2pointsNoAlpha(p00, pts[1], vfrac); 1044 } else { 1045 cval = p00; 1046 } 1047 assert(pidx >= 0); 1048 assert(pidx < rdr->_paint_length); 1049 paint[pidx] = cval; 1050 ++a; 1051 ++pidx; 1052 ltx += rdr->_texture_m00; 1053 lty += rdr->_texture_m10; 1054 } // while (a < am)b 1055 break; 1056 } 1057 PISCES_DEBUG("\n"); 1058 paintOffset += paintStride; 1059 }//for 1060 } 1061 break; 1062 } 1063 } 1064 1065 void 1066 genTexturePaint(Renderer *rdr, jint height) { 1067 genTexturePaintTarget(rdr, rdr->_paint, height); 1068 } 1069 1070 void 1071 genTexturePaintMultiply(Renderer *rdr, jint height) { 1072 jint i, j, idx; 1073 jint x_from = rdr->_minTouched; 1074 jint x_to = rdr->_maxTouched; 1075 jint w = (x_to - x_from + 1); 1076 jint *paint = rdr->_paint; 1077 jint paintStride = rdr->_alphaWidth; 1078 jint pval, tval, palpha_1; 1079 jint calpha = rdr->_calpha; 1080 jint cred = rdr->_cred; 1081 jint cgreen = rdr->_cgreen; 1082 jint cblue = rdr->_cblue; 1083 jint oalpha, ored, ogreen, oblue; 1084 1085 switch (rdr->_prevPaintMode) { 1086 case PAINT_FLAT_COLOR: 1087 genTexturePaintTarget(rdr, paint, height); 1088 palpha_1 = calpha + 1; 1089 if (cred == 0xFF && cgreen == 0xFF && cblue == 0xFF) { 1090 if (calpha < 0xFF) { 1091 for (i = 0; i < height; i++) { 1092 idx = i * paintStride; 1093 for (j = 0; j < w; j++) { 1094 tval = paint[idx + j]; 1095 oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8; 1096 ored = (palpha_1 * ((tval >> 16) & 0xFF)) >> 8; 1097 ogreen = (palpha_1 * ((tval >> 8) & 0xFF)) >> 8; 1098 oblue = (palpha_1 * (tval & 0xFF)) >> 8; 1099 paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue; 1100 } 1101 } 1102 } 1103 } else { 1104 for (i = 0; i < height; i++) { 1105 idx = i * paintStride; 1106 for (j = 0; j < w; j++) { 1107 tval = paint[idx + j]; 1108 oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8; 1109 ored = ((((cred + 1) * ((tval >> 16) & 0xFF)) >> 8) * palpha_1) >> 8; 1110 ogreen = ((((cgreen + 1) * ((tval >> 8) & 0xFF)) >> 8) * palpha_1) >> 8; 1111 oblue = ((((cblue + 1) * (tval & 0xFF)) >> 8) * palpha_1) >> 8; 1112 paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue; 1113 } 1114 } 1115 } 1116 break; 1117 case PAINT_LINEAR_GRADIENT: 1118 case PAINT_RADIAL_GRADIENT: 1119 { 1120 jint *imagePaint = my_malloc(jint, w * height); 1121 if (imagePaint != NULL) { 1122 if (rdr->_prevPaintMode == PAINT_LINEAR_GRADIENT) { 1123 genLinearGradientPaint(rdr, height); 1124 } else { 1125 genRadialGradientPaint(rdr, height); 1126 } 1127 genTexturePaintTarget(rdr, imagePaint, height); 1128 for (i = 0; i < height; i++) { 1129 idx = i * paintStride; 1130 for (j = 0; j < w; j++) { 1131 pval = paint[idx + j]; 1132 tval = imagePaint[idx + j]; 1133 palpha_1 = ((pval >> 24) & 0xFF) + 1; 1134 oalpha = (palpha_1 * ((tval >> 24) & 0xFF)) >> 8; 1135 ored = ((((((pval >> 16) & 0xFF) + 1) * ((tval >> 16) & 0xFF)) >> 8) * palpha_1) >> 8; 1136 ogreen = ((((((pval >> 8) & 0xFF) + 1) * ((tval >> 8) & 0xFF)) >> 8) * palpha_1) >> 8; 1137 oblue = (((((pval & 0xFF) + 1) * (tval & 0xFF)) >> 8) * palpha_1) >> 8; 1138 paint[idx + j] = (oalpha << 24) | (ored << 16) | (ogreen << 8) | oblue; 1139 } 1140 } 1141 my_free(imagePaint); 1142 } 1143 } 1144 break; 1145 } 1146 } 1147