11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkXfermode.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// idea for higher precision blends in xfer procs (and slightly faster)
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// see DstATop as a probable caller
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(a <= 255);
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(b <= 255);
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(c <= 255);
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(d <= 255);
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned result = (prod + (prod >> 8)) >> 8;
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(result <= 255);
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return result;
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
30fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reedstatic inline unsigned saturated_add(unsigned a, unsigned b) {
31eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed    SkASSERT(a <= 255);
32eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed    SkASSERT(b <= 255);
33eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed    unsigned sum = a + b;
34eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed    if (sum > 255) {
35eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed        sum = 255;
36eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed    }
37eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed    return sum;
38eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed}
39eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed
40fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reedstatic inline int clamp_signed_byte(int n) {
419f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (n < 0) {
429f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        n = 0;
439f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else if (n > 255) {
449f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        n = 255;
459f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
469f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return n;
479f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
489f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
49fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reedstatic inline int clamp_div255round(int prod) {
509f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (prod <= 0) {
519f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return 0;
529f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else if (prod >= 255*255) {
539f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return 255;
549f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else {
559f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return SkDiv255Round(prod);
569f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
579f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
589f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
59fadb93e0b43c7451032c46f3c58a1effa9d681b3Mike Reedstatic inline int clamp_max(int value, int max) {
609f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (value > max) {
619f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        value = max;
629f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
639f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return value;
649f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
659f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kClear_Mode,    //!< [0, 0]
6940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
7040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return 0;
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kSrc_Mode,      //!< [Sa, Sc]
7440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
7540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return src;
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kDst_Mode,      //!< [Da, Dc]
7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
8040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return dst;
8140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
8540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#if 0
8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // this is the old, more-correct way, but it doesn't guarantee that dst==255
8740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // will always stay opaque
8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#else
9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // this is slightly faster, but more importantly guarantees that dst==255
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // will always stay opaque
9240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
9340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // this is the reverse of srcover, just flipping src and dst
9940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // see srcover's comment about the 256 for opaqueness guarantees
10040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
10140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
10940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned sa = SkGetPackedA32(src);
12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned da = SkGetPackedA32(dst);
12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned isa = 255 - sa;
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(da,
13040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
13940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned sa = SkGetPackedA32(src);
14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned da = SkGetPackedA32(dst);
14240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned ida = 255 - da;
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(sa,
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
15540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned sa = SkGetPackedA32(src);
15640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned da = SkGetPackedA32(dst);
15740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned isa = 255 - sa;
15840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned ida = 255 - da;
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
16140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
16240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
16340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
16440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
16540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
16640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
16740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
17040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
17140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kPlus_Mode
17240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
17340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
17440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
17540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
17640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
17740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kMultiply_Mode
18140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
18240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
18340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
18440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
18540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
18640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
18740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1899f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed// kScreen_Mode
1909f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic inline int srcover_byte(int a, int b) {
1919f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return a + b - SkAlphaMulAlpha(a, b);
1929f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
1939f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
1949f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
1959f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
1969f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
1979f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
1989f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return SkPackARGB32(a, r, g, b);
1999f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2009f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
2019f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed// kOverlay_Mode
2029f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic inline int overlay_byte(int sc, int dc, int sa, int da) {
2039f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int tmp = sc * (255 - da) + dc * (255 - sa);
2049f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int rc;
2059f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (2 * dc <= da) {
2069f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        rc = 2 * sc * dc;
2079f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else {
2089f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        rc = sa * da - 2 * (da - dc) * (sa - sc);
2099f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
2109f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return clamp_div255round(rc + tmp);
2119f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2129f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
2139f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int sa = SkGetPackedA32(src);
2149f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int da = SkGetPackedA32(dst);
2159f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int a = srcover_byte(sa, da);
2169f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2179f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2189f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
2199f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return SkPackARGB32(a, r, g, b);
2209f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2219f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
2229f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed// kDarken_Mode
2239f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic inline int darken_byte(int sc, int dc, int sa, int da) {
2249f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int sd = sc * da;
2259f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int ds = dc * sa;
2269f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (sd < ds) {
2279f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        // srcover
2289f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return sc + dc - SkDiv255Round(ds);
2299f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else {
2309f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        // dstover
2319f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return dc + sc - SkDiv255Round(sd);
2329f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
2339f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
2359f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int sa = SkGetPackedA32(src);
2369f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int da = SkGetPackedA32(dst);
2379f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int a = srcover_byte(sa, da);
2389f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2399f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2409f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
2419f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return SkPackARGB32(a, r, g, b);
2429f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2449f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed// kLighten_Mode
2459f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic inline int lighten_byte(int sc, int dc, int sa, int da) {
2469f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int sd = sc * da;
2479f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int ds = dc * sa;
2489f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (sd > ds) {
2499f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        // srcover
2509f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return sc + dc - SkDiv255Round(ds);
2519f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else {
2529f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        // dstover
2539f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        return dc + sc - SkDiv255Round(sd);
2549f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
2559f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2569f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
2579f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int sa = SkGetPackedA32(src);
2589f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int da = SkGetPackedA32(dst);
2599f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int a = srcover_byte(sa, da);
2609f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
2619f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
2629f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
2639f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    return SkPackARGB32(a, r, g, b);
2649f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2669f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed// kColorDodge_Mode
2679f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic inline int colordodge_byte(int sc, int dc, int sa, int da) {
2689f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int diff = sa - sc;
2699f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    int rc;
2709f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if (0 == diff) {
2719f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
2729f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        rc = SkDiv255Round(rc);
2739f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    } else {
2749f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        int tmp = (dc * sa << 15) / (da * diff);
2759f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        rc = SkDiv255Round(sa * da) * tmp >> 15;
2769f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        // don't clamp here, since we'll do it in our modeproc
2779f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
27840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return rc;
27940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
28040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
28140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // added to avoid div-by-zero in colordodge_byte
28240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (0 == dst) {
28340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return src;
28440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
28540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
28640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int sa = SkGetPackedA32(src);
28740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int da = SkGetPackedA32(dst);
28840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = srcover_byte(sa, da);
28940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
29040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
29140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
29240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    r = clamp_max(r, a);
29340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    g = clamp_max(g, a);
29440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    b = clamp_max(b, a);
29540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
29640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
29740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
29840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kColorBurn_Mode
29940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline int colorburn_byte(int sc, int dc, int sa, int da) {
30040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int rc;
30140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (dc == da && 0 == sc) {
30240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = sa * da + dc * (255 - sa);
30340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else if (0 == sc) {
30440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return SkAlphaMulAlpha(dc, 255 - sa);
30540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
30640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        int tmp = (sa * (da - dc) * 256) / (sc * da);
30740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (tmp > 256) {
30840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            tmp = 256;
30940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
31040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        int tmp2 = sa * da;
31140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
31240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
31340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkDiv255Round(rc);
31440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
31540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
31640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // added to avoid div-by-zero in colorburn_byte
31740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (0 == dst) {
31840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return src;
31940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
32035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
32140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int sa = SkGetPackedA32(src);
32240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int da = SkGetPackedA32(dst);
32340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = srcover_byte(sa, da);
32440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
32540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
32640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
32740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
32840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
32940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
33040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kHardLight_Mode
33140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline int hardlight_byte(int sc, int dc, int sa, int da) {
33240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int rc;
33340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (2 * sc <= sa) {
33440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = 2 * sc * dc;
33540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
33640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = sa * da - 2 * (da - dc) * (sa - sc);
33740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
33840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
33940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
34040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
34140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int sa = SkGetPackedA32(src);
34240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int da = SkGetPackedA32(dst);
34340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = srcover_byte(sa, da);
34440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
34540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
34640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
34740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
34840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
34940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
35040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// returns 255 * sqrt(n/255)
35140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic U8CPU sqrt_unit_byte(U8CPU n) {
35240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkSqrtBits(n, 15+4);
35340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
35440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
35540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kSoftLight_Mode
35640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline int softlight_byte(int sc, int dc, int sa, int da) {
35740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int m = da ? dc * 256 / da : 0;
35840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int rc;
35940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (2 * sc <= sa) {
36040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
36140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else if (4 * dc <= da) {
36240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
36340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
36440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
36540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        int tmp = sqrt_unit_byte(m) - m;
36640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
36740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
36840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
36940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
37040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
37140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int sa = SkGetPackedA32(src);
37240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int da = SkGetPackedA32(dst);
37340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = srcover_byte(sa, da);
37440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
37540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
37640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
37740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
37840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
37940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
38040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kDifference_Mode
38140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline int difference_byte(int sc, int dc, int sa, int da) {
38240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int tmp = SkMin32(sc * da, dc * sa);
38340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
38440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
38540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
38640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int sa = SkGetPackedA32(src);
38740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int da = SkGetPackedA32(dst);
38840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = srcover_byte(sa, da);
38940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
39040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
39140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
39240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
39340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
39440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
39540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger// kExclusion_Mode
39640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline int exclusion_byte(int sc, int dc, int sa, int da) {
39740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // this equations is wacky, wait for SVG to confirm it
39840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
39940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return clamp_div255round(r);
40040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
40140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
40240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int sa = SkGetPackedA32(src);
40340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int da = SkGetPackedA32(dst);
40440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int a = srcover_byte(sa, da);
40540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
40640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
40740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
40840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return SkPackARGB32(a, r, g, b);
40940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
41040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
41140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstruct ProcCoeff {
41240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermodeProc      fProc;
41340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermode::Coeff   fSC;
41440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermode::Coeff   fDC;
41540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
41640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
41740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
41840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
41940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const ProcCoeff gProcCoeffs[] = {
42040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
42140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
42240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
42340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
42440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
42540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
42640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
42740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
42840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
42940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
43040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
43140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
43240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
43387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
43487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    { multiply_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
43540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
43640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
43740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
43840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
43940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
44640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
44740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
44840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
44940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerbool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
45040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return false;
45140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
45240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
45340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerbool SkXfermode::asMode(Mode* mode) {
45435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return false;
45540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
45640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
45740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) {
45840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // no-op. subclasses should override this
45940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return dst;
46040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
46140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
4631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const SkPMColor* SK_RESTRICT src, int count,
4641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const SkAlpha* SK_RESTRICT aa) {
46540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
46640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
46740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == aa) {
46840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
46940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            dst[i] = this->xferColor(src[i], dst[i]);
47040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
47140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
47240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
47340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            unsigned a = aa[i];
47440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (0 != a) {
47540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor dstC = dst[i];
47640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor C = this->xferColor(src[i], dstC);
47740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0xFF != a) {
47840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    C = SkFourByteInterp(C, dstC, a);
47940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
48040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = C;
48140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
48240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
48340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
48440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
48540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkXfermode::xfer16(uint16_t* dst,
4871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const SkPMColor* SK_RESTRICT src, int count,
4881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const SkAlpha* SK_RESTRICT aa) {
48940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
49040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
49140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == aa) {
49240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
49340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
49440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
49540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
49640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
49740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
49840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            unsigned a = aa[i];
49940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (0 != a) {
50040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
50140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor C = this->xferColor(src[i], dstC);
50240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0xFF != a) {
50340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    C = SkFourByteInterp(C, dstC, a);
50440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
50540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = SkPixel32ToPixel16_ToU16(C);
50640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
50740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
50840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
50940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
51040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
5121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                          const SkPMColor* SK_RESTRICT src, int count,
5131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                          const SkAlpha* SK_RESTRICT aa)
51440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger{
51540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
51635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
51740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == aa) {
51840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
51940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
52040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
52140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
52240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
52340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
52440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            unsigned a = aa[i];
52540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (0 != a) {
52640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
52740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor C = this->xferColor(src[i], dstC);
52840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0xFF != a) {
52940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    C = SkFourByteInterp(C, dstC, a);
53040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
53140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = SkPixel32ToPixel4444(C);
53240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
53340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
53440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
53540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
53640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
53840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        const SkPMColor src[], int count,
5391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                        const SkAlpha* SK_RESTRICT aa)
54040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger{
54140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
54240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
54340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == aa) {
54440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
54540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
54640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            dst[i] = SkToU8(SkGetPackedA32(res));
54740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
54840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
54940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int i = count - 1; i >= 0; --i) {
55040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            unsigned a = aa[i];
55140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (0 != a) {
55240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkAlpha dstA = dst[i];
55340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                unsigned A = SkGetPackedA32(this->xferColor(src[i],
55440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
55540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0xFF != a) {
55640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
55740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
55840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = SkToU8(A);
55940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
56040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
56140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
56240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
56340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
56440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
56540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
5671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const SkPMColor* SK_RESTRICT src, int count,
5681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const SkAlpha* SK_RESTRICT aa) {
56940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
57040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
57140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermodeProc proc = fProc;
57240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
57340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL != proc) {
57440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (NULL == aa) {
57540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
57640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = proc(src[i], dst[i]);
57740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
57840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
57940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
58040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                unsigned a = aa[i];
58140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0 != a) {
58240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor dstC = dst[i];
58340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor C = proc(src[i], dstC);
58440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    if (a != 0xFF) {
58540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        C = SkFourByteInterp(C, dstC, a);
58640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    }
58740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    dst[i] = C;
58840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
58940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
59040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
59140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
59240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
59340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
5951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const SkPMColor* SK_RESTRICT src, int count,
5961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const SkAlpha* SK_RESTRICT aa) {
59740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
59840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
59940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermodeProc proc = fProc;
60040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
60140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL != proc) {
60240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (NULL == aa) {
60340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
60440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
60540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
60640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
60740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
60840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
60940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                unsigned a = aa[i];
61040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0 != a) {
61140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
61240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor C = proc(src[i], dstC);
61340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    if (0xFF != a) {
61440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        C = SkFourByteInterp(C, dstC, a);
61540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    }
61640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    dst[i] = SkPixel32ToPixel16_ToU16(C);
61740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
61840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
61940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
62040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
6241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              const SkPMColor* SK_RESTRICT src, int count,
6251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              const SkAlpha* SK_RESTRICT aa) {
62640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
62735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
62840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermodeProc proc = fProc;
6290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
63040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL != proc) {
63140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (NULL == aa) {
63240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
63340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
63440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
63540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
63640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
63740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
63840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                unsigned a = aa[i];
63940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0 != a) {
64040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
64140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor C = proc(src[i], dstC);
64240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    if (0xFF != a) {
64340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        C = SkFourByteInterp(C, dstC, a);
64440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    }
64540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    dst[i] = SkPixel32ToPixel4444(C);
64640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
64740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
6489f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        }
6499f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
6509f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed}
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
6531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const SkPMColor* SK_RESTRICT src, int count,
6541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            const SkAlpha* SK_RESTRICT aa) {
65540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(dst && src && count >= 0);
65640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
65740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkXfermodeProc proc = fProc;
65840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
65940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL != proc) {
66040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (NULL == aa) {
66140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
66240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
66340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                dst[i] = SkToU8(SkGetPackedA32(res));
66440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
66540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
66640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            for (int i = count - 1; i >= 0; --i) {
66740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                unsigned a = aa[i];
66840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                if (0 != a) {
66940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkAlpha dstA = dst[i];
67040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
67140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    unsigned A = SkGetPackedA32(res);
67240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    if (0xFF != a) {
67340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
67440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    }
67540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                    dst[i] = SkToU8(A);
67640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                }
67740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
67840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
6799f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    }
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
68140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
68240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
68340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        : SkXfermode(buffer) {
6841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // Might be a NULL if the Xfermode is recorded using the CrossProcess flag
68540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    fProc = (SkXfermodeProc)buffer.readFunctionPtr();
6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
68840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
6891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (buffer.isCrossProcess()) {
6901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // function pointer is only valid in the current process. Write a NULL
6911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // so it can't be accidentally used
6921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        buffer.writeFunctionPtr(NULL);
6931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
6941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        buffer.writeFunctionPtr((void*)fProc);
6951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
69840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
69940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
7009f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
70140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerclass SkProcCoeffXfermode : public SkProcXfermode {
70240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic:
70335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
70435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            : INHERITED(rec.fProc) {
70535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fMode = mode;
70635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // these may be valid, or may be CANNOT_USE_COEFF
70735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fSrcCoeff = rec.fSC;
70835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fDstCoeff = rec.fDC;
70940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
71035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
71135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    virtual bool asMode(Mode* mode) {
71235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (mode) {
71335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            *mode = fMode;
71435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
71535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return true;
71635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
71735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
71840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual bool asCoeff(Coeff* sc, Coeff* dc) {
71935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (CANNOT_USE_COEFF == fSrcCoeff) {
72035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            return false;
72135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
72235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
72340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (sc) {
72440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            *sc = fSrcCoeff;
72540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
72640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (dc) {
72740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            *dc = fDstCoeff;
72840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
72940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return true;
73040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
73135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
73240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual Factory getFactory() { return CreateProc; }
73340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
73440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        this->INHERITED::flatten(buffer);
73535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        buffer.write32(fMode);
73640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
73740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
73835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
73935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return SkNEW_ARGS(SkProcCoeffXfermode, (buffer));
74035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
74135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
74240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprotected:
74340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
74440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            : INHERITED(buffer) {
74535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fMode = (SkXfermode::Mode)buffer.readU32();
7461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) {
7484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            fSrcCoeff = (Coeff)buffer.readU32();
7494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            fDstCoeff = (Coeff)buffer.readU32();
7504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return;
7514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
7524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
7531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const ProcCoeff& rec = gProcCoeffs[fMode];
7541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // these may be valid, or may be CANNOT_USE_COEFF
7551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fSrcCoeff = rec.fSC;
7561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fDstCoeff = rec.fDC;
7571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // now update our function-ptr in the super class
7581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->INHERITED::setProc(rec.fProc);
75940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
76035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
76140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprivate:
76235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    Mode    fMode;
76340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Coeff   fSrcCoeff, fDstCoeff;
76435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
76540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
76640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    typedef SkProcXfermode INHERITED;
76740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
768eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed
7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
7700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkClearXfermode : public SkProcCoeffXfermode {
7720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
77335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
7740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
7761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
7771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
7800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return SkNEW_ARGS(SkClearXfermode, (buffer));
7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
78235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
78335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerprivate:
78435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkClearXfermode(SkFlattenableReadBuffer& buffer)
78535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        : SkProcCoeffXfermode(buffer) {}
78635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
7870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
7880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
7901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkPMColor* SK_RESTRICT, int count,
7911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkAlpha* SK_RESTRICT aa) {
7921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst && count >= 0);
7930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == aa) {
7951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        memset(dst, 0, count << 2);
7961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
7971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
7981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned a = aa[i];
7991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (0xFF == a) {
8001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dst[i] = 0;
8011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else if (a != 0) {
8021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
8071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
8081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkPMColor* SK_RESTRICT, int count,
8091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkAlpha* SK_RESTRICT aa) {
8101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst && count >= 0);
8110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == aa) {
8131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        memset(dst, 0, count);
8141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
8151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
8161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned a = aa[i];
8171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (0xFF == a) {
8181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dst[i] = 0;
8191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else if (0 != a) {
8201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
8210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
82535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
8271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerclass SkSrcXfermode : public SkProcCoeffXfermode {
8291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerpublic:
8301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
8311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
8331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
8341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
8350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
8370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return SkNEW_ARGS(SkSrcXfermode, (buffer));
8380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
83935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
84035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerprivate:
84135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
84235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        : SkProcCoeffXfermode(buffer) {}
84335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
8450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
8471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const SkPMColor* SK_RESTRICT src, int count,
8481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const SkAlpha* SK_RESTRICT aa) {
8491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst && src && count >= 0);
8501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == aa) {
8521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        memcpy(dst, src, count << 2);
8531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
8541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
8551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned a = aa[i];
8561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (a == 0xFF) {
8571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dst[i] = src[i];
8581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else if (a != 0) {
8591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                dst[i] = SkFourByteInterp(src[i], dst[i], a);
8601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
8611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
8621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
86435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
8661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const SkPMColor* SK_RESTRICT src, int count,
8671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const SkAlpha* SK_RESTRICT aa) {
8681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst && src && count >= 0);
86935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL == aa) {
8711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
8721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            dst[i] = SkToU8(SkGetPackedA32(src[i]));
8730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
8751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
8761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            unsigned a = aa[i];
8771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (0 != a) {
8781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                unsigned srcA = SkGetPackedA32(src[i]);
8791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                if (a == 0xFF) {
8801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    dst[i] = SkToU8(srcA);
8811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                } else {
8821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
8831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                }
8841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
8850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
88835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger////////////////////////////////////////////////////////////////////////////////////
8901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerclass SkDstInXfermode : public SkProcCoeffXfermode {
8921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerpublic:
8931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
8941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
8961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
89735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
8990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return SkNEW_ARGS(SkDstInXfermode, (buffer));
9000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
90135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
90235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerprivate:
90335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
90435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef SkProcCoeffXfermode INHERITED;
9060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
9070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
9091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkPMColor* SK_RESTRICT src, int count,
9101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkAlpha* SK_RESTRICT aa) {
9111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst && src);
91235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (count <= 0) {
9141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return;
9151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL != aa) {
9171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return this->INHERITED::xfer32(dst, src, count, aa);
9181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
91935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    do {
9211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        unsigned a = SkGetPackedA32(*src);
9221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
9231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst++;
9241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        src++;
9251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } while (--count != 0);
9261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
92735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/////////////////////////////////////////////////////////////////////////////////////////
92935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerclass SkDstOutXfermode : public SkProcCoeffXfermode {
9311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerpublic:
9321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
9331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
9351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
93635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
9380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return SkNEW_ARGS(SkDstOutXfermode, (buffer));
9390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
94035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
94135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerprivate:
94235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
94335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        : INHERITED(buffer) {}
94435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    typedef SkProcCoeffXfermode INHERITED;
9460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
9470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
9491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              const SkPMColor* SK_RESTRICT src, int count,
9501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                              const SkAlpha* SK_RESTRICT aa) {
9511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst && src);
9521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (count <= 0) {
9541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return;
9551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (NULL != aa) {
9571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return this->INHERITED::xfer32(dst, src, count, aa);
9581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    do {
9611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        unsigned a = SkGetPackedA32(*src);
9621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
9631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        dst++;
9641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        src++;
9651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } while (--count != 0);
9661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
9671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
9690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9709f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike ReedSkXfermode* SkXfermode::Create(Mode mode) {
9719f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
9729f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    SkASSERT((unsigned)mode < kModeCount);
9730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
97435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    const ProcCoeff& rec = gProcCoeffs[mode];
97535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
9760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (mode) {
9770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kClear_Mode:
97835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            return SkNEW_ARGS(SkClearXfermode, (rec));
9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kSrc_Mode:
98035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            return SkNEW_ARGS(SkSrcXfermode, (rec));
9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kSrcOver_Mode:
9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return NULL;
9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kDstIn_Mode:
98435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            return SkNEW_ARGS(SkDstInXfermode, (rec));
9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kDstOut_Mode:
98635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            return SkNEW_ARGS(SkDstOutXfermode, (rec));
98735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        default:
98835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
9890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
99235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek SollenbergerSkXfermodeProc SkXfermode::GetProc(Mode mode) {
99335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkXfermodeProc  proc = NULL;
99435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if ((unsigned)mode < kModeCount) {
99535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        proc = gProcCoeffs[mode].fProc;
99635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
99735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return proc;
99835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
99935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
100035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
100135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
100235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
100335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if ((unsigned)mode >= (unsigned)kModeCount) {
100435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // illegal mode parameter
100535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return false;
100635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
100735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
100835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    const ProcCoeff& rec = gProcCoeffs[mode];
100935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
101035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (CANNOT_USE_COEFF == rec.fSC) {
101135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return false;
101235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
101335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
101435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
101535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (src) {
101635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        *src = rec.fSC;
101735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
101835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (dst) {
101935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        *dst = rec.fDC;
102035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
102135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return true;
102235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
102335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
102435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) {
10250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == xfer) {
10260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (mode) {
10270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *mode = kSrcOver_Mode;
10280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
10300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
103135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return xfer->asMode(mode);
10320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
103435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerbool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) {
103535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (NULL == xfer) {
103635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return ModeAsCoeff(kSrcOver_Mode, src, dst);
10370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
103835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return xfer->asCoeff(src, dst);
10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkXfermode::IsMode(SkXfermode* xfer, Mode mode) {
10421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if xfer==null then the mode is srcover
10431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Mode m = kSrcOver_Mode;
10441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (xfer && !xfer->asMode(&m)) {
10451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
10461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return mode == m;
10481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
10491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
10510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////// 16bit xfermode procs
10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
10550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
10560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
10570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
10590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
10600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPixel32ToPixel16(src);
10610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
10650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
10680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_0(src));
10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
10700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
10740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPixel32ToPixel16(src);
10750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
10780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_0(src));
10790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
10800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
10830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
10840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
10850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
10880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
10890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPixel32ToPixel16(src);
10900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
10930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
10940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
10950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
10980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_0(src));
10990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
11000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
11030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned isa = 255 - SkGetPackedA32(src);
110435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
11050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPackRGB16(
11060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
11070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
11080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
11090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
11120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_0(src));
11130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
11140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
11170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
11180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPixel32ToPixel16(src);
11190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
11220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
11230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
11240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*********
11270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    darken and lighten boil down to this.
11280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    darken  = (1 - Sa) * Dc + min(Sc, Dc)
11300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    lighten = (1 - Sa) * Dc + max(Sc, Dc)
11310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (Sa == 0) these become
11330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        darken  = Dc + min(0, Dc) = 0
11340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        lighten = Dc + max(0, Dc) = Dc
11350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (Sa == 1) these become
11370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        darken  = min(Sc, Dc)
11380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        lighten = max(Sc, Dc)
11390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
11420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_0(src));
11430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return 0;
11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
11470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
11480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPackRGB16(r, g, b);
11520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
11550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_0(src));
11560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
11570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(require_255(src));
11610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
11620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
11630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPackRGB16(r, g, b);
11650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstruct Proc16Rec {
11680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkXfermodeProc16    fProc16_0;
11690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkXfermodeProc16    fProc16_255;
11700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkXfermodeProc16    fProc16_General;
11710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
11720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11739f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reedstatic const Proc16Rec gModeProcs16[] = {
11740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 NULL,                   NULL            }, // CLEAR
11750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 src_modeproc16_255,     NULL            },
11760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
11770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 srcin_modeproc16_255,   NULL            },
11800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 dstin_modeproc16_255,   NULL            },
11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 NULL,                   NULL            },// SRC_OUT
11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { dstout_modeproc16_0,  NULL,                   NULL            },
11830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
11840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 dstatop_modeproc16_255, NULL            },
11850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { NULL,                 NULL,                   NULL            }, // XOR
11869f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed
11879f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // plus
11889f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // multiply
11899f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // screen
11909f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // overlay
11919f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
11929f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
11939f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // colordodge
11949f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // colorburn
11959f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // hardlight
11969f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // softlight
11979f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // difference
11989f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    { NULL,                 NULL,                   NULL            }, // exclusion
11990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12019f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike ReedSkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
12020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkXfermodeProc16  proc16 = NULL;
12039f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed    if ((unsigned)mode < kModeCount) {
12049f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed        const Proc16Rec& rec = gModeProcs16[mode];
12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned a = SkColorGetA(srcColor);
12060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (0 == a) {
12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            proc16 = rec.fProc16_0;
12090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else if (255 == a) {
12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            proc16 = rec.fProc16_255;
12110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            proc16 = rec.fProc16_General;
12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return proc16;
12160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12181cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
12191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
12201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
12211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
12221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
12231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
12241cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1225