grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkColorFilters.cpp b/src/effects/SkColorFilters.cpp
new file mode 100644
index 0000000..50be1ad
--- /dev/null
+++ b/src/effects/SkColorFilters.cpp
@@ -0,0 +1,553 @@
+/* libs/graphics/effects/SkColorFilters.cpp
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#include "SkColorFilter.h"
+#include "SkColorPriv.h"
+#include "SkPorterDuff.h"
+#include "SkUtils.h"
+
+//#define TRACE_CreatePorterDuffFilter
+
+// common baseclass
+class Sk_XfermodeColorFilter : public SkColorFilter {
+protected:
+    Sk_XfermodeColorFilter(SkColor color) : fColor(SkPreMultiplyColor(color)) {}
+
+    virtual void flatten(SkFlattenableWriteBuffer& buffer) 
+    {
+        buffer.write32(fColor);
+    }
+    
+    Sk_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) 
+    {
+        fColor = buffer.readU32();
+    }
+    
+    SkPMColor   fColor;
+};
+
+class SkSrc_XfermodeColorFilter : public Sk_XfermodeColorFilter {
+public:
+    SkSrc_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
+
+    virtual uint32_t getFlags()
+    {
+        if (SkGetPackedA32(fColor) == 0xFF)
+            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
+        else
+            return 0;
+    }
+
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        sk_memset32(result, fColor, count);
+    }
+
+    virtual void filterSpan16(const uint16_t shader[], int count, uint16_t result[])
+    {
+        SkASSERT(this->getFlags() & kHasFilter16_Flag);
+        
+        sk_memset16(result, SkPixel32ToPixel16(fColor), count);
+    }
+
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+
+    SkSrc_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+    
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (buffer));
+    }
+    
+    typedef Sk_XfermodeColorFilter INHERITED;
+};
+
+class SkSrcOver_XfermodeColorFilter : public Sk_XfermodeColorFilter {
+public:
+    SkSrcOver_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
+
+    virtual uint32_t getFlags()
+    {
+        if (SkGetPackedA32(fColor) == 0xFF)
+            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
+        else
+            return 0;
+    }
+    
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        SkPMColor   src = fColor;
+        unsigned    scale = SkAlpha255To256(255 - SkGetPackedA32(src));
+        
+        for (int i = 0; i < count; i++)
+            result[i] = src + SkAlphaMulQ(shader[i], scale);
+    }
+
+    virtual void filterSpan16(const uint16_t shader[], int count, uint16_t result[])
+    {
+        SkASSERT(this->getFlags() & kHasFilter16_Flag);
+
+        sk_memset16(result, SkPixel32ToPixel16(fColor), count);
+    }
+        
+protected:
+    virtual Factory getFactory() { return CreateProc;  }
+    
+    SkSrcOver_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
+    
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (buffer));
+    }
+    
+    typedef Sk_XfermodeColorFilter INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+class SkXfermodeColorFilter : public Sk_XfermodeColorFilter {
+public:
+    SkXfermodeColorFilter(SkColor color, SkXfermodeProc proc,
+                          SkXfermodeProc16 proc16) : INHERITED(color)
+    {
+        fProc = proc;
+        fProc16 = proc16;
+    }
+    
+    virtual uint32_t getFlags()
+    {
+        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
+    }
+
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        SkPMColor       color = fColor;
+        SkXfermodeProc  proc = fProc;
+        
+        for (int i = 0; i < count; i++)
+            result[i] = proc(color, shader[i]);
+    }
+    
+    virtual void filterSpan16(const uint16_t shader[], int count, uint16_t result[])
+    {
+        SkASSERT(this->getFlags() & kHasFilter16_Flag);
+        
+        SkPMColor        color = fColor;
+        SkXfermodeProc16 proc16 = fProc16;
+        
+        for (int i = 0; i < count; i++)
+            result[i] = proc16(color, shader[i]);
+    }
+    
+protected:
+    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
+        this->INHERITED::flatten(buffer);
+        buffer.writeFunctionPtr((void*)fProc);
+        buffer.writeFunctionPtr((void*)fProc16);
+    }
+    
+    virtual Factory getFactory() { 
+        return CreateProc;
+    }
+
+    SkXfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
+        fProc = (SkXfermodeProc) buffer.readFunctionPtr();
+        fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr();
+    }
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
+        return SkNEW_ARGS(SkXfermodeColorFilter, (buffer));
+    }
+
+    SkXfermodeProc   fProc;
+    SkXfermodeProc16 fProc16;
+    
+    typedef Sk_XfermodeColorFilter INHERITED;
+};
+
+SkColorFilter* SkColorFilter::CreatXfermodeProcFilter(SkColor color,
+                                                      SkXfermodeProc proc,
+                                                      SkXfermodeProc16 proc16)
+{
+    return proc ?
+            SkNEW_ARGS(SkXfermodeColorFilter, (color, proc, proc16)) :
+            NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkColorFilter* SkColorFilter::CreatePorterDuffFilter(SkColor color,
+                                                     SkPorterDuff::Mode mode)
+{
+    unsigned alpha = SkColorGetA(color);
+
+    // first collaps some modes if possible
+
+    if (SkPorterDuff::kClear_Mode == mode)
+    {
+        color = 0;
+        mode = SkPorterDuff::kSrc_Mode;
+    }
+    else if (SkPorterDuff::kSrcOver_Mode == mode)
+    {
+        if (0 == alpha)
+        {
+            mode = SkPorterDuff::kDst_Mode;
+        }
+        else if (255 == alpha)
+        {
+            mode = SkPorterDuff::kSrc_Mode;
+        }
+        // else just stay srcover
+    }
+
+    // weed out combinations that are noops, and just return null
+    if (SkPorterDuff::kDst_Mode == mode ||
+        (0 == alpha && (SkPorterDuff::kSrcOver_Mode == mode ||
+                        SkPorterDuff::kDstOver_Mode == mode ||
+                        SkPorterDuff::kDstOut_Mode == mode ||
+                        SkPorterDuff::kSrcATop_Mode == mode ||
+                        SkPorterDuff::kXor_Mode == mode ||
+                        SkPorterDuff::kDarken_Mode == mode)) ||
+        (0xFF == alpha && SkPorterDuff::kDstIn_Mode == mode))
+    {
+        return NULL;
+    }
+        
+    switch (mode) {
+    case SkPorterDuff::kSrc_Mode:
+        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (color));
+    case SkPorterDuff::kSrcOver_Mode:
+        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (color));
+    default:
+        return SkColorFilter::CreatXfermodeProcFilter(color,
+                                SkPorterDuff::GetXfermodeProc(mode),
+                                SkPorterDuff::GetXfermodeProc16(mode, color));
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+static inline unsigned pin(unsigned value, unsigned max)
+{
+    if (value > max)
+        value = max;
+    return value;
+}
+
+static inline unsigned SkUClampMax(unsigned value, unsigned max)
+{
+    SkASSERT((int32_t)value >= 0);
+    SkASSERT((int32_t)max >= 0);
+
+    int diff = max - value;
+    // clear diff if diff is positive
+    diff &= diff >> 31;
+
+    return value + diff;
+}
+
+class SkLightingColorFilter : public SkColorFilter {
+public:
+    SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
+
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
+        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
+        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
+        
+        unsigned addR = SkColorGetR(fAdd);
+        unsigned addG = SkColorGetG(fAdd);
+        unsigned addB = SkColorGetB(fAdd);
+
+        for (int i = 0; i < count; i++)
+        {
+            SkPMColor c = shader[i];
+            if (c)
+            {
+                unsigned a = SkGetPackedA32(c);
+                unsigned scaleA = SkAlpha255To256(a);                
+                unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
+                unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
+                unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
+                c = SkPackARGB32(a, r, g, b);
+            }
+            result[i] = c;
+        }
+    }
+
+protected:
+    virtual void flatten(SkFlattenableWriteBuffer& buffer) 
+    {
+        buffer.write32(fMul);
+        buffer.write32(fAdd);
+    }
+    
+    virtual Factory getFactory() 
+    { 
+        return CreateProc;
+    }
+
+    SkLightingColorFilter(SkFlattenableReadBuffer& buffer) 
+    {
+        fMul = buffer.readU32();
+        fAdd = buffer.readU32();
+    }
+    
+    SkColor fMul, fAdd;
+
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkLightingColorFilter, (buffer));
+    }
+};
+
+class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
+public:
+    SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
+        : INHERITED(mul, add) {}
+
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        unsigned addR = SkColorGetR(fAdd);
+        unsigned addG = SkColorGetG(fAdd);
+        unsigned addB = SkColorGetB(fAdd);
+
+        for (int i = 0; i < count; i++)
+        {
+            SkPMColor c = shader[i];
+            if (c)
+            {
+                unsigned a = SkGetPackedA32(c);
+                unsigned scaleA = SkAlpha255To256(a);                
+                unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
+                unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
+                unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
+                c = SkPackARGB32(a, r, g, b);
+            }
+            result[i] = c;
+        }
+    }
+
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+
+    SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
+        : INHERITED(buffer) {}
+
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (buffer));
+    }
+    typedef SkLightingColorFilter INHERITED;
+};
+
+class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
+public:
+    SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
+        : INHERITED(mul, add) {}
+
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
+        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
+        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
+        
+        for (int i = 0; i < count; i++)
+        {
+            SkPMColor c = shader[i];
+            if (c)
+            {
+                unsigned a = SkGetPackedA32(c);
+                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
+                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
+                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
+                c = SkPackARGB32(a, r, g, b);
+            }
+            result[i] = c;
+        }
+    }
+
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+
+    SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
+        : INHERITED(buffer) {}
+    
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkLightingColorFilter_JustMul, (buffer));
+    }
+
+    typedef SkLightingColorFilter INHERITED;
+};
+
+class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
+public:
+    SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
+        : INHERITED(mul, add)
+    {
+        SkASSERT(SkColorGetR(add) == 0);
+        SkASSERT(SkColorGetG(add) == 0);
+        SkASSERT(SkColorGetB(add) == 0);
+        SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
+        SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
+    }
+    
+    virtual uint32_t getFlags()
+    {
+        return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
+    }
+
+    virtual void filterSpan16(const uint16_t shader[], int count, uint16_t result[])
+    {
+        // all mul components are the same
+        unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
+
+        if (count > 0)
+            do {
+                *result++ = SkAlphaMulRGB16(*shader++, scale);
+            } while (--count > 0);
+    }
+
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+
+    SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
+        : INHERITED(buffer) {}
+
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (buffer));
+    }
+    
+    typedef SkLightingColorFilter INHERITED;
+};
+
+class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
+public:
+    SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
+    : INHERITED(mul, add) {}
+    
+    virtual void filterSpan(const SkPMColor shader[], int count, SkPMColor result[])
+    {
+        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
+        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
+        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
+        
+        unsigned addR = SkColorGetR(fAdd);
+        unsigned addG = SkColorGetG(fAdd);
+        unsigned addB = SkColorGetB(fAdd);
+        
+        for (int i = 0; i < count; i++)
+        {
+            SkPMColor c = shader[i];
+            if (c)
+            {
+                unsigned a = SkGetPackedA32(c);
+                unsigned scaleA = SkAlpha255To256(a);                
+                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
+                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
+                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
+                c = SkPackARGB32(a, r, g, b);
+            }
+            result[i] = c;
+        }
+    }
+    
+protected:
+    virtual Factory getFactory() { return CreateProc; }
+    
+    SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
+        : INHERITED(buffer) {}
+    
+private:
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW_ARGS(SkLightingColorFilter_NoPin, (buffer));
+    }
+    
+    typedef SkLightingColorFilter INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+class SkSimpleColorFilter : public SkColorFilter {
+protected:
+    void filterSpan(const SkPMColor src[], int count, SkPMColor result[])
+    {
+        if (result != src)
+            memcpy(result, src, count * sizeof(SkPMColor));
+    }
+
+    virtual void flatten(SkFlattenableWriteBuffer& buffer) 
+    {
+    }
+    
+    virtual Factory getFactory() 
+    { 
+        return CreateProc;
+    }
+
+    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) 
+    {
+        return SkNEW(SkSimpleColorFilter);
+    }
+};
+
+SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add)
+{
+    mul &= 0x00FFFFFF;
+    add &= 0x00FFFFFF;
+
+    if (0xFFFFFF == mul)
+    {
+        if (0 == add)
+            return SkNEW(SkSimpleColorFilter);   // no change to the colors
+        else
+            return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
+    }
+
+    if (0 == add)
+    {
+        if (SkColorGetR(mul) == SkColorGetG(mul) &&
+            SkColorGetR(mul) == SkColorGetB(mul))
+        {
+            return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
+        }
+        else
+        {
+            return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
+        }
+    }
+
+    if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
+        SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
+        SkColorGetB(mul) + SkColorGetB(add) <= 255)
+        return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
+
+    return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
+}
+