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