180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkXfermode.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColorPriv.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkFlattenableBuffers.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMathPriv.h"
14d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#include "SkString.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_INST_COUNT(SkXfermode)
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// idea for higher precision blends in xfer procs (and slightly faster)
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// see DstATop as a probable caller
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(a <= 255);
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(b <= 255);
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(c <= 255);
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(d <= 255);
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned result = (prod + (prod >> 8)) >> 8;
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(result <= 255);
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return result;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned saturated_add(unsigned a, unsigned b) {
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(a <= 255);
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(b <= 255);
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned sum = a + b;
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sum > 255) {
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sum = 255;
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return sum;
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int clamp_signed_byte(int n) {
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (n < 0) {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = 0;
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (n > 255) {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n = 255;
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return n;
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int clamp_div255round(int prod) {
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (prod <= 0) {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 0;
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (prod >= 255*255) {
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return 255;
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkDiv255Round(prod);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int clamp_max(int value, int max) {
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (value > max) {
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        value = max;
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return value;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kClear_Mode,    //!< [0, 0]
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kSrc_Mode,      //!< [Sa, Sc]
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return src;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kDst_Mode,      //!< [Da, Dc]
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this is the old, more-correct way, but it doesn't guarantee that dst==255
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // will always stay opaque
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this is slightly faster, but more importantly guarantees that dst==255
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // will always stay opaque
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this is the reverse of srcover, just flipping src and dst
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // see srcover's comment about the 256 for opaqueness guarantees
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned sa = SkGetPackedA32(src);
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned da = SkGetPackedA32(dst);
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned isa = 255 - sa;
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(da,
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned sa = SkGetPackedA32(src);
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned da = SkGetPackedA32(dst);
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned ida = 255 - da;
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(sa,
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned sa = SkGetPackedA32(src);
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned da = SkGetPackedA32(dst);
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned isa = 255 - sa;
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned ida = 255 - da;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kPlus_Mode
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
185d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger// kModulate_Mode
186d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergerstatic SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kScreen_Mode
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int srcover_byte(int a, int b) {
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return a + b - SkAlphaMulAlpha(a, b);
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kOverlay_Mode
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int overlay_byte(int sc, int dc, int sa, int da) {
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int tmp = sc * (255 - da) + dc * (255 - sa);
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int rc;
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (2 * dc <= da) {
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = 2 * sc * dc;
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = sa * da - 2 * (da - dc) * (sa - sc);
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return clamp_div255round(rc + tmp);
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kDarken_Mode
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int darken_byte(int sc, int dc, int sa, int da) {
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sd = sc * da;
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int ds = dc * sa;
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sd < ds) {
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // srcover
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return sc + dc - SkDiv255Round(ds);
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // dstover
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return dc + sc - SkDiv255Round(sd);
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kLighten_Mode
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int lighten_byte(int sc, int dc, int sa, int da) {
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sd = sc * da;
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int ds = dc * sa;
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (sd > ds) {
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // srcover
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return sc + dc - SkDiv255Round(ds);
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // dstover
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return dc + sc - SkDiv255Round(sd);
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kColorDodge_Mode
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int colordodge_byte(int sc, int dc, int sa, int da) {
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int diff = sa - sc;
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int rc;
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == diff) {
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = SkDiv255Round(rc);
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int tmp = (dc * sa << 15) / (da * diff);
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = SkDiv255Round(sa * da) * tmp >> 15;
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // don't clamp here, since we'll do it in our modeproc
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return rc;
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // added to avoid div-by-zero in colordodge_byte
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == dst) {
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return src;
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    r = clamp_max(r, a);
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    g = clamp_max(g, a);
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    b = clamp_max(b, a);
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kColorBurn_Mode
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int colorburn_byte(int sc, int dc, int sa, int da) {
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int rc;
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dc == da && 0 == sc) {
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = sa * da + dc * (255 - sa);
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (0 == sc) {
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return SkAlphaMulAlpha(dc, 255 - sa);
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int tmp = (sa * (da - dc) * 256) / (sc * da);
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (tmp > 256) {
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            tmp = 256;
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int tmp2 = sa * da;
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkDiv255Round(rc);
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // added to avoid div-by-zero in colorburn_byte
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == dst) {
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return src;
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kHardLight_Mode
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int hardlight_byte(int sc, int dc, int sa, int da) {
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int rc;
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (2 * sc <= sa) {
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = 2 * sc * dc;
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = sa * da - 2 * (da - dc) * (sa - sc);
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// returns 255 * sqrt(n/255)
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic U8CPU sqrt_unit_byte(U8CPU n) {
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkSqrtBits(n, 15+4);
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kSoftLight_Mode
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int softlight_byte(int sc, int dc, int sa, int da) {
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int m = da ? dc * 256 / da : 0;
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int rc;
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (2 * sc <= sa) {
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (4 * dc <= da) {
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int tmp = sqrt_unit_byte(m) - m;
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kDifference_Mode
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int difference_byte(int sc, int dc, int sa, int da) {
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int tmp = SkMin32(sc * da, dc * sa);
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// kExclusion_Mode
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int exclusion_byte(int sc, int dc, int sa, int da) {
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // this equations is wacky, wait for SVG to confirm it
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return clamp_div255round(r);
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int sa = SkGetPackedA32(src);
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int da = SkGetPackedA32(dst);
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int a = srcover_byte(sa, da);
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackARGB32(a, r, g, b);
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct ProcCoeff {
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc      fProc;
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode::Coeff   fSC;
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermode::Coeff   fDC;
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const ProcCoeff gProcCoeffs[] = {
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
439d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
454363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
458363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkXfermode::asMode(Mode* mode) const {
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
462363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // no-op. subclasses should override this
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        const SkPMColor* SK_RESTRICT src, int count,
469363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        const SkAlpha* SK_RESTRICT aa) const {
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[i] = this->xferColor(src[i], dst[i]);
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 != a) {
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor dstC = dst[i];
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor C = this->xferColor(src[i], dstC);
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0xFF != a) {
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    C = SkFourByteInterp(C, dstC, a);
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = C;
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkXfermode::xfer16(uint16_t* dst,
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        const SkPMColor* SK_RESTRICT src, int count,
493363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        const SkAlpha* SK_RESTRICT aa) const {
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 != a) {
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor C = this->xferColor(src[i], dstC);
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0xFF != a) {
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    C = SkFourByteInterp(C, dstC, a);
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkPixel32ToPixel16_ToU16(C);
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          const SkPMColor* SK_RESTRICT src, int count,
518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                          const SkAlpha* SK_RESTRICT aa) const {
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 != a) {
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor C = this->xferColor(src[i], dstC);
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0xFF != a) {
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    C = SkFourByteInterp(C, dstC, a);
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkPixel32ToPixel4444(C);
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        const SkPMColor src[], int count,
543363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        const SkAlpha* SK_RESTRICT aa) const {
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[i] = SkToU8(SkGetPackedA32(res));
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 != a) {
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkAlpha dstA = dst[i];
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                unsigned A = SkGetPackedA32(this->xferColor(src[i],
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0xFF != a) {
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkToU8(A);
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const SkPMColor* SK_RESTRICT src, int count,
571363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            const SkAlpha* SK_RESTRICT aa) const {
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc proc = fProc;
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != proc) {
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == aa) {
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = proc(src[i], dst[i]);
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                unsigned a = aa[i];
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0 != a) {
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor dstC = dst[i];
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor C = proc(src[i], dstC);
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (a != 0xFF) {
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        C = SkFourByteInterp(C, dstC, a);
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[i] = C;
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const SkPMColor* SK_RESTRICT src, int count,
599363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            const SkAlpha* SK_RESTRICT aa) const {
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc proc = fProc;
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != proc) {
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == aa) {
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                unsigned a = aa[i];
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0 != a) {
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor C = proc(src[i], dstC);
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (0xFF != a) {
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        C = SkFourByteInterp(C, dstC, a);
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[i] = SkPixel32ToPixel16_ToU16(C);
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkPMColor* SK_RESTRICT src, int count,
628363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              const SkAlpha* SK_RESTRICT aa) const {
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc proc = fProc;
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != proc) {
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == aa) {
63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                unsigned a = aa[i];
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0 != a) {
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor C = proc(src[i], dstC);
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (0xFF != a) {
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        C = SkFourByteInterp(C, dstC, a);
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[i] = SkPixel32ToPixel4444(C);
64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            const SkPMColor* SK_RESTRICT src, int count,
657363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                            const SkAlpha* SK_RESTRICT aa) const {
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc proc = fProc;
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != proc) {
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == aa) {
66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkToU8(SkGetPackedA32(res));
66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = count - 1; i >= 0; --i) {
67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                unsigned a = aa[i];
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (0 != a) {
67280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkAlpha dstA = dst[i];
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    unsigned A = SkGetPackedA32(res);
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    if (0xFF != a) {
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[i] = SkToU8(A);
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : SkXfermode(buffer) {
68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fProc = NULL;
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!buffer.isCrossProcess()) {
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fProc = (SkXfermodeProc)buffer.readFunctionPtr();
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->INHERITED::flatten(buffer);
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!buffer.isCrossProcess()) {
69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.writeFunctionPtr((void*)fProc);
69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
700d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
701d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkProcXfermode::toString(SkString* str) const {
702d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->appendf("SkProcXfermode: %p", fProc);
703d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
704d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
705d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkProcCoeffXfermode : public SkProcXfermode {
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            : INHERITED(rec.fProc) {
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMode = mode;
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // these may be valid, or may be CANNOT_USE_COEFF
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSrcCoeff = rec.fSC;
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDstCoeff = rec.fDC;
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
719363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual bool asMode(Mode* mode) const SK_OVERRIDE {
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (mode) {
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *mode = fMode;
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
726363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (CANNOT_USE_COEFF == fSrcCoeff) {
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sc) {
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *sc = fSrcCoeff;
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (dc) {
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *dc = fDstCoeff;
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
740d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SK_DEVELOPER_TO_STRING()
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected:
74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fMode = (SkXfermode::Mode)buffer.read32();
74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const ProcCoeff& rec = gProcCoeffs[fMode];
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // these may be valid, or may be CANNOT_USE_COEFF
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fSrcCoeff = rec.fSC;
75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDstCoeff = rec.fDC;
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // now update our function-ptr in the super class
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->INHERITED::setProc(rec.fProc);
75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->INHERITED::flatten(buffer);
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        buffer.write32(fMode);
75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Mode    fMode;
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Coeff   fSrcCoeff, fDstCoeff;
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkProcXfermode INHERITED;
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
767d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
768d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkProcCoeffXfermode::toString(SkString* str) const {
769d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append("SkProcCoeffXfermode: ");
770d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
771d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    const char *gModeStrings[kLastMode+1] = {
772d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
773d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
774d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
775d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion"
776d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    };
777d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
778d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append("mode: ");
779d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append(gModeStrings[fMode]);
780d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
781d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    static const char* gCoeffStrings[kCoeffCount] = {
782d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
783d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    };
784d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
785d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append(" src: ");
786d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (CANNOT_USE_COEFF == fSrcCoeff) {
787d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        str->append("can't use");
788d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    } else {
789d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        str->append(gCoeffStrings[fSrcCoeff]);
790d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
791d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
792d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    str->append(" dst: ");
793d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    if (CANNOT_USE_COEFF == fDstCoeff) {
794d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        str->append("can't use");
795d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    } else {
796d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger        str->append(gCoeffStrings[fDstCoeff]);
797d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    }
798d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
799d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
800d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkClearXfermode : public SkProcCoeffXfermode {
80480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
807363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
808363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
810d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SK_DEVELOPER_TO_STRING()
81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClearXfermode(SkFlattenableReadBuffer& buffer)
81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : SkProcCoeffXfermode(buffer) {}
81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
817d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    typedef SkProcCoeffXfermode INHERITED;
81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
81980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkPMColor* SK_RESTRICT, int count,
822363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                             const SkAlpha* SK_RESTRICT aa) const {
82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && count >= 0);
82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memset(dst, 0, count << 2);
82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0xFF == a) {
83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = 0;
83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (a != 0) {
83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkPMColor* SK_RESTRICT, int count,
840363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                             const SkAlpha* SK_RESTRICT aa) const {
84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && count >= 0);
84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memset(dst, 0, count);
84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0xFF == a) {
84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = 0;
85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (0 != a) {
85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
857d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
858d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkClearXfermode::toString(SkString* str) const {
859d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    this->INHERITED::toString(str);
860d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
861d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
862d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkSrcXfermode : public SkProcCoeffXfermode {
86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
869363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
870363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
872d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SK_DEVELOPER_TO_STRING()
87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : SkProcCoeffXfermode(buffer) {}
87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
879d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    typedef SkProcCoeffXfermode INHERITED;
88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const SkPMColor* SK_RESTRICT src, int count,
884363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                           const SkAlpha* SK_RESTRICT aa) const {
88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(dst, src, count << 2);
88980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
89080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
89180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
89280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (a == 0xFF) {
89380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = src[i];
89480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else if (a != 0) {
89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst[i] = SkFourByteInterp(src[i], dst[i], a);
89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
89980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                           const SkPMColor* SK_RESTRICT src, int count,
903363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                           const SkAlpha* SK_RESTRICT aa) const {
90480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src && count >= 0);
90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
90680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == aa) {
90780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
90880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            dst[i] = SkToU8(SkGetPackedA32(src[i]));
90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
91180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = count - 1; i >= 0; --i) {
91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned a = aa[i];
91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (0 != a) {
91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                unsigned srcA = SkGetPackedA32(src[i]);
91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (a == 0xFF) {
91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[i] = SkToU8(srcA);
91780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
91880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
91980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
92080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
92180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
92280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
92380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
924d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
925d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkSrcXfermode::toString(SkString* str) const {
926d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    this->INHERITED::toString(str);
927d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
928d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
92980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
930363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
93180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
93280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkDstInXfermode : public SkProcCoeffXfermode {
93380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
93480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
93580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
936363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
93780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
938d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SK_DEVELOPER_TO_STRING()
93980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
94080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
94280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
94380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkProcCoeffXfermode INHERITED;
94580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
94680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
94780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
94880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                             const SkPMColor* SK_RESTRICT src, int count,
949363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                             const SkAlpha* SK_RESTRICT aa) const {
95080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src);
95180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count <= 0) {
95380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
95480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
95580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != aa) {
95680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->INHERITED::xfer32(dst, src, count, aa);
95780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
95880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
95980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
96080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned a = SkGetPackedA32(*src);
96180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
96280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst++;
96380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        src++;
96480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (--count != 0);
96580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
96680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
967d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
968d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkDstInXfermode::toString(SkString* str) const {
969d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    this->INHERITED::toString(str);
970d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
971d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
972d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
973363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
97480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
97580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkDstOutXfermode : public SkProcCoeffXfermode {
97680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
97780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
97880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
979363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
98080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
981d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    SK_DEVELOPER_TO_STRING()
98280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
98380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
98580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
98680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : INHERITED(buffer) {}
98780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
98880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkProcCoeffXfermode INHERITED;
98980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
99080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
99280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                              const SkPMColor* SK_RESTRICT src, int count,
993363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                              const SkAlpha* SK_RESTRICT aa) const {
99480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(dst && src);
99580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
99680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count <= 0) {
99780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
99880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
99980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != aa) {
100080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->INHERITED::xfer32(dst, src, count, aa);
100180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
100280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
100380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    do {
100480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned a = SkGetPackedA32(*src);
100580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
100680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        dst++;
100780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        src++;
100880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } while (--count != 0);
100980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
101080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1011d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#ifdef SK_DEVELOPER
1012d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenbergervoid SkDstOutXfermode::toString(SkString* str) const {
1013d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    this->INHERITED::toString(str);
1014d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger}
1015d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger#endif
1016d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger
101780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
101880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
101980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkXfermode* SkXfermode::Create(Mode mode) {
102080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
102180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)mode < kModeCount);
102280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const ProcCoeff& rec = gProcCoeffs[mode];
102480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
102580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (mode) {
102680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kClear_Mode:
102780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkNEW_ARGS(SkClearXfermode, (rec));
102880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kSrc_Mode:
102980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkNEW_ARGS(SkSrcXfermode, (rec));
103080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kSrcOver_Mode:
103180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
103280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kDstIn_Mode:
103380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkNEW_ARGS(SkDstInXfermode, (rec));
103480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kDstOut_Mode:
103580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkNEW_ARGS(SkDstOutXfermode, (rec));
103680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
103780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
103880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
103980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
104080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
104180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkXfermodeProc SkXfermode::GetProc(Mode mode) {
104280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc  proc = NULL;
104380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((unsigned)mode < kModeCount) {
104480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        proc = gProcCoeffs[mode].fProc;
104580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
104680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return proc;
104780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
104880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
104980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
105080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
105180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((unsigned)mode >= (unsigned)kModeCount) {
105380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // illegal mode parameter
105480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
105580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
105680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const ProcCoeff& rec = gProcCoeffs[mode];
105880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
105980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (CANNOT_USE_COEFF == rec.fSC) {
106080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
106180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
106280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
106380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
106480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src) {
106580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *src = rec.fSC;
106680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
106780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (dst) {
106880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *dst = rec.fDC;
106980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
107080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
107180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
107280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1073363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
107480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == xfer) {
107580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (mode) {
107680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *mode = kSrcOver_Mode;
107780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
107880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
107980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
108080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return xfer->asMode(mode);
108180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
108280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1083363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
108480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == xfer) {
108580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return ModeAsCoeff(kSrcOver_Mode, src, dst);
108680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
108780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return xfer->asCoeff(src, dst);
108880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
108980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1090363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
109180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // if xfer==null then the mode is srcover
109280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Mode m = kSrcOver_Mode;
109380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (xfer && !xfer->asMode(&m)) {
109480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
109580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
109680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return mode == m;
109780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
109880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
109980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
110080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////// 16bit xfermode procs
110180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
110380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
110480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
110580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
110680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
110780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
110880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
110980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPixel32ToPixel16(src);
111080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
111180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
111380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
111480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
111580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
111680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
111780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_0(src));
111880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
111980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
112080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
112280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
112380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPixel32ToPixel16(src);
112480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
112580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
112680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
112780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_0(src));
112880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
112980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
113080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
113280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
113380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
113480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
113580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
113680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
113780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
113880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPixel32ToPixel16(src);
113980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
114080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
114180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
114280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
114380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
114480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
114580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
114680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
114780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_0(src));
114880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
114980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
115080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
115280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned isa = 255 - SkGetPackedA32(src);
115380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
115480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackRGB16(
115580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
115680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
115780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
115880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
115980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
116180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_0(src));
116280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
116380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
116480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
116580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
116680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
116780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPixel32ToPixel16(src);
116880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
116980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
117180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
117280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
117380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
117480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*********
117680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    darken and lighten boil down to this.
117780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
117880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    darken  = (1 - Sa) * Dc + min(Sc, Dc)
117980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    lighten = (1 - Sa) * Dc + max(Sc, Dc)
118080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
118180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (Sa == 0) these become
118280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        darken  = Dc + min(0, Dc) = 0
118380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        lighten = Dc + max(0, Dc) = Dc
118480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
118580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (Sa == 1) these become
118680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        darken  = min(Sc, Dc)
118780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        lighten = max(Sc, Dc)
118880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
118980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
119180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_0(src));
119280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return 0;
119380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
119480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
119580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
119680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
119780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
119880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
119980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
120080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackRGB16(r, g, b);
120180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
120280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
120380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
120480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_0(src));
120580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
120680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
120780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
120880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
120980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(require_255(src));
121080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
121180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
121280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
121380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkPackRGB16(r, g, b);
121480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
121580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
121680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct Proc16Rec {
121780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc16    fProc16_0;
121880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc16    fProc16_255;
121980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc16    fProc16_General;
122080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
122180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
122280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const Proc16Rec gModeProcs16[] = {
122380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // CLEAR
122480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 src_modeproc16_255,     NULL            },
122580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
122680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
122780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
122880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 srcin_modeproc16_255,   NULL            },
122980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 dstin_modeproc16_255,   NULL            },
123080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            },// SRC_OUT
123180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { dstout_modeproc16_0,  NULL,                   NULL            },
123280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
123380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 dstatop_modeproc16_255, NULL            },
123480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // XOR
123580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
123680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // plus
1237d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // modulate
123880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // screen
123980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // overlay
124080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
124180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
124280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // colordodge
124380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // colorburn
124480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // hardlight
124580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // softlight
124680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // difference
124780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    { NULL,                 NULL,                   NULL            }, // exclusion
124880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
124980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
125180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkXfermodeProc16  proc16 = NULL;
125280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if ((unsigned)mode < kModeCount) {
125380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const Proc16Rec& rec = gModeProcs16[mode];
125480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        unsigned a = SkColorGetA(srcColor);
125580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
125680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (0 == a) {
125780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc16 = rec.fProc16_0;
125880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else if (255 == a) {
125980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc16 = rec.fProc16_255;
126080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
126180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc16 = rec.fProc16_General;
126280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
126380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
126480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return proc16;
126580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
126680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
126780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
126880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
126980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
127080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
127180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
127280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
127380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1274