1 /* 2 * Copyright (c) 2000, 2008, 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 #ifndef AlphaMacros_h_Included 27 #define AlphaMacros_h_Included 28 29 #include "GraphicsPrimitiveMgr.h" 30 #include "AlphaMath.h" 31 #include "IntArgb.h" /* for "Extract...FromArgb" macros */ 32 33 #define DeclareAlphaOperands(PREFIX) \ 34 jint PREFIX ## And, PREFIX ## Xor, PREFIX ## Add; 35 36 #define ExtractAlphaOperandsFor4ByteArgb(f, PREFIX) \ 37 do { \ 38 PREFIX ## And = (f).andval; \ 39 PREFIX ## Xor = (f).xorval; \ 40 PREFIX ## Add = (jint) (f).addval - PREFIX ## Xor; \ 41 } while (0) 42 43 #define ExtractAlphaOperandsFor1ByteGray(f, PREFIX) \ 44 ExtractAlphaOperandsFor4ByteArgb(f, PREFIX) 45 46 #define ExtractAlphaOperandsFor1ShortGray(f, PREFIX) \ 47 do { \ 48 PREFIX ## And = ((f).andval << 8) + (f).andval; \ 49 PREFIX ## Xor = (f).xorval; \ 50 PREFIX ## Add = (jint) (((f).addval << 8) + (f).addval) - \ 51 PREFIX ## Xor; \ 52 } while (0) 53 54 #define ApplyAlphaOperands(PREFIX, a) \ 55 ((((a) & PREFIX ## And) ^ PREFIX ## Xor) + PREFIX ## Add) 56 57 #define FuncNeedsAlpha(PREFIX) (PREFIX ## And != 0) 58 #define FuncIsZero(PREFIX) ((PREFIX ## And | PREFIX ## Add) == 0) 59 60 typedef struct { 61 jubyte addval; 62 jubyte andval; 63 jshort xorval; 64 } AlphaOperands; 65 66 typedef struct { 67 AlphaOperands srcOps; 68 AlphaOperands dstOps; 69 } AlphaFunc; 70 71 extern AlphaFunc AlphaRules[]; 72 73 #define DEFINE_ALPHA_MASKBLIT(SRC, DST, STRATEGY) \ 74 void NAME_ALPHA_MASKBLIT(SRC, DST) \ 75 (void *dstBase, void *srcBase, \ 76 jubyte *pMask, jint maskOff, jint maskScan, \ 77 jint width, jint height, \ 78 SurfaceDataRasInfo *pDstInfo, \ 79 SurfaceDataRasInfo *pSrcInfo, \ 80 NativePrimitive *pPrim, \ 81 CompositeInfo *pCompInfo) \ 82 { \ 83 DeclareAndSetOpaqueAlphaVarFor ## STRATEGY(pathA) \ 84 DeclareAndClearAlphaVarFor ## STRATEGY(srcA) \ 85 DeclareAndClearAlphaVarFor ## STRATEGY(dstA) \ 86 DeclareAndInitExtraAlphaFor ## STRATEGY(extraA) \ 87 jint srcScan = pSrcInfo->scanStride; \ 88 jint dstScan = pDstInfo->scanStride; \ 89 jboolean loadsrc, loaddst; \ 90 SRC ## DataType *pSrc = (SRC ## DataType *) (srcBase); \ 91 DST ## DataType *pDst = (DST ## DataType *) (dstBase); \ 92 Declare ## SRC ## AlphaLoadData(SrcPix) \ 93 Declare ## DST ## AlphaLoadData(DstPix) \ 94 Declare ## DST ## StoreVars(DstWrite) \ 95 DeclareAlphaOperands(SrcOp) \ 96 DeclareAlphaOperands(DstOp) \ 97 \ 98 ExtractAlphaOperandsFor ## STRATEGY(AlphaRules[pCompInfo->rule].srcOps, \ 99 SrcOp); \ 100 ExtractAlphaOperandsFor ## STRATEGY(AlphaRules[pCompInfo->rule].dstOps, \ 101 DstOp); \ 102 loadsrc = !FuncIsZero(SrcOp) || FuncNeedsAlpha(DstOp); \ 103 loaddst = pMask || !FuncIsZero(DstOp) || FuncNeedsAlpha(SrcOp); \ 104 \ 105 Init ## SRC ## AlphaLoadData(SrcPix, pSrcInfo); \ 106 Init ## DST ## AlphaLoadData(DstPix, pDstInfo); \ 107 srcScan -= width * SRC ## PixelStride; \ 108 dstScan -= width * DST ## PixelStride; \ 109 maskScan -= width; \ 110 if (pMask) { \ 111 pMask += maskOff; \ 112 } \ 113 \ 114 Init ## DST ## StoreVarsY(DstWrite, pDstInfo); \ 115 do { \ 116 jint w = width; \ 117 Init ## DST ## StoreVarsX(DstWrite, pDstInfo); \ 118 do { \ 119 DeclareAlphaVarFor ## STRATEGY(resA) \ 120 DeclareCompVarsFor ## STRATEGY(res) \ 121 DeclareAlphaVarFor ## STRATEGY(srcF) \ 122 DeclareAlphaVarFor ## STRATEGY(dstF) \ 123 \ 124 if (pMask) { \ 125 pathA = *pMask++; \ 126 if (!pathA) { \ 127 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 128 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 129 Next ## DST ## StoreVarsX(DstWrite); \ 130 continue; \ 131 } \ 132 PromoteByteAlphaFor ## STRATEGY(pathA); \ 133 } \ 134 if (loadsrc) { \ 135 LoadAlphaFrom ## SRC ## For ## STRATEGY(pSrc, SrcPix, src); \ 136 srcA = MultiplyAlphaFor ## STRATEGY(extraA, srcA); \ 137 } \ 138 if (loaddst) { \ 139 LoadAlphaFrom ## DST ## For ## STRATEGY(pDst, DstPix, dst); \ 140 } \ 141 srcF = ApplyAlphaOperands(SrcOp, dstA); \ 142 dstF = ApplyAlphaOperands(DstOp, srcA); \ 143 if (pathA != MaxValFor ## STRATEGY) { \ 144 srcF = MultiplyAlphaFor ## STRATEGY(pathA, srcF); \ 145 dstF = MaxValFor ## STRATEGY - pathA + \ 146 MultiplyAlphaFor ## STRATEGY(pathA, dstF); \ 147 } \ 148 if (srcF) { \ 149 resA = MultiplyAlphaFor ## STRATEGY(srcF, srcA); \ 150 if (!(SRC ## IsPremultiplied)) { \ 151 srcF = resA; \ 152 } else { \ 153 srcF = MultiplyAlphaFor ## STRATEGY(srcF, extraA); \ 154 } \ 155 if (srcF) { \ 156 /* assert(loadsrc); */ \ 157 Postload ## STRATEGY ## From ## SRC(pSrc, SrcPix, res); \ 158 if (srcF != MaxValFor ## STRATEGY) { \ 159 MultiplyAndStore ## STRATEGY ## Comps(res, \ 160 srcF, res); \ 161 } \ 162 } else { \ 163 if (dstF == MaxValFor ## STRATEGY) { \ 164 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 165 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 166 Next ## DST ## StoreVarsX(DstWrite); \ 167 continue; \ 168 } \ 169 Set ## STRATEGY ## CompsToZero(res); \ 170 } \ 171 } else { \ 172 if (dstF == MaxValFor ## STRATEGY) { \ 173 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 174 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 175 Next ## DST ## StoreVarsX(DstWrite); \ 176 continue; \ 177 } \ 178 resA = 0; \ 179 Set ## STRATEGY ## CompsToZero(res); \ 180 } \ 181 if (dstF) { \ 182 dstA = MultiplyAlphaFor ## STRATEGY(dstF, dstA); \ 183 if (!(DST ## IsPremultiplied)) { \ 184 dstF = dstA; \ 185 } \ 186 resA += dstA; \ 187 if (dstF) { \ 188 DeclareCompVarsFor ## STRATEGY(tmp) \ 189 /* assert(loaddst); */ \ 190 Postload ## STRATEGY ## From ## DST(pDst, DstPix, tmp); \ 191 if (dstF != MaxValFor ## STRATEGY) { \ 192 MultiplyAndStore ## STRATEGY ## Comps(tmp, \ 193 dstF, tmp); \ 194 } \ 195 Store ## STRATEGY ## CompsUsingOp(res, +=, tmp); \ 196 } \ 197 } \ 198 if (!(DST ## IsPremultiplied) && resA && \ 199 resA < MaxValFor ## STRATEGY) \ 200 { \ 201 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 202 } \ 203 Store ## DST ## From ## STRATEGY ## Comps(pDst, DstWrite, \ 204 0, res); \ 205 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 206 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 207 Next ## DST ## StoreVarsX(DstWrite); \ 208 } while (--w > 0); \ 209 pSrc = PtrAddBytes(pSrc, srcScan); \ 210 pDst = PtrAddBytes(pDst, dstScan); \ 211 Next ## DST ## StoreVarsY(DstWrite); \ 212 if (pMask) { \ 213 pMask = PtrAddBytes(pMask, maskScan); \ 214 } \ 215 } while (--height > 0); \ 216 } 217 218 /* REMIND: This macro is as yet, untested */ 219 #define DEFINE_SRC_MASKBLIT(SRC, DST, STRATEGY) \ 220 void NAME_SRC_MASKBLIT(SRC, DST) \ 221 (void *dstBase, void *srcBase, \ 222 jubyte *pMask, jint maskOff, jint maskScan, \ 223 jint width, jint height, \ 224 SurfaceDataRasInfo *pDstInfo, \ 225 SurfaceDataRasInfo *pSrcInfo, \ 226 NativePrimitive *pPrim, \ 227 CompositeInfo *pCompInfo) \ 228 { \ 229 DeclareAndInitExtraAlphaFor ## STRATEGY(extraA) \ 230 jint srcScan = pSrcInfo->scanStride; \ 231 jint dstScan = pDstInfo->scanStride; \ 232 SRC ## DataType *pSrc = (SRC ## DataType *) (srcBase); \ 233 DST ## DataType *pDst = (DST ## DataType *) (dstBase); \ 234 Declare ## SRC ## AlphaLoadData(SrcPix) \ 235 Declare ## DST ## AlphaLoadData(DstPix) \ 236 Declare ## DST ## StoreVars(DstWrite) \ 237 \ 238 Init ## SRC ## AlphaLoadData(SrcPix, pSrcInfo); \ 239 Init ## DST ## AlphaLoadData(DstPix, pDstInfo); \ 240 srcScan -= width * SRC ## PixelStride; \ 241 dstScan -= width * DST ## PixelStride; \ 242 \ 243 Init ## DST ## StoreVarsY(DstWrite, pDstInfo); \ 244 if (pMask) { \ 245 maskScan -= width; \ 246 pMask += maskOff; \ 247 do { \ 248 jint w = width; \ 249 Init ## DST ## StoreVarsX(DstWrite, pDstInfo); \ 250 do { \ 251 DeclareAlphaVarFor ## STRATEGY(resA) \ 252 DeclareCompVarsFor ## STRATEGY(res) \ 253 DeclareAlphaVarFor ## STRATEGY(srcF) \ 254 DeclareAlphaVarFor ## STRATEGY(dstF) \ 255 DeclareAndInitPathAlphaFor ## STRATEGY(pathA) \ 256 \ 257 if (pathA) { \ 258 LoadAlphaFrom ## SRC ## For ## STRATEGY(pSrc, \ 259 SrcPix, res); \ 260 resA = MultiplyAlphaFor ## STRATEGY(extraA, resA); \ 261 if (SRC ## IsPremultiplied) { \ 262 srcF = extraA; \ 263 } else { \ 264 srcF = resA; \ 265 } \ 266 Postload ## STRATEGY ## From ## SRC(pSrc, SrcPix, res); \ 267 if (pathA < 0xff) { \ 268 DeclareAlphaVarFor ## STRATEGY(dstA) \ 269 DeclareCompVarsFor ## STRATEGY(dst) \ 270 PromoteByteAlphaFor ## STRATEGY(pathA); \ 271 srcF = MultiplyAlphaFor ## STRATEGY(pathA, srcF); \ 272 dstF = MaxValFor ## STRATEGY - pathA; \ 273 LoadAlphaFrom ## DST ## For ## STRATEGY(pDst, \ 274 DstPix, \ 275 dst); \ 276 dstA = MultiplyAlphaFor ## STRATEGY(dstF, dstA) \ 277 if (!(DST ## IsPremultiplied)) { \ 278 dstF = dstA; \ 279 } \ 280 Postload ## STRATEGY ## From ## DST(pDst, DstPix, \ 281 dst); \ 282 resA = dstA + \ 283 MultiplyAlphaFor ## STRATEGY(pathA, resA); \ 284 MultMultAddAndStore ## STRATEGY ## Comps(res, \ 285 dstF, dst, \ 286 srcF, res); \ 287 } else if (srcF < MaxValFor ## STRATEGY) { \ 288 MultiplyAndStore ## STRATEGY ## Comps(res, \ 289 srcF, src); \ 290 } \ 291 if (!(DST ## IsPremultiplied) && resA && \ 292 resA < MaxValFor ## STRATEGY) \ 293 { \ 294 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 295 } \ 296 Store ## DST ## From ## STRATEGY ## Comps(pDst, DstWrite,\ 297 0, res);\ 298 } \ 299 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 300 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 301 Next ## DST ## StoreVarsX(DstWrite); \ 302 } while (--w > 0); \ 303 pSrc = PtrAddBytes(pSrc, srcScan); \ 304 pDst = PtrAddBytes(pDst, dstScan); \ 305 Next ## DST ## StoreVarsY(DstWrite); \ 306 pMask = PtrAddBytes(pMask, maskScan); \ 307 } while (--height > 0); \ 308 } else /* pMask == 0 */ { \ 309 do { \ 310 jint w = width; \ 311 Init ## DST ## StoreVarsX(DstWrite, pDstInfo); \ 312 do { \ 313 DeclareAlphaVarFor ## STRATEGY(resA) \ 314 DeclareCompVarsFor ## STRATEGY(res) \ 315 DeclareAlphaVarFor ## STRATEGY(srcF) \ 316 \ 317 LoadAlphaFrom ## SRC ## For ## STRATEGY(pSrc, SrcPix, res); \ 318 resA = MultiplyAlphaFor ## STRATEGY(extraA, resA); \ 319 if (SRC ## IsPremultiplied) { \ 320 srcF = extraA; \ 321 } else { \ 322 srcF = resA; \ 323 } \ 324 Postload ## STRATEGY ## From ## SRC(pSrc, SrcPix, res); \ 325 if (srcF < MaxValFor ## STRATEGY) { \ 326 MultiplyAndStore ## STRATEGY ## Comps(res, srcF, src); \ 327 } \ 328 if (!(DST ## IsPremultiplied) && resA && \ 329 resA < MaxValFor ## STRATEGY) \ 330 { \ 331 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 332 } \ 333 Store ## DST ## From ## STRATEGY ## Comps(pDst, DstWrite, \ 334 0, res); \ 335 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 336 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 337 Next ## DST ## StoreVarsX(DstWrite); \ 338 } while (--w > 0); \ 339 pSrc = PtrAddBytes(pSrc, srcScan); \ 340 pDst = PtrAddBytes(pDst, dstScan); \ 341 Next ## DST ## StoreVarsY(DstWrite); \ 342 } while (--height > 0); \ 343 } \ 344 } 345 346 #define DEFINE_SRCOVER_MASKBLIT(SRC, DST, STRATEGY) \ 347 void NAME_SRCOVER_MASKBLIT(SRC, DST) \ 348 (void *dstBase, void *srcBase, \ 349 jubyte *pMask, jint maskOff, jint maskScan, \ 350 jint width, jint height, \ 351 SurfaceDataRasInfo *pDstInfo, \ 352 SurfaceDataRasInfo *pSrcInfo, \ 353 NativePrimitive *pPrim, \ 354 CompositeInfo *pCompInfo) \ 355 { \ 356 DeclareAndInitExtraAlphaFor ## STRATEGY(extraA) \ 357 jint srcScan = pSrcInfo->scanStride; \ 358 jint dstScan = pDstInfo->scanStride; \ 359 SRC ## DataType *pSrc = (SRC ## DataType *) (srcBase); \ 360 DST ## DataType *pDst = (DST ## DataType *) (dstBase); \ 361 Declare ## SRC ## AlphaLoadData(SrcPix) \ 362 Declare ## DST ## AlphaLoadData(DstPix) \ 363 Declare ## DST ## StoreVars(DstWrite) \ 364 \ 365 Init ## SRC ## AlphaLoadData(SrcPix, pSrcInfo); \ 366 Init ## DST ## AlphaLoadData(DstPix, pDstInfo); \ 367 srcScan -= width * SRC ## PixelStride; \ 368 dstScan -= width * DST ## PixelStride; \ 369 \ 370 Init ## DST ## StoreVarsY(DstWrite, pDstInfo); \ 371 if (pMask) { \ 372 pMask += maskOff; \ 373 maskScan -= width; \ 374 do { \ 375 jint w = width; \ 376 Init ## DST ## StoreVarsX(DstWrite, pDstInfo); \ 377 do { \ 378 DeclareAndInitPathAlphaFor ## STRATEGY(pathA) \ 379 \ 380 if (pathA) { \ 381 DeclareAlphaVarFor ## STRATEGY(resA) \ 382 DeclareCompVarsFor ## STRATEGY(res) \ 383 DeclareAlphaVarFor ## STRATEGY(srcF) \ 384 PromoteByteAlphaFor ## STRATEGY(pathA); \ 385 pathA = MultiplyAlphaFor ## STRATEGY(pathA, extraA); \ 386 LoadAlphaFrom ## SRC ## For ## STRATEGY(pSrc, \ 387 SrcPix, res); \ 388 resA = MultiplyAlphaFor ## STRATEGY(pathA, resA); \ 389 if (resA) { \ 390 if (SRC ## IsPremultiplied) { \ 391 srcF = pathA; \ 392 } else { \ 393 srcF = resA; \ 394 } \ 395 Postload ## STRATEGY ## From ## SRC(pSrc, SrcPix, \ 396 res); \ 397 if (resA < MaxValFor ## STRATEGY) { \ 398 DeclareAlphaVarFor ## STRATEGY(dstA) \ 399 DeclareCompVarsFor ## STRATEGY(dst) \ 400 DeclareAndInvertAlphaVarFor ## STRATEGY(dstF, \ 401 resA) \ 402 LoadAlphaFrom ## DST ## For ## STRATEGY(pDst, \ 403 DstPix, \ 404 dst); \ 405 dstA = MultiplyAlphaFor ## STRATEGY(dstF, dstA); \ 406 if (!(DST ## IsPremultiplied)) { \ 407 dstF = dstA; \ 408 } \ 409 Postload ## STRATEGY ## From ## DST(pDst, DstPix,\ 410 dst); \ 411 resA += dstA; \ 412 MultMultAddAndStore ## STRATEGY ## Comps(res, \ 413 dstF, dst, \ 414 srcF, res);\ 415 } else if (srcF < MaxValFor ## STRATEGY) { \ 416 MultiplyAndStore ## STRATEGY ## Comps(res, \ 417 srcF, res);\ 418 } \ 419 if (!(DST ## IsOpaque) && \ 420 !(DST ## IsPremultiplied) && resA && \ 421 resA < MaxValFor ## STRATEGY) \ 422 { \ 423 DivideAndStore ## STRATEGY ## Comps(res, \ 424 res, resA); \ 425 } \ 426 Store ## DST ## From ## STRATEGY ## Comps(pDst, \ 427 DstWrite, \ 428 0, res); \ 429 } \ 430 } \ 431 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 432 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 433 Next ## DST ## StoreVarsX(DstWrite); \ 434 } while (--w > 0); \ 435 pSrc = PtrAddBytes(pSrc, srcScan); \ 436 pDst = PtrAddBytes(pDst, dstScan); \ 437 Next ## DST ## StoreVarsY(DstWrite); \ 438 pMask = PtrAddBytes(pMask, maskScan); \ 439 } while (--height > 0); \ 440 } else /* pMask == 0 */ { \ 441 do { \ 442 jint w = width; \ 443 Init ## DST ## StoreVarsX(DstWrite, pDstInfo); \ 444 do { \ 445 DeclareAlphaVarFor ## STRATEGY(resA) \ 446 DeclareCompVarsFor ## STRATEGY(res) \ 447 DeclareAlphaVarFor ## STRATEGY(srcF) \ 448 \ 449 LoadAlphaFrom ## SRC ## For ## STRATEGY(pSrc, SrcPix, res); \ 450 resA = MultiplyAlphaFor ## STRATEGY(extraA, resA); \ 451 if (resA) { \ 452 if (SRC ## IsPremultiplied) { \ 453 srcF = extraA; \ 454 } else { \ 455 srcF = resA; \ 456 } \ 457 Postload ## STRATEGY ## From ## SRC(pSrc, SrcPix, res); \ 458 if (resA < MaxValFor ## STRATEGY) { \ 459 DeclareAlphaVarFor ## STRATEGY(dstA) \ 460 DeclareCompVarsFor ## STRATEGY(dst) \ 461 DeclareAndInvertAlphaVarFor ## STRATEGY(dstF, resA) \ 462 LoadAlphaFrom ## DST ## For ## STRATEGY(pDst, \ 463 DstPix, \ 464 dst); \ 465 dstA = MultiplyAlphaFor ## STRATEGY(dstF, dstA); \ 466 if (!(DST ## IsPremultiplied)) { \ 467 dstF = dstA; \ 468 } \ 469 Postload ## STRATEGY ## From ## DST(pDst, DstPix, \ 470 dst); \ 471 resA += dstA; \ 472 MultMultAddAndStore ## STRATEGY ## Comps(res, \ 473 dstF, dst, \ 474 srcF, res); \ 475 } else if (srcF < MaxValFor ## STRATEGY) { \ 476 MultiplyAndStore ## STRATEGY ## Comps(res, \ 477 srcF, res); \ 478 } \ 479 if (!(DST ## IsOpaque) && \ 480 !(DST ## IsPremultiplied) && resA && \ 481 resA < MaxValFor ## STRATEGY) \ 482 { \ 483 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 484 } \ 485 Store ## DST ## From ## STRATEGY ## Comps(pDst, DstWrite,\ 486 0, res); \ 487 } \ 488 pSrc = PtrAddBytes(pSrc, SRC ## PixelStride); \ 489 pDst = PtrAddBytes(pDst, DST ## PixelStride); \ 490 Next ## DST ## StoreVarsX(DstWrite); \ 491 } while (--w > 0); \ 492 pSrc = PtrAddBytes(pSrc, srcScan); \ 493 pDst = PtrAddBytes(pDst, dstScan); \ 494 Next ## DST ## StoreVarsY(DstWrite); \ 495 } while (--height > 0); \ 496 } \ 497 } 498 499 #define DEFINE_ALPHA_MASKFILL(TYPE, STRATEGY) \ 500 void NAME_ALPHA_MASKFILL(TYPE) \ 501 (void *rasBase, \ 502 jubyte *pMask, jint maskOff, jint maskScan, \ 503 jint width, jint height, \ 504 jint fgColor, \ 505 SurfaceDataRasInfo *pRasInfo, \ 506 NativePrimitive *pPrim, \ 507 CompositeInfo *pCompInfo) \ 508 { \ 509 DeclareAndSetOpaqueAlphaVarFor ## STRATEGY(pathA) \ 510 DeclareAlphaVarFor ## STRATEGY(srcA) \ 511 DeclareCompVarsFor ## STRATEGY(src) \ 512 DeclareAndClearAlphaVarFor ## STRATEGY(dstA) \ 513 DeclareAlphaVarFor ## STRATEGY(dstF) \ 514 DeclareAlphaVarFor ## STRATEGY(dstFbase) \ 515 jint rasScan = pRasInfo->scanStride; \ 516 jboolean loaddst; \ 517 TYPE ## DataType *pRas = (TYPE ## DataType *) (rasBase); \ 518 Declare ## TYPE ## AlphaLoadData(DstPix) \ 519 Declare ## TYPE ## StoreVars(DstWrite) \ 520 DeclareAlphaOperands(SrcOp) \ 521 DeclareAlphaOperands(DstOp) \ 522 \ 523 Extract ## STRATEGY ## CompsAndAlphaFromArgb(fgColor, src); \ 524 if (srcA != MaxValFor ## STRATEGY) { \ 525 MultiplyAndStore ## STRATEGY ## Comps(src, srcA, src); \ 526 } \ 527 \ 528 ExtractAlphaOperandsFor ## STRATEGY(AlphaRules[pCompInfo->rule].srcOps, \ 529 SrcOp); \ 530 ExtractAlphaOperandsFor ## STRATEGY(AlphaRules[pCompInfo->rule].dstOps, \ 531 DstOp); \ 532 loaddst = pMask || !FuncIsZero(DstOp) || FuncNeedsAlpha(SrcOp); \ 533 \ 534 dstFbase = dstF = ApplyAlphaOperands(DstOp, srcA); \ 535 \ 536 Init ## TYPE ## AlphaLoadData(DstPix, pRasInfo); \ 537 rasScan -= width * TYPE ## PixelStride; \ 538 maskScan -= width; \ 539 if (pMask) { \ 540 pMask += maskOff; \ 541 } \ 542 \ 543 Init ## TYPE ## StoreVarsY(DstWrite, pRasInfo); \ 544 do { \ 545 jint w = width; \ 546 Init ## TYPE ## StoreVarsX(DstWrite, pRasInfo); \ 547 do { \ 548 DeclareAlphaVarFor ## STRATEGY(resA) \ 549 DeclareCompVarsFor ## STRATEGY(res) \ 550 DeclareAlphaVarFor ## STRATEGY(srcF) \ 551 \ 552 if (pMask) { \ 553 pathA = *pMask++; \ 554 if (!pathA) { \ 555 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 556 Next ## TYPE ## StoreVarsX(DstWrite); \ 557 continue; \ 558 } \ 559 PromoteByteAlphaFor ## STRATEGY(pathA); \ 560 dstF = dstFbase; \ 561 } \ 562 if (loaddst) { \ 563 LoadAlphaFrom ## TYPE ## For ## STRATEGY(pRas, DstPix, dst);\ 564 } \ 565 srcF = ApplyAlphaOperands(SrcOp, dstA); \ 566 if (pathA != MaxValFor ## STRATEGY) { \ 567 srcF = MultiplyAlphaFor ## STRATEGY(pathA, srcF); \ 568 dstF = MaxValFor ## STRATEGY - pathA + \ 569 MultiplyAlphaFor ## STRATEGY(pathA, dstF); \ 570 } \ 571 if (srcF) { \ 572 if (srcF == MaxValFor ## STRATEGY) { \ 573 resA = srcA; \ 574 Store ## STRATEGY ## CompsUsingOp(res, =, src); \ 575 } else { \ 576 resA = MultiplyAlphaFor ## STRATEGY(srcF, srcA); \ 577 MultiplyAndStore ## STRATEGY ## Comps(res, srcF, src); \ 578 } \ 579 } else { \ 580 if (dstF == MaxValFor ## STRATEGY) { \ 581 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 582 Next ## TYPE ## StoreVarsX(DstWrite); \ 583 continue; \ 584 } \ 585 resA = 0; \ 586 Set ## STRATEGY ## CompsToZero(res); \ 587 } \ 588 if (dstF) { \ 589 dstA = MultiplyAlphaFor ## STRATEGY(dstF, dstA); \ 590 resA += dstA; \ 591 if (TYPE ## IsPremultiplied) { \ 592 dstA = dstF; \ 593 } \ 594 if (dstA) { \ 595 DeclareCompVarsFor ## STRATEGY(tmp) \ 596 /* assert(loaddst); */ \ 597 Postload ## STRATEGY ## From ## TYPE(pRas, DstPix, tmp); \ 598 if (dstA != MaxValFor ## STRATEGY) { \ 599 MultiplyAndStore ## STRATEGY ## Comps(tmp, \ 600 dstA, tmp); \ 601 } \ 602 Store ## STRATEGY ## CompsUsingOp(res, +=, tmp); \ 603 } \ 604 } \ 605 if (!(TYPE ## IsPremultiplied) && resA && \ 606 resA < MaxValFor ## STRATEGY) \ 607 { \ 608 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 609 } \ 610 Store ## TYPE ## From ## STRATEGY ## Comps(pRas, DstWrite, \ 611 0, res); \ 612 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 613 Next ## TYPE ## StoreVarsX(DstWrite); \ 614 } while (--w > 0); \ 615 pRas = PtrAddBytes(pRas, rasScan); \ 616 Next ## TYPE ## StoreVarsY(DstWrite); \ 617 if (pMask) { \ 618 pMask = PtrAddBytes(pMask, maskScan); \ 619 } \ 620 } while (--height > 0); \ 621 } 622 623 #define DEFINE_SRC_MASKFILL(TYPE, STRATEGY) \ 624 void NAME_SRC_MASKFILL(TYPE) \ 625 (void *rasBase, \ 626 jubyte *pMask, jint maskOff, jint maskScan, \ 627 jint width, jint height, \ 628 jint fgColor, \ 629 SurfaceDataRasInfo *pRasInfo, \ 630 NativePrimitive *pPrim, \ 631 CompositeInfo *pCompInfo) \ 632 { \ 633 DeclareAlphaVarFor ## STRATEGY(srcA) \ 634 DeclareCompVarsFor ## STRATEGY(src) \ 635 jint rasScan = pRasInfo->scanStride; \ 636 TYPE ## DataType *pRas = (TYPE ## DataType *) (rasBase); \ 637 Declare ## TYPE ## AlphaLoadData(DstPix) \ 638 Declare ## TYPE ## StoreVars(DstWrite) \ 639 Declare ## TYPE ## BlendFillVars(DstFill) \ 640 \ 641 Extract ## STRATEGY ## CompsAndAlphaFromArgb(fgColor, src); \ 642 if (srcA == 0) { \ 643 Set ## STRATEGY ## CompsToZero(src); \ 644 Clear ## TYPE ## BlendFillVars(DstFill, fgColor); \ 645 } else { \ 646 if (!(TYPE ## IsPremultiplied)) { \ 647 Init ## TYPE ## BlendFillVarsNonPre(DstFill, fgColor, src); \ 648 } \ 649 if (srcA != MaxValFor ## STRATEGY) { \ 650 MultiplyAndStore ## STRATEGY ## Comps(src, srcA, src); \ 651 } \ 652 if (TYPE ## IsPremultiplied) { \ 653 Init ## TYPE ## BlendFillVarsPre(DstFill, fgColor, src); \ 654 } \ 655 } \ 656 \ 657 Init ## TYPE ## AlphaLoadData(DstPix, pRasInfo); \ 658 Init ## TYPE ## StoreVarsY(DstWrite, pRasInfo); \ 659 \ 660 rasScan -= width * TYPE ## PixelStride; \ 661 if (pMask) { \ 662 pMask += maskOff; \ 663 maskScan -= width; \ 664 do { \ 665 jint w = width; \ 666 Init ## TYPE ## StoreVarsX(DstWrite, pRasInfo); \ 667 do { \ 668 DeclareAlphaVarFor ## STRATEGY(resA) \ 669 DeclareCompVarsFor ## STRATEGY(res) \ 670 DeclareAlphaVarFor ## STRATEGY(dstF) \ 671 DeclareAndInitPathAlphaFor ## STRATEGY(pathA) \ 672 \ 673 if (pathA > 0) { \ 674 if (pathA == 0xff) { \ 675 /* pathA ignored here, not promoted */ \ 676 Store ## TYPE ## BlendFill(pRas, DstFill, 0, \ 677 fgColor, src); \ 678 } else { \ 679 PromoteByteAlphaFor ## STRATEGY(pathA); \ 680 dstF = MaxValFor ## STRATEGY - pathA; \ 681 LoadAlphaFrom ## TYPE ## For ## STRATEGY(pRas, \ 682 DstPix, \ 683 res); \ 684 resA = MultiplyAlphaFor ## STRATEGY(dstF, resA); \ 685 if (!(TYPE ## IsPremultiplied)) { \ 686 dstF = resA; \ 687 } \ 688 resA += MultiplyAlphaFor ## STRATEGY(pathA, srcA); \ 689 Postload ## STRATEGY ## From ## TYPE(pRas, DstPix, \ 690 res); \ 691 MultMultAddAndStore ## STRATEGY ## Comps(res, \ 692 dstF, res, \ 693 pathA, src);\ 694 if (!(TYPE ## IsPremultiplied) && resA && \ 695 resA < MaxValFor ## STRATEGY) \ 696 { \ 697 DivideAndStore ## STRATEGY ## Comps(res, \ 698 res, resA); \ 699 } \ 700 Store ## TYPE ## From ## STRATEGY ## Comps(pRas, \ 701 DstWrite, \ 702 0, res); \ 703 } \ 704 } \ 705 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 706 Next ## TYPE ## StoreVarsX(DstWrite); \ 707 } while (--w > 0); \ 708 pRas = PtrAddBytes(pRas, rasScan); \ 709 Next ## TYPE ## StoreVarsY(DstWrite); \ 710 pMask = PtrAddBytes(pMask, maskScan); \ 711 } while (--height > 0); \ 712 } else /* pMask == 0 */ { \ 713 do { \ 714 jint w = width; \ 715 Init ## TYPE ## StoreVarsX(DstWrite, pRasInfo); \ 716 do { \ 717 Store ## TYPE ## BlendFill(pRas, DstFill, 0, fgColor, src); \ 718 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 719 Next ## TYPE ## StoreVarsX(DstWrite); \ 720 } while (--w > 0); \ 721 pRas = PtrAddBytes(pRas, rasScan); \ 722 Next ## TYPE ## StoreVarsY(DstWrite); \ 723 } while (--height > 0); \ 724 } \ 725 } 726 727 #define DEFINE_SRCOVER_MASKFILL(TYPE, STRATEGY) \ 728 void NAME_SRCOVER_MASKFILL(TYPE) \ 729 (void *rasBase, \ 730 jubyte *pMask, jint maskOff, jint maskScan, \ 731 jint width, jint height, \ 732 jint fgColor, \ 733 SurfaceDataRasInfo *pRasInfo, \ 734 NativePrimitive *pPrim, \ 735 CompositeInfo *pCompInfo) \ 736 { \ 737 DeclareAlphaVarFor ## STRATEGY(srcA) \ 738 DeclareCompVarsFor ## STRATEGY(src) \ 739 jint rasScan = pRasInfo->scanStride; \ 740 TYPE ## DataType *pRas = (TYPE ## DataType *) (rasBase); \ 741 Declare ## TYPE ## AlphaLoadData(DstPix) \ 742 Declare ## TYPE ## StoreVars(DstWrite) \ 743 \ 744 Extract ## STRATEGY ## CompsAndAlphaFromArgb(fgColor, src); \ 745 if (srcA != MaxValFor ## STRATEGY) { \ 746 if (srcA == 0) { \ 747 return; \ 748 } \ 749 MultiplyAndStore ## STRATEGY ## Comps(src, srcA, src); \ 750 } \ 751 \ 752 Init ## TYPE ## AlphaLoadData(DstPix, pRasInfo); \ 753 Init ## TYPE ## StoreVarsY(DstWrite, pRasInfo); \ 754 \ 755 rasScan -= width * TYPE ## PixelStride; \ 756 if (pMask) { \ 757 pMask += maskOff; \ 758 maskScan -= width; \ 759 do { \ 760 jint w = width; \ 761 Init ## TYPE ## StoreVarsX(DstWrite, pRasInfo); \ 762 do { \ 763 DeclareAlphaVarFor ## STRATEGY(resA) \ 764 DeclareCompVarsFor ## STRATEGY(res) \ 765 DeclareAndInitPathAlphaFor ## STRATEGY(pathA) \ 766 \ 767 if (pathA > 0) { \ 768 if (pathA != 0xff) { \ 769 PromoteByteAlphaFor ## STRATEGY(pathA); \ 770 resA = MultiplyAlphaFor ## STRATEGY(pathA, srcA); \ 771 MultiplyAndStore ## STRATEGY ## Comps(res, \ 772 pathA, src); \ 773 } else { \ 774 /* pathA ignored here, not promoted */ \ 775 resA = srcA; \ 776 Store ## STRATEGY ## CompsUsingOp(res, =, src); \ 777 } \ 778 if (resA != MaxValFor ## STRATEGY) { \ 779 DeclareAndInvertAlphaVarFor ## STRATEGY(dstF, resA) \ 780 DeclareAndClearAlphaVarFor ## STRATEGY(dstA) \ 781 LoadAlphaFrom ## TYPE ## For ## STRATEGY(pRas, \ 782 DstPix, \ 783 dst); \ 784 dstA = MultiplyAlphaFor ## STRATEGY(dstF, dstA); \ 785 if (!(TYPE ## IsPremultiplied)) { \ 786 dstF = dstA; \ 787 } \ 788 resA += dstA; \ 789 if (dstF) { \ 790 DeclareCompVarsFor ## STRATEGY(tmp) \ 791 Postload ## STRATEGY ## From ## TYPE(pRas, \ 792 DstPix, \ 793 tmp); \ 794 if (dstF != MaxValFor ## STRATEGY) { \ 795 MultiplyAndStore ## STRATEGY ## Comps(tmp, \ 796 dstF, \ 797 tmp); \ 798 } \ 799 Store ## STRATEGY ## CompsUsingOp(res, +=, tmp); \ 800 } \ 801 } \ 802 if (!(TYPE ## IsOpaque) && \ 803 !(TYPE ## IsPremultiplied) && resA && \ 804 resA < MaxValFor ## STRATEGY) \ 805 { \ 806 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 807 } \ 808 Store ## TYPE ## From ## STRATEGY ## Comps(pRas, \ 809 DstWrite, 0, \ 810 res); \ 811 } \ 812 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 813 Next ## TYPE ## StoreVarsX(DstWrite); \ 814 } while (--w > 0); \ 815 pRas = PtrAddBytes(pRas, rasScan); \ 816 Next ## TYPE ## StoreVarsY(DstWrite); \ 817 pMask = PtrAddBytes(pMask, maskScan); \ 818 } while (--height > 0); \ 819 } else /* pMask == 0 */ { \ 820 do { \ 821 jint w = width; \ 822 Init ## TYPE ## StoreVarsX(DstWrite, pRasInfo); \ 823 do { \ 824 DeclareAlphaVarFor ## STRATEGY(resA) \ 825 DeclareCompVarsFor ## STRATEGY(res) \ 826 DeclareAndInvertAlphaVarFor ## STRATEGY(dstF, srcA) \ 827 \ 828 LoadAlphaFrom ## TYPE ## For ## STRATEGY(pRas, DstPix, res);\ 829 resA = MultiplyAlphaFor ## STRATEGY(dstF, resA); \ 830 if (!(TYPE ## IsPremultiplied)) { \ 831 dstF = resA; \ 832 } \ 833 resA += srcA; \ 834 Postload ## STRATEGY ## From ## TYPE(pRas, DstPix, res); \ 835 MultiplyAddAndStore ## STRATEGY ## Comps(res, \ 836 dstF, res, src); \ 837 if (!(TYPE ## IsOpaque) && \ 838 !(TYPE ## IsPremultiplied) && resA && \ 839 resA < MaxValFor ## STRATEGY) \ 840 { \ 841 DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ 842 } \ 843 Store ## TYPE ## From ## STRATEGY ## Comps(pRas, DstWrite, \ 844 0, res); \ 845 pRas = PtrAddBytes(pRas, TYPE ## PixelStride); \ 846 Next ## TYPE ## StoreVarsX(DstWrite); \ 847 } while (--w > 0); \ 848 pRas = PtrAddBytes(pRas, rasScan); \ 849 Next ## TYPE ## StoreVarsY(DstWrite); \ 850 } while (--height > 0); \ 851 } \ 852 } 853 854 855 /* 856 * The macros defined above use the following macro definitions supplied 857 * for the various surface types to manipulate pixels and pixel data. 858 * The surface-specific macros are typically supplied by header files 859 * named after the SurfaceType name (eg. IntArgb.h, ByteGray.h, etc.). 860 * 861 * In the macro names in the following definitions, the string <stype> 862 * is used as a place holder for the SurfaceType name (eg. IntArgb). The 863 * string <strategy> is a place holder for the strategy name (eg. 4ByteArgb). 864 * The macros above access these type specific macros using the ANSI 865 * CPP token concatenation operator "##". 866 * 867 * Declare<stype>AlphaLoadData Declare the variables used when an alpha 868 * value is pre-fetched to see whether or 869 * not blending needs to occur 870 * Init<stype>AlphaLoadData Initialize the aforementioned variables 871 * LoadAlphaFrom<stype>For<strategy> Load the alpha value for the given pixel 872 * into a variable used later (the strategy 873 * type determines the bit depth of the 874 * alpha value) 875 * Postload<strategy>From<stype> Load the pixel components from the given 876 * surface type into the form required by 877 * the given strategy. Typically there will 878 * be a couple macros of this variety, one 879 * for 4ByteArgb, one for 1ByteGray, one 880 * for 1ShortGray, etc. Its code is only 881 * executed when blending needs to occur. 882 * 883 * <stype>IsPremultiplied Constant specifying whether the pixel 884 * components have been premultiplied with 885 * the alpha value 886 * Declare<stype>BlendFillVars Declare the variables used when alpha 887 * blending need not occur (mask and source 888 * pixel are opaque) 889 * Clear<stype>BlendFillVars Clear the variables used in a no-blend 890 * situation (may modify argb argument) 891 * Init<stype>BlendFillVarsNonPre Initialize the variables used for a 892 * no-blending situation (this macro is for 893 * surfaces that do not have premultiplied 894 * components) (may modify argb argument) 895 * Init<stype>BlendFillVarsPre Initialize the variables used for a 896 * no-blending situation (this macro is for 897 * surfaces that have premultiplied 898 * components) (may modify argb argument) 899 * Store<stype>BlendFill Simply store the pixel for the given 900 * surface (used when blending is 901 * unnecessary) 902 * Store<stype>From<strategy>Comps Store the pixel for the given surface 903 * type after converting it from a pixel of 904 * the given strategy 905 */ 906 907 #endif /* AlphaMacros_h_Included */