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 */