1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkBlitRow.h"
11#include "SkColorFilter.h"
12#include "SkColorPriv.h"
13#include "SkFlattenableBuffers.h"
14#include "SkUtils.h"
15
16#define ILLEGAL_XFERMODE_MODE   ((SkXfermode::Mode)-1)
17
18// baseclass for filters that store a color and mode
19class SkModeColorFilter : public SkColorFilter {
20public:
21    SkModeColorFilter(SkColor color) {
22        fColor = color;
23        fMode = ILLEGAL_XFERMODE_MODE;
24        this->updateCache();
25    }
26
27    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
28        fColor = color;
29        fMode = mode;
30        this->updateCache();
31    };
32
33    SkColor getColor() const { return fColor; }
34    SkXfermode::Mode getMode() const { return fMode; }
35    bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; }
36    SkPMColor getPMColor() const { return fPMColor; }
37
38    virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
39        if (ILLEGAL_XFERMODE_MODE == fMode) {
40            return false;
41        }
42
43        if (color) {
44            *color = fColor;
45        }
46        if (mode) {
47            *mode = fMode;
48        }
49        return true;
50    }
51
52    virtual uint32_t getFlags() const SK_OVERRIDE {
53        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
54    }
55
56    virtual void filterSpan(const SkPMColor shader[], int count,
57                            SkPMColor result[]) const SK_OVERRIDE {
58        SkPMColor       color = fPMColor;
59        SkXfermodeProc  proc = fProc;
60
61        for (int i = 0; i < count; i++) {
62            result[i] = proc(color, shader[i]);
63        }
64    }
65
66    virtual void filterSpan16(const uint16_t shader[], int count,
67                              uint16_t result[]) const SK_OVERRIDE {
68        SkASSERT(this->getFlags() & kHasFilter16_Flag);
69
70        SkPMColor        color = fPMColor;
71        SkXfermodeProc16 proc16 = fProc16;
72
73        for (int i = 0; i < count; i++) {
74            result[i] = proc16(color, shader[i]);
75        }
76    }
77
78    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
79
80protected:
81    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
82        this->INHERITED::flatten(buffer);
83        buffer.writeColor(fColor);
84        buffer.writeUInt(fMode);
85    }
86
87    SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
88        fColor = buffer.readColor();
89        fMode = (SkXfermode::Mode)buffer.readUInt();
90        this->updateCache();
91    }
92
93private:
94    SkColor             fColor;
95    SkXfermode::Mode    fMode;
96    // cache
97    SkPMColor           fPMColor;
98    SkXfermodeProc      fProc;
99    SkXfermodeProc16    fProc16;
100
101    void updateCache() {
102        fPMColor = SkPreMultiplyColor(fColor);
103        fProc = SkXfermode::GetProc(fMode);
104        fProc16 = SkXfermode::GetProc16(fMode, fColor);
105    }
106
107    typedef SkColorFilter INHERITED;
108};
109
110class Src_SkModeColorFilter : public SkModeColorFilter {
111public:
112    Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
113
114    virtual uint32_t getFlags() const SK_OVERRIDE {
115        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
116            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
117        } else {
118            return 0;
119        }
120    }
121
122    virtual void filterSpan(const SkPMColor shader[], int count,
123                            SkPMColor result[]) const SK_OVERRIDE {
124        sk_memset32(result, this->getPMColor(), count);
125    }
126
127    virtual void filterSpan16(const uint16_t shader[], int count,
128                              uint16_t result[]) const SK_OVERRIDE {
129        SkASSERT(this->getFlags() & kHasFilter16_Flag);
130        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
131    }
132
133    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
134
135protected:
136    Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
137        : INHERITED(buffer) {}
138
139private:
140    typedef SkModeColorFilter INHERITED;
141};
142
143class SrcOver_SkModeColorFilter : public SkModeColorFilter {
144public:
145    SrcOver_SkModeColorFilter(SkColor color)
146            : INHERITED(color, SkXfermode::kSrcOver_Mode) {
147        fColor32Proc = SkBlitRow::ColorProcFactory();
148    }
149
150    virtual uint32_t getFlags() const SK_OVERRIDE {
151        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
152            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
153        } else {
154            return 0;
155        }
156    }
157
158    virtual void filterSpan(const SkPMColor shader[], int count,
159                            SkPMColor result[]) const SK_OVERRIDE {
160        fColor32Proc(result, shader, count, this->getPMColor());
161    }
162
163    virtual void filterSpan16(const uint16_t shader[], int count,
164                              uint16_t result[]) const SK_OVERRIDE {
165        SkASSERT(this->getFlags() & kHasFilter16_Flag);
166        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
167    }
168
169    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
170
171protected:
172    SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
173        : INHERITED(buffer) {
174            fColor32Proc = SkBlitRow::ColorProcFactory();
175        }
176
177private:
178
179    SkBlitRow::ColorProc fColor32Proc;
180
181    typedef SkModeColorFilter INHERITED;
182};
183
184///////////////////////////////////////////////////////////////////////////////
185
186SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
187                                               SkXfermode::Mode mode) {
188    unsigned alpha = SkColorGetA(color);
189
190    // first collaps some modes if possible
191
192    if (SkXfermode::kClear_Mode == mode) {
193        color = 0;
194        mode = SkXfermode::kSrc_Mode;
195    } else if (SkXfermode::kSrcOver_Mode == mode) {
196        if (0 == alpha) {
197            mode = SkXfermode::kDst_Mode;
198        } else if (255 == alpha) {
199            mode = SkXfermode::kSrc_Mode;
200        }
201        // else just stay srcover
202    }
203
204    // weed out combinations that are noops, and just return null
205    if (SkXfermode::kDst_Mode == mode ||
206        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
207                        SkXfermode::kDstOver_Mode == mode ||
208                        SkXfermode::kDstOut_Mode == mode ||
209                        SkXfermode::kSrcATop_Mode == mode ||
210                        SkXfermode::kXor_Mode == mode ||
211                        SkXfermode::kDarken_Mode == mode)) ||
212            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
213        return NULL;
214    }
215
216    switch (mode) {
217        case SkXfermode::kSrc_Mode:
218            return SkNEW_ARGS(Src_SkModeColorFilter, (color));
219        case SkXfermode::kSrcOver_Mode:
220            return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
221        default:
222            return SkNEW_ARGS(SkModeColorFilter, (color, mode));
223    }
224}
225
226///////////////////////////////////////////////////////////////////////////////
227
228static inline unsigned pin(unsigned value, unsigned max) {
229    if (value > max) {
230        value = max;
231    }
232    return value;
233}
234
235class SkLightingColorFilter : public SkColorFilter {
236public:
237    SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
238
239    virtual void filterSpan(const SkPMColor shader[], int count,
240                            SkPMColor result[]) const SK_OVERRIDE {
241        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
242        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
243        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
244
245        unsigned addR = SkColorGetR(fAdd);
246        unsigned addG = SkColorGetG(fAdd);
247        unsigned addB = SkColorGetB(fAdd);
248
249        for (int i = 0; i < count; i++) {
250            SkPMColor c = shader[i];
251            if (c) {
252                unsigned a = SkGetPackedA32(c);
253                unsigned scaleA = SkAlpha255To256(a);
254                unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
255                unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
256                unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
257                c = SkPackARGB32(a, r, g, b);
258            }
259            result[i] = c;
260        }
261    }
262
263    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter)
264
265protected:
266    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
267        this->INHERITED::flatten(buffer);
268        buffer.writeColor(fMul);
269        buffer.writeColor(fAdd);
270    }
271
272    SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
273        fMul = buffer.readColor();
274        fAdd = buffer.readColor();
275    }
276
277    SkColor fMul, fAdd;
278
279private:
280    typedef SkColorFilter INHERITED;
281};
282
283class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
284public:
285    SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
286        : INHERITED(mul, add) {}
287
288    virtual void filterSpan(const SkPMColor shader[], int count,
289                            SkPMColor result[]) const SK_OVERRIDE {
290        unsigned addR = SkColorGetR(fAdd);
291        unsigned addG = SkColorGetG(fAdd);
292        unsigned addB = SkColorGetB(fAdd);
293
294        for (int i = 0; i < count; i++) {
295            SkPMColor c = shader[i];
296            if (c) {
297                unsigned a = SkGetPackedA32(c);
298                unsigned scaleA = SkAlpha255To256(a);
299                unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
300                unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
301                unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
302                c = SkPackARGB32(a, r, g, b);
303            }
304            result[i] = c;
305        }
306    }
307
308    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustAdd)
309
310protected:
311    SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
312        : INHERITED(buffer) {}
313
314private:
315    typedef SkLightingColorFilter INHERITED;
316};
317
318class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
319public:
320    SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
321        : INHERITED(mul, add) {}
322
323    virtual void filterSpan(const SkPMColor shader[], int count,
324                            SkPMColor result[]) const SK_OVERRIDE {
325        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
326        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
327        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
328
329        for (int i = 0; i < count; i++) {
330            SkPMColor c = shader[i];
331            if (c) {
332                unsigned a = SkGetPackedA32(c);
333                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
334                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
335                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
336                c = SkPackARGB32(a, r, g, b);
337            }
338            result[i] = c;
339        }
340    }
341
342    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustMul)
343
344protected:
345    SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
346        : INHERITED(buffer) {}
347
348private:
349    typedef SkLightingColorFilter INHERITED;
350};
351
352class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
353public:
354    SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
355            : INHERITED(mul, add) {
356        SkASSERT(SkColorGetR(add) == 0);
357        SkASSERT(SkColorGetG(add) == 0);
358        SkASSERT(SkColorGetB(add) == 0);
359        SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
360        SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
361    }
362
363    virtual uint32_t getFlags() const SK_OVERRIDE {
364        return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
365    }
366
367    virtual void filterSpan16(const uint16_t shader[], int count,
368                              uint16_t result[]) const SK_OVERRIDE {
369        // all mul components are the same
370        unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
371
372        if (count > 0) {
373            do {
374                *result++ = SkAlphaMulRGB16(*shader++, scale);
375            } while (--count > 0);
376        }
377    }
378
379    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_SingleMul)
380
381protected:
382    SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
383        : INHERITED(buffer) {}
384
385private:
386    typedef SkLightingColorFilter INHERITED;
387};
388
389class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
390public:
391    SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
392    : INHERITED(mul, add) {}
393
394    virtual void filterSpan(const SkPMColor shader[], int count,
395                            SkPMColor result[]) const SK_OVERRIDE {
396        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
397        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
398        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
399
400        unsigned addR = SkColorGetR(fAdd);
401        unsigned addG = SkColorGetG(fAdd);
402        unsigned addB = SkColorGetB(fAdd);
403
404        for (int i = 0; i < count; i++) {
405            SkPMColor c = shader[i];
406            if (c) {
407                unsigned a = SkGetPackedA32(c);
408                unsigned scaleA = SkAlpha255To256(a);
409                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
410                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
411                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
412                c = SkPackARGB32(a, r, g, b);
413            }
414            result[i] = c;
415        }
416    }
417
418    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_NoPin)
419
420protected:
421    SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
422        : INHERITED(buffer) {}
423
424private:
425    typedef SkLightingColorFilter INHERITED;
426};
427
428///////////////////////////////////////////////////////////////////////////////
429
430class SkSimpleColorFilter : public SkColorFilter {
431public:
432    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
433        return SkNEW(SkSimpleColorFilter);
434    }
435
436protected:
437    void filterSpan(const SkPMColor src[], int count, SkPMColor
438                    result[]) const SK_OVERRIDE {
439        if (result != src) {
440            memcpy(result, src, count * sizeof(SkPMColor));
441        }
442    }
443
444    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {}
445
446    virtual Factory getFactory() {
447        return CreateProc;
448    }
449
450};
451
452SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
453    mul &= 0x00FFFFFF;
454    add &= 0x00FFFFFF;
455
456    if (0xFFFFFF == mul) {
457        if (0 == add) {
458            return SkNEW(SkSimpleColorFilter);   // no change to the colors
459        } else {
460            return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
461        }
462    }
463
464    if (0 == add) {
465        if (SkColorGetR(mul) == SkColorGetG(mul) &&
466                SkColorGetR(mul) == SkColorGetB(mul)) {
467            return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
468        } else {
469            return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
470        }
471    }
472
473    if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
474        SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
475        SkColorGetB(mul) + SkColorGetB(add) <= 255) {
476            return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
477    }
478
479    return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
480}
481
482SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
483    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
484    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
485    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
486    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter)
487    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustAdd)
488    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustMul)
489    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_SingleMul)
490    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_NoPin)
491    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSimpleColorFilter)
492SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
493