SkColorFilters.cpp revision 40528743dbb9ce7f39f093e0cdc47849ac8887cf
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "SkBlitRow.h"
18#include "SkColorFilter.h"
19#include "SkColorPriv.h"
20#include "SkUtils.h"
21
22// common baseclass
23class Sk_XfermodeColorFilter : public SkColorFilter {
24protected:
25    Sk_XfermodeColorFilter(SkColor color)
26        : fPMColor(SkPreMultiplyColor(color)) {}
27
28    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
29        buffer.write32(fPMColor);
30    }
31
32    Sk_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) {
33        fPMColor = buffer.readU32();
34    }
35
36    SkPMColor   fPMColor;
37};
38
39class SkSrc_XfermodeColorFilter : public Sk_XfermodeColorFilter {
40public:
41    SkSrc_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
42
43    virtual uint32_t getFlags() {
44        if (SkGetPackedA32(fPMColor) == 0xFF) {
45            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
46        } else {
47            return 0;
48        }
49    }
50
51    virtual void filterSpan(const SkPMColor shader[], int count,
52                            SkPMColor result[]) {
53        sk_memset32(result, fPMColor, count);
54    }
55
56    virtual void filterSpan16(const uint16_t shader[], int count,
57                              uint16_t result[]) {
58        SkASSERT(this->getFlags() & kHasFilter16_Flag);
59        sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
60    }
61
62protected:
63    virtual Factory getFactory() { return CreateProc; }
64
65    SkSrc_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
66        : INHERITED(buffer) {}
67
68private:
69    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
70        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (buffer));
71    }
72
73    typedef Sk_XfermodeColorFilter INHERITED;
74};
75
76class SkSrcOver_XfermodeColorFilter : public Sk_XfermodeColorFilter {
77public:
78    SkSrcOver_XfermodeColorFilter(SkColor color)
79        : INHERITED(color), fColor32Proc(SkBlitRow::ColorProcFactory()) {}
80
81    virtual uint32_t getFlags() {
82        if (SkGetPackedA32(fPMColor) == 0xFF) {
83            return kAlphaUnchanged_Flag | kHasFilter16_Flag;
84        } else {
85            return 0;
86        }
87    }
88
89    virtual void filterSpan(const SkPMColor shader[], int count,
90                            SkPMColor result[]) {
91        fColor32Proc(result, shader, count, fPMColor);
92    }
93
94    virtual void filterSpan16(const uint16_t shader[], int count,
95                              uint16_t result[]) {
96        SkASSERT(this->getFlags() & kHasFilter16_Flag);
97        sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
98    }
99
100protected:
101    virtual Factory getFactory() { return CreateProc;  }
102
103    SkSrcOver_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
104        : INHERITED(buffer), fColor32Proc(SkBlitRow::ColorProcFactory()) {}
105
106private:
107    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
108        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (buffer));
109    }
110
111    typedef Sk_XfermodeColorFilter INHERITED;
112    SkBlitRow::ColorProc fColor32Proc;
113};
114
115//////////////////////////////////////////////////////////////////////////////
116
117class SkXfermodeColorFilter : public Sk_XfermodeColorFilter {
118public:
119    SkXfermodeColorFilter(SkColor color, SkXfermodeProc proc,
120                          SkXfermodeProc16 proc16) : INHERITED(color) {
121        fProc = proc;
122        fProc16 = proc16;
123    }
124
125    virtual uint32_t getFlags() {
126        return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
127    }
128
129    virtual void filterSpan(const SkPMColor shader[], int count,
130                            SkPMColor result[]) {
131        SkPMColor       color = fPMColor;
132        SkXfermodeProc  proc = fProc;
133
134        for (int i = 0; i < count; i++) {
135            result[i] = proc(color, shader[i]);
136        }
137    }
138
139    virtual void filterSpan16(const uint16_t shader[], int count,
140                              uint16_t result[]) {
141        SkASSERT(this->getFlags() & kHasFilter16_Flag);
142
143        SkPMColor        color = fPMColor;
144        SkXfermodeProc16 proc16 = fProc16;
145
146        for (int i = 0; i < count; i++) {
147            result[i] = proc16(color, shader[i]);
148        }
149    }
150
151protected:
152    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
153        this->INHERITED::flatten(buffer);
154        buffer.writeFunctionPtr((void*)fProc);
155        buffer.writeFunctionPtr((void*)fProc16);
156    }
157
158    virtual Factory getFactory() {
159        return CreateProc;
160    }
161
162    SkXfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
163        fProc = (SkXfermodeProc) buffer.readFunctionPtr();
164        fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr();
165    }
166private:
167    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
168        return SkNEW_ARGS(SkXfermodeColorFilter, (buffer));
169    }
170
171    SkXfermodeProc   fProc;
172    SkXfermodeProc16 fProc16;
173
174    typedef Sk_XfermodeColorFilter INHERITED;
175};
176
177SkColorFilter* SkColorFilter::CreateProcFilter(SkColor color,
178                                               SkXfermodeProc proc,
179                                               SkXfermodeProc16 proc16) {
180    return proc ?
181            SkNEW_ARGS(SkXfermodeColorFilter, (color, proc, proc16)) :
182            NULL;
183}
184
185///////////////////////////////////////////////////////////////////////////////
186
187SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
188                                               SkXfermode::Mode mode) {
189    unsigned alpha = SkColorGetA(color);
190
191    // first collaps some modes if possible
192
193    if (SkXfermode::kClear_Mode == mode) {
194        color = 0;
195        mode = SkXfermode::kSrc_Mode;
196    } else if (SkXfermode::kSrcOver_Mode == mode) {
197        if (0 == alpha) {
198            mode = SkXfermode::kDst_Mode;
199        } else if (255 == alpha) {
200            mode = SkXfermode::kSrc_Mode;
201        }
202        // else just stay srcover
203    }
204
205    // weed out combinations that are noops, and just return null
206    if (SkXfermode::kDst_Mode == mode ||
207        (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
208                        SkXfermode::kDstOver_Mode == mode ||
209                        SkXfermode::kDstOut_Mode == mode ||
210                        SkXfermode::kSrcATop_Mode == mode ||
211                        SkXfermode::kXor_Mode == mode ||
212                        SkXfermode::kDarken_Mode == mode)) ||
213            (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
214        return NULL;
215    }
216
217    switch (mode) {
218    case SkXfermode::kSrc_Mode:
219        return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (color));
220    case SkXfermode::kSrcOver_Mode:
221        return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (color));
222    default:
223        return SkColorFilter::CreateProcFilter(color, SkXfermode::GetProc(mode),
224                                            SkXfermode::GetProc16(mode, color));
225    }
226}
227
228///////////////////////////////////////////////////////////////////////////////
229
230static inline unsigned pin(unsigned value, unsigned max) {
231    if (value > max) {
232        value = max;
233    }
234    return value;
235}
236
237static inline unsigned SkUClampMax(unsigned value, unsigned max) {
238    SkASSERT((int32_t)value >= 0);
239    SkASSERT((int32_t)max >= 0);
240
241    int diff = max - value;
242    // clear diff if diff is positive
243    diff &= diff >> 31;
244
245    return value + diff;
246}
247
248class SkLightingColorFilter : public SkColorFilter {
249public:
250    SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
251
252    virtual void filterSpan(const SkPMColor shader[], int count,
253                            SkPMColor result[]) {
254        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
255        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
256        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
257
258        unsigned addR = SkColorGetR(fAdd);
259        unsigned addG = SkColorGetG(fAdd);
260        unsigned addB = SkColorGetB(fAdd);
261
262        for (int i = 0; i < count; i++) {
263            SkPMColor c = shader[i];
264            if (c) {
265                unsigned a = SkGetPackedA32(c);
266                unsigned scaleA = SkAlpha255To256(a);
267                unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
268                unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
269                unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
270                c = SkPackARGB32(a, r, g, b);
271            }
272            result[i] = c;
273        }
274    }
275
276protected:
277    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
278        buffer.write32(fMul);
279        buffer.write32(fAdd);
280    }
281
282    virtual Factory getFactory() {
283        return CreateProc;
284    }
285
286    SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
287        fMul = buffer.readU32();
288        fAdd = buffer.readU32();
289    }
290
291    SkColor fMul, fAdd;
292
293private:
294    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
295        return SkNEW_ARGS(SkLightingColorFilter, (buffer));
296    }
297};
298
299class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
300public:
301    SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
302        : INHERITED(mul, add) {}
303
304    virtual void filterSpan(const SkPMColor shader[], int count,
305                            SkPMColor result[]) {
306        unsigned addR = SkColorGetR(fAdd);
307        unsigned addG = SkColorGetG(fAdd);
308        unsigned addB = SkColorGetB(fAdd);
309
310        for (int i = 0; i < count; i++) {
311            SkPMColor c = shader[i];
312            if (c) {
313                unsigned a = SkGetPackedA32(c);
314                unsigned scaleA = SkAlpha255To256(a);
315                unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
316                unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
317                unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
318                c = SkPackARGB32(a, r, g, b);
319            }
320            result[i] = c;
321        }
322    }
323
324protected:
325    virtual Factory getFactory() { return CreateProc; }
326
327    SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
328        : INHERITED(buffer) {}
329
330private:
331    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer)  {
332        return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (buffer));
333    }
334    typedef SkLightingColorFilter INHERITED;
335};
336
337class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
338public:
339    SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
340        : INHERITED(mul, add) {}
341
342    virtual void filterSpan(const SkPMColor shader[], int count,
343                            SkPMColor result[]) {
344        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
345        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
346        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
347
348        for (int i = 0; i < count; i++) {
349            SkPMColor c = shader[i];
350            if (c) {
351                unsigned a = SkGetPackedA32(c);
352                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
353                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
354                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
355                c = SkPackARGB32(a, r, g, b);
356            }
357            result[i] = c;
358        }
359    }
360
361protected:
362    virtual Factory getFactory() { return CreateProc; }
363
364    SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
365        : INHERITED(buffer) {}
366
367private:
368    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
369        return SkNEW_ARGS(SkLightingColorFilter_JustMul, (buffer));
370    }
371
372    typedef SkLightingColorFilter INHERITED;
373};
374
375class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
376public:
377    SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
378            : INHERITED(mul, add) {
379        SkASSERT(SkColorGetR(add) == 0);
380        SkASSERT(SkColorGetG(add) == 0);
381        SkASSERT(SkColorGetB(add) == 0);
382        SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
383        SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
384    }
385
386    virtual uint32_t getFlags() {
387        return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
388    }
389
390    virtual void filterSpan16(const uint16_t shader[], int count,
391                              uint16_t result[]) {
392        // all mul components are the same
393        unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
394
395        if (count > 0) {
396            do {
397                *result++ = SkAlphaMulRGB16(*shader++, scale);
398            } while (--count > 0);
399        }
400    }
401
402protected:
403    virtual Factory getFactory() { return CreateProc; }
404
405    SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
406        : INHERITED(buffer) {}
407
408private:
409    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
410        return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (buffer));
411    }
412
413    typedef SkLightingColorFilter INHERITED;
414};
415
416class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
417public:
418    SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
419    : INHERITED(mul, add) {}
420
421    virtual void filterSpan(const SkPMColor shader[], int count,
422                            SkPMColor result[]) {
423        unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
424        unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
425        unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
426
427        unsigned addR = SkColorGetR(fAdd);
428        unsigned addG = SkColorGetG(fAdd);
429        unsigned addB = SkColorGetB(fAdd);
430
431        for (int i = 0; i < count; i++) {
432            SkPMColor c = shader[i];
433            if (c) {
434                unsigned a = SkGetPackedA32(c);
435                unsigned scaleA = SkAlpha255To256(a);
436                unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
437                unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
438                unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
439                c = SkPackARGB32(a, r, g, b);
440            }
441            result[i] = c;
442        }
443    }
444
445protected:
446    virtual Factory getFactory() { return CreateProc; }
447
448    SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
449        : INHERITED(buffer) {}
450
451private:
452    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
453        return SkNEW_ARGS(SkLightingColorFilter_NoPin, (buffer));
454    }
455
456    typedef SkLightingColorFilter INHERITED;
457};
458
459///////////////////////////////////////////////////////////////////////////////
460
461class SkSimpleColorFilter : public SkColorFilter {
462protected:
463    void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
464        if (result != src) {
465            memcpy(result, src, count * sizeof(SkPMColor));
466        }
467    }
468
469    virtual void flatten(SkFlattenableWriteBuffer& buffer) {}
470
471    virtual Factory getFactory() {
472        return CreateProc;
473    }
474
475    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
476        return SkNEW(SkSimpleColorFilter);
477    }
478};
479
480SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
481    mul &= 0x00FFFFFF;
482    add &= 0x00FFFFFF;
483
484    if (0xFFFFFF == mul) {
485        if (0 == add) {
486            return SkNEW(SkSimpleColorFilter);   // no change to the colors
487        } else {
488            return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
489        }
490    }
491
492    if (0 == add) {
493        if (SkColorGetR(mul) == SkColorGetG(mul) &&
494                SkColorGetR(mul) == SkColorGetB(mul)) {
495            return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
496        } else {
497            return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
498        }
499    }
500
501    if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
502        SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
503        SkColorGetB(mul) + SkColorGetB(add) <= 255) {
504            return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
505    }
506
507    return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
508}
509
510