SkColorFilters.cpp revision 845fdaca174f4675e9acc164b510e3a5ffa9053c
1845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com/*
2845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * Copyright (C) 2006 The Android Open Source Project
3845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com *
4845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * Licensed under the Apache License, Version 2.0 (the "License");
5845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * you may not use this file except in compliance with the License.
6845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * You may obtain a copy of the License at
7845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com *
8845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com *      http://www.apache.org/licenses/LICENSE-2.0
9845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com *
10845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * Unless required by applicable law or agreed to in writing, software
11845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * distributed under the License is distributed on an "AS IS" BASIS,
12845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * See the License for the specific language governing permissions and
14845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com * limitations under the License.
15845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com */
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// common baseclass
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk_XfermodeColorFilter : public SkColorFilter {
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
24845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    Sk_XfermodeColorFilter(SkColor color)
25845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        : fPMColor(SkPreMultiplyColor(color)) {}
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
28845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        buffer.write32(fPMColor);
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
30845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
31845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    Sk_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) {
32845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        fPMColor = buffer.readU32();
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
34845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
35845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkPMColor   fPMColor;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSrc_XfermodeColorFilter : public Sk_XfermodeColorFilter {
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSrc_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
43845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (SkGetPackedA32(fPMColor) == 0xFF) {
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
45845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return 0;
47845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
51845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
52845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        sk_memset32(result, fPMColor, count);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
56845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
58845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkSrc_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
65845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        : INHERITED(buffer) {}
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
68845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (buffer));
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
71845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sk_XfermodeColorFilter INHERITED;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSrcOver_XfermodeColorFilter : public Sk_XfermodeColorFilter {
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSrcOver_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
79845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
80845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (SkGetPackedA32(fPMColor) == 0xFF) {
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
82845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return 0;
84845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
87845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
88845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
89845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkPMColor   src = fPMColor;
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned    scale = SkAlpha255To256(255 - SkGetPackedA32(src));
91845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
92845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = src + SkAlphaMulQ(shader[i], scale);
94845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
97845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
98845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
100845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc;  }
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
106845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkSrcOver_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
107845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        : INHERITED(buffer) {}
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
110845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (buffer));
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sk_XfermodeColorFilter INHERITED;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkXfermodeColorFilter : public Sk_XfermodeColorFilter {
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeColorFilter(SkColor color, SkXfermodeProc proc,
122845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                          SkXfermodeProc16 proc16) : INHERITED(color) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc = proc;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc16 = proc16;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
127845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
131845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
132845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
133845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkPMColor       color = fPMColor;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkXfermodeProc  proc = fProc;
135845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
136845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = proc(color, shader[i]);
138845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
142845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
145845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkPMColor        color = fPMColor;
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkXfermodeProc16 proc16 = fProc16;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
148845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = proc16(color, shader[i]);
150845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::flatten(buffer);
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.writeFunctionPtr((void*)fProc);
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.writeFunctionPtr((void*)fProc16);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() {
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc = (SkXfermodeProc) buffer.readFunctionPtr();
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr();
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkXfermodeColorFilter, (buffer));
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc   fProc;
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16 fProc16;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sk_XfermodeColorFilter INHERITED;
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
179845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateProcFilter(SkColor color,
180845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermodeProc proc,
181845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermodeProc16 proc16) {
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return proc ?
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkNEW_ARGS(SkXfermodeColorFilter, (color, proc, proc16)) :
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            NULL;
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
189845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
190845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermode::Mode mode) {
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alpha = SkColorGetA(color);
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // first collaps some modes if possible
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
195845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kClear_Mode == mode) {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color = 0;
197845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        mode = SkXfermode::kSrc_Mode;
198845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    } else if (SkXfermode::kSrcOver_Mode == mode) {
199845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (0 == alpha) {
200845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            mode = SkXfermode::kDst_Mode;
201845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else if (255 == alpha) {
202845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            mode = SkXfermode::kSrc_Mode;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // else just stay srcover
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // weed out combinations that are noops, and just return null
208845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kDst_Mode == mode ||
209845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
210845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDstOver_Mode == mode ||
211845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDstOut_Mode == mode ||
212845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kSrcATop_Mode == mode ||
213845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kXor_Mode == mode ||
214845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDarken_Mode == mode)) ||
215845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (mode) {
220845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    case SkXfermode::kSrc_Mode:
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (color));
222845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    case SkXfermode::kSrcOver_Mode:
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (color));
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
225845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        return SkColorFilter::CreateProcFilter(color, SkXfermode::GetProc(mode),
226845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                            SkXfermode::GetProc16(mode, color));
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
230845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com///////////////////////////////////////////////////////////////////////////////
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
232845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comstatic inline unsigned pin(unsigned value, unsigned max) {
233845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (value > max) {
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        value = max;
235845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    }
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
239845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comstatic inline unsigned SkUClampMax(unsigned value, unsigned max) {
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((int32_t)value >= 0);
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((int32_t)max >= 0);
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int diff = max - value;
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // clear diff if diff is positive
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    diff &= diff >> 31;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value + diff;
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter : public SkColorFilter {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
254845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
255845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addR = SkColorGetR(fAdd);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addG = SkColorGetG(fAdd);
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addB = SkColorGetB(fAdd);
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
264845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
266845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scaleA = SkAlpha255To256(a);
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
279845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(fMul);
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(fAdd);
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
284845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual Factory getFactory() {
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
288845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMul = buffer.readU32();
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fAdd = buffer.readU32();
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor fMul, fAdd;
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
296845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter, (buffer));
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(mul, add) {}
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
306845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
307845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addR = SkColorGetR(fAdd);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addG = SkColorGetG(fAdd);
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addB = SkColorGetB(fAdd);
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
312845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
314845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scaleA = SkAlpha255To256(a);
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
333845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)  {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (buffer));
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_JustMul : public SkLightingColorFilter {
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(mul, add) {}
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
344845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
345845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
350845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
352845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
370845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_JustMul, (buffer));
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
380845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            : INHERITED(mul, add) {
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetR(add) == 0);
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetG(add) == 0);
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetB(add) == 0);
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
388845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
392845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
393845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // all mul components are the same
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
397845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (count > 0) {
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *result++ = SkAlphaMulRGB16(*shader++, scale);
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--count > 0);
401845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
411845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (buffer));
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_NoPin : public SkLightingColorFilter {
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : INHERITED(mul, add) {}
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
423845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
424845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addR = SkColorGetR(fAdd);
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addG = SkColorGetG(fAdd);
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addB = SkColorGetB(fAdd);
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
433845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
435845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scaleA = SkAlpha255To256(a);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
454845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_NoPin, (buffer));
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
461845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com///////////////////////////////////////////////////////////////////////////////
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSimpleColorFilter : public SkColorFilter {
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
465845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
466845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (result != src) {
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(result, src, count * sizeof(SkPMColor));
468845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
471845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {}
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
473845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual Factory getFactory() {
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
477845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW(SkSimpleColorFilter);
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
482845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    mul &= 0x00FFFFFF;
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    add &= 0x00FFFFFF;
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
486845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (0xFFFFFF == mul) {
487845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (0 == add) {
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW(SkSimpleColorFilter);   // no change to the colors
489845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
491845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
494845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (0 == add) {
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (SkColorGetR(mul) == SkColorGetG(mul) &&
496845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                SkColorGetR(mul) == SkColorGetB(mul)) {
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
498845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
505845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkColorGetB(mul) + SkColorGetB(add) <= 255) {
506845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
507845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    }
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
512