blob: 2970c7c2187aa182d2530dc43edcc4a3fbce11e9 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com845fdac2009-06-23 03:01:32 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com845fdac2009-06-23 03:01:32 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com845fdac2009-06-23 03:01:32 +00007 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.comc4cae852009-09-23 15:06:10 +000010#include "SkBlitRow.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000011#include "SkColorFilter.h"
12#include "SkColorPriv.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkUtils.h"
14
reed@google.com43c50c82011-04-14 15:50:52 +000015#define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1)
16
17// baseclass for filters that store a color and mode
18class SkModeColorFilter : public SkColorFilter {
19public:
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 };
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000033
reed@google.com43c50c82011-04-14 15:50:52 +000034 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
reed@android.com8a1c16f2008-12-17 15:59:43 +000052protected:
reed@android.com845fdac2009-06-23 03:01:32 +000053 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000054 this->INHERITED::flatten(buffer);
reed@google.com43c50c82011-04-14 15:50:52 +000055 buffer.write32(fColor);
56 buffer.write32(fMode);
57 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000058
reed@google.com43c50c82011-04-14 15:50:52 +000059 SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
60 fColor = buffer.readU32();
61 fMode = (SkXfermode::Mode)buffer.readU32();
62
63 fPMColor = SkPreMultiplyColor(fColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 }
reed@android.com845fdac2009-06-23 03:01:32 +000065
reed@google.com43c50c82011-04-14 15:50:52 +000066 // cache of fColor in premultiply space
reed@android.com845fdac2009-06-23 03:01:32 +000067 SkPMColor fPMColor;
reed@google.com43c50c82011-04-14 15:50:52 +000068
69private:
70 SkColor fColor;
71 SkXfermode::Mode fMode;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +000072
73 typedef SkColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +000074};
75
reed@google.com43c50c82011-04-14 15:50:52 +000076class Src_SkModeColorFilter : public SkModeColorFilter {
reed@android.com8a1c16f2008-12-17 15:59:43 +000077public:
reed@google.com43c50c82011-04-14 15:50:52 +000078 Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
reed@android.com8a1c16f2008-12-17 15:59:43 +000079
reed@android.com845fdac2009-06-23 03:01:32 +000080 virtual uint32_t getFlags() {
81 if (SkGetPackedA32(fPMColor) == 0xFF) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000082 return kAlphaUnchanged_Flag | kHasFilter16_Flag;
reed@android.com845fdac2009-06-23 03:01:32 +000083 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000084 return 0;
reed@android.com845fdac2009-06-23 03:01:32 +000085 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000086 }
87
reed@android.com845fdac2009-06-23 03:01:32 +000088 virtual void filterSpan(const SkPMColor shader[], int count,
89 SkPMColor result[]) {
90 sk_memset32(result, fPMColor, count);
reed@android.com8a1c16f2008-12-17 15:59:43 +000091 }
92
reed@android.com845fdac2009-06-23 03:01:32 +000093 virtual void filterSpan16(const uint16_t shader[], int count,
94 uint16_t result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 SkASSERT(this->getFlags() & kHasFilter16_Flag);
reed@android.com845fdac2009-06-23 03:01:32 +000096 sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
reed@android.com8a1c16f2008-12-17 15:59:43 +000097 }
98
djsollen@google.comba28d032012-03-26 17:57:35 +000099 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Src_SkModeColorFilter)
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000100
reed@android.com8a1c16f2008-12-17 15:59:43 +0000101protected:
reed@google.com43c50c82011-04-14 15:50:52 +0000102 Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
reed@android.com845fdac2009-06-23 03:01:32 +0000103 : INHERITED(buffer) {}
reed@android.com845fdac2009-06-23 03:01:32 +0000104
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000105private:
reed@google.com43c50c82011-04-14 15:50:52 +0000106 typedef SkModeColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107};
108
reed@google.com43c50c82011-04-14 15:50:52 +0000109class SrcOver_SkModeColorFilter : public SkModeColorFilter {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000110public:
reed@google.com43c50c82011-04-14 15:50:52 +0000111 SrcOver_SkModeColorFilter(SkColor color)
112 : INHERITED(color, SkXfermode::kSrcOver_Mode) {
113 fColor32Proc = NULL;
114 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115
reed@android.com845fdac2009-06-23 03:01:32 +0000116 virtual uint32_t getFlags() {
117 if (SkGetPackedA32(fPMColor) == 0xFF) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118 return kAlphaUnchanged_Flag | kHasFilter16_Flag;
reed@android.com845fdac2009-06-23 03:01:32 +0000119 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 return 0;
reed@android.com845fdac2009-06-23 03:01:32 +0000121 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000123
reed@android.com845fdac2009-06-23 03:01:32 +0000124 virtual void filterSpan(const SkPMColor shader[], int count,
125 SkPMColor result[]) {
reed@google.com43c50c82011-04-14 15:50:52 +0000126 if (NULL == fColor32Proc) {
127 fColor32Proc = SkBlitRow::ColorProcFactory();
128 }
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000129 fColor32Proc(result, shader, count, fPMColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000130 }
131
reed@android.com845fdac2009-06-23 03:01:32 +0000132 virtual void filterSpan16(const uint16_t shader[], int count,
133 uint16_t result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 SkASSERT(this->getFlags() & kHasFilter16_Flag);
reed@android.com845fdac2009-06-23 03:01:32 +0000135 sk_memset16(result, SkPixel32ToPixel16(fPMColor), count);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000137
djsollen@google.comba28d032012-03-26 17:57:35 +0000138 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SrcOver_SkModeColorFilter)
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000139
140protected:
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000141 SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
142 : INHERITED(buffer), fColor32Proc(NULL) {}
143
144private:
145
senorblanco@chromium.org29e50542010-12-16 19:07:45 +0000146 SkBlitRow::ColorProc fColor32Proc;
reed@google.com43c50c82011-04-14 15:50:52 +0000147
148 typedef SkModeColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149};
150
reed@google.com43c50c82011-04-14 15:50:52 +0000151///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152
reed@google.com43c50c82011-04-14 15:50:52 +0000153class Proc_SkModeColorFilter : public SkModeColorFilter {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154public:
reed@google.com43c50c82011-04-14 15:50:52 +0000155 Proc_SkModeColorFilter(SkColor color, SkXfermode::Mode mode) : INHERITED(color, mode) {
156 fProc = SkXfermode::GetProc(mode);
157 fProc16 = SkXfermode::GetProc16(mode, color);
158 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000159
reed@google.com43c50c82011-04-14 15:50:52 +0000160 Proc_SkModeColorFilter(SkColor color,
161 SkXfermodeProc proc, SkXfermodeProc16 proc16)
162 : INHERITED(color, ILLEGAL_XFERMODE_MODE) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163 fProc = proc;
164 fProc16 = proc16;
165 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000166
reed@android.com845fdac2009-06-23 03:01:32 +0000167 virtual uint32_t getFlags() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
169 }
170
reed@android.com845fdac2009-06-23 03:01:32 +0000171 virtual void filterSpan(const SkPMColor shader[], int count,
172 SkPMColor result[]) {
173 SkPMColor color = fPMColor;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 SkXfermodeProc proc = fProc;
reed@android.com845fdac2009-06-23 03:01:32 +0000175
176 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000177 result[i] = proc(color, shader[i]);
reed@android.com845fdac2009-06-23 03:01:32 +0000178 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000180
reed@android.com845fdac2009-06-23 03:01:32 +0000181 virtual void filterSpan16(const uint16_t shader[], int count,
182 uint16_t result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183 SkASSERT(this->getFlags() & kHasFilter16_Flag);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000184
reed@android.com845fdac2009-06-23 03:01:32 +0000185 SkPMColor color = fPMColor;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 SkXfermodeProc16 proc16 = fProc16;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000187
reed@android.com845fdac2009-06-23 03:01:32 +0000188 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 result[i] = proc16(color, shader[i]);
reed@android.com845fdac2009-06-23 03:01:32 +0000190 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000192
djsollen@google.comba28d032012-03-26 17:57:35 +0000193 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Proc_SkModeColorFilter)
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000194
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195protected:
196 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
197 this->INHERITED::flatten(buffer);
198 buffer.writeFunctionPtr((void*)fProc);
199 buffer.writeFunctionPtr((void*)fProc16);
200 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000201
reed@google.com43c50c82011-04-14 15:50:52 +0000202 Proc_SkModeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203 fProc = (SkXfermodeProc) buffer.readFunctionPtr();
204 fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr();
205 }
reed@google.com43c50c82011-04-14 15:50:52 +0000206
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 SkXfermodeProc fProc;
209 SkXfermodeProc16 fProc16;
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000210
reed@google.com43c50c82011-04-14 15:50:52 +0000211 typedef SkModeColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212};
213
reed@android.com845fdac2009-06-23 03:01:32 +0000214SkColorFilter* SkColorFilter::CreateProcFilter(SkColor color,
215 SkXfermodeProc proc,
216 SkXfermodeProc16 proc16) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 return proc ?
reed@google.com43c50c82011-04-14 15:50:52 +0000218 SkNEW_ARGS(Proc_SkModeColorFilter, (color, proc, proc16)) :
reed@android.com8a1c16f2008-12-17 15:59:43 +0000219 NULL;
220}
221
222///////////////////////////////////////////////////////////////////////////////
223
reed@android.com845fdac2009-06-23 03:01:32 +0000224SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
225 SkXfermode::Mode mode) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 unsigned alpha = SkColorGetA(color);
227
228 // first collaps some modes if possible
229
reed@android.com845fdac2009-06-23 03:01:32 +0000230 if (SkXfermode::kClear_Mode == mode) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 color = 0;
reed@android.com845fdac2009-06-23 03:01:32 +0000232 mode = SkXfermode::kSrc_Mode;
233 } else if (SkXfermode::kSrcOver_Mode == mode) {
234 if (0 == alpha) {
235 mode = SkXfermode::kDst_Mode;
236 } else if (255 == alpha) {
237 mode = SkXfermode::kSrc_Mode;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238 }
239 // else just stay srcover
240 }
241
242 // weed out combinations that are noops, and just return null
reed@android.com845fdac2009-06-23 03:01:32 +0000243 if (SkXfermode::kDst_Mode == mode ||
244 (0 == alpha && (SkXfermode::kSrcOver_Mode == mode ||
245 SkXfermode::kDstOver_Mode == mode ||
246 SkXfermode::kDstOut_Mode == mode ||
247 SkXfermode::kSrcATop_Mode == mode ||
248 SkXfermode::kXor_Mode == mode ||
249 SkXfermode::kDarken_Mode == mode)) ||
250 (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 return NULL;
252 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000253
reed@android.com8a1c16f2008-12-17 15:59:43 +0000254 switch (mode) {
reed@google.com43c50c82011-04-14 15:50:52 +0000255 case SkXfermode::kSrc_Mode:
256 return SkNEW_ARGS(Src_SkModeColorFilter, (color));
257 case SkXfermode::kSrcOver_Mode:
258 return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
259 default:
260 return SkNEW_ARGS(Proc_SkModeColorFilter, (color, mode));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261 }
262}
263
reed@android.com845fdac2009-06-23 03:01:32 +0000264///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000265
reed@android.com845fdac2009-06-23 03:01:32 +0000266static inline unsigned pin(unsigned value, unsigned max) {
267 if (value > max) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000268 value = max;
reed@android.com845fdac2009-06-23 03:01:32 +0000269 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270 return value;
271}
272
reed@android.com845fdac2009-06-23 03:01:32 +0000273static inline unsigned SkUClampMax(unsigned value, unsigned max) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274 SkASSERT((int32_t)value >= 0);
275 SkASSERT((int32_t)max >= 0);
276
277 int diff = max - value;
278 // clear diff if diff is positive
279 diff &= diff >> 31;
280
281 return value + diff;
282}
283
284class SkLightingColorFilter : public SkColorFilter {
285public:
286 SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {}
287
reed@android.com845fdac2009-06-23 03:01:32 +0000288 virtual void filterSpan(const SkPMColor shader[], int count,
289 SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290 unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
291 unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
292 unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000293
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294 unsigned addR = SkColorGetR(fAdd);
295 unsigned addG = SkColorGetG(fAdd);
296 unsigned addB = SkColorGetB(fAdd);
297
reed@android.com845fdac2009-06-23 03:01:32 +0000298 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299 SkPMColor c = shader[i];
reed@android.com845fdac2009-06-23 03:01:32 +0000300 if (c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000301 unsigned a = SkGetPackedA32(c);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000302 unsigned scaleA = SkAlpha255To256(a);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a);
304 unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a);
305 unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a);
306 c = SkPackARGB32(a, r, g, b);
307 }
308 result[i] = c;
309 }
310 }
311
djsollen@google.comba28d032012-03-26 17:57:35 +0000312 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter)
caryclark@google.comd26147a2011-12-15 14:16:43 +0000313
reed@android.com8a1c16f2008-12-17 15:59:43 +0000314protected:
reed@android.com845fdac2009-06-23 03:01:32 +0000315 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000316 this->INHERITED::flatten(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000317 buffer.write32(fMul);
318 buffer.write32(fAdd);
319 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000320
reed@android.com845fdac2009-06-23 03:01:32 +0000321 SkLightingColorFilter(SkFlattenableReadBuffer& buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 fMul = buffer.readU32();
323 fAdd = buffer.readU32();
324 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000325
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 SkColor fMul, fAdd;
327
328private:
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000329 typedef SkColorFilter INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000330};
331
332class SkLightingColorFilter_JustAdd : public SkLightingColorFilter {
333public:
334 SkLightingColorFilter_JustAdd(SkColor mul, SkColor add)
335 : INHERITED(mul, add) {}
336
reed@android.com845fdac2009-06-23 03:01:32 +0000337 virtual void filterSpan(const SkPMColor shader[], int count,
338 SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000339 unsigned addR = SkColorGetR(fAdd);
340 unsigned addG = SkColorGetG(fAdd);
341 unsigned addB = SkColorGetB(fAdd);
342
reed@android.com845fdac2009-06-23 03:01:32 +0000343 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344 SkPMColor c = shader[i];
reed@android.com845fdac2009-06-23 03:01:32 +0000345 if (c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346 unsigned a = SkGetPackedA32(c);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000347 unsigned scaleA = SkAlpha255To256(a);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000348 unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a);
349 unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a);
350 unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a);
351 c = SkPackARGB32(a, r, g, b);
352 }
353 result[i] = c;
354 }
355 }
356
djsollen@google.comba28d032012-03-26 17:57:35 +0000357 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustAdd)
caryclark@google.comd26147a2011-12-15 14:16:43 +0000358
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000360 SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer)
361 : INHERITED(buffer) {}
362
363private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364 typedef SkLightingColorFilter INHERITED;
365};
366
367class SkLightingColorFilter_JustMul : public SkLightingColorFilter {
368public:
369 SkLightingColorFilter_JustMul(SkColor mul, SkColor add)
370 : INHERITED(mul, add) {}
371
reed@android.com845fdac2009-06-23 03:01:32 +0000372 virtual void filterSpan(const SkPMColor shader[], int count,
373 SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000374 unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
375 unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
376 unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000377
reed@android.com845fdac2009-06-23 03:01:32 +0000378 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000379 SkPMColor c = shader[i];
reed@android.com845fdac2009-06-23 03:01:32 +0000380 if (c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381 unsigned a = SkGetPackedA32(c);
382 unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR);
383 unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG);
384 unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB);
385 c = SkPackARGB32(a, r, g, b);
386 }
387 result[i] = c;
388 }
389 }
390
djsollen@google.comba28d032012-03-26 17:57:35 +0000391 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_JustMul)
caryclark@google.comd26147a2011-12-15 14:16:43 +0000392
reed@android.com8a1c16f2008-12-17 15:59:43 +0000393protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000394 SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer)
395 : INHERITED(buffer) {}
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000396
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398 typedef SkLightingColorFilter INHERITED;
399};
400
401class SkLightingColorFilter_SingleMul : public SkLightingColorFilter {
402public:
403 SkLightingColorFilter_SingleMul(SkColor mul, SkColor add)
reed@android.com845fdac2009-06-23 03:01:32 +0000404 : INHERITED(mul, add) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405 SkASSERT(SkColorGetR(add) == 0);
406 SkASSERT(SkColorGetG(add) == 0);
407 SkASSERT(SkColorGetB(add) == 0);
408 SkASSERT(SkColorGetR(mul) == SkColorGetG(mul));
409 SkASSERT(SkColorGetR(mul) == SkColorGetB(mul));
410 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000411
reed@android.com845fdac2009-06-23 03:01:32 +0000412 virtual uint32_t getFlags() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000413 return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag);
414 }
415
reed@android.com845fdac2009-06-23 03:01:32 +0000416 virtual void filterSpan16(const uint16_t shader[], int count,
417 uint16_t result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 // all mul components are the same
419 unsigned scale = SkAlpha255To256(SkColorGetR(fMul));
420
reed@android.com845fdac2009-06-23 03:01:32 +0000421 if (count > 0) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422 do {
423 *result++ = SkAlphaMulRGB16(*shader++, scale);
424 } while (--count > 0);
reed@android.com845fdac2009-06-23 03:01:32 +0000425 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000426 }
427
djsollen@google.comba28d032012-03-26 17:57:35 +0000428 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_SingleMul)
caryclark@google.comd26147a2011-12-15 14:16:43 +0000429
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer)
432 : INHERITED(buffer) {}
433
434private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000435 typedef SkLightingColorFilter INHERITED;
436};
437
438class SkLightingColorFilter_NoPin : public SkLightingColorFilter {
439public:
440 SkLightingColorFilter_NoPin(SkColor mul, SkColor add)
441 : INHERITED(mul, add) {}
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000442
reed@android.com845fdac2009-06-23 03:01:32 +0000443 virtual void filterSpan(const SkPMColor shader[], int count,
444 SkPMColor result[]) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000445 unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul));
446 unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul));
447 unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul));
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000448
reed@android.com8a1c16f2008-12-17 15:59:43 +0000449 unsigned addR = SkColorGetR(fAdd);
450 unsigned addG = SkColorGetG(fAdd);
451 unsigned addB = SkColorGetB(fAdd);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000452
reed@android.com845fdac2009-06-23 03:01:32 +0000453 for (int i = 0; i < count; i++) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000454 SkPMColor c = shader[i];
reed@android.com845fdac2009-06-23 03:01:32 +0000455 if (c) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000456 unsigned a = SkGetPackedA32(c);
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000457 unsigned scaleA = SkAlpha255To256(a);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458 unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA);
459 unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA);
460 unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA);
461 c = SkPackARGB32(a, r, g, b);
462 }
463 result[i] = c;
464 }
465 }
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000466
djsollen@google.comba28d032012-03-26 17:57:35 +0000467 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkLightingColorFilter_NoPin)
caryclark@google.comd26147a2011-12-15 14:16:43 +0000468
reed@android.com8a1c16f2008-12-17 15:59:43 +0000469protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000470 SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer)
471 : INHERITED(buffer) {}
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000472
reed@android.com8a1c16f2008-12-17 15:59:43 +0000473private:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000474 typedef SkLightingColorFilter INHERITED;
475};
476
reed@android.com845fdac2009-06-23 03:01:32 +0000477///////////////////////////////////////////////////////////////////////////////
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478
479class SkSimpleColorFilter : public SkColorFilter {
caryclark@google.comd26147a2011-12-15 14:16:43 +0000480public:
481 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
482 return SkNEW(SkSimpleColorFilter);
483 }
484
reed@android.com8a1c16f2008-12-17 15:59:43 +0000485protected:
reed@android.com845fdac2009-06-23 03:01:32 +0000486 void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) {
487 if (result != src) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000488 memcpy(result, src, count * sizeof(SkPMColor));
reed@android.com845fdac2009-06-23 03:01:32 +0000489 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000490 }
491
reed@android.com845fdac2009-06-23 03:01:32 +0000492 virtual void flatten(SkFlattenableWriteBuffer& buffer) {}
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000493
reed@android.com845fdac2009-06-23 03:01:32 +0000494 virtual Factory getFactory() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000495 return CreateProc;
496 }
497
reed@android.com8a1c16f2008-12-17 15:59:43 +0000498};
499
reed@android.com845fdac2009-06-23 03:01:32 +0000500SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000501 mul &= 0x00FFFFFF;
502 add &= 0x00FFFFFF;
503
reed@android.com845fdac2009-06-23 03:01:32 +0000504 if (0xFFFFFF == mul) {
505 if (0 == add) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000506 return SkNEW(SkSimpleColorFilter); // no change to the colors
reed@android.com845fdac2009-06-23 03:01:32 +0000507 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000508 return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add));
reed@android.com845fdac2009-06-23 03:01:32 +0000509 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000510 }
511
reed@android.com845fdac2009-06-23 03:01:32 +0000512 if (0 == add) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000513 if (SkColorGetR(mul) == SkColorGetG(mul) &&
reed@android.com845fdac2009-06-23 03:01:32 +0000514 SkColorGetR(mul) == SkColorGetB(mul)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000515 return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add));
reed@android.com845fdac2009-06-23 03:01:32 +0000516 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000517 return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add));
518 }
519 }
520
521 if (SkColorGetR(mul) + SkColorGetR(add) <= 255 &&
522 SkColorGetG(mul) + SkColorGetG(add) <= 255 &&
reed@android.com845fdac2009-06-23 03:01:32 +0000523 SkColorGetB(mul) + SkColorGetB(add) <= 255) {
524 return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add));
525 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000526
527 return SkNEW_ARGS(SkLightingColorFilter, (mul, add));
528}
529
caryclark@google.comd26147a2011-12-15 14:16:43 +0000530SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
531 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Src_SkModeColorFilter)
532 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SrcOver_SkModeColorFilter)
533 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(Proc_SkModeColorFilter)
534 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter)
535 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustAdd)
536 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_JustMul)
537 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_SingleMul)
538 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLightingColorFilter_NoPin)
539 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSimpleColorFilter)
540SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
tomhudson@google.com1447c6f2011-04-27 14:09:52 +0000541