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