Home | History | Annotate | Download | only in effects
      1 #include "SkColorMatrixFilter.h"
      2 #include "SkColorMatrix.h"
      3 #include "SkColorPriv.h"
      4 #include "SkUnPreMultiply.h"
      5 
      6 static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g,
      7                           unsigned b, unsigned a) {
      8     return array[0] * r + array[1] * g  + array[2] * b + array[3] * a + array[4];
      9 }
     10 
     11 static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g,
     12                        unsigned b) {
     13     return array[0] * r + array[1] * g  + array[2] * b + array[4];
     14 }
     15 
     16 static void General(SkColorMatrixFilter::State* state,
     17                     unsigned r, unsigned g, unsigned b, unsigned a) {
     18     const int32_t* SK_RESTRICT array = state->fArray;
     19     const int shift = state->fShift;
     20     int32_t* SK_RESTRICT result = state->fResult;
     21 
     22     result[0] = rowmul4(&array[0], r, g, b, a) >> shift;
     23     result[1] = rowmul4(&array[5], r, g, b, a) >> shift;
     24     result[2] = rowmul4(&array[10], r, g, b, a) >> shift;
     25     result[3] = rowmul4(&array[15], r, g, b, a) >> shift;
     26 }
     27 
     28 static void General16(SkColorMatrixFilter::State* state,
     29                       unsigned r, unsigned g, unsigned b, unsigned a) {
     30     const int32_t* SK_RESTRICT array = state->fArray;
     31     int32_t* SK_RESTRICT result = state->fResult;
     32 
     33     result[0] = rowmul4(&array[0], r, g, b, a) >> 16;
     34     result[1] = rowmul4(&array[5], r, g, b, a) >> 16;
     35     result[2] = rowmul4(&array[10], r, g, b, a) >> 16;
     36     result[3] = rowmul4(&array[15], r, g, b, a) >> 16;
     37 }
     38 
     39 static void AffineAdd(SkColorMatrixFilter::State* state,
     40                       unsigned r, unsigned g, unsigned b, unsigned a) {
     41     const int32_t* SK_RESTRICT array = state->fArray;
     42     const int shift = state->fShift;
     43     int32_t* SK_RESTRICT result = state->fResult;
     44 
     45     result[0] = rowmul3(&array[0], r, g, b) >> shift;
     46     result[1] = rowmul3(&array[5], r, g, b) >> shift;
     47     result[2] = rowmul3(&array[10], r, g, b) >> shift;
     48     result[3] = a;
     49 }
     50 
     51 static void AffineAdd16(SkColorMatrixFilter::State* state,
     52                         unsigned r, unsigned g, unsigned b, unsigned a) {
     53     const int32_t* SK_RESTRICT array = state->fArray;
     54     int32_t* SK_RESTRICT result = state->fResult;
     55 
     56     result[0] = rowmul3(&array[0], r, g, b) >> 16;
     57     result[1] = rowmul3(&array[5], r, g, b) >> 16;
     58     result[2] = rowmul3(&array[10], r, g, b) >> 16;
     59     result[3] = a;
     60 }
     61 
     62 static void ScaleAdd(SkColorMatrixFilter::State* state,
     63                      unsigned r, unsigned g, unsigned b, unsigned a) {
     64     const int32_t* SK_RESTRICT array = state->fArray;
     65     const int shift = state->fShift;
     66     int32_t* SK_RESTRICT result = state->fResult;
     67 
     68     // cast to (int) to keep the expression signed for the shift
     69     result[0] = (array[0] * (int)r + array[4]) >> shift;
     70     result[1] = (array[6] * (int)g + array[9]) >> shift;
     71     result[2] = (array[12] * (int)b + array[14]) >> shift;
     72     result[3] = a;
     73 }
     74 
     75 static void ScaleAdd16(SkColorMatrixFilter::State* state,
     76                        unsigned r, unsigned g, unsigned b, unsigned a) {
     77     const int32_t* SK_RESTRICT array = state->fArray;
     78     int32_t* SK_RESTRICT result = state->fResult;
     79 
     80     // cast to (int) to keep the expression signed for the shift
     81     result[0] = (array[0] * (int)r + array[4]) >> 16;
     82     result[1] = (array[6] * (int)g + array[9]) >> 16;
     83     result[2] = (array[12] * (int)b + array[14]) >> 16;
     84     result[3] = a;
     85 }
     86 
     87 static void Add(SkColorMatrixFilter::State* state,
     88                 unsigned r, unsigned g, unsigned b, unsigned a) {
     89     const int32_t* SK_RESTRICT array = state->fArray;
     90     const int shift = state->fShift;
     91     int32_t* SK_RESTRICT result = state->fResult;
     92 
     93     result[0] = r + (array[4] >> shift);
     94     result[1] = g + (array[9] >> shift);
     95     result[2] = b + (array[14] >> shift);
     96     result[3] = a;
     97 }
     98 
     99 static void Add16(SkColorMatrixFilter::State* state,
    100                   unsigned r, unsigned g, unsigned b, unsigned a) {
    101     const int32_t* SK_RESTRICT array = state->fArray;
    102     int32_t* SK_RESTRICT result = state->fResult;
    103 
    104     result[0] = r + (array[4] >> 16);
    105     result[1] = g + (array[9] >> 16);
    106     result[2] = b + (array[14] >> 16);
    107     result[3] = a;
    108 }
    109 
    110 #define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag |  \
    111                          SkColorFilter::kHasFilter16_Flag)
    112 
    113 void SkColorMatrixFilter::setup(const SkScalar SK_RESTRICT src[20]) {
    114     if (NULL == src) {
    115         fProc = NULL;   // signals identity
    116         fFlags  = kNO_ALPHA_FLAGS;
    117         // fState is undefined, but that is OK, since we shouldn't look at it
    118         return;
    119     }
    120 
    121     int32_t* SK_RESTRICT array = fState.fArray;
    122 
    123     int i;
    124     SkFixed max = 0;
    125 
    126     for (int i = 0; i < 20; i++) {
    127         SkFixed value = SkScalarToFixed(src[i]);
    128         array[i] = value;
    129         value = SkAbs32(value);
    130         max = SkMax32(max, value);
    131     }
    132 
    133     /*  All of fArray[] values must fit in 23 bits, to safely allow me to
    134         multiply them by 8bit unsigned values, and get a signed answer without
    135         overflow. This means clz needs to be 9 or bigger
    136     */
    137     int bits = SkCLZ(max);
    138     int32_t one = SK_Fixed1;
    139 
    140     fState.fShift = 16; // we are starting out as fixed 16.16
    141     if (bits < 9) {
    142         bits = 9 - bits;
    143         fState.fShift -= bits;
    144         for (i = 0; i < 20; i++) {
    145             array[i] >>= bits;
    146         }
    147         one >>= bits;
    148     }
    149 
    150     // check if we have to munge Alpha
    151     int32_t changesAlpha = (array[15] | array[16] | array[17] |
    152                             (array[18] - one) | array[19]);
    153     int32_t usesAlpha = (array[3] | array[8] | array[13]);
    154     bool shiftIs16 = (16 == fState.fShift);
    155 
    156     if (changesAlpha | usesAlpha) {
    157         fProc = shiftIs16 ? General16 : General;
    158         fFlags = changesAlpha ? 0 : SkColorFilter::kAlphaUnchanged_Flag;
    159     } else {
    160         fFlags = kNO_ALPHA_FLAGS;
    161 
    162         int32_t needsScale = (array[0] - one) |       // red axis
    163                              (array[6] - one) |       // green axis
    164                              (array[12] - one);       // blue axis
    165 
    166         int32_t needs3x3 =  array[1] | array[2] |     // red off-axis
    167                             array[5] | array[7] |     // green off-axis
    168                             array[10] | array[11];    // blue off-axis
    169 
    170         if (needs3x3) {
    171             fProc = shiftIs16 ? AffineAdd16 : AffineAdd;
    172         } else if (needsScale) {
    173             fProc = shiftIs16 ? ScaleAdd16 : ScaleAdd;
    174         } else if (array[4] | array[9] | array[14]) {   // needs add
    175             fProc = shiftIs16 ? Add16 : Add;
    176         } else {
    177             fProc = NULL;   // identity
    178         }
    179     }
    180 
    181     /*  preround our add values so we get a rounded shift. We do this after we
    182         analyze the array, so we don't miss the case where the caller has zeros
    183         which could make us accidentally take the General or Add case.
    184     */
    185     if (NULL != fProc) {
    186         int32_t add = 1 << (fState.fShift - 1);
    187         array[4] += add;
    188         array[9] += add;
    189         array[14] += add;
    190         array[19] += add;
    191     }
    192 }
    193 
    194 ///////////////////////////////////////////////////////////////////////////////
    195 
    196 static int32_t pin(int32_t value, int32_t max) {
    197     if (value < 0) {
    198         value = 0;
    199     }
    200     if (value > max) {
    201         value = max;
    202     }
    203     return value;
    204 }
    205 
    206 SkColorMatrixFilter::SkColorMatrixFilter() {
    207     this->setup(NULL);
    208 }
    209 
    210 SkColorMatrixFilter::SkColorMatrixFilter(const SkColorMatrix& cm) {
    211     this->setup(cm.fMat);
    212 }
    213 
    214 SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) {
    215     this->setup(array);
    216 }
    217 
    218 uint32_t SkColorMatrixFilter::getFlags() {
    219     return this->INHERITED::getFlags() | fFlags;
    220 }
    221 
    222 void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count,
    223                                      SkPMColor dst[]) {
    224     Proc proc = fProc;
    225     State* state = &fState;
    226     int32_t* SK_RESTRICT result = state->fResult;
    227 
    228     if (NULL == proc) {
    229         if (src != dst) {
    230             memcpy(dst, src, count * sizeof(SkPMColor));
    231         }
    232         return;
    233     }
    234 
    235     const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
    236 
    237     for (int i = 0; i < count; i++) {
    238         SkPMColor c = src[i];
    239 
    240         unsigned r = SkGetPackedR32(c);
    241         unsigned g = SkGetPackedG32(c);
    242         unsigned b = SkGetPackedB32(c);
    243         unsigned a = SkGetPackedA32(c);
    244 
    245         // need our components to be un-premultiplied
    246         if (255 != a) {
    247             SkUnPreMultiply::Scale scale = table[a];
    248             r = SkUnPreMultiply::ApplyScale(scale, r);
    249             g = SkUnPreMultiply::ApplyScale(scale, g);
    250             b = SkUnPreMultiply::ApplyScale(scale, b);
    251 
    252             SkASSERT(r <= 255);
    253             SkASSERT(g <= 255);
    254             SkASSERT(b <= 255);
    255         }
    256 
    257         proc(state, r, g, b, a);
    258 
    259         r = pin(result[0], SK_R32_MASK);
    260         g = pin(result[1], SK_G32_MASK);
    261         b = pin(result[2], SK_B32_MASK);
    262         a = pin(result[3], SK_A32_MASK);
    263         // re-prepremultiply if needed
    264         if (255 != a) {
    265             int scale = SkAlpha255To256(a);
    266             r = SkAlphaMul(r, scale);
    267             g = SkAlphaMul(g, scale);
    268             b = SkAlphaMul(b, scale);
    269         }
    270         dst[i] = SkPackARGB32(a, r, g, b);
    271     }
    272 }
    273 
    274 void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
    275                                        uint16_t dst[]) {
    276     SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag);
    277 
    278     Proc   proc = fProc;
    279     State* state = &fState;
    280     int32_t* SK_RESTRICT result = state->fResult;
    281 
    282     if (NULL == proc) {
    283         if (src != dst) {
    284             memcpy(dst, src, count * sizeof(uint16_t));
    285         }
    286         return;
    287     }
    288 
    289     for (int i = 0; i < count; i++) {
    290         uint16_t c = src[i];
    291 
    292         // expand to 8bit components (since our matrix translate is 8bit biased
    293         unsigned r = SkPacked16ToR32(c);
    294         unsigned g = SkPacked16ToG32(c);
    295         unsigned b = SkPacked16ToB32(c);
    296 
    297         proc(state, r, g, b, 0);
    298 
    299         r = pin(result[0], SK_R32_MASK);
    300         g = pin(result[1], SK_G32_MASK);
    301         b = pin(result[2], SK_B32_MASK);
    302 
    303         // now packed it back down to 16bits (hmmm, could dither...)
    304         dst[i] = SkPack888ToRGB16(r, g, b);
    305     }
    306 }
    307 
    308 ///////////////////////////////////////////////////////////////////////////////
    309 
    310 void SkColorMatrixFilter::flatten(SkFlattenableWriteBuffer& buffer)  {
    311     this->INHERITED::flatten(buffer);
    312 
    313     buffer.writeFunctionPtr((void*)fProc);
    314     buffer.writeMul4(&fState, sizeof(fState));
    315     buffer.write32(fFlags);
    316 }
    317 
    318 SkFlattenable::Factory SkColorMatrixFilter::getFactory() { return CreateProc;  }
    319 
    320 SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer)
    321         : INHERITED(buffer) {
    322     fProc = (Proc)buffer.readFunctionPtr();
    323     buffer.read(&fState, sizeof(fState));
    324     fFlags = buffer.readU32();
    325 }
    326 
    327 SkFlattenable* SkColorMatrixFilter::CreateProc(SkFlattenableReadBuffer& buf) {
    328     return SkNEW_ARGS(SkColorMatrixFilter, (buf));
    329 }
    330 
    331