SkColorFilters.cpp revision 29e5054dd07c97c2195c5f64bf67aaa6b5afa204
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
17c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com#include "SkBlitRow.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// common baseclass
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk_XfermodeColorFilter : public SkColorFilter {
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
25845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    Sk_XfermodeColorFilter(SkColor color)
26845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        : fPMColor(SkPreMultiplyColor(color)) {}
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
29845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        buffer.write32(fPMColor);
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
31845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
32845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    Sk_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) {
33845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        fPMColor = buffer.readU32();
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
35845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
36845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkPMColor   fPMColor;
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSrc_XfermodeColorFilter : public Sk_XfermodeColorFilter {
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkSrc_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
43845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
44845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (SkGetPackedA32(fPMColor) == 0xFF) {
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
46845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return 0;
48845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
51845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
52845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
53845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        sk_memset32(result, fPMColor, count);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
57845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
59845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkSrc_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
66845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        : INHERITED(buffer) {}
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
69845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (buffer));
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
72845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sk_XfermodeColorFilter INHERITED;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSrcOver_XfermodeColorFilter : public Sk_XfermodeColorFilter {
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
7829e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org    SkSrcOver_XfermodeColorFilter(SkColor color)
7929e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org        : INHERITED(color), fColor32Proc(SkBlitRow::ColorProcFactory()) {}
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
81845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
82845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (SkGetPackedA32(fPMColor) == 0xFF) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
84845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return 0;
86845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
89845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
90845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
9129e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org        fColor32Proc(result, shader, count, fPMColor);
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
94845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
95845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
97845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc;  }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
103845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkSrcOver_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
10429e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org        : INHERITED(buffer), fColor32Proc(SkBlitRow::ColorProcFactory()) {}
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
107845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (buffer));
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sk_XfermodeColorFilter INHERITED;
11229e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org    SkBlitRow::ColorProc fColor32Proc;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkXfermodeColorFilter : public Sk_XfermodeColorFilter {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeColorFilter(SkColor color, SkXfermodeProc proc,
120845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                          SkXfermodeProc16 proc16) : INHERITED(color) {
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc = proc;
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc16 = proc16;
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
125845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
129845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
130845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
131845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkPMColor       color = fPMColor;
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkXfermodeProc  proc = fProc;
133845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com
134845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = proc(color, shader[i]);
136845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
139845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
140845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->getFlags() & kHasFilter16_Flag);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
143845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkPMColor        color = fPMColor;
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkXfermodeProc16 proc16 = fProc16;
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
146845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = proc16(color, shader[i]);
148845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::flatten(buffer);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.writeFunctionPtr((void*)fProc);
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.writeFunctionPtr((void*)fProc16);
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() {
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc = (SkXfermodeProc) buffer.readFunctionPtr();
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr();
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkXfermodeColorFilter, (buffer));
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc   fProc;
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkXfermodeProc16 fProc16;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef Sk_XfermodeColorFilter INHERITED;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
177845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateProcFilter(SkColor color,
178845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermodeProc proc,
179845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermodeProc16 proc16) {
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return proc ?
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkNEW_ARGS(SkXfermodeColorFilter, (color, proc, proc16)) :
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            NULL;
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
187845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
188845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                               SkXfermode::Mode mode) {
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alpha = SkColorGetA(color);
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // first collaps some modes if possible
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
193845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kClear_Mode == mode) {
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color = 0;
195845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        mode = SkXfermode::kSrc_Mode;
196845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    } else if (SkXfermode::kSrcOver_Mode == mode) {
197845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (0 == alpha) {
198845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            mode = SkXfermode::kDst_Mode;
199845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else if (255 == alpha) {
200845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            mode = SkXfermode::kSrc_Mode;
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // else just stay srcover
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // weed out combinations that are noops, and just return null
206845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::kDst_Mode == mode ||
207845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
208845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDstOver_Mode == mode ||
209845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDstOut_Mode == mode ||
210845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kSrcATop_Mode == mode ||
211845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kXor_Mode == mode ||
212845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                        SkXfermode::kDarken_Mode == mode)) ||
213845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return NULL;
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (mode) {
218845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    case SkXfermode::kSrc_Mode:
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (color));
220845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    case SkXfermode::kSrcOver_Mode:
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (color));
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
223845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        return SkColorFilter::CreateProcFilter(color, SkXfermode::GetProc(mode),
224845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                                            SkXfermode::GetProc16(mode, color));
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com///////////////////////////////////////////////////////////////////////////////
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
230845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comstatic inline unsigned pin(unsigned value, unsigned max) {
231845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (value > max) {
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        value = max;
233845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    }
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
237845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comstatic inline unsigned SkUClampMax(unsigned value, unsigned max) {
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((int32_t)value >= 0);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((int32_t)max >= 0);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int diff = max - value;
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // clear diff if diff is positive
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    diff &= diff >> 31;
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return value + diff;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter : public SkColorFilter {
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
252845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
253845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addR = SkColorGetR(fAdd);
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addG = SkColorGetG(fAdd);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addB = SkColorGetB(fAdd);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
262845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
264845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scaleA = SkAlpha255To256(a);
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
277845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(fMul);
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(fAdd);
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
282845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual Factory getFactory() {
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
286845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMul = buffer.readU32();
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fAdd = buffer.readU32();
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkColor fMul, fAdd;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
294845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter, (buffer));
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(mul, add) {}
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
304845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
305845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addR = SkColorGetR(fAdd);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addG = SkColorGetG(fAdd);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addB = SkColorGetB(fAdd);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
310845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
312845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scaleA = SkAlpha255To256(a);
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
331845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)  {
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (buffer));
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_JustMul : public SkLightingColorFilter {
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(mul, add) {}
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
342845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
343845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
348845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
350845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
368845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_JustMul, (buffer));
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
378845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            : INHERITED(mul, add) {
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetR(add) == 0);
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetG(add) == 0);
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetB(add) == 0);
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
386845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual uint32_t getFlags() {
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
390845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan16(const uint16_t shader[], int count,
391845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                              uint16_t result[]) {
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // all mul components are the same
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
395845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (count > 0) {
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            do {
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *result++ = SkAlphaMulRGB16(*shader++, scale);
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } while (--count > 0);
399845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
409845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (buffer));
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkLightingColorFilter_NoPin : public SkLightingColorFilter {
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    : INHERITED(mul, add) {}
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
421845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void filterSpan(const SkPMColor shader[], int count,
422845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                            SkPMColor result[]) {
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addR = SkColorGetR(fAdd);
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addG = SkColorGetG(fAdd);
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned addB = SkColorGetB(fAdd);
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
431845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        for (int i = 0; i < count; i++) {
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkPMColor c = shader[i];
433845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            if (c) {
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned a = SkGetPackedA32(c);
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned scaleA = SkAlpha255To256(a);
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                c = SkPackARGB32(a, r, g, b);
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result[i] = c;
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    virtual Factory getFactory() { return CreateProc; }
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(buffer) {}
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
452845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(SkLightingColorFilter_NoPin, (buffer));
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkLightingColorFilter INHERITED;
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
459845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com///////////////////////////////////////////////////////////////////////////////
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkSimpleColorFilter : public SkColorFilter {
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
463845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
464845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (result != src) {
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(result, src, count * sizeof(SkPMColor));
466845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
469845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {}
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
471845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    virtual Factory getFactory() {
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
475845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW(SkSimpleColorFilter);
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
480845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    mul &= 0x00FFFFFF;
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    add &= 0x00FFFFFF;
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
484845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (0xFFFFFF == mul) {
485845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        if (0 == add) {
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW(SkSimpleColorFilter);   // no change to the colors
487845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
489845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        }
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
492845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (0 == add) {
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (SkColorGetR(mul) == SkColorGetG(mul) &&
494845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com                SkColorGetR(mul) == SkColorGetB(mul)) {
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
496845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        } else {
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
503845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com        SkColorGetB(mul) + SkColorGetB(add) <= 255) {
504845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
505845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    }
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
510