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