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
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
10c524e98f1edf06b53e65543f5f28217fa13b7aa9commit-bot@chromium.org#include "SkXfermode_opts_SSE2.h"
11df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org#include "SkXfermode_proccoeff.h"
126cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein#include "Sk4px.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
1497de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org#include "SkLazyPtr.h"
154b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
16f92ace90d89cc99b34162dda26be564e34ca80efreed#include "SkPMFloat.h"
17140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org#include "SkReadBuffer.h"
18b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#include "SkString.h"
19cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#include "SkUtilsArm.h"
20140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org#include "SkWriteBuffer.h"
21cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org
2204d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein// When implemented, the Sk4f and Sk4px xfermodes beat src/opts/SkXfermodes_opts_SSE2's.
2304d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein// When implemented, the Sk4px, but not Sk4f, xfermodes beat src/opts/SkXfermodes_arm_neon's.
243006b2e013f29f8b00f6afabbe5b2a8737840bc6reed#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
2504d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein    #define SK_4F_XFERMODES_ARE_FAST
2604d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein    #define SK_4PX_XFERMODES_ARE_FAST
2704d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein#elif defined(SK_ARM_HAS_NEON)
2804d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein    #define SK_4PX_XFERMODES_ARE_FAST
293006b2e013f29f8b00f6afabbe5b2a8737840bc6reed#endif
30f92ace90d89cc99b34162dda26be564e34ca80efreed
31cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#if !SK_ARM_NEON_IS_NONE
3204d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein    #include "SkXfermode_opts_arm_neon.h"
33cd7992ba55e8b87580f54e7c19fc033bed01640dcommit-bot@chromium.org#endif
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37da94699149a40a90731425766d3b994e34c5ba26deanm@chromium.orgstatic inline unsigned saturated_add(unsigned a, unsigned b) {
38543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    SkASSERT(a <= 255);
39543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    SkASSERT(b <= 255);
40543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    unsigned sum = a + b;
41543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    if (sum > 255) {
42543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com        sum = 255;
43543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    }
44543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com    return sum;
45543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com}
46543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com
47da94699149a40a90731425766d3b994e34c5ba26deanm@chromium.orgstatic inline int clamp_signed_byte(int n) {
48a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (n < 0) {
49a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        n = 0;
50a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else if (n > 255) {
51a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        n = 255;
52a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
53a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return n;
54a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
55a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
56da94699149a40a90731425766d3b994e34c5ba26deanm@chromium.orgstatic inline int clamp_div255round(int prod) {
57a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (prod <= 0) {
58a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return 0;
59a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else if (prod >= 255*255) {
60a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return 255;
61a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
62a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return SkDiv255Round(prod);
63a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
64a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
65a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kClear_Mode,    //!< [0, 0]
6948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
7048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return 0;
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrc_Mode,      //!< [Sa, Sc]
7448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
7548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return src;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDst_Mode,      //!< [Da, Dc]
7948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
8048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return dst;
8148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
831447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
8448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
8548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org#if 0
8648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this is the old, more-correct way, but it doesn't guarantee that dst==255
8748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // will always stay opaque
8848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
8948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org#else
9048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this is slightly faster, but more importantly guarantees that dst==255
9148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // will always stay opaque
9248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
9348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org#endif
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
9748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
9848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this is the reverse of srcover, just flipping src and dst
9948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // see srcover's comment about the 256 for opaqueness guarantees
10048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
10148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
10448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
10548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
10948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
11048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
11448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
11548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
11648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
11948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
12048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
12448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
12548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned sa = SkGetPackedA32(src);
12648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned da = SkGetPackedA32(dst);
12748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned isa = 255 - sa;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(da,
13048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
13148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
13248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
13348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
13448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
13548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
13648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
13948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
14048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned sa = SkGetPackedA32(src);
14148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned da = SkGetPackedA32(dst);
14248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned ida = 255 - da;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(sa,
14548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
14648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
14748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
14848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
14948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
15048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
15448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
15548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned sa = SkGetPackedA32(src);
15648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned da = SkGetPackedA32(dst);
15748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned isa = 255 - sa;
15848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned ida = 255 - da;
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
16148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
16248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
16348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
16448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
16548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
16648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
16748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
17048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
17148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kPlus_Mode
17248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
17348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
17448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
17548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
17648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
17748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1808d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com// kModulate_Mode
1818d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.comstatic SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
18248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
18348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
18448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
18548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
18648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
18748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
189a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int srcover_byte(int a, int b) {
190a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return a + b - SkAlphaMulAlpha(a, b);
191a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
19225cfa693420b6da4182bda42ba15970999b840ddreed@google.com
19325cfa693420b6da4182bda42ba15970999b840ddreed@google.com// kMultiply_Mode
19425cfa693420b6da4182bda42ba15970999b840ddreed@google.com// B(Cb, Cs) = Cb x Cs
19525cfa693420b6da4182bda42ba15970999b840ddreed@google.com// multiply uses its own version of blendfunc_byte because sa and da are not needed
19625cfa693420b6da4182bda42ba15970999b840ddreed@google.comstatic int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
19725cfa693420b6da4182bda42ba15970999b840ddreed@google.com    return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
19825cfa693420b6da4182bda42ba15970999b840ddreed@google.com}
19925cfa693420b6da4182bda42ba15970999b840ddreed@google.com
20025cfa693420b6da4182bda42ba15970999b840ddreed@google.comstatic SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
20125cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int sa = SkGetPackedA32(src);
20225cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int da = SkGetPackedA32(dst);
20325cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int a = srcover_byte(sa, da);
20425cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
20525cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
20625cfa693420b6da4182bda42ba15970999b840ddreed@google.com    int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
20725cfa693420b6da4182bda42ba15970999b840ddreed@google.com    return SkPackARGB32(a, r, g, b);
20825cfa693420b6da4182bda42ba15970999b840ddreed@google.com}
20925cfa693420b6da4182bda42ba15970999b840ddreed@google.com
21025cfa693420b6da4182bda42ba15970999b840ddreed@google.com// kScreen_Mode
211a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
212a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
213a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
214a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
215a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
216a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
217a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
218a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
219a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kOverlay_Mode
220a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int overlay_byte(int sc, int dc, int sa, int da) {
221a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int tmp = sc * (255 - da) + dc * (255 - sa);
222a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int rc;
223a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (2 * dc <= da) {
224a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        rc = 2 * sc * dc;
225a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
226a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        rc = sa * da - 2 * (da - dc) * (sa - sc);
227a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
228a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return clamp_div255round(rc + tmp);
229a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
230a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
231a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sa = SkGetPackedA32(src);
232a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int da = SkGetPackedA32(dst);
233a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(sa, da);
234a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
235a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
236a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
237a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
238a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
239a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
240a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kDarken_Mode
241a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int darken_byte(int sc, int dc, int sa, int da) {
242a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sd = sc * da;
243a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int ds = dc * sa;
244a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (sd < ds) {
245a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // srcover
246a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return sc + dc - SkDiv255Round(ds);
247a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
248a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // dstover
249a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return dc + sc - SkDiv255Round(sd);
250a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
251a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
253a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sa = SkGetPackedA32(src);
254a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int da = SkGetPackedA32(dst);
255a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(sa, da);
256a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
257a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
258a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
259a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
260a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
262a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kLighten_Mode
263a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int lighten_byte(int sc, int dc, int sa, int da) {
264a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sd = sc * da;
265a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int ds = dc * sa;
266a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if (sd > ds) {
267a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // srcover
268a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return sc + dc - SkDiv255Round(ds);
269a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
270a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        // dstover
271a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        return dc + sc - SkDiv255Round(sd);
272a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
273a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
274a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
275a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int sa = SkGetPackedA32(src);
276a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int da = SkGetPackedA32(dst);
277a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int a = srcover_byte(sa, da);
278a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
279a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
280a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
281a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    return SkPackARGB32(a, r, g, b);
282a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com}
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
284a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com// kColorDodge_Mode
285a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic inline int colordodge_byte(int sc, int dc, int sa, int da) {
286a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int diff = sa - sc;
287a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    int rc;
288311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    if (0 == dc) {
289311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        return SkAlphaMulAlpha(sc, 255 - da);
290311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    } else if (0 == diff) {
291a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
292a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    } else {
293311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        diff = dc * sa / diff;
294311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
295a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    }
296311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    return clamp_div255round(rc);
29748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
29848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
29948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
30048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
30148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
30248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
30348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
30448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
30548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
30648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
30748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
30848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kColorBurn_Mode
30948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int colorburn_byte(int sc, int dc, int sa, int da) {
31048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int rc;
311311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    if (dc == da) {
312311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
31348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else if (0 == sc) {
31448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        return SkAlphaMulAlpha(dc, 255 - sa);
31548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
316311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        int tmp = (da - dc) * sa / sc;
317311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        rc = sa * (da - ((da < tmp) ? da : tmp))
318311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org            + sc * (255 - da) + dc * (255 - sa);
31948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
320311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    return clamp_div255round(rc);
32148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
32248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
32348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
32448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
32548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
32648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
32748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
32848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
32948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
33048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
33148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
33248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kHardLight_Mode
33348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int hardlight_byte(int sc, int dc, int sa, int da) {
33448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int rc;
33548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (2 * sc <= sa) {
33648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = 2 * sc * dc;
33748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
33848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = sa * da - 2 * (da - dc) * (sa - sc);
33948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
34048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
34148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
34248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
34348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
34448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
34548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
34648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
34748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
34848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
34948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
35048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
35148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
35248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// returns 255 * sqrt(n/255)
35348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic U8CPU sqrt_unit_byte(U8CPU n) {
35448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkSqrtBits(n, 15+4);
35548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
35648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
35748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kSoftLight_Mode
35848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int softlight_byte(int sc, int dc, int sa, int da) {
35948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int m = da ? dc * 256 / da : 0;
36048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int rc;
36148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (2 * sc <= sa) {
36248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
36348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else if (4 * dc <= da) {
36448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
36548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
36648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
36748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        int tmp = sqrt_unit_byte(m) - m;
36848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
36948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
37048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
37148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
37248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
37348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
37448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
37548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
37648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
37748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
37848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
37948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
38048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
38148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
38248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kDifference_Mode
38348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic inline int difference_byte(int sc, int dc, int sa, int da) {
38448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int tmp = SkMin32(sc * da, dc * sa);
38548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
38648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
38748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
38848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
38948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
39048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
39148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
39248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
39348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
39448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
39548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
39648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
39748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org// kExclusion_Mode
398e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.orgstatic inline int exclusion_byte(int sc, int dc, int, int) {
39948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // this equations is wacky, wait for SVG to confirm it
400e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org    //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
401e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org
402e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org    // The above equation can be simplified as follows
403e38e53b5327e2618a97fb26a697a477b74c44d3dcommit-bot@chromium.org    int r = 255*(sc + dc) - 2 * sc * dc;
40448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return clamp_div255round(r);
40548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
40648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.orgstatic SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
40748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int sa = SkGetPackedA32(src);
40848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int da = SkGetPackedA32(dst);
40948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int a = srcover_byte(sa, da);
41048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
41148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
41248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
41348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return SkPackARGB32(a, r, g, b);
41448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
41548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
416b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// The CSS compositing spec introduces the following formulas:
417b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
418b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
419b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// while PDF and CG uses the one from Rec. Rec. 601
420b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
421b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int Lum(int r, int g, int b)
422b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org{
423311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org    return SkDiv255Round(r * 77 + g * 150 + b * 28);
424b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
425b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
426b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int min2(int a, int b) { return a < b ? a : b; }
427b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int max2(int a, int b) { return a > b ? a : b; }
42864334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com#define minimum(a, b, c) min2(min2(a, b), c)
42964334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com#define maximum(a, b, c) max2(max2(a, b), c)
430b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
431b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline int Sat(int r, int g, int b) {
432b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return maximum(r, g, b) - minimum(r, g, b);
433b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
434b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
435b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
4363c1ea3a7e5127513d3b3335d92292e02f273efefreed@google.com    if(*Cmax > *Cmin) {
437311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
438b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        *Cmax = s;
439b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
440b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        *Cmax = 0;
441b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        *Cmid = 0;
442b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
443b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
444b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    *Cmin = 0;
445b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
446b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
447b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic inline void SetSat(int* r, int* g, int* b, int s) {
448b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(*r <= *g) {
449b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        if(*g <= *b) {
450b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org            setSaturationComponents(r, g, b, s);
451b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        } else if(*r <= *b) {
452b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org            setSaturationComponents(r, b, g, s);
453b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        } else {
454b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org            setSaturationComponents(b, r, g, s);
455b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        }
456b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else if(*r <= *b) {
457b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        setSaturationComponents(g, r, b, s);
458b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else if(*g <= *b) {
459b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        setSaturationComponents(g, b, r, s);
460b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
461b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        setSaturationComponents(b, g, r, s);
462b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
463b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
464b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
465311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.orgstatic inline void clipColor(int* r, int* g, int* b, int a) {
466b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int L = Lum(*r, *g, *b);
467b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int n = minimum(*r, *g, *b);
468b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int x = maximum(*r, *g, *b);
469b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org    int denom;
470b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org    if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
471b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *r = L + SkMulDiv(*r - L, L, denom);
472b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *g = L + SkMulDiv(*g - L, L, denom);
473b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *b = L + SkMulDiv(*b - L, L, denom);
474b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
475b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
476b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org    if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
477b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       int numer = a - L;
478b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *r = L + SkMulDiv(*r - L, numer, denom);
479b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *g = L + SkMulDiv(*g - L, numer, denom);
480b85ebea5267ec0b9630d828840fa2d7df29b9f43commit-bot@chromium.org       *b = L + SkMulDiv(*b - L, numer, denom);
481b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
482b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
483b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
484311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.orgstatic inline void SetLum(int* r, int* g, int* b, int a, int l) {
485b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  int d = l - Lum(*r, *g, *b);
486b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  *r +=  d;
487b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  *g +=  d;
488b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org  *b +=  d;
489b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
490311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org  clipColor(r, g, b, a);
491b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
492b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
493b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// non-separable blend modes are done in non-premultiplied alpha
494b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
495311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org  clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
496b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
497b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kHue_Mode
498b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
499b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
500b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
501b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
502b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
503b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
504b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
505b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
506b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
507b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
508b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
509b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
510b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Sr, Sg, Sb;
511b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
512b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
513311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sr = sr * sa;
514311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sg = sg * sa;
515311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sb = sb * sa;
516311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
517311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
518b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
519b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sr = 0;
520b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sg = 0;
521b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sb = 0;
522b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
523b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
524b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
525b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
526b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
527b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
528b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
529b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
530b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
531b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kSaturation_Mode
532b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
53364334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
534b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
535b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
536b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
537b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
538b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
539b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
540b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
541b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
542b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
543b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
544b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Dr, Dg, Db;
545b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
546b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
547311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dr = dr * sa;
548311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dg = dg * sa;
549311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Db = db * sa;
550311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
551311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
552b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
553b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dr = 0;
554b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dg = 0;
555b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Db = 0;
556b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
557b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
558b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
559b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
560b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
561b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
562b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
563b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
564b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
565b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kColor_Mode
566b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
56764334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
568b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
569b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
570b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
571b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
572b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
573b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
574b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
575b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
576b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
577b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
578b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Sr, Sg, Sb;
579b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
580b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
581311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sr = sr * da;
582311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sg = sg * da;
583311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Sb = sb * da;
584311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
585b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
586b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sr = 0;
587b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sg = 0;
588b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Sb = 0;
589b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
590b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
591b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
592b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
593b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
594b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
595b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
596b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
597b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
598b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// kLuminosity_Mode
599b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
60064334352cc3f29f52dfa07225d65eb218d2fd830skia.committer@gmail.com// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
601b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.orgstatic SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
602b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sr = SkGetPackedR32(src);
603b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sg = SkGetPackedG32(src);
604b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sb = SkGetPackedB32(src);
605b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int sa = SkGetPackedA32(src);
606b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
607b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dr = SkGetPackedR32(dst);
608b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int dg = SkGetPackedG32(dst);
609b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int db = SkGetPackedB32(dst);
610b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int da = SkGetPackedA32(dst);
611b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int Dr, Dg, Db;
612b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
613b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    if(sa && da) {
614311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dr = dr * sa;
615311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Dg = dg * sa;
616311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        Db = db * sa;
617311d4eafab513adae3ef6c37dd4d573844bccd63commit-bot@chromium.org        SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
618b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    } else {
619b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dr = 0;
620b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Dg = 0;
621b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org        Db = 0;
622b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    }
623b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
624b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int a = srcover_byte(sa, da);
625b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
626b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
627b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
628b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    return SkPackARGB32(a, r, g, b);
629b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org}
630b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org
631df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.orgconst ProcCoeff gProcCoeffs[] = {
63248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
63348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
63448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
63548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
63648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
63748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
63848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
63948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
64048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
64148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
64248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
64348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
64448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
645521e34e2912d835ab1b33a06cb8fb416510d7c53reed@google.com    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
6468d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
647b0091b8382970c28dba57adc170e27b2e3d7394absalomon@google.com    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
64848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
64948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
65725cfa693420b6da4182bda42ba15970999b840ddreed@google.com    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
658b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
659b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
660b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
661b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
66248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org};
66348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
66448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
66548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
66630da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::asMode(Mode* mode) const {
667c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com    return false;
66848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
66948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
670b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
6711a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.org    return false;
672f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com}
673f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com
674378092f3d10b1dd62967f419c35cfefec7c10ee7egdanielbool SkXfermode::asXPFactory(GrXPFactory**) const {
675378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    return false;
676378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel}
677378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
678378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
679378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#if SK_SUPPORT_GPU
680378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "effects/GrPorterDuffXferProcessor.h"
681378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel
68258136167fc596fb945b58b34f500cf370c0dec7cegdanielbool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
683f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    if (NULL == xfermode) {
68458136167fc596fb945b58b34f500cf370c0dec7cegdaniel        if (xpf) {
68558136167fc596fb945b58b34f500cf370c0dec7cegdaniel            *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
68658136167fc596fb945b58b34f500cf370c0dec7cegdaniel        }
6871a6382f5e76c051ffbbb60f3a68524dfe57cf798senorblanco@chromium.org        return true;
688f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    } else {
68958136167fc596fb945b58b34f500cf370c0dec7cegdaniel        return xfermode->asXPFactory(xpf);
690f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    }
691f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com}
692378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#else
69358136167fc596fb945b58b34f500cf370c0dec7cegdanielbool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
694378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel    return false;
695378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel}
696378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#endif
697f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com
69830da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.comSkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
69948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    // no-op. subclasses should override this
70048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    return dst;
70148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
70248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
703a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
704a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                        const SkPMColor* SK_RESTRICT src, int count,
70530da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha* SK_RESTRICT aa) const {
70648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    SkASSERT(dst && src && count >= 0);
70748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
70848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (NULL == aa) {
70948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
71048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            dst[i] = this->xferColor(src[i], dst[i]);
71148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
71248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
71348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
71448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            unsigned a = aa[i];
71548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            if (0 != a) {
71648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor dstC = dst[i];
71748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor C = this->xferColor(src[i], dstC);
71848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                if (0xFF != a) {
71948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                    C = SkFourByteInterp(C, dstC, a);
72048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                }
72148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                dst[i] = C;
72248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            }
72348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
72448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
72548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
72648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
727a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkXfermode::xfer16(uint16_t* dst,
728a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.com                        const SkPMColor* SK_RESTRICT src, int count,
72930da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha* SK_RESTRICT aa) const {
73048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    SkASSERT(dst && src && count >= 0);
73148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
73248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (NULL == aa) {
73348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
73448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
73548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
73648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
73748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
73848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
73948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            unsigned a = aa[i];
74048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            if (0 != a) {
74148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
74248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkPMColor C = this->xferColor(src[i], dstC);
74348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                if (0xFF != a) {
74448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                    C = SkFourByteInterp(C, dstC, a);
74548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                }
74648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                dst[i] = SkPixel32ToPixel16_ToU16(C);
74748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            }
74848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
74948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
75048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
75148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
752a87cd2af4c7f46ba8437c2e500805c9deb9e3a40tomhudson@google.comvoid SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
75348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                        const SkPMColor src[], int count,
75430da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                        const SkAlpha* SK_RESTRICT aa) const {
75548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    SkASSERT(dst && src && count >= 0);
75648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
75748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    if (NULL == aa) {
75848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
75948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
76048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            dst[i] = SkToU8(SkGetPackedA32(res));
76148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
76248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    } else {
76348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        for (int i = count - 1; i >= 0; --i) {
76448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            unsigned a = aa[i];
76548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            if (0 != a) {
76648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                SkAlpha dstA = dst[i];
76748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                unsigned A = SkGetPackedA32(this->xferColor(src[i],
76848543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
76948543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                if (0xFF != a) {
77048543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
77148543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                }
77248543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org                dst[i] = SkToU8(A);
77348543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org            }
77448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org        }
77548543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
77648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org}
77748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org
778dcfb7cf336cafffd8d149c908b615e1deaa3a49begdanielbool SkXfermode::supportsCoverageAsAlpha() const {
779dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    return false;
780dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel}
781dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
782dcfb7cf336cafffd8d149c908b615e1deaa3a49begdanielbool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
783dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    return false;
784dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel}
785dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
78648543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
78748543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org///////////////////////////////////////////////////////////////////////////////
788a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
7899fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
7909fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    uint32_t mode32 = buffer.read32();
7910f7197bc0ddbe6c61732d6fe69df86bdba00a060senorblanco    if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
7929fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
7939fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
7949fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkXfermode::Create((SkXfermode::Mode)mode32);
7959fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
7969fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
7979fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedvoid SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
7989fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    buffer.write32(fMode);
7999fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
80052314f82ba8696e957e70eabde672b6470fedf7areed@google.com
801df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.orgbool SkProcCoeffXfermode::asMode(Mode* mode) const {
802df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (mode) {
803df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        *mode = fMode;
80448543277728fdf66b993f17421f65fba532a23a2vandebo@chromium.org    }
805df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    return true;
806df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org}
807c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com
808dcfb7cf336cafffd8d149c908b615e1deaa3a49begdanielbool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
809df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    if (CANNOT_USE_COEFF == fSrcCoeff) {
810df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        return false;
811c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com    }
812c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com
813dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    switch (fDstCoeff) {
814dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kOne_Coeff:
815dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kISA_Coeff:
816dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kISC_Coeff:
817dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return true;
818dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        default:
819dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return false;
820dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    }
821dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel}
822dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
823dcfb7cf336cafffd8d149c908b615e1deaa3a49begdanielbool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
824dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    if (CANNOT_USE_COEFF == fSrcCoeff) {
825dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        return false;
826df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    }
8273d626834b4b5ee2d6dda34da365dfe40520253aamtklein
828dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
829dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
830dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        return false;
83184cc1ebc5a4789e93e23c65eb4014ef5b8b0bab4commit-bot@chromium.org    }
8323d626834b4b5ee2d6dda34da365dfe40520253aamtklein
833dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    switch (fDstCoeff) {
834dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kZero_Coeff:
835dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return true;
836dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kISA_Coeff:
837dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
838dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kSA_Coeff:
839dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
840dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel                   SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
841dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        case SkXfermode::kSC_Coeff:
842dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
843dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        default:
844dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel            return false;
845dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    }
846dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
847df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org}
8486f980c6a2354fed70a6258fb4dd4155936660930djsollen@google.com
849cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.orgvoid SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
850cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT src, int count,
851cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkAlpha* SK_RESTRICT aa) const {
852cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkASSERT(dst && src && count >= 0);
85360bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
854cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkXfermodeProc proc = fProc;
85560bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
85649f085dddff10473b6ebf832a974288300224e60bsalomon    if (proc) {
857cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        if (NULL == aa) {
858cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
859cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                dst[i] = proc(src[i], dst[i]);
860cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
861cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        } else {
862cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
863cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                unsigned a = aa[i];
864cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                if (0 != a) {
865cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor dstC = dst[i];
866cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor C = proc(src[i], dstC);
867cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    if (a != 0xFF) {
868cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                        C = SkFourByteInterp(C, dstC, a);
869cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    }
870cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    dst[i] = C;
871cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                }
872cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
873cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        }
874cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    }
875cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org}
876cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org
877cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.orgvoid SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
878cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT src, int count,
879cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkAlpha* SK_RESTRICT aa) const {
880cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkASSERT(dst && src && count >= 0);
88160bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
882cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkXfermodeProc proc = fProc;
88360bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
88449f085dddff10473b6ebf832a974288300224e60bsalomon    if (proc) {
885cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        if (NULL == aa) {
886cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
887cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
888cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
889cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
890cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        } else {
891cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
892cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                unsigned a = aa[i];
893cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                if (0 != a) {
894cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
895cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor C = proc(src[i], dstC);
896cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    if (0xFF != a) {
897cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                        C = SkFourByteInterp(C, dstC, a);
898cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    }
899cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    dst[i] = SkPixel32ToPixel16_ToU16(C);
900cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                }
901cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
902cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        }
903cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    }
904cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org}
905cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org
906cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.orgvoid SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
907cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkPMColor* SK_RESTRICT src, int count,
908cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                                 const SkAlpha* SK_RESTRICT aa) const {
909cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkASSERT(dst && src && count >= 0);
91060bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
911cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    SkXfermodeProc proc = fProc;
91260bd7519a9db4ddddd95e490f93165e5676f90f5skia.committer@gmail.com
91349f085dddff10473b6ebf832a974288300224e60bsalomon    if (proc) {
914cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        if (NULL == aa) {
915cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
916cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
917cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                dst[i] = SkToU8(SkGetPackedA32(res));
918cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
919cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        } else {
920cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            for (int i = count - 1; i >= 0; --i) {
921cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                unsigned a = aa[i];
922cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                if (0 != a) {
923cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkAlpha dstA = dst[i];
924cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
925cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    unsigned A = SkGetPackedA32(res);
926cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    if (0xFF != a) {
927cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
928cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    }
929cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                    dst[i] = SkToU8(A);
930cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org                }
931cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org            }
932cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org        }
933cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org    }
934cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org}
935cc277b729b16c0d8d042f9ae1db6563fb4538d88commit-bot@chromium.org
9366f980c6a2354fed70a6258fb4dd4155936660930djsollen@google.com#if SK_SUPPORT_GPU
9370063a9b69a6a5d377f207c2aa1ea1e7220c19ba9egdaniel#include "effects/GrCustomXfermode.h"
9380063a9b69a6a5d377f207c2aa1ea1e7220c19ba9egdaniel
939b0a8a377f832c59cee939ad721e1f87d378b7142joshualittbool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
940b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt                                              GrTexture* background) const {
9410063a9b69a6a5d377f207c2aa1ea1e7220c19ba9egdaniel    if (GrCustomXfermode::IsSupportedMode(fMode)) {
942b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        if (fp) {
9430063a9b69a6a5d377f207c2aa1ea1e7220c19ba9egdaniel            *fp = GrCustomXfermode::CreateFP(fMode, background);
944b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt            SkASSERT(*fp);
9456f980c6a2354fed70a6258fb4dd4155936660930djsollen@google.com        }
946df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org        return true;
947f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com    }
948df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org    return false;
949df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org}
95054f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel
95154f0e9d784122cfd3f5968e0fea971d5b5a4805aegdanielbool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
95258136167fc596fb945b58b34f500cf370c0dec7cegdaniel    if (CANNOT_USE_COEFF != fSrcCoeff) {
95358136167fc596fb945b58b34f500cf370c0dec7cegdaniel        if (xp) {
95458136167fc596fb945b58b34f500cf370c0dec7cegdaniel            *xp = GrPorterDuffXPFactory::Create(fMode);
95558136167fc596fb945b58b34f500cf370c0dec7cegdaniel            SkASSERT(*xp);
95658136167fc596fb945b58b34f500cf370c0dec7cegdaniel        }
95758136167fc596fb945b58b34f500cf370c0dec7cegdaniel        return true;
95858136167fc596fb945b58b34f500cf370c0dec7cegdaniel    }
95958136167fc596fb945b58b34f500cf370c0dec7cegdaniel
96054f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel    if (GrCustomXfermode::IsSupportedMode(fMode)) {
96154f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel        if (xp) {
96254f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel            *xp = GrCustomXfermode::CreateXPFactory(fMode);
96354f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel            SkASSERT(*xp);
96454f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel        }
96554f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel        return true;
96654f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel    }
96754f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel    return false;
96854f0e9d784122cfd3f5968e0fea971d5b5a4805aegdaniel}
96926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com#endif
970f51c01328dc52a87c07e056d6fc4eb7452ccac7absalomon@google.com
971d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.orgconst char* SkXfermode::ModeName(Mode mode) {
972d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
973d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    const char* gModeStrings[] = {
974b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
975b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
9768d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
977d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
978d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
979b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    };
980d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    return gModeStrings[mode];
981d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
982d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org}
983d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org
9840f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
985d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.orgvoid SkProcCoeffXfermode::toString(SkString* str) const {
986d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    str->append("SkProcCoeffXfermode: ");
987b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
988b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append("mode: ");
989d7aaf6034e519ea9b70649c1d344f2f24de90ccbcommit-bot@chromium.org    str->append(ModeName(fMode));
990b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
991b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    static const char* gCoeffStrings[kCoeffCount] = {
99298ded84b80918ac1e40224c125922941f3b2eb03skia.committer@gmail.com        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
993b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    };
994b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
995b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append(" src: ");
996b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    if (CANNOT_USE_COEFF == fSrcCoeff) {
997b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append("can't use");
998b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    } else {
999b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append(gCoeffStrings[fSrcCoeff]);
1000b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    }
1001b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
1002b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    str->append(" dst: ");
1003b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    if (CANNOT_USE_COEFF == fDstCoeff) {
1004b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append("can't use");
1005b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    } else {
1006b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com        str->append(gCoeffStrings[fDstCoeff]);
1007b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    }
1008b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1009b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1010b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkClearXfermode : public SkProcCoeffXfermode {
10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
10150a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkClearXfermode* Create(const ProcCoeff& rec) {
10160a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkClearXfermode, (rec));
10170a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
101936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
102036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10220f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
10231447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
10241447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
10250a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
10261447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
1027b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    typedef SkProcCoeffXfermode INHERITED;
10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
103086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
103186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                             const SkPMColor* SK_RESTRICT, int count,
103230da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                             const SkAlpha* SK_RESTRICT aa) const {
103386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && count >= 0);
10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
103586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
103686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        memset(dst, 0, count << 2);
103786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
103886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
103986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
104086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (0xFF == a) {
104186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = 0;
104286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            } else if (a != 0) {
104386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
104786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
104886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
104986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                             const SkPMColor* SK_RESTRICT, int count,
105030da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                             const SkAlpha* SK_RESTRICT aa) const {
105186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && count >= 0);
10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
105386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
105486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        memset(dst, 0, count);
105586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
105686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
105786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
105886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (0xFF == a) {
105986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = 0;
106086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            } else if (0 != a) {
106186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
106586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
10661447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
10670f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1068b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkClearXfermode::toString(SkString* str) const {
1069b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1070b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1071b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1072b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
107386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com///////////////////////////////////////////////////////////////////////////////
107486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
107586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comclass SkSrcXfermode : public SkProcCoeffXfermode {
107686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.compublic:
10770a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkSrcXfermode* Create(const ProcCoeff& rec) {
10780a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkSrcXfermode, (rec));
10790a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
108086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
108136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
108236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10840f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
10851447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
10861447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
10870a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1088b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    typedef SkProcCoeffXfermode INHERITED;
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
109186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
109286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                           const SkPMColor* SK_RESTRICT src, int count,
109330da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                           const SkAlpha* SK_RESTRICT aa) const {
109486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src && count >= 0);
10951447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
109686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
109786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        memcpy(dst, src, count << 2);
109886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
109986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
110086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
110186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (a == 0xFF) {
110286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = src[i];
110386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            } else if (a != 0) {
110486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                dst[i] = SkFourByteInterp(src[i], dst[i], a);
110586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            }
110686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        }
110786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
110886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
110986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
111086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
111186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                           const SkPMColor* SK_RESTRICT src, int count,
111230da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                           const SkAlpha* SK_RESTRICT aa) const {
111386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src && count >= 0);
11141447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
111586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (NULL == aa) {
111686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
111786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            dst[i] = SkToU8(SkGetPackedA32(src[i]));
11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
111986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } else {
112086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        for (int i = count - 1; i >= 0; --i) {
112186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            unsigned a = aa[i];
112286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            if (0 != a) {
112386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                unsigned srcA = SkGetPackedA32(src[i]);
112486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                if (a == 0xFF) {
112586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                    dst[i] = SkToU8(srcA);
112686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                } else {
112786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
112886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                }
112986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com            }
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
113286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
11330f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1134b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkSrcXfermode::toString(SkString* str) const {
1135b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1136b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1137b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
11381447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
113930da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com///////////////////////////////////////////////////////////////////////////////
114086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
114186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comclass SkDstInXfermode : public SkProcCoeffXfermode {
114286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.compublic:
11430a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkDstInXfermode* Create(const ProcCoeff& rec) {
11440a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkDstInXfermode, (rec));
11450a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
114686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
114736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
11481447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
11490f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
11501447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
11511447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
11520a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
11531447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkProcCoeffXfermode INHERITED;
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
115786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
115886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                             const SkPMColor* SK_RESTRICT src, int count,
115930da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                             const SkAlpha* SK_RESTRICT aa) const {
116086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src);
11611447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
116286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (count <= 0) {
116386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return;
116486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
116549f085dddff10473b6ebf832a974288300224e60bsalomon    if (aa) {
116686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return this->INHERITED::xfer32(dst, src, count, aa);
116786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
11681447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
116986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    do {
117086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        unsigned a = SkGetPackedA32(*src);
117186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
117286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        dst++;
117386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        src++;
117486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } while (--count != 0);
117586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
11761447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
11770f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1178b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkDstInXfermode::toString(SkString* str) const {
1179b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1180b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1181b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1182b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
118330da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com///////////////////////////////////////////////////////////////////////////////
11841447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
1185f92ace90d89cc99b34162dda26be564e34ca80efreed/* These modes can merge coverage into src-alpha
1186f92ace90d89cc99b34162dda26be564e34ca80efreed *
1187f92ace90d89cc99b34162dda26be564e34ca80efreed{ dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
1188f92ace90d89cc99b34162dda26be564e34ca80efreed{ srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
1189f92ace90d89cc99b34162dda26be564e34ca80efreed{ dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
1190f92ace90d89cc99b34162dda26be564e34ca80efreed{ dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
1191f92ace90d89cc99b34162dda26be564e34ca80efreed{ srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
1192f92ace90d89cc99b34162dda26be564e34ca80efreed{ xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
1193f92ace90d89cc99b34162dda26be564e34ca80efreed{ plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
1194f92ace90d89cc99b34162dda26be564e34ca80efreed{ screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
1195f92ace90d89cc99b34162dda26be564e34ca80efreed*/
1196f92ace90d89cc99b34162dda26be564e34ca80efreed
1197f92ace90d89cc99b34162dda26be564e34ca80efreedstatic const float gInv255 = 0.0039215683f; //  (1.0f / 255) - ULP == SkBits2Float(0x3B808080)
1198f92ace90d89cc99b34162dda26be564e34ca80efreed
1199f92ace90d89cc99b34162dda26be564e34ca80efreedstatic Sk4f ramp(const Sk4f& v0, const Sk4f& v1, const Sk4f& t) {
1200f92ace90d89cc99b34162dda26be564e34ca80efreed    return v0 + (v1 - v0) * t;
1201f92ace90d89cc99b34162dda26be564e34ca80efreed}
1202f92ace90d89cc99b34162dda26be564e34ca80efreed
1203f92ace90d89cc99b34162dda26be564e34ca80efreedstatic Sk4f clamp_255(const Sk4f& value) {
1204f8f5478f92d6bce30448203857156a4cda4a13d7reed    return Sk4f::Min(Sk4f(255), value);
1205f8f5478f92d6bce30448203857156a4cda4a13d7reed}
1206f8f5478f92d6bce30448203857156a4cda4a13d7reed
1207f8f5478f92d6bce30448203857156a4cda4a13d7reedstatic Sk4f clamp_0_255(const Sk4f& value) {
1208f8f5478f92d6bce30448203857156a4cda4a13d7reed    return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value));
1209f92ace90d89cc99b34162dda26be564e34ca80efreed}
1210f92ace90d89cc99b34162dda26be564e34ca80efreed
1211f92ace90d89cc99b34162dda26be564e34ca80efreed/**
1212f92ace90d89cc99b34162dda26be564e34ca80efreed *  Some modes can, due to very slight numerical error, generate "invalid" pmcolors...
1213f92ace90d89cc99b34162dda26be564e34ca80efreed *
1214f92ace90d89cc99b34162dda26be564e34ca80efreed *  e.g.
1215f92ace90d89cc99b34162dda26be564e34ca80efreed *      alpha = 100.9999
1216f92ace90d89cc99b34162dda26be564e34ca80efreed *      red   = 101
1217f92ace90d89cc99b34162dda26be564e34ca80efreed *
1218f92ace90d89cc99b34162dda26be564e34ca80efreed *  or
1219f92ace90d89cc99b34162dda26be564e34ca80efreed *      alpha = 255.0001
1220f92ace90d89cc99b34162dda26be564e34ca80efreed *
1221f92ace90d89cc99b34162dda26be564e34ca80efreed *  If we know we're going to write-out the values as bytes, we can relax these somewhat,
1222f92ace90d89cc99b34162dda26be564e34ca80efreed *  since we only really need to enforce that the bytes are valid premul...
1223f92ace90d89cc99b34162dda26be564e34ca80efreed *
1224f92ace90d89cc99b34162dda26be564e34ca80efreed *  To that end, this method asserts that the resulting pmcolor will be valid, but does not call
1225f92ace90d89cc99b34162dda26be564e34ca80efreed *  SkPMFloat::isValid(), as that would fire sometimes, but not result in a bad pixel.
1226f92ace90d89cc99b34162dda26be564e34ca80efreed */
1227f92ace90d89cc99b34162dda26be564e34ca80efreedstatic inline SkPMFloat check_as_pmfloat(const Sk4f& value) {
1228f92ace90d89cc99b34162dda26be564e34ca80efreed    SkPMFloat pm = value;
1229f92ace90d89cc99b34162dda26be564e34ca80efreed#ifdef SK_DEBUG
12303d626834b4b5ee2d6dda34da365dfe40520253aamtklein    (void)pm.round();
1231f92ace90d89cc99b34162dda26be564e34ca80efreed#endif
1232f92ace90d89cc99b34162dda26be564e34ca80efreed    return pm;
1233f92ace90d89cc99b34162dda26be564e34ca80efreed}
1234f92ace90d89cc99b34162dda26be564e34ca80efreed
1235f92ace90d89cc99b34162dda26be564e34ca80efreed//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
1236f92ace90d89cc99b34162dda26be564e34ca80efreedstruct SrcATop4f {
1237f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1238f92ace90d89cc99b34162dda26be564e34ca80efreed        const Sk4f inv255(gInv255);
12397792dbf7ea089b3bcb81792a3ecda8a6f8b421e7mtklein        return check_as_pmfloat(dst + (src * Sk4f(dst.a()) - dst * Sk4f(src.a())) * inv255);
1240f92ace90d89cc99b34162dda26be564e34ca80efreed    }
12412d8d33e9e825f9919875be64a71b746189b385bemtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
12422d8d33e9e825f9919875be64a71b746189b385bemtklein        return Sk4px::Wide(src.mulWiden(dst.alphas()) + dst.mulWiden(src.alphas().inv()))
12432d8d33e9e825f9919875be64a71b746189b385bemtklein            .div255RoundNarrow();
12442d8d33e9e825f9919875be64a71b746189b385bemtklein    }
1245f92ace90d89cc99b34162dda26be564e34ca80efreed    static const bool kFoldCoverageIntoSrcAlpha = true;
1246f92ace90d89cc99b34162dda26be564e34ca80efreed    static const SkXfermode::Mode kMode = SkXfermode::kSrcATop_Mode;
1247f92ace90d89cc99b34162dda26be564e34ca80efreed};
1248f92ace90d89cc99b34162dda26be564e34ca80efreed
1249f92ace90d89cc99b34162dda26be564e34ca80efreed//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
1250f92ace90d89cc99b34162dda26be564e34ca80efreedstruct DstATop4f {
1251f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
12522d8d33e9e825f9919875be64a71b746189b385bemtklein        return SrcATop4f::Xfer(dst, src);
12532d8d33e9e825f9919875be64a71b746189b385bemtklein    }
12542d8d33e9e825f9919875be64a71b746189b385bemtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
12552d8d33e9e825f9919875be64a71b746189b385bemtklein        return SrcATop4f::Xfer(dst, src);
1256f92ace90d89cc99b34162dda26be564e34ca80efreed    }
1257f92ace90d89cc99b34162dda26be564e34ca80efreed    static const bool kFoldCoverageIntoSrcAlpha = false;
1258f92ace90d89cc99b34162dda26be564e34ca80efreed    static const SkXfermode::Mode kMode = SkXfermode::kDstATop_Mode;
1259f92ace90d89cc99b34162dda26be564e34ca80efreed};
1260f92ace90d89cc99b34162dda26be564e34ca80efreed
1261f92ace90d89cc99b34162dda26be564e34ca80efreed//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
1262f92ace90d89cc99b34162dda26be564e34ca80efreedstruct Xor4f {
1263f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1264f92ace90d89cc99b34162dda26be564e34ca80efreed        const Sk4f inv255(gInv255);
12657792dbf7ea089b3bcb81792a3ecda8a6f8b421e7mtklein        return check_as_pmfloat(src + dst - (src * Sk4f(dst.a()) + dst * Sk4f(src.a())) * inv255);
1266f92ace90d89cc99b34162dda26be564e34ca80efreed    }
12672d8d33e9e825f9919875be64a71b746189b385bemtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
12682d8d33e9e825f9919875be64a71b746189b385bemtklein        return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) + dst.mulWiden(src.alphas().inv()))
12692d8d33e9e825f9919875be64a71b746189b385bemtklein            .div255RoundNarrow();
12702d8d33e9e825f9919875be64a71b746189b385bemtklein    }
1271f92ace90d89cc99b34162dda26be564e34ca80efreed    static const bool kFoldCoverageIntoSrcAlpha = true;
1272f92ace90d89cc99b34162dda26be564e34ca80efreed    static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode;
1273f92ace90d89cc99b34162dda26be564e34ca80efreed};
1274f92ace90d89cc99b34162dda26be564e34ca80efreed
1275f92ace90d89cc99b34162dda26be564e34ca80efreed//  kPlus_Mode   [Sa + Da, Sc + Dc]
1276f92ace90d89cc99b34162dda26be564e34ca80efreedstruct Plus4f {
1277f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
12787792dbf7ea089b3bcb81792a3ecda8a6f8b421e7mtklein        return check_as_pmfloat(clamp_255(src + dst));
1279f92ace90d89cc99b34162dda26be564e34ca80efreed    }
12806cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
12816cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        return src.saturatedAdd(dst);
12826cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    }
12836cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    static const bool kFoldCoverageIntoSrcAlpha = false;
1284f92ace90d89cc99b34162dda26be564e34ca80efreed    static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode;
1285f92ace90d89cc99b34162dda26be564e34ca80efreed};
1286f92ace90d89cc99b34162dda26be564e34ca80efreed
1287f92ace90d89cc99b34162dda26be564e34ca80efreed//  kModulate_Mode   [Sa * Da, Sc * Dc]
1288f92ace90d89cc99b34162dda26be564e34ca80efreedstruct Modulate4f {
1289f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1290f92ace90d89cc99b34162dda26be564e34ca80efreed        const Sk4f inv255(gInv255);
12917792dbf7ea089b3bcb81792a3ecda8a6f8b421e7mtklein        return check_as_pmfloat(src * dst * inv255);
1292f92ace90d89cc99b34162dda26be564e34ca80efreed    }
12936cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
12946cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        return src.mulWiden(dst).div255RoundNarrow();
12956cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    }
1296f92ace90d89cc99b34162dda26be564e34ca80efreed    static const bool kFoldCoverageIntoSrcAlpha = false;
1297f92ace90d89cc99b34162dda26be564e34ca80efreed    static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode;
1298f92ace90d89cc99b34162dda26be564e34ca80efreed};
1299f92ace90d89cc99b34162dda26be564e34ca80efreed
1300f92ace90d89cc99b34162dda26be564e34ca80efreed//  kScreen_Mode   [S + D - S * D]
1301f92ace90d89cc99b34162dda26be564e34ca80efreedstruct Screen4f {
1302f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1303f92ace90d89cc99b34162dda26be564e34ca80efreed        const Sk4f inv255(gInv255);
13047792dbf7ea089b3bcb81792a3ecda8a6f8b421e7mtklein        return check_as_pmfloat(src + dst - src * dst * inv255);
1305f92ace90d89cc99b34162dda26be564e34ca80efreed    }
13066cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
13076cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract can be done
13082d8d33e9e825f9919875be64a71b746189b385bemtklein        // in 8-bit space without overflow.  S + (1-S)*D is a touch faster because inv() is cheap.
13092d8d33e9e825f9919875be64a71b746189b385bemtklein        return src + src.inv().mulWiden(dst).div255RoundNarrow();
13106cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    }
1311f92ace90d89cc99b34162dda26be564e34ca80efreed    static const bool kFoldCoverageIntoSrcAlpha = true;
1312f92ace90d89cc99b34162dda26be564e34ca80efreed    static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode;
1313f92ace90d89cc99b34162dda26be564e34ca80efreed};
1314f92ace90d89cc99b34162dda26be564e34ca80efreed
1315f8f5478f92d6bce30448203857156a4cda4a13d7reedstruct Multiply4f {
1316f8f5478f92d6bce30448203857156a4cda4a13d7reed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1317f8f5478f92d6bce30448203857156a4cda4a13d7reed        const Sk4f inv255(gInv255);
1318f8f5478f92d6bce30448203857156a4cda4a13d7reed        Sk4f sa = Sk4f(src.a());
1319f8f5478f92d6bce30448203857156a4cda4a13d7reed        Sk4f da = Sk4f(dst.a());
1320f8f5478f92d6bce30448203857156a4cda4a13d7reed        Sk4f sc = src;
1321f8f5478f92d6bce30448203857156a4cda4a13d7reed        Sk4f dc = dst;
1322f8f5478f92d6bce30448203857156a4cda4a13d7reed        Sk4f rc = sc + dc + (sc * (dc - da) - dc * sa) * inv255;
1323f8f5478f92d6bce30448203857156a4cda4a13d7reed        // ra = srcover(sa, da), but the calc for rc happens to accomplish this for us
1324f8f5478f92d6bce30448203857156a4cda4a13d7reed        return check_as_pmfloat(clamp_0_255(rc));
1325f8f5478f92d6bce30448203857156a4cda4a13d7reed    }
13262d8d33e9e825f9919875be64a71b746189b385bemtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
13272d8d33e9e825f9919875be64a71b746189b385bemtklein        return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) +
13282d8d33e9e825f9919875be64a71b746189b385bemtklein                           dst.mulWiden(src.alphas().inv()) +
13292d8d33e9e825f9919875be64a71b746189b385bemtklein                           src.mulWiden(dst))
13302d8d33e9e825f9919875be64a71b746189b385bemtklein            .div255RoundNarrow();
13312d8d33e9e825f9919875be64a71b746189b385bemtklein    }
1332f8f5478f92d6bce30448203857156a4cda4a13d7reed    static const bool kFoldCoverageIntoSrcAlpha = false;
1333f8f5478f92d6bce30448203857156a4cda4a13d7reed    static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode;
1334f8f5478f92d6bce30448203857156a4cda4a13d7reed};
1335f8f5478f92d6bce30448203857156a4cda4a13d7reed
13360135a41e095a433414e21e37b277dab7dcbec373mtklein// [ sa + da - sa*da, sc + dc - 2*min(sc*da, dc*sa) ]  (And notice sa*da == min(sa*da, da*sa).)
133792dabe7421aa6ba4149901108d8ab72956f67eebreedstruct Difference4f {
133892dabe7421aa6ba4149901108d8ab72956f67eebreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
133992dabe7421aa6ba4149901108d8ab72956f67eebreed        const Sk4f inv255(gInv255);
134092dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f sa = Sk4f(src.a());
134192dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f da = Sk4f(dst.a());
134292dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f sc = src;
134392dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f dc = dst;
134492dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f min = Sk4f::Min(sc * da, dc * sa) * inv255;
134592dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f ra = sc + dc - min;
13466cad1da6ef6a41c25258a42cd36e9a591a1cc076reed        return check_as_pmfloat(ra - min * SkPMFloat(0, 1, 1, 1));
134792dabe7421aa6ba4149901108d8ab72956f67eebreed    }
13480135a41e095a433414e21e37b277dab7dcbec373mtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
13490135a41e095a433414e21e37b277dab7dcbec373mtklein        auto m = Sk4px::Wide(Sk16h::Min(src.mulWiden(dst.alphas()), dst.mulWiden(src.alphas())))
13500135a41e095a433414e21e37b277dab7dcbec373mtklein            .div255RoundNarrow();
13510135a41e095a433414e21e37b277dab7dcbec373mtklein        // There's no chance of underflow, and if we subtract m before adding src+dst, no overflow.
13520135a41e095a433414e21e37b277dab7dcbec373mtklein        return (src - m) + (dst - m.zeroAlphas());
13530135a41e095a433414e21e37b277dab7dcbec373mtklein    }
135492dabe7421aa6ba4149901108d8ab72956f67eebreed    static const bool kFoldCoverageIntoSrcAlpha = false;
135592dabe7421aa6ba4149901108d8ab72956f67eebreed    static const SkXfermode::Mode kMode = SkXfermode::kDifference_Mode;
135692dabe7421aa6ba4149901108d8ab72956f67eebreed};
135792dabe7421aa6ba4149901108d8ab72956f67eebreed
13580135a41e095a433414e21e37b277dab7dcbec373mtklein// [ sa + da - sa*da, sc + dc - 2*sc*dc ]
135992dabe7421aa6ba4149901108d8ab72956f67eebreedstruct Exclusion4f {
136092dabe7421aa6ba4149901108d8ab72956f67eebreed    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
136192dabe7421aa6ba4149901108d8ab72956f67eebreed        const Sk4f inv255(gInv255);
136292dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f sc = src;
136392dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f dc = dst;
136492dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f prod = sc * dc * inv255;
136592dabe7421aa6ba4149901108d8ab72956f67eebreed        Sk4f ra = sc + dc - prod;
13666cad1da6ef6a41c25258a42cd36e9a591a1cc076reed        return check_as_pmfloat(ra - prod * SkPMFloat(0, 1, 1, 1));
136792dabe7421aa6ba4149901108d8ab72956f67eebreed    }
13680135a41e095a433414e21e37b277dab7dcbec373mtklein    static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
13690135a41e095a433414e21e37b277dab7dcbec373mtklein        auto p = src.mulWiden(dst).div255RoundNarrow();
13700135a41e095a433414e21e37b277dab7dcbec373mtklein        // There's no chance of underflow, and if we subtract p before adding src+dst, no overflow.
13710135a41e095a433414e21e37b277dab7dcbec373mtklein        return (src - p) + (dst - p.zeroAlphas());
13720135a41e095a433414e21e37b277dab7dcbec373mtklein    }
137392dabe7421aa6ba4149901108d8ab72956f67eebreed    static const bool kFoldCoverageIntoSrcAlpha = false;
137492dabe7421aa6ba4149901108d8ab72956f67eebreed    static const SkXfermode::Mode kMode = SkXfermode::kExclusion_Mode;
137592dabe7421aa6ba4149901108d8ab72956f67eebreed};
137692dabe7421aa6ba4149901108d8ab72956f67eebreed
1377f92ace90d89cc99b34162dda26be564e34ca80efreedtemplate <typename ProcType>
1378f92ace90d89cc99b34162dda26be564e34ca80efreedclass SkT4fXfermode : public SkProcCoeffXfermode {
1379f92ace90d89cc99b34162dda26be564e34ca80efreedpublic:
1380f92ace90d89cc99b34162dda26be564e34ca80efreed    static SkXfermode* Create(const ProcCoeff& rec) {
1381f92ace90d89cc99b34162dda26be564e34ca80efreed        return SkNEW_ARGS(SkT4fXfermode, (rec));
1382f92ace90d89cc99b34162dda26be564e34ca80efreed    }
13833d626834b4b5ee2d6dda34da365dfe40520253aamtklein
1384f92ace90d89cc99b34162dda26be564e34ca80efreed    void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
1385f92ace90d89cc99b34162dda26be564e34ca80efreed        if (NULL == aa) {
1386f92ace90d89cc99b34162dda26be564e34ca80efreed            for (int i = 0; i < n; ++i) {
13876cad1da6ef6a41c25258a42cd36e9a591a1cc076reed                dst[i] = ProcType::Xfer(SkPMFloat(src[i]), SkPMFloat(dst[i])).round();
1388f92ace90d89cc99b34162dda26be564e34ca80efreed            }
1389f92ace90d89cc99b34162dda26be564e34ca80efreed        } else {
1390f92ace90d89cc99b34162dda26be564e34ca80efreed            for (int i = 0; i < n; ++i) {
1391f92ace90d89cc99b34162dda26be564e34ca80efreed                const Sk4f aa4 = Sk4f(aa[i] * gInv255);
1392f92ace90d89cc99b34162dda26be564e34ca80efreed                SkPMFloat dstF(dst[i]);
1393f92ace90d89cc99b34162dda26be564e34ca80efreed                SkPMFloat srcF(src[i]);
1394f92ace90d89cc99b34162dda26be564e34ca80efreed                Sk4f res;
1395f92ace90d89cc99b34162dda26be564e34ca80efreed                if (ProcType::kFoldCoverageIntoSrcAlpha) {
1396f92ace90d89cc99b34162dda26be564e34ca80efreed                    Sk4f src4 = srcF;
1397f92ace90d89cc99b34162dda26be564e34ca80efreed                    res = ProcType::Xfer(src4 * aa4, dstF);
1398f92ace90d89cc99b34162dda26be564e34ca80efreed                } else {
1399f92ace90d89cc99b34162dda26be564e34ca80efreed                    res = ramp(dstF, ProcType::Xfer(srcF, dstF), aa4);
1400f92ace90d89cc99b34162dda26be564e34ca80efreed                }
14013d626834b4b5ee2d6dda34da365dfe40520253aamtklein                dst[i] = SkPMFloat(res).round();
1402f92ace90d89cc99b34162dda26be564e34ca80efreed            }
1403f92ace90d89cc99b34162dda26be564e34ca80efreed        }
1404f92ace90d89cc99b34162dda26be564e34ca80efreed    }
14053d626834b4b5ee2d6dda34da365dfe40520253aamtklein
1406f92ace90d89cc99b34162dda26be564e34ca80efreedprivate:
1407f92ace90d89cc99b34162dda26be564e34ca80efreed    SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
14083d626834b4b5ee2d6dda34da365dfe40520253aamtklein
1409f92ace90d89cc99b34162dda26be564e34ca80efreed    typedef SkProcCoeffXfermode INHERITED;
1410f92ace90d89cc99b34162dda26be564e34ca80efreed};
14116cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein
14126cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtkleintemplate <typename ProcType>
14136cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtkleinclass SkT4pxXfermode : public SkProcCoeffXfermode {
14146cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtkleinpublic:
14156cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    static SkXfermode* Create(const ProcCoeff& rec) {
14166cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        return SkNEW_ARGS(SkT4pxXfermode, (rec));
14176cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    }
14186cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein
14196cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
14206cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        if (NULL == aa) {
14216cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein            Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& src4) {
14226cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein                return ProcType::Xfer(src4, dst4);
14236cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein            });
14246cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        } else {
14256cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein            Sk4px::MapDstSrcAlpha(n, dst, src, aa,
14266cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein                    [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha) {
14276cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein                // We can't exploit kFoldCoverageIntoSrcAlpha. That requires >=24-bit intermediates.
14286cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein                Sk4px res4 = ProcType::Xfer(src4, dst4);
14290135a41e095a433414e21e37b277dab7dcbec373mtklein                return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk4px(alpha).inv()))
14306cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein                           .div255RoundNarrow();
14316cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein            });
14326cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein        }
14336cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    }
14346cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein
14356cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtkleinprivate:
14366cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
14376cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein
14386cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein    typedef SkProcCoeffXfermode INHERITED;
14396cbf18c70bf99f58b2bb1c49cdf8d41be561fee4mtklein};
1440f92ace90d89cc99b34162dda26be564e34ca80efreed
1441f92ace90d89cc99b34162dda26be564e34ca80efreed///////////////////////////////////////////////////////////////////////////////
1442f92ace90d89cc99b34162dda26be564e34ca80efreed
144386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comclass SkDstOutXfermode : public SkProcCoeffXfermode {
144486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.compublic:
14450a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
14460a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org        return SkNEW_ARGS(SkDstOutXfermode, (rec));
14470a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    }
144886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
144936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
14501447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
14510f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org    SK_TO_STRING_OVERRIDE()
14521447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
14531447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.comprivate:
14540a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
14551447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkProcCoeffXfermode INHERITED;
14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.comvoid SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
146086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com                              const SkPMColor* SK_RESTRICT src, int count,
146130da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.com                              const SkAlpha* SK_RESTRICT aa) const {
146286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    SkASSERT(dst && src);
146386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
146486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    if (count <= 0) {
146586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return;
146686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
146749f085dddff10473b6ebf832a974288300224e60bsalomon    if (aa) {
146886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        return this->INHERITED::xfer32(dst, src, count, aa);
146986ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    }
147086ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
147186ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    do {
147286ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        unsigned a = SkGetPackedA32(*src);
147386ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
147486ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        dst++;
147586ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com        src++;
147686ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com    } while (--count != 0);
147786ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com}
147886ab6c694c0b29cb49363746ac6982faa4eef1b2reed@google.com
14790f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
1480b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.comvoid SkDstOutXfermode::toString(SkString* str) const {
1481b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com    this->INHERITED::toString(str);
1482b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com}
1483b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com#endif
1484b83b6b4f7690fe929d8d6b1a3d2b7ed562b95ba6robertphillips@google.com
14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
148797de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgextern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1488d611864e679a58865b111e74fe7ac919cba42163commit-bot@chromium.orgextern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1489df187c7eb27d7616b75d91f3329deb97c4cd6de2commit-bot@chromium.org
149097de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org// Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
149197de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgnamespace {
149297de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.orgSkXfermode* create_mode(int iMode) {
149397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1494140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org
1495140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    ProcCoeff rec = gProcCoeffs[mode];
1496140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1497140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    if (pp != NULL) {
1498140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        rec.fProc = pp;
1499140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    }
1500140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org
150104d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein#if defined(SK_4PX_XFERMODES_ARE_FAST) && !defined(SK_PREFER_LEGACY_FLOAT_XFERMODES)
1502f92ace90d89cc99b34162dda26be564e34ca80efreed    switch (mode) {
15030135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kSrcATop_Mode:    return SkT4pxXfermode<SrcATop4f>::Create(rec);
15040135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kDstATop_Mode:    return SkT4pxXfermode<DstATop4f>::Create(rec);
15050135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kXor_Mode:        return SkT4pxXfermode<Xor4f>::Create(rec);
15060135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kPlus_Mode:       return SkT4pxXfermode<Plus4f>::Create(rec);
15070135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kModulate_Mode:   return SkT4pxXfermode<Modulate4f>::Create(rec);
15080135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kScreen_Mode:     return SkT4pxXfermode<Screen4f>::Create(rec);
15090135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kMultiply_Mode:   return SkT4pxXfermode<Multiply4f>::Create(rec);
15100135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference4f>::Create(rec);
15110135a41e095a433414e21e37b277dab7dcbec373mtklein        case SkXfermode::kExclusion_Mode:  return SkT4pxXfermode<Exclusion4f>::Create(rec);
151204d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        default: break;
1513f92ace90d89cc99b34162dda26be564e34ca80efreed    }
151404d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein#endif
151504d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein
151604d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein#if defined(SK_4F_XFERMODES_ARE_FAST)
151704d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein    switch (mode) {
151804d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kSrcATop_Mode:    return SkT4fXfermode<SrcATop4f>::Create(rec);
151904d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kDstATop_Mode:    return SkT4fXfermode<DstATop4f>::Create(rec);
152004d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kXor_Mode:        return SkT4fXfermode<Xor4f>::Create(rec);
152104d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kPlus_Mode:       return SkT4fXfermode<Plus4f>::Create(rec);
152204d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kModulate_Mode:   return SkT4fXfermode<Modulate4f>::Create(rec);
152304d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kScreen_Mode:     return SkT4fXfermode<Screen4f>::Create(rec);
152404d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kMultiply_Mode:   return SkT4fXfermode<Multiply4f>::Create(rec);
152504d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kDifference_Mode: return SkT4fXfermode<Difference4f>::Create(rec);
152604d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        case SkXfermode::kExclusion_Mode:  return SkT4fXfermode<Exclusion4f>::Create(rec);
152704d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein        default: break;
1528f92ace90d89cc99b34162dda26be564e34ca80efreed    }
1529f92ace90d89cc99b34162dda26be564e34ca80efreed#endif
1530f92ace90d89cc99b34162dda26be564e34ca80efreed
153104d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein    SkXfermode* xfer = NULL;
153204d24a3f86b6f2382e5c6ffaf161ffc734a4d02amtklein
1533140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    // check if we have a platform optim for that
1534140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1535140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    if (xfm != NULL) {
1536140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        xfer = xfm;
1537140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    } else {
1538140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        // All modes can in theory be represented by the ProcCoeff rec, since
1539140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        // it contains function ptrs. However, a few modes are both simple and
1540140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        // commonly used, so we call those out for their own subclasses here.
1541140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        switch (mode) {
1542140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kClear_Mode:
1543140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkClearXfermode::Create(rec);
1544140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1545140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kSrc_Mode:
1546140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkSrcXfermode::Create(rec);
1547140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1548140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kSrcOver_Mode:
1549140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                SkASSERT(false);    // should not land here
1550140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1551140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kDstIn_Mode:
1552140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkDstInXfermode::Create(rec);
1553140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1554140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            case SkXfermode::kDstOut_Mode:
1555140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                xfer = SkDstOutXfermode::Create(rec);
1556140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1557140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org            default:
1558140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                // no special-case, just rely in the rec and its function-ptrs
15599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1560140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org                break;
1561140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org        }
1562140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org    }
156397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    return xfer;
1564140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org}
156597de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org}  // namespace
156697de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org
1567148ec59001ca7d7e54aec580a048c6dd2a085991mtkleinSK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1568140950cc595a3058144681b088e44ff1f8f52d5bcommit-bot@chromium.org
1569a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comSkXfermode* SkXfermode::Create(Mode mode) {
1570a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
15718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
157286490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    if ((unsigned)mode >= kModeCount) {
157386490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org        // report error
157486490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org        return NULL;
157586490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    }
1576c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com
157797de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
157886490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    // so we can just return NULL from the factory.
157986490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    if (kSrcOver_Mode == mode) {
158086490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org        return NULL;
158186490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org    }
158286490573b5cba554a27637e22485455a7b133de7commit-bot@chromium.org
158397de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    return SkSafeRef(cached[mode]);
15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.comSkXfermodeProc SkXfermode::GetProc(Mode mode) {
158743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkXfermodeProc  proc = NULL;
158843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if ((unsigned)mode < kModeCount) {
158943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        proc = gProcCoeffs[mode].fProc;
159043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
159143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return proc;
159243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
159343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
159443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.combool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
159543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
15961447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
159743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if ((unsigned)mode >= (unsigned)kModeCount) {
159843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        // illegal mode parameter
159943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        return false;
160043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
16011447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
160243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    const ProcCoeff& rec = gProcCoeffs[mode];
16031447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
160443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (CANNOT_USE_COEFF == rec.fSC) {
160543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        return false;
160643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
16071447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
160843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
160943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (src) {
161043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        *src = rec.fSC;
161143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
161243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    if (dst) {
161343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        *dst = rec.fDC;
161443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
161543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    return true;
161643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
161743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
161830da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
16198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == xfer) {
16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mode) {
16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *mode = kSrcOver_Mode;
16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
16248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1625c0d4aa2088a0788f9df221497945d2ba1b342f44reed@google.com    return xfer->asMode(mode);
16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
162830da745bbf67a0ee0f305ca7bbdb685cc8a9e686reed@google.combool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1629e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    // if xfer==null then the mode is srcover
1630e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    Mode m = kSrcOver_Mode;
1631e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    if (xfer && !xfer->asMode(&m)) {
1632e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org        return false;
1633e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    }
1634e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org    return mode == m;
1635e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org}
1636e303fcf68d6fee2bf9ee0c4f6fb330a2c3e41a01mike@reedtribe.org
1637dcfb7cf336cafffd8d149c908b615e1deaa3a49begdanielbool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1638dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    // if xfer is NULL we treat it as srcOver which always supports coverageAsAlpha
1639dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    if (!xfer) {
1640dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        return true;
1641dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    }
1642dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
1643dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    return xfer->supportsCoverageAsAlpha();
1644dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel}
1645dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
1646dcfb7cf336cafffd8d149c908b615e1deaa3a49begdanielbool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1647dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    // if xfer is NULL we treat it as srcOver which is opaque if our src is opaque
1648dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    if (!xfer) {
1649dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel        return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1650dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    }
1651dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
1652dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel    return xfer->isOpaque(opacityType);
1653dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel}
1654dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel
16558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
16568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////// 16bit xfermode procs
16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
16658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
16668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
16738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
16748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
16758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
16998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
17008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
17038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
17058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned isa = 255 - SkGetPackedA32(src);
17091447c6f7f4579942b32af6ffff1eadede40b42bctomhudson@google.com
17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(
17118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
17178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPixel32ToPixel16(src);
17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
17278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
17288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
17298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*********
17328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    darken and lighten boil down to this.
17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    darken  = (1 - Sa) * Dc + min(Sc, Dc)
17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    lighten = (1 - Sa) * Dc + max(Sc, Dc)
17368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (Sa == 0) these become
17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        darken  = Dc + min(0, Dc) = 0
17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        lighten = Dc + max(0, Dc) = Dc
17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (Sa == 1) these become
17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        darken  = min(Sc, Dc)
17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        lighten = max(Sc, Dc)
17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
17458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
17488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return 0;
17498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
17528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
17558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
17568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
17578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_0(src));
17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(require_255(src));
17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
17688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct Proc16Rec {
17738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16    fProc16_0;
17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16    fProc16_255;
17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16    fProc16_General;
17768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
17778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1778a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comstatic const Proc16Rec gModeProcs16[] = {
17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 NULL,                   NULL            }, // CLEAR
17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 src_modeproc16_255,     NULL            },
17818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
17828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
17838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
17848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 srcin_modeproc16_255,   NULL            },
17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 dstin_modeproc16_255,   NULL            },
17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 NULL,                   NULL            },// SRC_OUT
17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { dstout_modeproc16_0,  NULL,                   NULL            },
17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 dstatop_modeproc16_255, NULL            },
17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { NULL,                 NULL,                   NULL            }, // XOR
1791a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com
1792a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // plus
17938d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com    { NULL,                 NULL,                   NULL            }, // modulate
1794a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // screen
1795a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // overlay
1796a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1797a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1798a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // colordodge
1799a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // colorburn
1800a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // hardlight
1801a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // softlight
1802a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // difference
1803a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    { NULL,                 NULL,                   NULL            }, // exclusion
1804b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // multiply
1805b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // hue
1806b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // saturation
1807b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // color
1808b24f89353ed7a45b27ab0ffc69c222b81bbf87c3commit-bot@chromium.org    { NULL,                 NULL,                   NULL            }, // luminosity
18098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
18108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1811a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.comSkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16  proc16 = NULL;
1813a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com    if ((unsigned)mode < kModeCount) {
1814a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com        const Proc16Rec& rec = gModeProcs16[mode];
18158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned a = SkColorGetA(srcColor);
18168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (0 == a) {
18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc16 = rec.fProc16_0;
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else if (255 == a) {
18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc16 = rec.fProc16_255;
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            proc16 = rec.fProc16_General;
18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return proc16;
18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1828d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1829d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1830d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1831