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#include "SkValidationUtils.h"
17
18#define ILLEGAL_XFERMODE_MODE   ((SkXfermode::Mode)-1)
19
20// baseclass for filters that store a color and mode
21class SkModeColorFilter : public SkColorFilter {
22public:
23    SkModeColorFilter(SkColor color) {
24        fColor = color;
25        fMode = ILLEGAL_XFERMODE_MODE;
26        this->updateCache();
27    }
28
29    SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
30        fColor = color;
31        fMode = mode;
32        this->updateCache();
33    };
34
35    SkColor getColor() const { return fColor; }
36    SkXfermode::Mode getMode() const { return fMode; }
37    bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; }
38    SkPMColor getPMColor() const { return fPMColor; }
39
40    virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
41        if (ILLEGAL_XFERMODE_MODE == fMode) {
42            return false;
43        }
44
45        if (color) {
46            *color = fColor;
47        }
48        if (mode) {
49            *mode = fMode;
50        }
51        return true;
52    }
53
54    virtual uint32_t getFlags() const SK_OVERRIDE {
55        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
56    }
57
58    virtual void filterSpan(const SkPMColor shader[], int count,
59                            SkPMColor result[]) const SK_OVERRIDE {
60        SkPMColor       color = fPMColor;
61        SkXfermodeProc  proc = fProc;
62
63        for (int i = 0; i < count; i++) {
64            result[i] = proc(color, shader[i]);
65        }
66    }
67
68    virtual void filterSpan16(const uint16_t shader[], int count,
69                              uint16_t result[]) const SK_OVERRIDE {
70        SkASSERT(this->getFlags() & kHasFilter16_Flag);
71
72        SkPMColor        color = fPMColor;
73        SkXfermodeProc16 proc16 = fProc16;
74
75        for (int i = 0; i < count; i++) {
76            result[i] = proc16(color, shader[i]);
77        }
78    }
79
80#ifdef SK_DEVELOPER
81    virtual void toString(SkString* str) const SK_OVERRIDE {
82        str->append("SkModeColorFilter: color: 0x");
83        str->appendHex(fColor);
84        str->append(" mode: ");
85        str->append(SkXfermode::ModeName(fMode));
86    }
87#endif
88
89#if SK_SUPPORT_GPU
90    virtual GrEffectRef* asNewEffect(GrContext*) const SK_OVERRIDE;
91#endif
92    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
93
94protected:
95    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
96        this->INHERITED::flatten(buffer);
97        buffer.writeColor(fColor);
98        buffer.writeUInt(fMode);
99    }
100
101    SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
102        fColor = buffer.readColor();
103        fMode = (SkXfermode::Mode)buffer.readUInt();
104        if (buffer.isValid()) {
105            this->updateCache();
106            buffer.validate(SkIsValidMode(fMode));
107        }
108    }
109
110private:
111    SkColor             fColor;
112    SkXfermode::Mode    fMode;
113    // cache
114    SkPMColor           fPMColor;
115    SkXfermodeProc      fProc;
116    SkXfermodeProc16    fProc16;
117
118    void updateCache() {
119        fPMColor = SkPreMultiplyColor(fColor);
120        fProc = SkXfermode::GetProc(fMode);
121        fProc16 = SkXfermode::GetProc16(fMode, fColor);
122    }
123
124    typedef SkColorFilter INHERITED;
125};
126
127///////////////////////////////////////////////////////////////////////////////
128#if SK_SUPPORT_GPU
129#include "GrBlend.h"
130#include "GrEffect.h"
131#include "GrEffectUnitTest.h"
132#include "GrTBackendEffectFactory.h"
133#include "gl/GrGLEffect.h"
134#include "SkGr.h"
135
136namespace {
137/**
138 * A definition of blend equation for one coefficient. Generates a
139 * blend_coeff * value "expression".
140 */
141template<typename ColorExpr>
142static inline ColorExpr blend_term(SkXfermode::Coeff coeff,
143                                   const ColorExpr& src,
144                                   const ColorExpr& dst,
145                                   const ColorExpr& value) {
146    switch (coeff) {
147    default:
148        GrCrash("Unexpected xfer coeff.");
149    case SkXfermode::kZero_Coeff:    /** 0 */
150        return ColorExpr(0);
151    case SkXfermode::kOne_Coeff:     /** 1 */
152        return value;
153    case SkXfermode::kSC_Coeff:
154        return src * value;
155    case SkXfermode::kISC_Coeff:
156        return (ColorExpr(1) - src) * dst;
157    case SkXfermode::kDC_Coeff:
158        return dst * value;
159    case SkXfermode::kIDC_Coeff:
160        return (ColorExpr(1) - dst) * value;
161    case SkXfermode::kSA_Coeff:      /** src alpha */
162        return src.a() * value;
163    case SkXfermode::kISA_Coeff:     /** inverse src alpha (i.e. 1 - sa) */
164        return (typename ColorExpr::AExpr(1) - src.a()) * value;
165    case SkXfermode::kDA_Coeff:      /** dst alpha */
166        return dst.a() * value;
167    case SkXfermode::kIDA_Coeff:     /** inverse dst alpha (i.e. 1 - da) */
168        return (typename ColorExpr::AExpr(1) - dst.a()) *  value;
169    }
170}
171/**
172 * Creates a color filter expression which modifies the color by
173 * the specified color filter.
174 */
175template <typename ColorExpr>
176static inline ColorExpr color_filter_expression(const SkXfermode::Mode& mode,
177                                                const ColorExpr& filterColor,
178                                                const ColorExpr& inColor) {
179    SkXfermode::Coeff colorCoeff;
180    SkXfermode::Coeff filterColorCoeff;
181    SkAssertResult(SkXfermode::ModeAsCoeff(mode, &filterColorCoeff, &colorCoeff));
182    return blend_term(colorCoeff, filterColor, inColor, inColor) +
183        blend_term(filterColorCoeff, filterColor, inColor, filterColor);
184}
185
186}
187
188class ModeColorFilterEffect : public GrEffect {
189public:
190    static GrEffectRef* Create(const GrColor& c, SkXfermode::Mode mode) {
191        // TODO: Make the effect take the coeffs rather than mode since we already do the
192        // conversion here.
193        SkXfermode::Coeff srcCoeff, dstCoeff;
194        if (!SkXfermode::ModeAsCoeff(mode, &srcCoeff, &dstCoeff)) {
195            SkDebugf("Failing to create color filter for mode %d\n", mode);
196            return NULL;
197        }
198        AutoEffectUnref effect(SkNEW_ARGS(ModeColorFilterEffect, (c, mode)));
199        return CreateEffectRef(effect);
200    }
201
202    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
203
204    bool willUseFilterColor() const {
205        SkXfermode::Coeff dstCoeff;
206        SkXfermode::Coeff srcCoeff;
207        SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
208        if (SkXfermode::kZero_Coeff == srcCoeff) {
209            return GrBlendCoeffRefsSrc(sk_blend_to_grblend(dstCoeff));
210        }
211        return true;
212    }
213
214    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
215        return GrTBackendEffectFactory<ModeColorFilterEffect>::getInstance();
216    }
217
218    static const char* Name() { return "ModeColorFilterEffect"; }
219
220    SkXfermode::Mode mode() const { return fMode; }
221    GrColor color() const { return fColor; }
222
223    class GLEffect : public GrGLEffect {
224    public:
225        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
226            : INHERITED(factory) {
227        }
228
229        virtual void emitCode(GrGLShaderBuilder* builder,
230                              const GrDrawEffect& drawEffect,
231                              EffectKey key,
232                              const char* outputColor,
233                              const char* inputColor,
234                              const TransformedCoordsArray& coords,
235                              const TextureSamplerArray& samplers) SK_OVERRIDE {
236            SkXfermode::Mode mode = drawEffect.castEffect<ModeColorFilterEffect>().mode();
237
238            SkASSERT(SkXfermode::kDst_Mode != mode);
239            const char* colorFilterColorUniName = NULL;
240            if (drawEffect.castEffect<ModeColorFilterEffect>().willUseFilterColor()) {
241                fFilterColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
242                                                      kVec4f_GrSLType, "FilterColor",
243                                                      &colorFilterColorUniName);
244            }
245
246            GrGLSLExpr4 filter =
247                color_filter_expression(mode, GrGLSLExpr4(colorFilterColorUniName), GrGLSLExpr4(inputColor));
248
249            builder->fsCodeAppendf("\t%s = %s;\n", outputColor, filter.c_str());
250        }
251
252        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
253            const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
254            // The SL code does not depend on filter color at the moment, so no need to represent it
255            // in the key.
256            EffectKey modeKey = colorModeFilter.mode();
257            return modeKey;
258        }
259
260        virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
261            if (fFilterColorUni.isValid()) {
262                const ModeColorFilterEffect& colorModeFilter = drawEffect.castEffect<ModeColorFilterEffect>();
263                GrGLfloat c[4];
264                GrColorToRGBAFloat(colorModeFilter.color(), c);
265                uman.set4fv(fFilterColorUni, 1, c);
266            }
267        }
268
269    private:
270
271        GrGLUniformManager::UniformHandle fFilterColorUni;
272        typedef GrGLEffect INHERITED;
273    };
274
275    GR_DECLARE_EFFECT_TEST;
276
277private:
278    ModeColorFilterEffect(GrColor color, SkXfermode::Mode mode)
279        : fMode(mode),
280          fColor(color) {
281
282        SkXfermode::Coeff dstCoeff;
283        SkXfermode::Coeff srcCoeff;
284        SkAssertResult(SkXfermode::ModeAsCoeff(fMode, &srcCoeff, &dstCoeff));
285        // These could be calculated from the blend equation with template trickery..
286        if (SkXfermode::kZero_Coeff == dstCoeff && !GrBlendCoeffRefsDst(sk_blend_to_grblend(srcCoeff))) {
287            this->setWillNotUseInputColor();
288        }
289    }
290
291    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
292        const ModeColorFilterEffect& s = CastEffect<ModeColorFilterEffect>(other);
293        return fMode == s.fMode && fColor == s.fColor;
294    }
295
296    SkXfermode::Mode fMode;
297    GrColor fColor;
298
299    typedef GrEffect INHERITED;
300};
301
302namespace {
303
304/** Function color_component_to_int tries to reproduce the GLSL rounding. The spec doesn't specify
305 * to which direction the 0.5 goes.
306 */
307static inline int color_component_to_int(float value) {
308    return sk_float_round2int(GrMax(0.f, GrMin(1.f, value)) * 255.f);
309}
310
311/** MaskedColorExpr is used to evaluate the color and valid color component flags through the
312 * blending equation. It has members similar to GrGLSLExpr so that it can be used with the
313 * templated helpers above.
314 */
315class MaskedColorExpr {
316public:
317    MaskedColorExpr(const float color[], uint32_t flags)
318        : fFlags(flags) {
319        fColor[0] = color[0];
320        fColor[1] = color[1];
321        fColor[2] = color[2];
322        fColor[3] = color[3];
323    }
324
325    MaskedColorExpr(float v, uint32_t flags = kRGBA_GrColorComponentFlags)
326        : fFlags(flags) {
327        fColor[0] = v;
328        fColor[1] = v;
329        fColor[2] = v;
330        fColor[3] = v;
331    }
332
333    MaskedColorExpr operator*(const MaskedColorExpr& other) const {
334        float tmp[4];
335        tmp[0] = fColor[0] * other.fColor[0];
336        tmp[1] = fColor[1] * other.fColor[1];
337        tmp[2] = fColor[2] * other.fColor[2];
338        tmp[3] = fColor[3] * other.fColor[3];
339
340        return MaskedColorExpr(tmp, fFlags & other.fFlags);
341    }
342
343    MaskedColorExpr operator+(const MaskedColorExpr& other) const {
344        float tmp[4];
345        tmp[0] = fColor[0] + other.fColor[0];
346        tmp[1] = fColor[1] + other.fColor[1];
347        tmp[2] = fColor[2] + other.fColor[2];
348        tmp[3] = fColor[3] + other.fColor[3];
349
350        return MaskedColorExpr(tmp, fFlags & other.fFlags);
351    }
352
353    MaskedColorExpr operator-(const MaskedColorExpr& other) const {
354        float tmp[4];
355        tmp[0] = fColor[0] - other.fColor[0];
356        tmp[1] = fColor[1] - other.fColor[1];
357        tmp[2] = fColor[2] - other.fColor[2];
358        tmp[3] = fColor[3] - other.fColor[3];
359
360        return MaskedColorExpr(tmp, fFlags & other.fFlags);
361    }
362
363    MaskedColorExpr a() const {
364        uint32_t flags = (fFlags & kA_GrColorComponentFlag) ? kRGBA_GrColorComponentFlags : 0;
365        return MaskedColorExpr(fColor[3], flags);
366    }
367
368    GrColor getColor() const {
369        return GrColorPackRGBA(color_component_to_int(fColor[0]),
370                               color_component_to_int(fColor[1]),
371                               color_component_to_int(fColor[2]),
372                               color_component_to_int(fColor[3]));
373    }
374
375    uint32_t getValidComponents() const  { return fFlags; }
376
377    typedef MaskedColorExpr AExpr;
378private:
379    float fColor[4];
380    uint32_t fFlags;
381};
382
383}
384
385void ModeColorFilterEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
386    float inputColor[4];
387    GrColorToRGBAFloat(*color, inputColor);
388    float filterColor[4];
389    GrColorToRGBAFloat(fColor, filterColor);
390    MaskedColorExpr result =
391        color_filter_expression(fMode,
392                                MaskedColorExpr(filterColor, kRGBA_GrColorComponentFlags),
393                                MaskedColorExpr(inputColor, *validFlags));
394
395    *color = result.getColor();
396    *validFlags = result.getValidComponents();
397}
398
399GR_DEFINE_EFFECT_TEST(ModeColorFilterEffect);
400GrEffectRef* ModeColorFilterEffect::TestCreate(SkRandom* rand,
401                                    GrContext*,
402                                    const GrDrawTargetCaps&,
403                                    GrTexture*[]) {
404    SkXfermode::Mode mode = SkXfermode::kDst_Mode;
405    while (SkXfermode::kDst_Mode == mode) {
406        mode = static_cast<SkXfermode::Mode>(rand->nextRangeU(0, SkXfermode::kLastCoeffMode));
407    }
408    GrColor color = rand->nextU();
409    return ModeColorFilterEffect::Create(color, mode);
410}
411
412GrEffectRef* SkModeColorFilter::asNewEffect(GrContext*) const {
413    if (SkXfermode::kDst_Mode != fMode) {
414        return ModeColorFilterEffect::Create(SkColor2GrColor(fColor), fMode);
415    }
416    return NULL;
417}
418
419#endif
420
421///////////////////////////////////////////////////////////////////////////////
422
423class Src_SkModeColorFilter : public SkModeColorFilter {
424public:
425    Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
426
427    virtual uint32_t getFlags() const SK_OVERRIDE {
428        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
429            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
430        } else {
431            return 0;
432        }
433    }
434
435    virtual void filterSpan(const SkPMColor shader[], int count,
436                            SkPMColor result[]) const SK_OVERRIDE {
437        sk_memset32(result, this->getPMColor(), count);
438    }
439
440    virtual void filterSpan16(const uint16_t shader[], int count,
441                              uint16_t result[]) const SK_OVERRIDE {
442        SkASSERT(this->getFlags() & kHasFilter16_Flag);
443        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
444    }
445
446    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
447
448protected:
449    Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
450        : INHERITED(buffer) {}
451
452private:
453    typedef SkModeColorFilter INHERITED;
454};
455
456class SrcOver_SkModeColorFilter : public SkModeColorFilter {
457public:
458    SrcOver_SkModeColorFilter(SkColor color)
459            : INHERITED(color, SkXfermode::kSrcOver_Mode) {
460        fColor32Proc = SkBlitRow::ColorProcFactory();
461    }
462
463    virtual uint32_t getFlags() const SK_OVERRIDE {
464        if (SkGetPackedA32(this->getPMColor()) == 0xFF) {
465            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
466        } else {
467            return 0;
468        }
469    }
470
471    virtual void filterSpan(const SkPMColor shader[], int count,
472                            SkPMColor result[]) const SK_OVERRIDE {
473        fColor32Proc(result, shader, count, this->getPMColor());
474    }
475
476    virtual void filterSpan16(const uint16_t shader[], int count,
477                              uint16_t result[]) const SK_OVERRIDE {
478        SkASSERT(this->getFlags() & kHasFilter16_Flag);
479        sk_memset16(result, SkPixel32ToPixel16(this->getPMColor()), count);
480    }
481
482    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
483
484protected:
485    SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
486        : INHERITED(buffer) {
487            fColor32Proc = SkBlitRow::ColorProcFactory();
488        }
489
490private:
491
492    SkBlitRow::ColorProc fColor32Proc;
493
494    typedef SkModeColorFilter INHERITED;
495};
496
497///////////////////////////////////////////////////////////////////////////////
498
499SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
500                                               SkXfermode::Mode mode) {
501    unsigned alpha = SkColorGetA(color);
502
503    // first collaps some modes if possible
504
505    if (SkXfermode::kClear_Mode == mode) {
506        color = 0;
507        mode = SkXfermode::kSrc_Mode;
508    } else if (SkXfermode::kSrcOver_Mode == mode) {
509        if (0 == alpha) {
510            mode = SkXfermode::kDst_Mode;
511        } else if (255 == alpha) {
512            mode = SkXfermode::kSrc_Mode;
513        }
514        // else just stay srcover
515    }
516
517    // weed out combinations that are noops, and just return null
518    if (SkXfermode::kDst_Mode == mode ||
519        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
520                        SkXfermode::kDstOver_Mode == mode ||
521                        SkXfermode::kDstOut_Mode == mode ||
522                        SkXfermode::kSrcATop_Mode == mode ||
523                        SkXfermode::kXor_Mode == mode ||
524                        SkXfermode::kDarken_Mode == mode)) ||
525            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
526        return NULL;
527    }
528
529    switch (mode) {
530        case SkXfermode::kSrc_Mode:
531            return SkNEW_ARGS(Src_SkModeColorFilter, (color));
532        case SkXfermode::kSrcOver_Mode:
533            return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
534        default:
535            return SkNEW_ARGS(SkModeColorFilter, (color, mode));
536    }
537}
538
539///////////////////////////////////////////////////////////////////////////////
540
541static inline unsigned pin(unsigned value, unsigned max) {
542    if (value > max) {
543        value = max;
544    }
545    return value;
546}
547
548class SkLightingColorFilter : public SkColorFilter {
549public:
550    SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
551
552    virtual void filterSpan(const SkPMColor shader[], int count,
553                            SkPMColor result[]) const SK_OVERRIDE {
554        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
555        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
556        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
557
558        unsigned addR = SkColorGetR(fAdd);
559        unsigned addG = SkColorGetG(fAdd);
560        unsigned addB = SkColorGetB(fAdd);
561
562        for (int i = 0; i < count; i++) {
563            SkPMColor c = shader[i];
564            if (c) {
565                unsigned a = SkGetPackedA32(c);
566                unsigned scaleA = SkAlpha255To256(a);
567                unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
568                unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
569                unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
570                c = SkPackARGB32(a, r, g, b);
571            }
572            result[i] = c;
573        }
574    }
575
576#ifdef SK_DEVELOPER
577    virtual void toString(SkString* str) const SK_OVERRIDE {
578        str->append("SkLightingColorFilter: mul: 0x");
579        str->appendHex(fMul);
580        str->append(" add: 0x");
581        str->appendHex(fAdd);
582    }
583#endif
584
585    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter)
586
587protected:
588    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
589        this->INHERITED::flatten(buffer);
590        buffer.writeColor(fMul);
591        buffer.writeColor(fAdd);
592    }
593
594    SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
595        fMul = buffer.readColor();
596        fAdd = buffer.readColor();
597    }
598
599    SkColor fMul, fAdd;
600
601private:
602    typedef SkColorFilter INHERITED;
603};
604
605class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
606public:
607    SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
608        : INHERITED(mul, add) {}
609
610    virtual void filterSpan(const SkPMColor shader[], int count,
611                            SkPMColor result[]) const SK_OVERRIDE {
612        unsigned addR = SkColorGetR(fAdd);
613        unsigned addG = SkColorGetG(fAdd);
614        unsigned addB = SkColorGetB(fAdd);
615
616        for (int i = 0; i < count; i++) {
617            SkPMColor c = shader[i];
618            if (c) {
619                unsigned a = SkGetPackedA32(c);
620                unsigned scaleA = SkAlpha255To256(a);
621                unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
622                unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
623                unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
624                c = SkPackARGB32(a, r, g, b);
625            }
626            result[i] = c;
627        }
628    }
629
630#ifdef SK_DEVELOPER
631    virtual void toString(SkString* str) const SK_OVERRIDE {
632        str->append("SkLightingColorFilter_JustAdd: add: 0x");
633        str->appendHex(fAdd);
634    }
635#endif
636
637    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustAdd)
638
639protected:
640    SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
641        : INHERITED(buffer) {}
642
643private:
644    typedef SkLightingColorFilter INHERITED;
645};
646
647class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
648public:
649    SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
650        : INHERITED(mul, add) {}
651
652    virtual void filterSpan(const SkPMColor shader[], int count,
653                            SkPMColor result[]) const SK_OVERRIDE {
654        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
655        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
656        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
657
658        for (int i = 0; i < count; i++) {
659            SkPMColor c = shader[i];
660            if (c) {
661                unsigned a = SkGetPackedA32(c);
662                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
663                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
664                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
665                c = SkPackARGB32(a, r, g, b);
666            }
667            result[i] = c;
668        }
669    }
670
671#ifdef SK_DEVELOPER
672    virtual void toString(SkString* str) const SK_OVERRIDE {
673        str->append("SkLightingColorFilter_JustMul: mul: 0x");
674        str->appendHex(fMul);
675    }
676#endif
677
678    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustMul)
679
680protected:
681    SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
682        : INHERITED(buffer) {}
683
684private:
685    typedef SkLightingColorFilter INHERITED;
686};
687
688class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
689public:
690    SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
691            : INHERITED(mul, add) {
692        SkASSERT(SkColorGetR(add) == 0);
693        SkASSERT(SkColorGetG(add) == 0);
694        SkASSERT(SkColorGetB(add) == 0);
695        SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
696        SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
697    }
698
699    virtual uint32_t getFlags() const SK_OVERRIDE {
700        return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
701    }
702
703    virtual void filterSpan16(const uint16_t shader[], int count,
704                              uint16_t result[]) const SK_OVERRIDE {
705        // all mul components are the same
706        unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
707
708        if (count > 0) {
709            do {
710                *result++ = SkAlphaMulRGB16(*shader++, scale);
711            } while (--count > 0);
712        }
713    }
714
715#ifdef SK_DEVELOPER
716    virtual void toString(SkString* str) const SK_OVERRIDE {
717        str->append("SkLightingColorFilter_SingleMul: mul: 0x");
718        str->appendHex(fMul);
719    }
720#endif
721
722    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_SingleMul)
723
724protected:
725    SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
726        : INHERITED(buffer) {}
727
728private:
729    typedef SkLightingColorFilter INHERITED;
730};
731
732class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
733public:
734    SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
735    : INHERITED(mul, add) {}
736
737    virtual void filterSpan(const SkPMColor shader[], int count,
738                            SkPMColor result[]) const SK_OVERRIDE {
739        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
740        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
741        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
742
743        unsigned addR = SkColorGetR(fAdd);
744        unsigned addG = SkColorGetG(fAdd);
745        unsigned addB = SkColorGetB(fAdd);
746
747        for (int i = 0; i < count; i++) {
748            SkPMColor c = shader[i];
749            if (c) {
750                unsigned a = SkGetPackedA32(c);
751                unsigned scaleA = SkAlpha255To256(a);
752                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
753                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
754                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
755                c = SkPackARGB32(a, r, g, b);
756            }
757            result[i] = c;
758        }
759    }
760
761#ifdef SK_DEVELOPER
762    virtual void toString(SkString* str) const SK_OVERRIDE {
763        str->append("SkLightingColorFilter_NoPin: mul: 0x");
764        str->appendHex(fMul);
765        str->append(" add: 0x");
766        str->appendHex(fAdd);
767    }
768#endif
769
770    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_NoPin)
771
772protected:
773    SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
774        : INHERITED(buffer) {}
775
776private:
777    typedef SkLightingColorFilter INHERITED;
778};
779
780///////////////////////////////////////////////////////////////////////////////
781
782class SkSimpleColorFilter : public SkColorFilter {
783public:
784    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
785        return SkNEW(SkSimpleColorFilter);
786    }
787
788#ifdef SK_DEVELOPER
789    virtual void toString(SkString* str) const SK_OVERRIDE {
790        str->append("SkSimpleColorFilter");
791    }
792#endif
793
794protected:
795    void filterSpan(const SkPMColor src[], int count, SkPMColor
796                    result[]) const SK_OVERRIDE {
797        if (result != src) {
798            memcpy(result, src, count * sizeof(SkPMColor));
799        }
800    }
801
802    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {}
803
804    virtual Factory getFactory() const {
805        return CreateProc;
806    }
807
808};
809
810SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
811    mul &= 0x00FFFFFF;
812    add &= 0x00FFFFFF;
813
814    if (0xFFFFFF == mul) {
815        if (0 == add) {
816            return SkNEW(SkSimpleColorFilter);   // no change to the colors
817        } else {
818            return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
819        }
820    }
821
822    if (0 == add) {
823        if (SkColorGetR(mul) == SkColorGetG(mul) &&
824                SkColorGetR(mul) == SkColorGetB(mul)) {
825            return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
826        } else {
827            return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
828        }
829    }
830
831    if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
832        SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
833        SkColorGetB(mul) + SkColorGetB(add) <= 255) {
834            return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
835    }
836
837    return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
838}
839
840SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
841    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
842    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
843    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
844    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter)
845    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustAdd)
846    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustMul)
847    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_SingleMul)
848    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_NoPin)
849    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSimpleColorFilter)
850SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
851