1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
11c524e98f1edf06b53e65543f5f28217fa13b7aa9commit-bot@chromium.org#include "SkXfermode_opts_SSE2.h"
12df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org#include "SkXfermode_proccoeff.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
1497de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org#include "SkLazyPtr.h"
154b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
16140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org#include "SkReadBuffer.h"
17b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#include "SkString.h"
18cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#include "SkUtilsArm.h"
19140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org#include "SkWriteBuffer.h"
20cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org
21cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#if !SK_ARM_NEON_IS_NONE
22cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#include "SkXfermode_opts_arm_neon.h"
23cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#endif
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com#if 0
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// idea for higher precision blends in xfer procs (and slightly faster)
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// see DstATop as a probable caller
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 255);
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= 255);
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c <= 255);
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(d <= 255);
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned result = (prod + (prod >> 8)) >> 8;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result <= 255);
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return result;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
40fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com#endif
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42da94699149a40a90731425766d3b994e34c5ba26deanm@chromium.orgstatic inline unsigned saturated_add(unsigned a, unsigned b) {
43543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    SkASSERT(a <= 255);
44543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    SkASSERT(b <= 255);
45543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    unsigned sum = a + b;
46543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    if (sum > 255) {
47543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        sum = 255;
48543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    }
49543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    return sum;
50543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com}
51543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com
52da94699149a40a90731425766d3b994e34c5ba26deanm@chromium.orgstatic inline int clamp_signed_byte(int n) {
53a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (n < 0) {
54a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        n = 0;
55a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else if (n > 255) {
56a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        n = 255;
57a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
58a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return n;
59a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
60a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
61da94699149a40a90731425766d3b994e34c5ba26deanm@chromium.orgstatic inline int clamp_div255round(int prod) {
62a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (prod <= 0) {
63a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return 0;
64a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else if (prod >= 255*255) {
65a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return 255;
66a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
67a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return SkDiv255Round(prod);
68a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
69a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
70a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kClear_Mode,    //!< [0, 0]
7448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
7548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return 0;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrc_Mode,      //!< [Sa, Sc]
7948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
8048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return src;
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDst_Mode,      //!< [Da, Dc]
8448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
8548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return dst;
8648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
881447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
8948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
9048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org#if 0
9148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this is the old, more-correct way, but it doesn't guarantee that dst==255
9248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // will always stay opaque
9348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
9448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org#else
9548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this is slightly faster, but more importantly guarantees that dst==255
9648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // will always stay opaque
9748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
9848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org#endif
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
10248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
10348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this is the reverse of srcover, just flipping src and dst
10448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // see srcover's comment about the 256 for opaqueness guarantees
10548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
10648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
10948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
11048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
11448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
11548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
11948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
12048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
12148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
12448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
12548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
12948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
13048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned sa = SkGetPackedA32(src);
13148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned da = SkGetPackedA32(dst);
13248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned isa = 255 - sa;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(da,
13548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
13648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
13748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
13848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
13948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
14048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
14148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
14448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
14548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned sa = SkGetPackedA32(src);
14648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned da = SkGetPackedA32(dst);
14748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned ida = 255 - da;
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(sa,
15048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
15148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
15248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
15348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
15448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
15548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
15948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
16048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned sa = SkGetPackedA32(src);
16148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned da = SkGetPackedA32(dst);
16248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned isa = 255 - sa;
16348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned ida = 255 - da;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
16648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
16748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
16848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
16948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
17048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
17148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
17248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
17548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
17648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kPlus_Mode
17748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
17848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
17948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
18048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
18148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
18248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com// kModulate_Mode
1868d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.comstatic SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
18748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
18848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
18948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
19048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
19148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
19248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
194a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int srcover_byte(int a, int b) {
195a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return a + b - SkAlphaMulAlpha(a, b);
196a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
19725cfa693420b6da4182bda42ba15970999b840ddreed@google.com
19825cfa693420b6da4182bda42ba15970999b840ddreed@google.com// kMultiply_Mode
19925cfa693420b6da4182bda42ba15970999b840ddreed@google.com// B(Cb, Cs) = Cb x Cs
20025cfa693420b6da4182bda42ba15970999b840ddreed@google.com// multiply uses its own version of blendfunc_byte because sa and da are not needed
20125cfa693420b6da4182bda42ba15970999b840ddreed@google.comstatic int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
20225cfa693420b6da4182bda42ba15970999b840ddreed@google.com    return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
20325cfa693420b6da4182bda42ba15970999b840ddreed@google.com}
20425cfa693420b6da4182bda42ba15970999b840ddreed@google.com
20525cfa693420b6da4182bda42ba15970999b840ddreed@google.comstatic SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
20625cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int sa = SkGetPackedA32(src);
20725cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int da = SkGetPackedA32(dst);
20825cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int a = srcover_byte(sa, da);
20925cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
21025cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
21125cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
21225cfa693420b6da4182bda42ba15970999b840ddreed@google.com    return SkPackARGB32(a, r, g, b);
21325cfa693420b6da4182bda42ba15970999b840ddreed@google.com}
21425cfa693420b6da4182bda42ba15970999b840ddreed@google.com
21525cfa693420b6da4182bda42ba15970999b840ddreed@google.com// kScreen_Mode
216a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
217a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
218a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
219a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
220a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
221a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
222a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
223a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
224a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kOverlay_Mode
225a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int overlay_byte(int sc, int dc, int sa, int da) {
226a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int tmp = sc * (255 - da) + dc * (255 - sa);
227a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int rc;
228a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (2 * dc <= da) {
229a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        rc = 2 * sc * dc;
230a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
231a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        rc = sa * da - 2 * (da - dc) * (sa - sc);
232a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
233a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return clamp_div255round(rc + tmp);
234a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
235a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
236a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sa = SkGetPackedA32(src);
237a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int da = SkGetPackedA32(dst);
238a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(sa, da);
239a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
240a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
241a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
242a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
243a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
244a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
245a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kDarken_Mode
246a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int darken_byte(int sc, int dc, int sa, int da) {
247a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sd = sc * da;
248a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int ds = dc * sa;
249a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (sd < ds) {
250a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // srcover
251a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return sc + dc - SkDiv255Round(ds);
252a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
253a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // dstover
254a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return dc + sc - SkDiv255Round(sd);
255a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
256a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
258a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sa = SkGetPackedA32(src);
259a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int da = SkGetPackedA32(dst);
260a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(sa, da);
261a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
262a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
263a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
264a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
265a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
267a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kLighten_Mode
268a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int lighten_byte(int sc, int dc, int sa, int da) {
269a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sd = sc * da;
270a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int ds = dc * sa;
271a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (sd > ds) {
272a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // srcover
273a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return sc + dc - SkDiv255Round(ds);
274a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
275a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // dstover
276a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return dc + sc - SkDiv255Round(sd);
277a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
278a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
279a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
280a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sa = SkGetPackedA32(src);
281a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int da = SkGetPackedA32(dst);
282a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(sa, da);
283a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
284a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
285a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
286a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
287a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
289a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kColorDodge_Mode
290a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int colordodge_byte(int sc, int dc, int sa, int da) {
291a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int diff = sa - sc;
292a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int rc;
293311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    if (0 == dc) {
294311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        return SkAlphaMulAlpha(sc, 255 - da);
295311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    } else if (0 == diff) {
296a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
297a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
298311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        diff = dc * sa / diff;
299311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
300a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
301311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    return clamp_div255round(rc);
30248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
30348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
30448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
30548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
30648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
30748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
30848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
30948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
31048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
31148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
31248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
31348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kColorBurn_Mode
31448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int colorburn_byte(int sc, int dc, int sa, int da) {
31548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int rc;
316311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    if (dc == da) {
317311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
31848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else if (0 == sc) {
31948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        return SkAlphaMulAlpha(dc, 255 - sa);
32048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
321311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        int tmp = (da - dc) * sa / sc;
322311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        rc = sa * (da - ((da < tmp) ? da : tmp))
323311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org            + sc * (255 - da) + dc * (255 - sa);
32448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
325311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    return clamp_div255round(rc);
32648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
32748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
32848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
32948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
33048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
33148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
33248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
33348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
33448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
33548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
33648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
33748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kHardLight_Mode
33848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int hardlight_byte(int sc, int dc, int sa, int da) {
33948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int rc;
34048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (2 * sc <= sa) {
34148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = 2 * sc * dc;
34248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
34348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = sa * da - 2 * (da - dc) * (sa - sc);
34448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
34548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
34648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
34748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
34848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
34948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
35048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
35148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
35248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
35348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
35448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
35548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
35648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
35748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// returns 255 * sqrt(n/255)
35848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic U8CPU sqrt_unit_byte(U8CPU n) {
35948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkSqrtBits(n, 15+4);
36048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
36148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
36248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kSoftLight_Mode
36348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int softlight_byte(int sc, int dc, int sa, int da) {
36448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int m = da ? dc * 256 / da : 0;
36548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int rc;
36648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (2 * sc <= sa) {
36748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
36848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else if (4 * dc <= da) {
36948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
37048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
37148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
37248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        int tmp = sqrt_unit_byte(m) - m;
37348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
37448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
37548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
37648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
37748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
37848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
37948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
38048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
38148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
38248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
38348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
38448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
38548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
38648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
38748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kDifference_Mode
38848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int difference_byte(int sc, int dc, int sa, int da) {
38948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int tmp = SkMin32(sc * da, dc * sa);
39048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
39148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
39248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
39348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
39448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
39548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
39648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
39748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
39848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
39948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
40048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
40148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
40248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kExclusion_Mode
403e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.orgstatic inline int exclusion_byte(int sc, int dc, int, int) {
40448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this equations is wacky, wait for SVG to confirm it
405e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org    //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
406e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org
407e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org    // The above equation can be simplified as follows
408e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org    int r = 255*(sc + dc) - 2 * sc * dc;
40948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_div255round(r);
41048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
41148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
41248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
41348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
41448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
41548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
41648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
41748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
41848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
41948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
42048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
421b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// The CSS compositing spec introduces the following formulas:
422b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
423b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
424b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// while PDF and CG uses the one from Rec. Rec. 601
425b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
426b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int Lum(int r, int g, int b)
427b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org{
428311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    return SkDiv255Round(r * 77 + g * 150 + b * 28);
429b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
430b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
431b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int min2(int a, int b) { return a < b ? a : b; }
432b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int max2(int a, int b) { return a > b ? a : b; }
43364334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com#define minimum(a, b, c) min2(min2(a, b), c)
43464334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com#define maximum(a, b, c) max2(max2(a, b), c)
435b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
436b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int Sat(int r, int g, int b) {
437b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return maximum(r, g, b) - minimum(r, g, b);
438b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
439b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
440b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
4413c1ea3a7e5127513d3b3335d92292e02f273efefreed@google.com    if(*Cmax > *Cmin) {
442311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
443b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        *Cmax = s;
444b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
445b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        *Cmax = 0;
446b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        *Cmid = 0;
447b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
448b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
449b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    *Cmin = 0;
450b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
451b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
452b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline void SetSat(int* r, int* g, int* b, int s) {
453b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(*r <= *g) {
454b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        if(*g <= *b) {
455b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org            setSaturationComponents(r, g, b, s);
456b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        } else if(*r <= *b) {
457b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org            setSaturationComponents(r, b, g, s);
458b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        } else {
459b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org            setSaturationComponents(b, r, g, s);
460b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        }
461b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else if(*r <= *b) {
462b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        setSaturationComponents(g, r, b, s);
463b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else if(*g <= *b) {
464b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        setSaturationComponents(g, b, r, s);
465b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
466b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        setSaturationComponents(b, g, r, s);
467b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
468b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
469b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
470311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.orgstatic inline void clipColor(int* r, int* g, int* b, int a) {
471b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int L = Lum(*r, *g, *b);
472b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int n = minimum(*r, *g, *b);
473b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int x = maximum(*r, *g, *b);
474b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org    int denom;
475b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org    if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
476b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *r = L + SkMulDiv(*r - L, L, denom);
477b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *g = L + SkMulDiv(*g - L, L, denom);
478b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *b = L + SkMulDiv(*b - L, L, denom);
479b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
480b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
481b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org    if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
482b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       int numer = a - L;
483b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *r = L + SkMulDiv(*r - L, numer, denom);
484b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *g = L + SkMulDiv(*g - L, numer, denom);
485b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *b = L + SkMulDiv(*b - L, numer, denom);
486b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
487b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
488b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
489311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.orgstatic inline void SetLum(int* r, int* g, int* b, int a, int l) {
490b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  int d = l - Lum(*r, *g, *b);
491b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  *r +=  d;
492b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  *g +=  d;
493b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  *b +=  d;
494b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
495311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org  clipColor(r, g, b, a);
496b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
497b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
498b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// non-separable blend modes are done in non-premultiplied alpha
499b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
500311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org  clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
501b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
502b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kHue_Mode
503b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
504b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
505b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
506b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
507b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
508b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
509b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
510b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
511b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
512b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
513b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
514b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
515b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Sr, Sg, Sb;
516b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
517b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
518311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sr = sr * sa;
519311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sg = sg * sa;
520311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sb = sb * sa;
521311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
522311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
523b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
524b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sr = 0;
525b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sg = 0;
526b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sb = 0;
527b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
528b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
529b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
530b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
531b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
532b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
533b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
534b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
535b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
536b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kSaturation_Mode
537b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
53864334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
539b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
540b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
541b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
542b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
543b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
544b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
545b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
546b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
547b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
548b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
549b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Dr, Dg, Db;
550b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
551b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
552311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dr = dr * sa;
553311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dg = dg * sa;
554311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Db = db * sa;
555311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
556311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
557b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
558b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dr = 0;
559b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dg = 0;
560b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Db = 0;
561b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
562b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
563b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
564b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
565b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
566b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
567b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
568b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
569b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
570b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kColor_Mode
571b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
57264334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
573b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
574b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
575b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
576b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
577b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
578b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
579b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
580b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
581b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
582b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
583b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Sr, Sg, Sb;
584b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
585b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
586311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sr = sr * da;
587311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sg = sg * da;
588311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sb = sb * da;
589311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
590b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
591b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sr = 0;
592b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sg = 0;
593b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sb = 0;
594b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
595b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
596b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
597b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
598b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
599b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
600b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
601b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
602b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
603b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kLuminosity_Mode
604b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
60564334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
606b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
607b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
608b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
609b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
610b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
611b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
612b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
613b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
614b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
615b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
616b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Dr, Dg, Db;
617b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
618b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
619311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dr = dr * sa;
620311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dg = dg * sa;
621311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Db = db * sa;
622311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
623b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
624b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dr = 0;
625b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dg = 0;
626b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Db = 0;
627b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
628b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
629b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
630b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
631b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
632b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
633b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
634b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
635b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
636df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.orgconst ProcCoeff gProcCoeffs[] = {
63748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
63848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
63948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
64048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
64148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
64248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
64348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
64448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
64548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
64648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
64748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
64848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
64948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
650521e34e2912d835ab1b33a06cb8fb416510d7c53reed@google.com    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
6518d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
652b0091b8382970c28dba57adc170e27b2e3d7394absalomon@google.com    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
65348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
66048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
66148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
66225cfa693420b6da4182bda42ba15970999b840ddreed@google.com    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
663b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
664b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
665b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
666b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
66748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org};
66848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
66948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
67048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
67130da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
67248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return false;
67348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
67448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
67530da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::asMode(Mode* mode) const {
676c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com    return false;
67748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
67848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
679b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
6801a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.org    return false;
681f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com}
682f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com
683b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkXfermode::asFragmentProcessorOrCoeff(SkXfermode* xfermode, GrFragmentProcessor** fp,
684b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            Coeff* src, Coeff* dst, GrTexture* background) {
685f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    if (NULL == xfermode) {
686f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com        return ModeAsCoeff(kSrcOver_Mode, src, dst);
6871a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.org    } else if (xfermode->asCoeff(src, dst)) {
6881a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.org        return true;
689f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    } else {
690b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        return xfermode->asFragmentProcessor(fp, background);
691f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    }
692f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com}
693f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com
69430da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.comSkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
69548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // no-op. subclasses should override this
69648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return dst;
69748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
69848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
699a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
700a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                        const SkPMColor* SK_RESTRICT src, int count,
70130da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha* SK_RESTRICT aa) const {
70248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    SkASSERT(dst && src && count >= 0);
70348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
70448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (NULL == aa) {
70548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
70648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            dst[i] = this->xferColor(src[i], dst[i]);
70748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
70848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
70948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
71048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            unsigned a = aa[i];
71148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            if (0 != a) {
71248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor dstC = dst[i];
71348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor C = this->xferColor(src[i], dstC);
71448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                if (0xFF != a) {
71548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                    C = SkFourByteInterp(C, dstC, a);
71648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                }
71748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                dst[i] = C;
71848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            }
71948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
72048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
72148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
72248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
723a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkXfermode::xfer16(uint16_t* dst,
724a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                        const SkPMColor* SK_RESTRICT src, int count,
72530da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha* SK_RESTRICT aa) const {
72648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    SkASSERT(dst && src && count >= 0);
72748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
72848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (NULL == aa) {
72948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
73048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
73148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
73248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
73348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
73448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
73548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            unsigned a = aa[i];
73648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            if (0 != a) {
73748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
73848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor C = this->xferColor(src[i], dstC);
73948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                if (0xFF != a) {
74048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                    C = SkFourByteInterp(C, dstC, a);
74148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                }
74248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                dst[i] = SkPixel32ToPixel16_ToU16(C);
74348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            }
74448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
74548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
74648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
74748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
748a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
74948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        const SkPMColor src[], int count,
75030da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha* SK_RESTRICT aa) const {
75148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    SkASSERT(dst && src && count >= 0);
75248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
75348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (NULL == aa) {
75448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
75548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
75648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            dst[i] = SkToU8(SkGetPackedA32(res));
75748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
75848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
75948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
76048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            unsigned a = aa[i];
76148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            if (0 != a) {
76248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkAlpha dstA = dst[i];
76348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                unsigned A = SkGetPackedA32(this->xferColor(src[i],
76448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
76548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                if (0xFF != a) {
76648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
76748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                }
76848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                dst[i] = SkToU8(A);
76948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            }
77048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
77148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
77248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
77348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
77426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com//////////////////////////////////////////////////////////////////////////////
77526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
77626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com#if SK_SUPPORT_GPU
77726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
778b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessor.h"
77977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com#include "GrCoordTransform.h"
780b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessorUnitTest.h"
781b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrTBackendProcessorFactory.h"
782b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "gl/GrGLProcessor.h"
78330ba436f04e61d4505fb854d5fc56079636e0788joshualitt#include "gl/builders/GrGLProgramBuilder.h"
78426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
78526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com/**
786b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * GrProcessor that implements the all the separable xfer modes that cannot be expressed as Coeffs.
78726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com */
788b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass XferEffect : public GrFragmentProcessor {
78926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.compublic:
7908da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com    static bool IsSupportedMode(SkXfermode::Mode mode) {
79177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
7928da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com    }
7938da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
794b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    static GrFragmentProcessor* Create(SkXfermode::Mode mode, GrTexture* background) {
7958da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        if (!IsSupportedMode(mode)) {
7968da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            return NULL;
7978da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        } else {
79855fad7af61c21d502acb9891d631e8aa29e3628cbsalomon            return SkNEW_ARGS(XferEffect, (mode, background));
7998da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        }
80026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    }
80126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
80226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    virtual void getConstantColorComponents(GrColor* color,
80326e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com                                            uint32_t* validFlags) const SK_OVERRIDE {
80426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        *validFlags = 0;
80526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    }
80626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
807b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
808b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        return GrTBackendFragmentProcessorFactory<XferEffect>::getInstance();
80926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    }
81026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
8118da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com    static const char* Name() { return "XferEffect"; }
8128da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
8138da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com    SkXfermode::Mode mode() const { return fMode; }
81486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
81526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
816b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    class GLProcessor : public GrGLFragmentProcessor {
81726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    public:
818b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        GLProcessor(const GrBackendProcessorFactory& factory, const GrProcessor&)
819b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            : INHERITED(factory) {
82026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        }
82130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        virtual void emitCode(GrGLProgramBuilder* builder,
822b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              const GrFragmentProcessor& fp,
823b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                              const GrProcessorKey& key,
82426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com                              const char* outputColor,
82526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com                              const char* inputColor,
82677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com                              const TransformedCoordsArray& coords,
82726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com                              const TextureSamplerArray& samplers) SK_OVERRIDE {
828b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkXfermode::Mode mode = fp.cast<XferEffect>().mode();
82949586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt            const GrTexture* backgroundTex =
830b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                    fp.cast<XferEffect>().backgroundAccess().getTexture();
83130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
83286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            const char* dstColor;
83386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            if (backgroundTex) {
83486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org                dstColor = "bgColor";
83530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppendf("\t\tvec4 %s = ", dstColor);
83623e280d1f227d94f6b3dfd0b47359cca1569e1b4joshualitt                fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
83730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppendf(";\n");
83886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            } else {
83930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                dstColor = fsBuilder->dstColor();
84086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            }
84149f085dddff10473b6ebf832a974288300224e60bsalomon            SkASSERT(dstColor);
8428da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
8438da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // We don't try to optimize for this case at all
844b79d865f03456b67273b568fa5046b8ba01e365absalomon@google.com            if (NULL == inputColor) {
84530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppendf("\t\tconst vec4 ones = vec4(1);\n");
8468da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                inputColor = "ones";
8478da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            }
84830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
84977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
8508da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // These all perform src-over on the alpha channel.
85130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
8528da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                    outputColor, inputColor, inputColor, dstColor);
8538da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
85477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            switch (mode) {
8558da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kOverlay_Mode:
8568da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    // Overlay is Hard-Light with the src and dst reversed
85730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    HardLight(fsBuilder, outputColor, dstColor, inputColor);
8588da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8598da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kDarken_Mode:
86030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
8618da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
8628da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                            outputColor,
8638da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                            inputColor, dstColor, inputColor,
8648da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                            dstColor, inputColor, dstColor);
8658da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8668da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kLighten_Mode:
86730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
8688da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
8698da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                            outputColor,
8708da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                            inputColor, dstColor, inputColor,
8718da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                            dstColor, inputColor, dstColor);
8728da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8738da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kColorDodge_Mode:
87430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'r');
87530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'g');
87630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    ColorDodgeComponent(fsBuilder, outputColor, inputColor, dstColor, 'b');
8778da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8788da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kColorBurn_Mode:
87930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'r');
88030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'g');
88130ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    ColorBurnComponent(fsBuilder, outputColor, inputColor, dstColor, 'b');
8828da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8838da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kHardLight_Mode:
88430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    HardLight(fsBuilder, outputColor, inputColor, dstColor);
8858da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8868da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kSoftLight_Mode:
88730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
88830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
88930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t} else {\n");
89030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'r');
89130ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'g');
89230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    SoftLightComponentPosDstAlpha(fsBuilder, outputColor, inputColor, dstColor, 'b');
89330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t}\n");
8948da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
8958da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kDifference_Mode:
89630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
89764b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com                                                       "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
8988da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                           outputColor, inputColor, dstColor, inputColor, dstColor,
8998da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                           dstColor, inputColor);
9008da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
9018da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kExclusion_Mode:
90230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
9038da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                        "2.0 * %s.rgb * %s.rgb;\n",
9048da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                           outputColor, dstColor, inputColor, dstColor, inputColor);
9058da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
9068da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                case SkXfermode::kMultiply_Mode:
90730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
9088da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                        "(1.0 - %s.a) * %s.rgb + "
9098da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                         "%s.rgb * %s.rgb;\n",
9108da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                           outputColor, inputColor, dstColor, dstColor, inputColor,
9118da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                           inputColor, dstColor);
9128da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
91377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                case SkXfermode::kHue_Mode: {
91477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
91577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    SkString setSat, setLum;
91630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    AddSatFunction(fsBuilder, &setSat);
91730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    AddLumFunction(fsBuilder, &setLum);
91830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
91977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           dstColor, inputColor);
92030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
92177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
92277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           dstColor);
92330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
92477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, inputColor, dstColor, dstColor, inputColor);
92577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    break;
92677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                }
92777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                case SkXfermode::kSaturation_Mode: {
92877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
92977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    SkString setSat, setLum;
93030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    AddSatFunction(fsBuilder, &setSat);
93130ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    AddLumFunction(fsBuilder, &setLum);
93230ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
93377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           dstColor, inputColor);
93430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
93577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
93677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           dstColor);
93730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
93877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, inputColor, dstColor, dstColor, inputColor);
9398da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
94077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                }
94177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                case SkXfermode::kColor_Mode: {
94277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
94377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    SkString setLum;
94430ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    AddLumFunction(fsBuilder, &setLum);
94530ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
94677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           inputColor, dstColor);
94730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
94877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, setLum.c_str(), dstColor, inputColor);
94930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
95077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, inputColor, dstColor, dstColor, inputColor);
95177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    break;
95277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                }
95377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                case SkXfermode::kLuminosity_Mode: {
95477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
95577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    SkString setLum;
95630ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    AddLumFunction(fsBuilder, &setLum);
95730ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
95877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           inputColor, dstColor);
95930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
96077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, setLum.c_str(), dstColor, inputColor);
96130ba436f04e61d4505fb854d5fc56079636e0788joshualitt                    fsBuilder->codeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
96277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                                           outputColor, inputColor, dstColor, dstColor, inputColor);
96377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                    break;
96477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                }
9658da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                default:
96688cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org                    SkFAIL("Unknown XferEffect mode.");
9678da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                    break;
968b79d865f03456b67273b568fa5046b8ba01e365absalomon@google.com            }
96926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        }
97026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
971b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        static inline void GenKey(const GrProcessor& proc, const GrGLCaps&,
972b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                  GrProcessorKeyBuilder* b) {
973372a9c3f443bdcc60b0e0c17f028461eaaed5fd1commit-bot@chromium.org            // The background may come from the dst or from a texture.
974b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            uint32_t key = proc.numTextures();
97563e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon            SkASSERT(key <= 1);
976b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            key |= proc.cast<XferEffect>().mode() << 1;
97763e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon            b->add32(key);
97886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        }
97926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
98026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    private:
98130ba436f04e61d4505fb854d5fc56079636e0788joshualitt        static void HardLight(GrGLFragmentShaderBuilder* fsBuilder,
9828da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                              const char* final,
9838da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                              const char* src,
9848da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                              const char* dst) {
985a0d91388bb6d3d18b7409dbc1654a4335b051ae5commit-bot@chromium.org            static const char kComponents[] = {'r', 'g', 'b'};
986a0d91388bb6d3d18b7409dbc1654a4335b051ae5commit-bot@chromium.org            for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
987a0d91388bb6d3d18b7409dbc1654a4335b051ae5commit-bot@chromium.org                char component = kComponents[i];
98830ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
98930ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
99030ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\t} else {\n");
99130ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
992a0d91388bb6d3d18b7409dbc1654a4335b051ae5commit-bot@chromium.org                                       final, component, src, dst, dst, dst, component, src, src, component);
99330ba436f04e61d4505fb854d5fc56079636e0788joshualitt                fsBuilder->codeAppend("\t\t}\n");
994a0d91388bb6d3d18b7409dbc1654a4335b051ae5commit-bot@chromium.org            }
99530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
9968da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, src, dst, dst, src);
9978da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        }
9988da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
9998da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        // Does one component of color-dodge
100030ba436f04e61d4505fb854d5fc56079636e0788joshualitt        static void ColorDodgeComponent(GrGLFragmentShaderBuilder* fsBuilder,
10018da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                        const char* final,
10028da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                        const char* src,
10038da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                        const char* dst,
10048da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                        const char component) {
100530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
100630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
10078da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, src, component, dst);
100830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t} else {\n");
100930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
101030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t\tif (0.0 == d) {\n");
101130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
10128da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, src, dst, src, component, dst, dst, component,
10138da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   src);
101430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t\t} else {\n");
101530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
10168da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   dst, dst, component, src);
101730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
10188da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, src, src, component, dst, dst, component, src);
101930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t\t}\n");
102030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t}\n");
10218da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        }
10228da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
10238da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        // Does one component of color-burn
102430ba436f04e61d4505fb854d5fc56079636e0788joshualitt        static void ColorBurnComponent(GrGLFragmentShaderBuilder* fsBuilder,
10258da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                       const char* final,
10268da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                       const char* src,
10278da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                       const char* dst,
10288da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                       const char component) {
102930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
103030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
10318da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, src, dst, src, component, dst, dst, component,
10328da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   src);
103330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
103430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
10358da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, dst, component, src);
103630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t} else {\n");
103730ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
10388da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   dst, dst, dst, component, src, src, component);
103930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
10408da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, src, src, component, dst, dst, component, src);
104130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppend("\t\t}\n");
10428da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        }
10438da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
10448da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
104530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        static void SoftLightComponentPosDstAlpha(GrGLFragmentShaderBuilder* fsBuilder,
10468da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                  const char* final,
10478da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                  const char* src,
10488da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                  const char* dst,
10498da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                                  const char component) {
10508da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // if (2S < Sa)
105130ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
10528da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
105330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n",
10548da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, dst, component, dst, component, src, src,
10558da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   component, dst, dst, src, component, dst, component, src, src,
10568da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   component);
10578da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // else if (4D < Da)
105830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
10598da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   dst, component, dst);
106030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
10618da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   dst, component, dst, component);
106230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
106330ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
106430ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
10658da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2
106630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n",
10678da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   final, component, src, component, src, component, dst, component,
10688da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   src, src, component, dst, src, src, component, src, src,
10698da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                   component);
107030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t} else {\n");
10718da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com            // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
107230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n",
10738da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                    final, component, dst, dst, component, src, src, component, dst,
10748da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                    src, component, dst, component, src, src, component, src,
10758da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com                                    component);
107630ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->codeAppendf("\t\t\t}\n");
10778da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com        }
10788da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com
107977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        // Adds a function that takes two colors and an alpha as input. It produces a color with the
108077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        // hue and saturation of the first color, the luminosity of the second color, and the input
108177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        // alpha. It has this signature:
108277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
108330ba436f04e61d4505fb854d5fc56079636e0788joshualitt        static void AddLumFunction(GrGLFragmentShaderBuilder* fsBuilder, SkString* setLumFunction) {
108477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            // Emit a helper that gets the luminance of a color.
108577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString getFunction;
108677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            GrGLShaderVar getLumArgs[] = {
108777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("color", kVec3f_GrSLType),
108877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            };
108977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
109030ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->emitFunction(kFloat_GrSLType,
109174a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    "luminance",
109274a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    SK_ARRAY_COUNT(getLumArgs), getLumArgs,
109374a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    getLumBody.c_str(),
109474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    &getFunction);
109577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
109677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            // Emit the set luminance function.
109777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            GrGLShaderVar setLumArgs[] = {
109877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("hueSat", kVec3f_GrSLType),
109977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("alpha", kFloat_GrSLType),
110077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("lumColor", kVec3f_GrSLType),
110177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            };
110277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString setLumBody;
110377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
110477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
110577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
110677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
110777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
110877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\tif (minComp < 0.0) {\n"
110977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
111077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\t}\n"
111177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\tif (maxComp > alpha) {\n"
111277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
111377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\t}\n"
111477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "\treturn outColor;\n");
111530ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->emitFunction(kVec3f_GrSLType,
111674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    "set_luminance",
111774a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    SK_ARRAY_COUNT(setLumArgs), setLumArgs,
111874a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    setLumBody.c_str(),
111974a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    setLumFunction);
112077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        }
112177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
112277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        // Adds a function that creates a color with the hue and luminosity of one input color and
112377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        // the saturation of another color. It will have this signature:
112477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        //      float set_saturation(vec3 hueLumColor, vec3 satColor)
112530ba436f04e61d4505fb854d5fc56079636e0788joshualitt        static void AddSatFunction(GrGLFragmentShaderBuilder* fsBuilder, SkString* setSatFunction) {
112677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            // Emit a helper that gets the saturation of a color
112777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString getFunction;
112877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
112977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString getSatBody;
113077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
113177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                              "min(min(color.r, color.g), color.b);\n");
113230ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->emitFunction(kFloat_GrSLType,
113374a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    "saturation",
113474a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    SK_ARRAY_COUNT(getSatArgs), getSatArgs,
113574a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    getSatBody.c_str(),
113674a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    &getFunction);
113777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
1138c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org            // Emit a helper that sets the saturation given sorted input channels. This used
1139c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org            // to use inout params for min, mid, and max components but that seems to cause
1140c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org            // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
1141c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org            // adjusted min, mid, and max inputs, respectively.
114277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString helperFunction;
114377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            GrGLShaderVar helperArgs[] = {
114477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("minComp", kFloat_GrSLType),
114577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("midComp", kFloat_GrSLType),
114677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("maxComp", kFloat_GrSLType),
114777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("sat", kFloat_GrSLType),
114877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            };
1149c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org            static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
1150c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t\tvec3 result;\n"
1151c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t\tresult.r = 0.0;\n"
1152c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
1153c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t\tresult.b = sat;\n"
1154c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t\treturn result;\n"
1155c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t} else {\n"
1156c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t\treturn vec3(0, 0, 0);\n"
1157c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                                              "\t}\n";
115830ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->emitFunction(kVec3f_GrSLType,
115974a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    "set_saturation_helper",
116074a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    SK_ARRAY_COUNT(helperArgs), helperArgs,
116174a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    kHelperBody,
116274a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    &helperFunction);
116377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
116477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            GrGLShaderVar setSatArgs[] = {
116577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
116677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                GrGLShaderVar("satColor", kVec3f_GrSLType),
116777cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            };
116877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            const char* helpFunc = helperFunction.c_str();
116977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            SkString setSatBody;
117077cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com            setSatBody.appendf("\tfloat sat = %s(satColor);\n"
117177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\tif (hueLumColor.r <= hueLumColor.g) {\n"
117277cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1173c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
117418c41acf35eefc75ef4631fbb680ec64861b30afcommit-bot@chromium.org                               "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1175c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
117618c41acf35eefc75ef4631fbb680ec64861b30afcommit-bot@chromium.org                               "\t\t} else {\n"
1177c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
117877cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\t\t}\n"
117977cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1180c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
118177cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1182c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
118377cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\t} else {\n"
1184c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
118577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com                               "\t}\n"
1186c718b35bce895aa945fc479451156985206fdae1commit-bot@chromium.org                               "\treturn hueLumColor;\n",
118718c41acf35eefc75ef4631fbb680ec64861b30afcommit-bot@chromium.org                               getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
118818c41acf35eefc75ef4631fbb680ec64861b30afcommit-bot@chromium.org                               helpFunc, helpFunc);
118930ba436f04e61d4505fb854d5fc56079636e0788joshualitt            fsBuilder->emitFunction(kVec3f_GrSLType,
119074a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    "set_saturation",
119174a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    SK_ARRAY_COUNT(setSatArgs), setSatArgs,
119274a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    setSatBody.c_str(),
119374a3a2135ca82ab9324b7e499caa3280348a4fdacommit-bot@chromium.org                                    setSatFunction);
119477cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
119577cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com        }
119677cf460e5df7dd5272e71f9835880ded48fe8d12bsalomon@google.com
1197b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        typedef GrGLFragmentProcessor INHERITED;
119826e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    };
119926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
1200b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
120126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
120226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.comprivate:
120386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    XferEffect(SkXfermode::Mode mode, GrTexture* background)
120486fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        : fMode(mode) {
120586fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        if (background) {
120677af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com            fBackgroundTransform.reset(kLocal_GrCoordSet, background);
120777af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com            this->addCoordTransform(&fBackgroundTransform);
120886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            fBackgroundAccess.reset(background);
120986fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            this->addTextureAccess(&fBackgroundAccess);
121086fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        } else {
121186fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org            this->setWillReadDstColor();
121286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        }
121386fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    }
1214b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE {
121549586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt        const XferEffect& s = other.cast<XferEffect>();
121686fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org        return fMode == s.fMode &&
121786fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org               fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
121886fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    }
121964b682ca42c75667e49251d3ab04f192f92d0dd8skia.committer@gmail.com
12208da9bc751e1898d50dd84d7e5ca666b00e4ff624bsalomon@google.com    SkXfermode::Mode fMode;
122177af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com    GrCoordTransform fBackgroundTransform;
122286fc266eda887920e3dd104bee8121ae19729cf5senorblanco@chromium.org    GrTextureAccess  fBackgroundAccess;
122326e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
1224b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrFragmentProcessor INHERITED;
122526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com};
122626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
1227b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGR_DEFINE_FRAGMENT_PROCESSOR_TEST(XferEffect);
1228b0a8a377f832c59cee939ad721e1f87d378b7142joshualittGrFragmentProcessor* XferEffect::TestCreate(SkRandom* rand,
1229b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            GrContext*,
1230b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            const GrDrawTargetCaps&,
1231b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                            GrTexture*[]) {
1232a0d91388bb6d3d18b7409dbc1654a4335b051ae5commit-bot@chromium.org    int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
12332cf444f7040614b43af67e368f3aa636ebeaa45askia.committer@gmail.com
123455fad7af61c21d502acb9891d631e8aa29e3628cbsalomon    return SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL));
123526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com}
123626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
123726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com#endif
123826e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
123948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
124048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
1241a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
12429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
12438b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
124452314f82ba8696e957e70eabde672b6470fedf7areed@google.com    uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs);
124552314f82ba8696e957e70eabde672b6470fedf7areed@google.com    if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) {
124652314f82ba8696e957e70eabde672b6470fedf7areed@google.com        // out of range, just set to something harmless
124752314f82ba8696e957e70eabde672b6470fedf7areed@google.com        mode32 = SkXfermode::kSrcOut_Mode;
124852314f82ba8696e957e70eabde672b6470fedf7areed@google.com    }
124952314f82ba8696e957e70eabde672b6470fedf7areed@google.com    fMode = (SkXfermode::Mode)mode32;
1250f61ebc0927d773fe4152a3521cdc3de0112f636eskia.committer@gmail.com
125152314f82ba8696e957e70eabde672b6470fedf7areed@google.com    const ProcCoeff& rec = gProcCoeffs[fMode];
1252cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    fProc = rec.fProc;
125352314f82ba8696e957e70eabde672b6470fedf7areed@google.com    // these may be valid, or may be CANNOT_USE_COEFF
125452314f82ba8696e957e70eabde672b6470fedf7areed@google.com    fSrcCoeff = rec.fSC;
125552314f82ba8696e957e70eabde672b6470fedf7areed@google.com    fDstCoeff = rec.fDC;
125652314f82ba8696e957e70eabde672b6470fedf7areed@google.com}
12579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
12589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
12599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
12609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    uint32_t mode32 = buffer.read32();
12610f7197bc0ddbe6c61732d6fe69df86bdba00a060senorblanco    if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
12629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
12639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
12649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkXfermode::Create((SkXfermode::Mode)mode32);
12659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
12669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
12679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedvoid SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
12689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.write32(fMode);
12699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
127052314f82ba8696e957e70eabde672b6470fedf7areed@google.com
1271df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.orgbool SkProcCoeffXfermode::asMode(Mode* mode) const {
1272df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (mode) {
1273df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        *mode = fMode;
127448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
1275df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    return true;
1276df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org}
1277c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com
1278df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.orgbool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
1279df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (CANNOT_USE_COEFF == fSrcCoeff) {
1280df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        return false;
1281c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com    }
1282c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com
1283df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (sc) {
1284df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        *sc = fSrcCoeff;
1285df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    }
1286df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (dc) {
1287df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        *dc = fDstCoeff;
128884cc1ebc5a4789e93e23c65eb4014ef5b8b0bab4commit-bot@chromium.org    }
1289df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    return true;
1290df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org}
12916f980c6a2354fed70a6258fb4dd4155936660930djsollen@google.com
1292cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.orgvoid SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1293cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT src, int count,
1294cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkAlpha* SK_RESTRICT aa) const {
1295cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkASSERT(dst && src && count >= 0);
129660bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
1297cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkXfermodeProc proc = fProc;
129860bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
129949f085dddff10473b6ebf832a974288300224e60bsalomon    if (proc) {
1300cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        if (NULL == aa) {
1301cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
1302cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                dst[i] = proc(src[i], dst[i]);
1303cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
1304cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        } else {
1305cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
1306cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                unsigned a = aa[i];
1307cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                if (0 != a) {
1308cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor dstC = dst[i];
1309cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor C = proc(src[i], dstC);
1310cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    if (a != 0xFF) {
1311cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                        C = SkFourByteInterp(C, dstC, a);
1312cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    }
1313cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    dst[i] = C;
1314cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                }
1315cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
1316cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        }
1317cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    }
1318cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org}
1319cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org
1320cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.orgvoid SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1321cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT src, int count,
1322cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkAlpha* SK_RESTRICT aa) const {
1323cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkASSERT(dst && src && count >= 0);
132460bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
1325cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkXfermodeProc proc = fProc;
132660bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
132749f085dddff10473b6ebf832a974288300224e60bsalomon    if (proc) {
1328cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        if (NULL == aa) {
1329cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
1330cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1331cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1332cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
1333cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        } else {
1334cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
1335cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                unsigned a = aa[i];
1336cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                if (0 != a) {
1337cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1338cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor C = proc(src[i], dstC);
1339cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    if (0xFF != a) {
1340cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                        C = SkFourByteInterp(C, dstC, a);
1341cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    }
1342cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    dst[i] = SkPixel32ToPixel16_ToU16(C);
1343cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                }
1344cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
1345cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        }
1346cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    }
1347cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org}
1348cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org
1349cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.orgvoid SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1350cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT src, int count,
1351cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkAlpha* SK_RESTRICT aa) const {
1352cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkASSERT(dst && src && count >= 0);
135360bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
1354cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkXfermodeProc proc = fProc;
135560bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
135649f085dddff10473b6ebf832a974288300224e60bsalomon    if (proc) {
1357cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        if (NULL == aa) {
1358cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
1359cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1360cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                dst[i] = SkToU8(SkGetPackedA32(res));
1361cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
1362cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        } else {
1363cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
1364cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                unsigned a = aa[i];
1365cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                if (0 != a) {
1366cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkAlpha dstA = dst[i];
1367cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1368cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    unsigned A = SkGetPackedA32(res);
1369cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    if (0xFF != a) {
1370cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1371cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    }
1372cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    dst[i] = SkToU8(A);
1373cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                }
1374cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
1375cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        }
1376cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    }
1377cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org}
1378cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org
13796f980c6a2354fed70a6258fb4dd4155936660930djsollen@google.com#if SK_SUPPORT_GPU
1380b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
1381b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                              GrTexture* background) const {
1382df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (XferEffect::IsSupportedMode(fMode)) {
1383b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        if (fp) {
1384b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            *fp = XferEffect::Create(fMode, background);
1385b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkASSERT(*fp);
13866f980c6a2354fed70a6258fb4dd4155936660930djsollen@google.com        }
1387df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        return true;
1388f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    }
1389df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    return false;
1390df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org}
139126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com#endif
1392f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com
1393d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.orgconst char* SkXfermode::ModeName(Mode mode) {
1394d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1395d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    const char* gModeStrings[] = {
1396b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1397b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
13988d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1399d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1400d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1401b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    };
1402d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    return gModeStrings[mode];
1403d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1404d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org}
1405d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org
14060f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1407d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.orgvoid SkProcCoeffXfermode::toString(SkString* str) const {
1408d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    str->append("SkProcCoeffXfermode: ");
1409b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
1410b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append("mode: ");
1411d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    str->append(ModeName(fMode));
1412b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
1413b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    static const char* gCoeffStrings[kCoeffCount] = {
141498ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1415b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    };
1416b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
1417b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append(" src: ");
1418b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    if (CANNOT_USE_COEFF == fSrcCoeff) {
1419b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append("can't use");
1420b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    } else {
1421b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append(gCoeffStrings[fSrcCoeff]);
1422b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    }
1423b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
1424b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append(" dst: ");
1425b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    if (CANNOT_USE_COEFF == fDstCoeff) {
1426b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append("can't use");
1427b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    } else {
1428b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append(gCoeffStrings[fDstCoeff]);
1429b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    }
1430b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1431b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1432b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkClearXfermode : public SkProcCoeffXfermode {
14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
14370a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkClearXfermode* Create(const ProcCoeff& rec) {
14380a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkClearXfermode, (rec));
14390a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
144130da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
144230da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14440f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
14451447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
14461447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
14470a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
14489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
14499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkClearXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
14509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
14511447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
1452b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    typedef SkProcCoeffXfermode INHERITED;
14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
145686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                             const SkPMColor* SK_RESTRICT, int count,
145730da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                             const SkAlpha* SK_RESTRICT aa) const {
145886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && count >= 0);
14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
146086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
146186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        memset(dst, 0, count << 2);
146286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
146386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
146486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
146586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (0xFF == a) {
146686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = 0;
146786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            } else if (a != 0) {
146886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
147286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
147386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
147486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                             const SkPMColor* SK_RESTRICT, int count,
147530da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                             const SkAlpha* SK_RESTRICT aa) const {
147686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && count >= 0);
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
147886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
147986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        memset(dst, 0, count);
148086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
148186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
148286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
148386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (0xFF == a) {
148486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = 0;
148586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            } else if (0 != a) {
148686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
149086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
14911447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
14920f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1493b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkClearXfermode::toString(SkString* str) const {
1494b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1495b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1496b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1497b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
149886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com///////////////////////////////////////////////////////////////////////////////
149986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
150086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comclass SkSrcXfermode : public SkProcCoeffXfermode {
150186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.compublic:
15020a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkSrcXfermode* Create(const ProcCoeff& rec) {
15030a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkSrcXfermode, (rec));
15040a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
150586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
150630da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
150730da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15090f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
15101447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
15111447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
15120a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
15139fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
15149fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkSrcXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {}
15159fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1516b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    typedef SkProcCoeffXfermode INHERITED;
15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
151986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
152086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                           const SkPMColor* SK_RESTRICT src, int count,
152130da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                           const SkAlpha* SK_RESTRICT aa) const {
152286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src && count >= 0);
15231447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
152486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
152586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        memcpy(dst, src, count << 2);
152686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
152786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
152886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
152986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (a == 0xFF) {
153086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = src[i];
153186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            } else if (a != 0) {
153286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = SkFourByteInterp(src[i], dst[i], a);
153386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            }
153486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        }
153586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
153686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
153786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
153886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
153986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                           const SkPMColor* SK_RESTRICT src, int count,
154030da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                           const SkAlpha* SK_RESTRICT aa) const {
154186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src && count >= 0);
15421447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
154386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
154486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
154586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            dst[i] = SkToU8(SkGetPackedA32(src[i]));
15468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
154786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
154886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
154986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
155086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (0 != a) {
155186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                unsigned srcA = SkGetPackedA32(src[i]);
155286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                if (a == 0xFF) {
155386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                    dst[i] = SkToU8(srcA);
155486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                } else {
155586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
155686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                }
155786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            }
15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
156086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
15610f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1562b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkSrcXfermode::toString(SkString* str) const {
1563b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1564b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1565b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
15661447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
156730da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com///////////////////////////////////////////////////////////////////////////////
156886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
156986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comclass SkDstInXfermode : public SkProcCoeffXfermode {
157086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.compublic:
15710a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkDstInXfermode* Create(const ProcCoeff& rec) {
15720a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkDstInXfermode, (rec));
15730a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
157486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
157530da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
15761447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
15770f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
15781447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
15791447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
15800a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
15819fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
15828b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
15839fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
15841447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkProcCoeffXfermode INHERITED;
15868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
158986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                             const SkPMColor* SK_RESTRICT src, int count,
159030da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                             const SkAlpha* SK_RESTRICT aa) const {
159186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src);
15921447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
159386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (count <= 0) {
159486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return;
159586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
159649f085dddff10473b6ebf832a974288300224e60bsalomon    if (aa) {
159786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return this->INHERITED::xfer32(dst, src, count, aa);
159886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
15991447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
160086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    do {
160186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        unsigned a = SkGetPackedA32(*src);
160286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
160386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        dst++;
160486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        src++;
160586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } while (--count != 0);
160686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
16071447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
16080f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1609b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkDstInXfermode::toString(SkString* str) const {
1610b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1611b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1612b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1613b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
161430da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com///////////////////////////////////////////////////////////////////////////////
16151447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
161686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comclass SkDstOutXfermode : public SkProcCoeffXfermode {
161786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.compublic:
16180a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
16190a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkDstOutXfermode, (rec));
16200a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
162186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
162230da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
16231447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
16240f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
16251447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
16261447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
16270a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
16289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
16299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkDstOutXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {}
16309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
16311447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkProcCoeffXfermode INHERITED;
16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
163586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
163686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                              const SkPMColor* SK_RESTRICT src, int count,
163730da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                              const SkAlpha* SK_RESTRICT aa) const {
163886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src);
163986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
164086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (count <= 0) {
164186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return;
164286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
164349f085dddff10473b6ebf832a974288300224e60bsalomon    if (aa) {
164486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return this->INHERITED::xfer32(dst, src, count, aa);
164586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
164686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
164786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    do {
164886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        unsigned a = SkGetPackedA32(*src);
164986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
165086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        dst++;
165186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        src++;
165286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } while (--count != 0);
165386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
165486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
16550f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1656b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkDstOutXfermode::toString(SkString* str) const {
1657b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1658b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1659b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1660b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
166397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgextern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1664d611864e679a58865b111e74fe7ac919cba42163commit-bot@chromium.orgextern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1665df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org
166697de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org// Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
166797de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgnamespace {
166897de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgSkXfermode* create_mode(int iMode) {
166997de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1670140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org
1671140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    ProcCoeff rec = gProcCoeffs[mode];
1672140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1673140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    if (pp != NULL) {
1674140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        rec.fProc = pp;
1675140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    }
1676140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org
1677140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    SkXfermode* xfer = NULL;
1678140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    // check if we have a platform optim for that
1679140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1680140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    if (xfm != NULL) {
1681140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        xfer = xfm;
1682140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    } else {
1683140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        // All modes can in theory be represented by the ProcCoeff rec, since
1684140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        // it contains function ptrs. However, a few modes are both simple and
1685140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        // commonly used, so we call those out for their own subclasses here.
1686140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        switch (mode) {
1687140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kClear_Mode:
1688140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkClearXfermode::Create(rec);
1689140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1690140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kSrc_Mode:
1691140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkSrcXfermode::Create(rec);
1692140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1693140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kSrcOver_Mode:
1694140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                SkASSERT(false);    // should not land here
1695140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1696140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kDstIn_Mode:
1697140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkDstInXfermode::Create(rec);
1698140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1699140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kDstOut_Mode:
1700140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkDstOutXfermode::Create(rec);
1701140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1702140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            default:
1703140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                // no special-case, just rely in the rec and its function-ptrs
17049fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1705140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1706140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        }
1707140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    }
170897de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    return xfer;
1709140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org}
171097de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org}  // namespace
171197de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org
1712140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org
1713a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comSkXfermode* SkXfermode::Create(Mode mode) {
1714a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
171686490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    if ((unsigned)mode >= kModeCount) {
171786490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org        // report error
171886490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org        return NULL;
171986490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    }
1720c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com
172197de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
172286490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    // so we can just return NULL from the factory.
172386490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    if (kSrcOver_Mode == mode) {
172486490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org        return NULL;
172586490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    }
172686490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org
172797de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, kModeCount, create_mode);
172897de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    return SkSafeRef(cached[mode]);
17298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
173143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comSkXfermodeProc SkXfermode::GetProc(Mode mode) {
173243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkXfermodeProc  proc = NULL;
173343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if ((unsigned)mode < kModeCount) {
173443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        proc = gProcCoeffs[mode].fProc;
173543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
173643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return proc;
173743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
173843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
173943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.combool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
174043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
17411447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
174243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if ((unsigned)mode >= (unsigned)kModeCount) {
174343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        // illegal mode parameter
174443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        return false;
174543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
17461447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
174743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    const ProcCoeff& rec = gProcCoeffs[mode];
17481447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
174943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (CANNOT_USE_COEFF == rec.fSC) {
175043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        return false;
175143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
17521447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
175343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
175443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (src) {
175543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        *src = rec.fSC;
175643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
175743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (dst) {
175843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        *dst = rec.fDC;
175943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
176043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return true;
176143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
176243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
176330da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == xfer) {
17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mode) {
17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *mode = kSrcOver_Mode;
17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
17688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1770c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com    return xfer->asMode(mode);
17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
177330da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
177443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (NULL == xfer) {
177543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        return ModeAsCoeff(kSrcOver_Mode, src, dst);
17768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
177743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return xfer->asCoeff(src, dst);
17788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178030da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1781e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    // if xfer==null then the mode is srcover
1782e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    Mode m = kSrcOver_Mode;
1783e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    if (xfer && !xfer->asMode(&m)) {
1784e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org        return false;
1785e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    }
1786e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    return mode == m;
1787e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org}
1788e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org
17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////// 16bit xfermode procs
17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
18148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
18388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned isa = 255 - SkGetPackedA32(src);
18431447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(
18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
18488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*********
18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    darken and lighten boil down to this.
18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    darken  = (1 - Sa) * Dc + min(Sc, Dc)
18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    lighten = (1 - Sa) * Dc + max(Sc, Dc)
18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (Sa == 0) these become
18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        darken  = Dc + min(0, Dc) = 0
18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        lighten = Dc + max(0, Dc) = Dc
18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (Sa == 1) these become
18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        darken  = min(Sc, Dc)
18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        lighten = max(Sc, Dc)
18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return 0;
18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
18888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
18898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
18908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
18918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
18998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
19008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
19018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
19028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
19038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
19048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct Proc16Rec {
19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16    fProc16_0;
19088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16    fProc16_255;
19098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16    fProc16_General;
19108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1912a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic const Proc16Rec gModeProcs16[] = {
19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 NULL,                   NULL            }, // CLEAR
19148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 src_modeproc16_255,     NULL            },
19158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
19168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
19178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
19188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 srcin_modeproc16_255,   NULL            },
19198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 dstin_modeproc16_255,   NULL            },
19208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 NULL,                   NULL            },// SRC_OUT
19218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { dstout_modeproc16_0,  NULL,                   NULL            },
19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 dstatop_modeproc16_255, NULL            },
19248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 NULL,                   NULL            }, // XOR
1925a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
1926a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // plus
19278d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com    { NULL,                 NULL,                   NULL            }, // modulate
1928a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // screen
1929a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // overlay
1930a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1931a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1932a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // colordodge
1933a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // colorburn
1934a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // hardlight
1935a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // softlight
1936a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // difference
1937a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // exclusion
1938b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // multiply
1939b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // hue
1940b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // saturation
1941b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // color
1942b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // luminosity
19438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
19448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1945a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comSkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16  proc16 = NULL;
1947a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if ((unsigned)mode < kModeCount) {
1948a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        const Proc16Rec& rec = gModeProcs16[mode];
19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned a = SkColorGetA(srcColor);
19508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == a) {
19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc16 = rec.fProc16_0;
19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else if (255 == a) {
19548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc16 = rec.fProc16_255;
19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
19568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc16 = rec.fProc16_General;
19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return proc16;
19608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1962d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1963d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1964d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1965