1f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
2f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/*
3f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Copyright 2006 The Android Open Source Project
4f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *
5f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
6f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * found in the LICENSE file.
7f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */
8f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
9f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
10f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkXfermode.h"
11f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkColorPriv.h"
12f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
13f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
14f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
15f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if 0
16f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// idea for higher precision blends in xfer procs (and slightly faster)
17f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// see DstATop as a probable caller
18f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
19f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(a <= 255);
20f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(b <= 255);
21f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(c <= 255);
22f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(d <= 255);
23f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
24f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned result = (prod + (prod >> 8)) >> 8;
25f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(result <= 255);
26f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return result;
27f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
28f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
29f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
30f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline unsigned saturated_add(unsigned a, unsigned b) {
31f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(a <= 255);
32f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(b <= 255);
33f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned sum = a + b;
34f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (sum > 255) {
35f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        sum = 255;
36f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
37f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return sum;
38f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
39f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
40f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int clamp_signed_byte(int n) {
41f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (n < 0) {
42f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        n = 0;
43f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else if (n > 255) {
44f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        n = 255;
45f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
46f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return n;
47f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
48f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
49f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int clamp_div255round(int prod) {
50f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (prod <= 0) {
51f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 0;
52f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else if (prod >= 255*255) {
53f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return 255;
54f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
55f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkDiv255Round(prod);
56f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
57f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
58f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
59f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int clamp_max(int value, int max) {
60f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (value > max) {
61f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        value = max;
62f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
63f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return value;
64f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
65f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
66f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
67f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
68f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kClear_Mode,    //!< [0, 0]
69f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
70f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return 0;
71f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
72f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
73f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kSrc_Mode,      //!< [Sa, Sc]
74f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
75f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return src;
76f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
77f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
78f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kDst_Mode,      //!< [Da, Dc]
79f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
80f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
81f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
82f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
83f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
84f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
85f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#if 0
86f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // this is the old, more-correct way, but it doesn't guarantee that dst==255
87f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // will always stay opaque
88f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
89f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else
90f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // this is slightly faster, but more importantly guarantees that dst==255
91f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // will always stay opaque
92f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
93f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
94f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
95f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
96f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
97f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
98f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // this is the reverse of srcover, just flipping src and dst
99f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // see srcover's comment about the 256 for opaqueness guarantees
100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned sa = SkGetPackedA32(src);
126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned da = SkGetPackedA32(dst);
127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned isa = 255 - sa;
128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(da,
130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned sa = SkGetPackedA32(src);
141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned da = SkGetPackedA32(dst);
142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned ida = 255 - da;
143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(sa,
145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned sa = SkGetPackedA32(src);
156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned da = SkGetPackedA32(dst);
157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned isa = 255 - sa;
158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned ida = 255 - da;
159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kPlus_Mode
172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kMultiply_Mode
181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kScreen_Mode
190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int srcover_byte(int a, int b) {
191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return a + b - SkAlphaMulAlpha(a, b);
192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kOverlay_Mode
202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int overlay_byte(int sc, int dc, int sa, int da) {
203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int tmp = sc * (255 - da) + dc * (255 - sa);
204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int rc;
205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (2 * dc <= da) {
206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = 2 * sc * dc;
207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = sa * da - 2 * (da - dc) * (sa - sc);
209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return clamp_div255round(rc + tmp);
211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
218f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
222f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kDarken_Mode
223f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int darken_byte(int sc, int dc, int sa, int da) {
224f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sd = sc * da;
225f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int ds = dc * sa;
226f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (sd < ds) {
227f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // srcover
228f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return sc + dc - SkDiv255Round(ds);
229f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
230f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // dstover
231f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return dc + sc - SkDiv255Round(sd);
232f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
233f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
234f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
235f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
236f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
237f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
238f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
239f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
240f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
241f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
242f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
243f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
244f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kLighten_Mode
245f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int lighten_byte(int sc, int dc, int sa, int da) {
246f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sd = sc * da;
247f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int ds = dc * sa;
248f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (sd > ds) {
249f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // srcover
250f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return sc + dc - SkDiv255Round(ds);
251f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
252f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // dstover
253f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return dc + sc - SkDiv255Round(sd);
254f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
255f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
256f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
257f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
258f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
259f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
260f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
261f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
262f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
263f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
264f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
265f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
266f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kColorDodge_Mode
267f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int colordodge_byte(int sc, int dc, int sa, int da) {
268f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int diff = sa - sc;
269f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int rc;
270f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (0 == diff) {
271f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
272f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = SkDiv255Round(rc);
273f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
274f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int tmp = (dc * sa << 15) / (da * diff);
275f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = SkDiv255Round(sa * da) * tmp >> 15;
276f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // don't clamp here, since we'll do it in our modeproc
277f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
278f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return rc;
279f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
280f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
281f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // added to avoid div-by-zero in colordodge_byte
282f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (0 == dst) {
283f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return src;
284f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
285f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
286f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
287f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
288f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
289f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
290f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
291f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
292f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    r = clamp_max(r, a);
293f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    g = clamp_max(g, a);
294f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    b = clamp_max(b, a);
295f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
296f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
297f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
298f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kColorBurn_Mode
299f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int colorburn_byte(int sc, int dc, int sa, int da) {
300f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int rc;
301f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (dc == da && 0 == sc) {
302f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = sa * da + dc * (255 - sa);
303f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else if (0 == sc) {
304f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkAlphaMulAlpha(dc, 255 - sa);
305f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
306f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int tmp = (sa * (da - dc) * 256) / (sc * da);
307f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (tmp > 256) {
308f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            tmp = 256;
309f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
310f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int tmp2 = sa * da;
311f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
312f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
313f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkDiv255Round(rc);
314f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
315f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
316f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // added to avoid div-by-zero in colorburn_byte
317f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (0 == dst) {
318f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return src;
319f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
320f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
321f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
322f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
323f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
324f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
325f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
326f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
327f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
328f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
329f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
330f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kHardLight_Mode
331f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int hardlight_byte(int sc, int dc, int sa, int da) {
332f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int rc;
333f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (2 * sc <= sa) {
334f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = 2 * sc * dc;
335f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
336f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = sa * da - 2 * (da - dc) * (sa - sc);
337f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
338f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
339f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
340f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
341f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
342f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
343f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
344f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
345f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
346f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
347f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
348f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
349f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
350f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// returns 255 * sqrt(n/255)
351f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic U8CPU sqrt_unit_byte(U8CPU n) {
352f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkSqrtBits(n, 15+4);
353f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
354f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
355f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kSoftLight_Mode
356f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int softlight_byte(int sc, int dc, int sa, int da) {
357f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int m = da ? dc * 256 / da : 0;
358f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int rc;
359f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (2 * sc <= sa) {
360f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
361f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else if (4 * dc <= da) {
362f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
363f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
364f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
365f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        int tmp = sqrt_unit_byte(m) - m;
366f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
367f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
368f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
369f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
370f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
371f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
372f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
373f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
374f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
375f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
376f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
377f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
378f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
379f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
380f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kDifference_Mode
381f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int difference_byte(int sc, int dc, int sa, int da) {
382f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int tmp = SkMin32(sc * da, dc * sa);
383f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
384f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
385f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
386f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
387f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
388f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
389f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
390f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
391f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
392f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
393f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
394f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
395f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// kExclusion_Mode
396f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline int exclusion_byte(int sc, int dc, int sa, int da) {
397f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // this equations is wacky, wait for SVG to confirm it
398f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
399f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return clamp_div255round(r);
400f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
401f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
402f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int sa = SkGetPackedA32(src);
403f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int da = SkGetPackedA32(dst);
404f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int a = srcover_byte(sa, da);
405f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
406f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
407f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
408f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackARGB32(a, r, g, b);
409f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
410f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
411f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct ProcCoeff {
412f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc      fProc;
413f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermode::Coeff   fSC;
414f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermode::Coeff   fDC;
415f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
416f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
417f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
418f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
419f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic const ProcCoeff gProcCoeffs[] = {
420f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
421f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
422f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
423f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
424f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
425f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
426f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
427f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
428f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
429f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
430f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
431f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
432f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
433f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
434f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { multiply_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
435f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
436f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
437f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
438f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
439f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
440f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
441f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
442f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
443f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
444f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
445f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
446f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
447f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
448f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
449f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
450f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return false;
451f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
452f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
453f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkXfermode::asMode(Mode* mode) {
454f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return false;
455f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
456f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
457f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) {
458f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // no-op. subclasses should override this
459f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
460f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
461f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
462f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
463f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        const SkPMColor* SK_RESTRICT src, int count,
464f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        const SkAlpha* SK_RESTRICT aa) {
465f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
466f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
467f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
468f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
469f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            dst[i] = this->xferColor(src[i], dst[i]);
470f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
471f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
472f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
473f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
474f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0 != a) {
475f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor dstC = dst[i];
476f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor C = this->xferColor(src[i], dstC);
477f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0xFF != a) {
478f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    C = SkFourByteInterp(C, dstC, a);
479f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
480f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = C;
481f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
482f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
483f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
484f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
485f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
486f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkXfermode::xfer16(uint16_t* dst,
487f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        const SkPMColor* SK_RESTRICT src, int count,
488f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        const SkAlpha* SK_RESTRICT aa) {
489f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
490f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
491f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
492f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
493f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
494f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
495f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
496f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
497f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
498f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
499f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0 != a) {
500f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
501f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor C = this->xferColor(src[i], dstC);
502f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0xFF != a) {
503f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    C = SkFourByteInterp(C, dstC, a);
504f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
505f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkPixel32ToPixel16_ToU16(C);
506f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
507f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
508f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
509f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
510f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
511f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
512f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                          const SkPMColor* SK_RESTRICT src, int count,
513f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                          const SkAlpha* SK_RESTRICT aa)
514f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger{
515f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
516f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
517f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
518f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
519f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
520f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
521f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
522f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
523f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
524f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
525f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0 != a) {
526f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
527f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor C = this->xferColor(src[i], dstC);
528f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0xFF != a) {
529f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    C = SkFourByteInterp(C, dstC, a);
530f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
531f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkPixel32ToPixel4444(C);
532f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
533f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
534f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
535f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
536f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
537f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
538f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        const SkPMColor src[], int count,
539f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        const SkAlpha* SK_RESTRICT aa)
540f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger{
541f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
542f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
543f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
544f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
545f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
546f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            dst[i] = SkToU8(SkGetPackedA32(res));
547f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
548f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
549f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
550f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
551f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0 != a) {
552f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkAlpha dstA = dst[i];
553f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                unsigned A = SkGetPackedA32(this->xferColor(src[i],
554f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
555f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0xFF != a) {
556f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
557f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
558f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkToU8(A);
559f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
560f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
561f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
562f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
563f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
564f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
565f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
566f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
567f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            const SkPMColor* SK_RESTRICT src, int count,
568f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            const SkAlpha* SK_RESTRICT aa) {
569f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
570f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
571f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc proc = fProc;
572f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
573f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL != proc) {
574f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (NULL == aa) {
575f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
576f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = proc(src[i], dst[i]);
577f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
578f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else {
579f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
580f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                unsigned a = aa[i];
581f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0 != a) {
582f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor dstC = dst[i];
583f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor C = proc(src[i], dstC);
584f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    if (a != 0xFF) {
585f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        C = SkFourByteInterp(C, dstC, a);
586f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    }
587f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    dst[i] = C;
588f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
589f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
590f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
591f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
592f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
593f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
594f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
595f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            const SkPMColor* SK_RESTRICT src, int count,
596f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            const SkAlpha* SK_RESTRICT aa) {
597f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
598f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
599f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc proc = fProc;
600f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
601f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL != proc) {
602f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (NULL == aa) {
603f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
604f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
605f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
606f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
607f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else {
608f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
609f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                unsigned a = aa[i];
610f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0 != a) {
611f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
612f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor C = proc(src[i], dstC);
613f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    if (0xFF != a) {
614f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        C = SkFourByteInterp(C, dstC, a);
615f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    }
616f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    dst[i] = SkPixel32ToPixel16_ToU16(C);
617f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
618f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
619f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
620f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
621f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
622f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
623f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
624f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                              const SkPMColor* SK_RESTRICT src, int count,
625f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                              const SkAlpha* SK_RESTRICT aa) {
626f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
627f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
628f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc proc = fProc;
629f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
630f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL != proc) {
631f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (NULL == aa) {
632f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
633f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
634f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
635f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
636f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else {
637f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
638f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                unsigned a = aa[i];
639f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0 != a) {
640f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
641f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor C = proc(src[i], dstC);
642f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    if (0xFF != a) {
643f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        C = SkFourByteInterp(C, dstC, a);
644f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    }
645f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    dst[i] = SkPixel32ToPixel4444(C);
646f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
647f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
648f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
649f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
650f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
651f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
652f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
653f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            const SkPMColor* SK_RESTRICT src, int count,
654f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                            const SkAlpha* SK_RESTRICT aa) {
655f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
656f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
657f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc proc = fProc;
658f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
659f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL != proc) {
660f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (NULL == aa) {
661f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
662f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
663f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkToU8(SkGetPackedA32(res));
664f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
665f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else {
666f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            for (int i = count - 1; i >= 0; --i) {
667f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                unsigned a = aa[i];
668f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (0 != a) {
669f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkAlpha dstA = dst[i];
670f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
671f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    unsigned A = SkGetPackedA32(res);
672f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    if (0xFF != a) {
673f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
674f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    }
675f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    dst[i] = SkToU8(A);
676f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
677f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
678f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
679f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
680f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
681f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
682f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
683f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        : SkXfermode(buffer) {
684f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // Might be a NULL if the Xfermode is recorded using the CrossProcess flag
685f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fProc = (SkXfermodeProc)buffer.readFunctionPtr();
686f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
687f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
688f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
689f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (buffer.isCrossProcess()) {
690f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // function pointer is only valid in the current process. Write a NULL
691f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // so it can't be accidentally used
692f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        buffer.writeFunctionPtr(NULL);
693f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
694f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        buffer.writeFunctionPtr((void*)fProc);
695f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
696f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
697f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
698f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
699f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
700f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
701f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerclass SkProcCoeffXfermode : public SkProcXfermode {
702f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerpublic:
703f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
704f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            : INHERITED(rec.fProc) {
705f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fMode = mode;
706f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // these may be valid, or may be CANNOT_USE_COEFF
707f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fSrcCoeff = rec.fSC;
708f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fDstCoeff = rec.fDC;
709f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
710f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
711f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual bool asMode(Mode* mode) {
712f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (mode) {
713f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            *mode = fMode;
714f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
715f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return true;
716f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
717f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
718f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual bool asCoeff(Coeff* sc, Coeff* dc) {
719f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (CANNOT_USE_COEFF == fSrcCoeff) {
720f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return false;
721f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
722f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
723f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (sc) {
724f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            *sc = fSrcCoeff;
725f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
726f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (dc) {
727f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            *dc = fDstCoeff;
728f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
729f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return true;
730f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
731f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
732f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual Factory getFactory() { return CreateProc; }
733f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
734f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        this->INHERITED::flatten(buffer);
735f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        buffer.write32(fMode);
736f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
737f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
738f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
739f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkNEW_ARGS(SkProcCoeffXfermode, (buffer));
740f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
741f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
742f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprotected:
743f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
744f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            : INHERITED(buffer) {
745f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fMode = (SkXfermode::Mode)buffer.readU32();
746f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
747f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) {
748f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fSrcCoeff = (Coeff)buffer.readU32();
749f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            fDstCoeff = (Coeff)buffer.readU32();
750f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return;
751f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
752f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
753f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        const ProcCoeff& rec = gProcCoeffs[fMode];
754f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // these may be valid, or may be CANNOT_USE_COEFF
755f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fSrcCoeff = rec.fSC;
756f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fDstCoeff = rec.fDC;
757f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // now update our function-ptr in the super class
758f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        this->INHERITED::setProc(rec.fProc);
759f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
760f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
761f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprivate:
762f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Mode    fMode;
763f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Coeff   fSrcCoeff, fDstCoeff;
764f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
765f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
766f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    typedef SkProcXfermode INHERITED;
767f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
768f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
769f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
770f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
771f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerclass SkClearXfermode : public SkProcCoeffXfermode {
772f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerpublic:
773f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
774f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
775f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
776f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
777f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
778f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
779f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
780f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkNEW_ARGS(SkClearXfermode, (buffer));
781f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
782f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
783f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprivate:
784f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkClearXfermode(SkFlattenableReadBuffer& buffer)
785f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        : SkProcCoeffXfermode(buffer) {}
786f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
787f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
788f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
789f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
790f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                             const SkPMColor* SK_RESTRICT, int count,
791f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                             const SkAlpha* SK_RESTRICT aa) {
792f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && count >= 0);
793f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
794f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
795f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        memset(dst, 0, count << 2);
796f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
797f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
798f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
799f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0xFF == a) {
800f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = 0;
801f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            } else if (a != 0) {
802f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
803f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
804f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
805f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
806f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
807f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
808f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                             const SkPMColor* SK_RESTRICT, int count,
809f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                             const SkAlpha* SK_RESTRICT aa) {
810f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && count >= 0);
811f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
812f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
813f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        memset(dst, 0, count);
814f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
815f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
816f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
817f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0xFF == a) {
818f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = 0;
819f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            } else if (0 != a) {
820f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
821f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
822f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
823f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
824f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
825f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
826f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
827f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
828f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerclass SkSrcXfermode : public SkProcCoeffXfermode {
829f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerpublic:
830f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
831f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
832f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
833f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
834f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
835f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
836f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
837f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkNEW_ARGS(SkSrcXfermode, (buffer));
838f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
839f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
840f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprivate:
841f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
842f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        : SkProcCoeffXfermode(buffer) {}
843f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
844f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
845f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
846f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
847f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                           const SkPMColor* SK_RESTRICT src, int count,
848f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                           const SkAlpha* SK_RESTRICT aa) {
849f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
850f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
851f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
852f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        memcpy(dst, src, count << 2);
853f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
854f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
855f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
856f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (a == 0xFF) {
857f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = src[i];
858f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            } else if (a != 0) {
859f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                dst[i] = SkFourByteInterp(src[i], dst[i], a);
860f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
861f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
862f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
863f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
864f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
865f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
866f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                           const SkPMColor* SK_RESTRICT src, int count,
867f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                           const SkAlpha* SK_RESTRICT aa) {
868f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src && count >= 0);
869f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
870f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == aa) {
871f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
872f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            dst[i] = SkToU8(SkGetPackedA32(src[i]));
873f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
874f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
875f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int i = count - 1; i >= 0; --i) {
876f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            unsigned a = aa[i];
877f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            if (0 != a) {
878f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                unsigned srcA = SkGetPackedA32(src[i]);
879f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                if (a == 0xFF) {
880f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    dst[i] = SkToU8(srcA);
881f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                } else {
882f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
883f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                }
884f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            }
885f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
886f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
887f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
888f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
889f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger////////////////////////////////////////////////////////////////////////////////////
890f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
891f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerclass SkDstInXfermode : public SkProcCoeffXfermode {
892f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerpublic:
893f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
894f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
895f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
896f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
897f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
898f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
899f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkNEW_ARGS(SkDstInXfermode, (buffer));
900f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
901f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
902f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprivate:
903f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
904f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
905f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    typedef SkProcCoeffXfermode INHERITED;
906f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
907f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
908f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
909f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                             const SkPMColor* SK_RESTRICT src, int count,
910f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                             const SkAlpha* SK_RESTRICT aa) {
911f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src);
912f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
913f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (count <= 0) {
914f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return;
915f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
916f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL != aa) {
917f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return this->INHERITED::xfer32(dst, src, count, aa);
918f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
919f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
920f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    do {
921f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unsigned a = SkGetPackedA32(*src);
922f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
923f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        dst++;
924f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        src++;
925f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } while (--count != 0);
926f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
927f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
928f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////////////////
929f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
930f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerclass SkDstOutXfermode : public SkProcCoeffXfermode {
931f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerpublic:
932f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
933f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
934f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
935f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
936f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
937f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
938f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return SkNEW_ARGS(SkDstOutXfermode, (buffer));
939f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
940f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
941f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerprivate:
942f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
943f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        : INHERITED(buffer) {}
944f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
945f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    typedef SkProcCoeffXfermode INHERITED;
946f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
947f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
948f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
949f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                              const SkPMColor* SK_RESTRICT src, int count,
950f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                              const SkAlpha* SK_RESTRICT aa) {
951f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(dst && src);
952f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
953f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (count <= 0) {
954f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return;
955f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
956f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL != aa) {
957f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return this->INHERITED::xfer32(dst, src, count, aa);
958f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
959f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
960f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    do {
961f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unsigned a = SkGetPackedA32(*src);
962f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
963f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        dst++;
964f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        src++;
965f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } while (--count != 0);
966f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
967f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
968f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
969f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
970f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkXfermode* SkXfermode::Create(Mode mode) {
971f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
972f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT((unsigned)mode < kModeCount);
973f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
974f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const ProcCoeff& rec = gProcCoeffs[mode];
975f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
976f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    switch (mode) {
977f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case kClear_Mode:
978f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return SkNEW_ARGS(SkClearXfermode, (rec));
979f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case kSrc_Mode:
980f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return SkNEW_ARGS(SkSrcXfermode, (rec));
981f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case kSrcOver_Mode:
982f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return NULL;
983f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case kDstIn_Mode:
984f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return SkNEW_ARGS(SkDstInXfermode, (rec));
985f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        case kDstOut_Mode:
986f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return SkNEW_ARGS(SkDstOutXfermode, (rec));
987f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        default:
988f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
989f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
990f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
991f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
992f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkXfermodeProc SkXfermode::GetProc(Mode mode) {
993f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc  proc = NULL;
994f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if ((unsigned)mode < kModeCount) {
995f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        proc = gProcCoeffs[mode].fProc;
996f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
997f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return proc;
998f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
999f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1000f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1001f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1002f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1003f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if ((unsigned)mode >= (unsigned)kModeCount) {
1004f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // illegal mode parameter
1005f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
1006f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1007f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1008f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const ProcCoeff& rec = gProcCoeffs[mode];
1009f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1010f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (CANNOT_USE_COEFF == rec.fSC) {
1011f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
1012f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1013f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1014f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1015f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (src) {
1016f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *src = rec.fSC;
1017f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1018f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (dst) {
1019f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *dst = rec.fDC;
1020f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1021f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return true;
1022f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1023f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1024f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) {
1025f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == xfer) {
1026f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (mode) {
1027f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            *mode = kSrcOver_Mode;
1028f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
1029f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return true;
1030f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1031f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return xfer->asMode(mode);
1032f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1033f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1034f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) {
1035f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (NULL == xfer) {
1036f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1037f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1038f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return xfer->asCoeff(src, dst);
1039f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1040f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1041f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkXfermode::IsMode(SkXfermode* xfer, Mode mode) {
1042f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // if xfer==null then the mode is srcover
1043f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Mode m = kSrcOver_Mode;
1044f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (xfer && !xfer->asMode(&m)) {
1045f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        return false;
1046f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1047f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return mode == m;
1048f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1049f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1050f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
1051f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//////////// 16bit xfermode procs
1052f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1053f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_DEBUG
1054f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1055f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1056f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
1057f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1058f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1059f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1060f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPixel32ToPixel16(src);
1061f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1062f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1063f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1064f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1065f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1066f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1067f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1068f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_0(src));
1069f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1070f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1071f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1072f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1073f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1074f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPixel32ToPixel16(src);
1075f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1076f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1077f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1078f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_0(src));
1079f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1080f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1081f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1082f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1083f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1084f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1085f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1086f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1087f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1088f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1089f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPixel32ToPixel16(src);
1090f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1091f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1092f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1093f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1094f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1095f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1096f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1097f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1098f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_0(src));
1099f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned isa = 255 - SkGetPackedA32(src);
1104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackRGB16(
1106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_0(src));
1113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPixel32ToPixel16(src);
1119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/*********
1127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    darken and lighten boil down to this.
1128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (Sa == 0) these become
1133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        darken  = Dc + min(0, Dc) = 0
1134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        lighten = Dc + max(0, Dc) = Dc
1135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (Sa == 1) these become
1137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        darken  = min(Sc, Dc)
1138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        lighten = max(Sc, Dc)
1139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger*/
1140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_0(src));
1143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return 0;
1144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackRGB16(r, g, b);
1152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_0(src));
1156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return dst;
1157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(require_255(src));
1161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkPackRGB16(r, g, b);
1165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstruct Proc16Rec {
1168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc16    fProc16_0;
1169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc16    fProc16_255;
1170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc16    fProc16_General;
1171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
1172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic const Proc16Rec gModeProcs16[] = {
1174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // CLEAR
1175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 src_modeproc16_255,     NULL            },
1176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 srcin_modeproc16_255,   NULL            },
1180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 dstin_modeproc16_255,   NULL            },
1181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            },// SRC_OUT
1182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { dstout_modeproc16_0,  NULL,                   NULL            },
1183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 dstatop_modeproc16_255, NULL            },
1185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // XOR
1186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // plus
1188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // multiply
1189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // screen
1190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // overlay
1191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // colordodge
1194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // colorburn
1195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // hardlight
1196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // softlight
1197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // difference
1198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    { NULL,                 NULL,                   NULL            }, // exclusion
1199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger};
1200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1201f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkXfermodeProc16  proc16 = NULL;
1203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if ((unsigned)mode < kModeCount) {
1204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        const Proc16Rec& rec = gModeProcs16[mode];
1205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unsigned a = SkColorGetA(srcColor);
1206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        if (0 == a) {
1208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            proc16 = rec.fProc16_0;
1209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else if (255 == a) {
1210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            proc16 = rec.fProc16_255;
1211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        } else {
1212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            proc16 = rec.fProc16_General;
1213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
1214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
1215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return proc16;
1216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
1217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
1218f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1222f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1223f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1224f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1225