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 "SkXfermode.h"
11 #include "SkColorPriv.h"
12 #include "SkFlattenableBuffers.h"
13 #include "SkMathPriv.h"
14 #include "SkString.h"
15
SK_DEFINE_INST_COUNT(SkXfermode)16 SK_DEFINE_INST_COUNT(SkXfermode)
17
18 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
19
20 #if 0
21 // idea for higher precision blends in xfer procs (and slightly faster)
22 // see DstATop as a probable caller
23 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
24 SkASSERT(a <= 255);
25 SkASSERT(b <= 255);
26 SkASSERT(c <= 255);
27 SkASSERT(d <= 255);
28 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
29 unsigned result = (prod + (prod >> 8)) >> 8;
30 SkASSERT(result <= 255);
31 return result;
32 }
33 #endif
34
35 static inline unsigned saturated_add(unsigned a, unsigned b) {
36 SkASSERT(a <= 255);
37 SkASSERT(b <= 255);
38 unsigned sum = a + b;
39 if (sum > 255) {
40 sum = 255;
41 }
42 return sum;
43 }
44
clamp_signed_byte(int n)45 static inline int clamp_signed_byte(int n) {
46 if (n < 0) {
47 n = 0;
48 } else if (n > 255) {
49 n = 255;
50 }
51 return n;
52 }
53
clamp_div255round(int prod)54 static inline int clamp_div255round(int prod) {
55 if (prod <= 0) {
56 return 0;
57 } else if (prod >= 255*255) {
58 return 255;
59 } else {
60 return SkDiv255Round(prod);
61 }
62 }
63
clamp_max(int value,int max)64 static inline int clamp_max(int value, int max) {
65 if (value > max) {
66 value = max;
67 }
68 return value;
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////
72
73 // kClear_Mode, //!< [0, 0]
clear_modeproc(SkPMColor src,SkPMColor dst)74 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
75 return 0;
76 }
77
78 // kSrc_Mode, //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)79 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
80 return src;
81 }
82
83 // kDst_Mode, //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)84 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
85 return dst;
86 }
87
88 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
srcover_modeproc(SkPMColor src,SkPMColor dst)89 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
90 #if 0
91 // this is the old, more-correct way, but it doesn't guarantee that dst==255
92 // will always stay opaque
93 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
94 #else
95 // this is slightly faster, but more importantly guarantees that dst==255
96 // will always stay opaque
97 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
98 #endif
99 }
100
101 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
dstover_modeproc(SkPMColor src,SkPMColor dst)102 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
103 // this is the reverse of srcover, just flipping src and dst
104 // see srcover's comment about the 256 for opaqueness guarantees
105 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
106 }
107
108 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
srcin_modeproc(SkPMColor src,SkPMColor dst)109 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
110 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
111 }
112
113 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
dstin_modeproc(SkPMColor src,SkPMColor dst)114 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
115 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
116 }
117
118 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
srcout_modeproc(SkPMColor src,SkPMColor dst)119 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
120 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
121 }
122
123 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
dstout_modeproc(SkPMColor src,SkPMColor dst)124 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
125 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
126 }
127
128 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
srcatop_modeproc(SkPMColor src,SkPMColor dst)129 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
130 unsigned sa = SkGetPackedA32(src);
131 unsigned da = SkGetPackedA32(dst);
132 unsigned isa = 255 - sa;
133
134 return SkPackARGB32(da,
135 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
136 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
137 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
138 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
139 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
140 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
141 }
142
143 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)144 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
145 unsigned sa = SkGetPackedA32(src);
146 unsigned da = SkGetPackedA32(dst);
147 unsigned ida = 255 - da;
148
149 return SkPackARGB32(sa,
150 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
151 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
152 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
153 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
154 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
155 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
156 }
157
158 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
xor_modeproc(SkPMColor src,SkPMColor dst)159 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
160 unsigned sa = SkGetPackedA32(src);
161 unsigned da = SkGetPackedA32(dst);
162 unsigned isa = 255 - sa;
163 unsigned ida = 255 - da;
164
165 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
166 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
167 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
168 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
169 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
170 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
171 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
172 }
173
174 ///////////////////////////////////////////////////////////////////////////////
175
176 // kPlus_Mode
plus_modeproc(SkPMColor src,SkPMColor dst)177 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
178 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
179 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
180 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
181 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
182 return SkPackARGB32(a, r, g, b);
183 }
184
185 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)186 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
187 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
188 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
189 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
190 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
191 return SkPackARGB32(a, r, g, b);
192 }
193
194 // kScreen_Mode
srcover_byte(int a,int b)195 static inline int srcover_byte(int a, int b) {
196 return a + b - SkAlphaMulAlpha(a, b);
197 }
screen_modeproc(SkPMColor src,SkPMColor dst)198 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
199 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
200 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
201 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
202 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
203 return SkPackARGB32(a, r, g, b);
204 }
205
206 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)207 static inline int overlay_byte(int sc, int dc, int sa, int da) {
208 int tmp = sc * (255 - da) + dc * (255 - sa);
209 int rc;
210 if (2 * dc <= da) {
211 rc = 2 * sc * dc;
212 } else {
213 rc = sa * da - 2 * (da - dc) * (sa - sc);
214 }
215 return clamp_div255round(rc + tmp);
216 }
overlay_modeproc(SkPMColor src,SkPMColor dst)217 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
218 int sa = SkGetPackedA32(src);
219 int da = SkGetPackedA32(dst);
220 int a = srcover_byte(sa, da);
221 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
222 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
223 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
224 return SkPackARGB32(a, r, g, b);
225 }
226
227 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)228 static inline int darken_byte(int sc, int dc, int sa, int da) {
229 int sd = sc * da;
230 int ds = dc * sa;
231 if (sd < ds) {
232 // srcover
233 return sc + dc - SkDiv255Round(ds);
234 } else {
235 // dstover
236 return dc + sc - SkDiv255Round(sd);
237 }
238 }
darken_modeproc(SkPMColor src,SkPMColor dst)239 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
240 int sa = SkGetPackedA32(src);
241 int da = SkGetPackedA32(dst);
242 int a = srcover_byte(sa, da);
243 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
244 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
245 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
246 return SkPackARGB32(a, r, g, b);
247 }
248
249 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)250 static inline int lighten_byte(int sc, int dc, int sa, int da) {
251 int sd = sc * da;
252 int ds = dc * sa;
253 if (sd > ds) {
254 // srcover
255 return sc + dc - SkDiv255Round(ds);
256 } else {
257 // dstover
258 return dc + sc - SkDiv255Round(sd);
259 }
260 }
lighten_modeproc(SkPMColor src,SkPMColor dst)261 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
262 int sa = SkGetPackedA32(src);
263 int da = SkGetPackedA32(dst);
264 int a = srcover_byte(sa, da);
265 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
266 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
267 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
268 return SkPackARGB32(a, r, g, b);
269 }
270
271 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)272 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
273 int diff = sa - sc;
274 int rc;
275 if (0 == diff) {
276 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
277 rc = SkDiv255Round(rc);
278 } else {
279 int tmp = (dc * sa << 15) / (da * diff);
280 rc = SkDiv255Round(sa * da) * tmp >> 15;
281 // don't clamp here, since we'll do it in our modeproc
282 }
283 return rc;
284 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)285 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
286 // added to avoid div-by-zero in colordodge_byte
287 if (0 == dst) {
288 return src;
289 }
290
291 int sa = SkGetPackedA32(src);
292 int da = SkGetPackedA32(dst);
293 int a = srcover_byte(sa, da);
294 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
295 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
296 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
297 r = clamp_max(r, a);
298 g = clamp_max(g, a);
299 b = clamp_max(b, a);
300 return SkPackARGB32(a, r, g, b);
301 }
302
303 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)304 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
305 int rc;
306 if (dc == da && 0 == sc) {
307 rc = sa * da + dc * (255 - sa);
308 } else if (0 == sc) {
309 return SkAlphaMulAlpha(dc, 255 - sa);
310 } else {
311 int tmp = (sa * (da - dc) * 256) / (sc * da);
312 if (tmp > 256) {
313 tmp = 256;
314 }
315 int tmp2 = sa * da;
316 rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
317 }
318 return SkDiv255Round(rc);
319 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)320 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
321 // added to avoid div-by-zero in colorburn_byte
322 if (0 == dst) {
323 return src;
324 }
325
326 int sa = SkGetPackedA32(src);
327 int da = SkGetPackedA32(dst);
328 int a = srcover_byte(sa, da);
329 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
330 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
331 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
332 return SkPackARGB32(a, r, g, b);
333 }
334
335 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)336 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
337 int rc;
338 if (2 * sc <= sa) {
339 rc = 2 * sc * dc;
340 } else {
341 rc = sa * da - 2 * (da - dc) * (sa - sc);
342 }
343 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
344 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)345 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
346 int sa = SkGetPackedA32(src);
347 int da = SkGetPackedA32(dst);
348 int a = srcover_byte(sa, da);
349 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
350 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
351 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
352 return SkPackARGB32(a, r, g, b);
353 }
354
355 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)356 static U8CPU sqrt_unit_byte(U8CPU n) {
357 return SkSqrtBits(n, 15+4);
358 }
359
360 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)361 static inline int softlight_byte(int sc, int dc, int sa, int da) {
362 int m = da ? dc * 256 / da : 0;
363 int rc;
364 if (2 * sc <= sa) {
365 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
366 } else if (4 * dc <= da) {
367 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
368 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
369 } else {
370 int tmp = sqrt_unit_byte(m) - m;
371 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
372 }
373 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
374 }
softlight_modeproc(SkPMColor src,SkPMColor dst)375 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
376 int sa = SkGetPackedA32(src);
377 int da = SkGetPackedA32(dst);
378 int a = srcover_byte(sa, da);
379 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
380 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
381 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
382 return SkPackARGB32(a, r, g, b);
383 }
384
385 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)386 static inline int difference_byte(int sc, int dc, int sa, int da) {
387 int tmp = SkMin32(sc * da, dc * sa);
388 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
389 }
difference_modeproc(SkPMColor src,SkPMColor dst)390 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
391 int sa = SkGetPackedA32(src);
392 int da = SkGetPackedA32(dst);
393 int a = srcover_byte(sa, da);
394 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
395 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
396 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
397 return SkPackARGB32(a, r, g, b);
398 }
399
400 // kExclusion_Mode
exclusion_byte(int sc,int dc,int sa,int da)401 static inline int exclusion_byte(int sc, int dc, int sa, int da) {
402 // this equations is wacky, wait for SVG to confirm it
403 int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
404 return clamp_div255round(r);
405 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)406 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
407 int sa = SkGetPackedA32(src);
408 int da = SkGetPackedA32(dst);
409 int a = srcover_byte(sa, da);
410 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
411 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
412 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
413 return SkPackARGB32(a, r, g, b);
414 }
415
416 struct ProcCoeff {
417 SkXfermodeProc fProc;
418 SkXfermode::Coeff fSC;
419 SkXfermode::Coeff fDC;
420 };
421
422 #define CANNOT_USE_COEFF SkXfermode::Coeff(-1)
423
424 static const ProcCoeff gProcCoeffs[] = {
425 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
426 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
427 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
428 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
429 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
430 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
431 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
432 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
433 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
434 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
435 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
436 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
437
438 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
439 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
440 { screen_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
441 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
442 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
443 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
444 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
445 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
446 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
447 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
448 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
449 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
450 };
451
452 ///////////////////////////////////////////////////////////////////////////////
453
asCoeff(Coeff * src,Coeff * dst) const454 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
455 return false;
456 }
457
asMode(Mode * mode) const458 bool SkXfermode::asMode(Mode* mode) const {
459 return false;
460 }
461
xferColor(SkPMColor src,SkPMColor dst) const462 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
463 // no-op. subclasses should override this
464 return dst;
465 }
466
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const467 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
468 const SkPMColor* SK_RESTRICT src, int count,
469 const SkAlpha* SK_RESTRICT aa) const {
470 SkASSERT(dst && src && count >= 0);
471
472 if (NULL == aa) {
473 for (int i = count - 1; i >= 0; --i) {
474 dst[i] = this->xferColor(src[i], dst[i]);
475 }
476 } else {
477 for (int i = count - 1; i >= 0; --i) {
478 unsigned a = aa[i];
479 if (0 != a) {
480 SkPMColor dstC = dst[i];
481 SkPMColor C = this->xferColor(src[i], dstC);
482 if (0xFF != a) {
483 C = SkFourByteInterp(C, dstC, a);
484 }
485 dst[i] = C;
486 }
487 }
488 }
489 }
490
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const491 void SkXfermode::xfer16(uint16_t* dst,
492 const SkPMColor* SK_RESTRICT src, int count,
493 const SkAlpha* SK_RESTRICT aa) const {
494 SkASSERT(dst && src && count >= 0);
495
496 if (NULL == aa) {
497 for (int i = count - 1; i >= 0; --i) {
498 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
499 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
500 }
501 } else {
502 for (int i = count - 1; i >= 0; --i) {
503 unsigned a = aa[i];
504 if (0 != a) {
505 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
506 SkPMColor C = this->xferColor(src[i], dstC);
507 if (0xFF != a) {
508 C = SkFourByteInterp(C, dstC, a);
509 }
510 dst[i] = SkPixel32ToPixel16_ToU16(C);
511 }
512 }
513 }
514 }
515
xfer4444(SkPMColor16 * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const516 void SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
517 const SkPMColor* SK_RESTRICT src, int count,
518 const SkAlpha* SK_RESTRICT aa) const {
519 SkASSERT(dst && src && count >= 0);
520
521 if (NULL == aa) {
522 for (int i = count - 1; i >= 0; --i) {
523 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
524 dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
525 }
526 } else {
527 for (int i = count - 1; i >= 0; --i) {
528 unsigned a = aa[i];
529 if (0 != a) {
530 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
531 SkPMColor C = this->xferColor(src[i], dstC);
532 if (0xFF != a) {
533 C = SkFourByteInterp(C, dstC, a);
534 }
535 dst[i] = SkPixel32ToPixel4444(C);
536 }
537 }
538 }
539 }
540
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const541 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
542 const SkPMColor src[], int count,
543 const SkAlpha* SK_RESTRICT aa) const {
544 SkASSERT(dst && src && count >= 0);
545
546 if (NULL == aa) {
547 for (int i = count - 1; i >= 0; --i) {
548 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
549 dst[i] = SkToU8(SkGetPackedA32(res));
550 }
551 } else {
552 for (int i = count - 1; i >= 0; --i) {
553 unsigned a = aa[i];
554 if (0 != a) {
555 SkAlpha dstA = dst[i];
556 unsigned A = SkGetPackedA32(this->xferColor(src[i],
557 (SkPMColor)(dstA << SK_A32_SHIFT)));
558 if (0xFF != a) {
559 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
560 }
561 dst[i] = SkToU8(A);
562 }
563 }
564 }
565 }
566
567 ///////////////////////////////////////////////////////////////////////////////
568
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const569 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
570 const SkPMColor* SK_RESTRICT src, int count,
571 const SkAlpha* SK_RESTRICT aa) const {
572 SkASSERT(dst && src && count >= 0);
573
574 SkXfermodeProc proc = fProc;
575
576 if (NULL != proc) {
577 if (NULL == aa) {
578 for (int i = count - 1; i >= 0; --i) {
579 dst[i] = proc(src[i], dst[i]);
580 }
581 } else {
582 for (int i = count - 1; i >= 0; --i) {
583 unsigned a = aa[i];
584 if (0 != a) {
585 SkPMColor dstC = dst[i];
586 SkPMColor C = proc(src[i], dstC);
587 if (a != 0xFF) {
588 C = SkFourByteInterp(C, dstC, a);
589 }
590 dst[i] = C;
591 }
592 }
593 }
594 }
595 }
596
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const597 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
598 const SkPMColor* SK_RESTRICT src, int count,
599 const SkAlpha* SK_RESTRICT aa) const {
600 SkASSERT(dst && src && count >= 0);
601
602 SkXfermodeProc proc = fProc;
603
604 if (NULL != proc) {
605 if (NULL == aa) {
606 for (int i = count - 1; i >= 0; --i) {
607 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
608 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
609 }
610 } else {
611 for (int i = count - 1; i >= 0; --i) {
612 unsigned a = aa[i];
613 if (0 != a) {
614 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
615 SkPMColor C = proc(src[i], dstC);
616 if (0xFF != a) {
617 C = SkFourByteInterp(C, dstC, a);
618 }
619 dst[i] = SkPixel32ToPixel16_ToU16(C);
620 }
621 }
622 }
623 }
624 }
625
xfer4444(SkPMColor16 * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const626 void SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
627 const SkPMColor* SK_RESTRICT src, int count,
628 const SkAlpha* SK_RESTRICT aa) const {
629 SkASSERT(dst && src && count >= 0);
630
631 SkXfermodeProc proc = fProc;
632
633 if (NULL != proc) {
634 if (NULL == aa) {
635 for (int i = count - 1; i >= 0; --i) {
636 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
637 dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
638 }
639 } else {
640 for (int i = count - 1; i >= 0; --i) {
641 unsigned a = aa[i];
642 if (0 != a) {
643 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
644 SkPMColor C = proc(src[i], dstC);
645 if (0xFF != a) {
646 C = SkFourByteInterp(C, dstC, a);
647 }
648 dst[i] = SkPixel32ToPixel4444(C);
649 }
650 }
651 }
652 }
653 }
654
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const655 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
656 const SkPMColor* SK_RESTRICT src, int count,
657 const SkAlpha* SK_RESTRICT aa) const {
658 SkASSERT(dst && src && count >= 0);
659
660 SkXfermodeProc proc = fProc;
661
662 if (NULL != proc) {
663 if (NULL == aa) {
664 for (int i = count - 1; i >= 0; --i) {
665 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
666 dst[i] = SkToU8(SkGetPackedA32(res));
667 }
668 } else {
669 for (int i = count - 1; i >= 0; --i) {
670 unsigned a = aa[i];
671 if (0 != a) {
672 SkAlpha dstA = dst[i];
673 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
674 unsigned A = SkGetPackedA32(res);
675 if (0xFF != a) {
676 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
677 }
678 dst[i] = SkToU8(A);
679 }
680 }
681 }
682 }
683 }
684
SkProcXfermode(SkFlattenableReadBuffer & buffer)685 SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
686 : SkXfermode(buffer) {
687 fProc = NULL;
688 if (!buffer.isCrossProcess()) {
689 fProc = (SkXfermodeProc)buffer.readFunctionPtr();
690 }
691 }
692
flatten(SkFlattenableWriteBuffer & buffer) const693 void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
694 this->INHERITED::flatten(buffer);
695 if (!buffer.isCrossProcess()) {
696 buffer.writeFunctionPtr((void*)fProc);
697 }
698 }
699
700 #ifdef SK_DEVELOPER
toString(SkString * str) const701 void SkProcXfermode::toString(SkString* str) const {
702 str->appendf("SkProcXfermode: %p", fProc);
703 }
704 #endif
705
706 ///////////////////////////////////////////////////////////////////////////////
707 ///////////////////////////////////////////////////////////////////////////////
708
709 class SkProcCoeffXfermode : public SkProcXfermode {
710 public:
SkProcCoeffXfermode(const ProcCoeff & rec,Mode mode)711 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
712 : INHERITED(rec.fProc) {
713 fMode = mode;
714 // these may be valid, or may be CANNOT_USE_COEFF
715 fSrcCoeff = rec.fSC;
716 fDstCoeff = rec.fDC;
717 }
718
asMode(Mode * mode) const719 virtual bool asMode(Mode* mode) const SK_OVERRIDE {
720 if (mode) {
721 *mode = fMode;
722 }
723 return true;
724 }
725
asCoeff(Coeff * sc,Coeff * dc) const726 virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
727 if (CANNOT_USE_COEFF == fSrcCoeff) {
728 return false;
729 }
730
731 if (sc) {
732 *sc = fSrcCoeff;
733 }
734 if (dc) {
735 *dc = fDstCoeff;
736 }
737 return true;
738 }
739
740 SK_DEVELOPER_TO_STRING()
741 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
742
743 protected:
SkProcCoeffXfermode(SkFlattenableReadBuffer & buffer)744 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
745 fMode = (SkXfermode::Mode)buffer.read32();
746
747 const ProcCoeff& rec = gProcCoeffs[fMode];
748 // these may be valid, or may be CANNOT_USE_COEFF
749 fSrcCoeff = rec.fSC;
750 fDstCoeff = rec.fDC;
751 // now update our function-ptr in the super class
752 this->INHERITED::setProc(rec.fProc);
753 }
754
flatten(SkFlattenableWriteBuffer & buffer) const755 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
756 this->INHERITED::flatten(buffer);
757 buffer.write32(fMode);
758 }
759
760 private:
761 Mode fMode;
762 Coeff fSrcCoeff, fDstCoeff;
763
764 typedef SkProcXfermode INHERITED;
765 };
766
767 #ifdef SK_DEVELOPER
toString(SkString * str) const768 void SkProcCoeffXfermode::toString(SkString* str) const {
769 str->append("SkProcCoeffXfermode: ");
770
771 const char *gModeStrings[kLastMode+1] = {
772 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
773 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
774 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
775 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion"
776 };
777
778 str->append("mode: ");
779 str->append(gModeStrings[fMode]);
780
781 static const char* gCoeffStrings[kCoeffCount] = {
782 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
783 };
784
785 str->append(" src: ");
786 if (CANNOT_USE_COEFF == fSrcCoeff) {
787 str->append("can't use");
788 } else {
789 str->append(gCoeffStrings[fSrcCoeff]);
790 }
791
792 str->append(" dst: ");
793 if (CANNOT_USE_COEFF == fDstCoeff) {
794 str->append("can't use");
795 } else {
796 str->append(gCoeffStrings[fDstCoeff]);
797 }
798 }
799 #endif
800
801 ///////////////////////////////////////////////////////////////////////////////
802
803 class SkClearXfermode : public SkProcCoeffXfermode {
804 public:
SkClearXfermode(const ProcCoeff & rec)805 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
806
807 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
808 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
809
810 SK_DEVELOPER_TO_STRING()
811 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
812
813 private:
SkClearXfermode(SkFlattenableReadBuffer & buffer)814 SkClearXfermode(SkFlattenableReadBuffer& buffer)
815 : SkProcCoeffXfermode(buffer) {}
816
817 typedef SkProcCoeffXfermode INHERITED;
818 };
819
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const820 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
821 const SkPMColor* SK_RESTRICT, int count,
822 const SkAlpha* SK_RESTRICT aa) const {
823 SkASSERT(dst && count >= 0);
824
825 if (NULL == aa) {
826 memset(dst, 0, count << 2);
827 } else {
828 for (int i = count - 1; i >= 0; --i) {
829 unsigned a = aa[i];
830 if (0xFF == a) {
831 dst[i] = 0;
832 } else if (a != 0) {
833 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
834 }
835 }
836 }
837 }
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const838 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
839 const SkPMColor* SK_RESTRICT, int count,
840 const SkAlpha* SK_RESTRICT aa) const {
841 SkASSERT(dst && count >= 0);
842
843 if (NULL == aa) {
844 memset(dst, 0, count);
845 } else {
846 for (int i = count - 1; i >= 0; --i) {
847 unsigned a = aa[i];
848 if (0xFF == a) {
849 dst[i] = 0;
850 } else if (0 != a) {
851 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
852 }
853 }
854 }
855 }
856
857 #ifdef SK_DEVELOPER
toString(SkString * str) const858 void SkClearXfermode::toString(SkString* str) const {
859 this->INHERITED::toString(str);
860 }
861 #endif
862
863 ///////////////////////////////////////////////////////////////////////////////
864
865 class SkSrcXfermode : public SkProcCoeffXfermode {
866 public:
SkSrcXfermode(const ProcCoeff & rec)867 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
868
869 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
870 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
871
872 SK_DEVELOPER_TO_STRING()
873 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
874
875 private:
SkSrcXfermode(SkFlattenableReadBuffer & buffer)876 SkSrcXfermode(SkFlattenableReadBuffer& buffer)
877 : SkProcCoeffXfermode(buffer) {}
878
879 typedef SkProcCoeffXfermode INHERITED;
880 };
881
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const882 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
883 const SkPMColor* SK_RESTRICT src, int count,
884 const SkAlpha* SK_RESTRICT aa) const {
885 SkASSERT(dst && src && count >= 0);
886
887 if (NULL == aa) {
888 memcpy(dst, src, count << 2);
889 } else {
890 for (int i = count - 1; i >= 0; --i) {
891 unsigned a = aa[i];
892 if (a == 0xFF) {
893 dst[i] = src[i];
894 } else if (a != 0) {
895 dst[i] = SkFourByteInterp(src[i], dst[i], a);
896 }
897 }
898 }
899 }
900
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const901 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
902 const SkPMColor* SK_RESTRICT src, int count,
903 const SkAlpha* SK_RESTRICT aa) const {
904 SkASSERT(dst && src && count >= 0);
905
906 if (NULL == aa) {
907 for (int i = count - 1; i >= 0; --i) {
908 dst[i] = SkToU8(SkGetPackedA32(src[i]));
909 }
910 } else {
911 for (int i = count - 1; i >= 0; --i) {
912 unsigned a = aa[i];
913 if (0 != a) {
914 unsigned srcA = SkGetPackedA32(src[i]);
915 if (a == 0xFF) {
916 dst[i] = SkToU8(srcA);
917 } else {
918 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
919 }
920 }
921 }
922 }
923 }
924 #ifdef SK_DEVELOPER
toString(SkString * str) const925 void SkSrcXfermode::toString(SkString* str) const {
926 this->INHERITED::toString(str);
927 }
928 #endif
929
930 ///////////////////////////////////////////////////////////////////////////////
931
932 class SkDstInXfermode : public SkProcCoeffXfermode {
933 public:
SkDstInXfermode(const ProcCoeff & rec)934 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
935
936 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
937
938 SK_DEVELOPER_TO_STRING()
939 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
940
941 private:
SkDstInXfermode(SkFlattenableReadBuffer & buffer)942 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
943
944 typedef SkProcCoeffXfermode INHERITED;
945 };
946
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const947 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
948 const SkPMColor* SK_RESTRICT src, int count,
949 const SkAlpha* SK_RESTRICT aa) const {
950 SkASSERT(dst && src);
951
952 if (count <= 0) {
953 return;
954 }
955 if (NULL != aa) {
956 return this->INHERITED::xfer32(dst, src, count, aa);
957 }
958
959 do {
960 unsigned a = SkGetPackedA32(*src);
961 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
962 dst++;
963 src++;
964 } while (--count != 0);
965 }
966
967 #ifdef SK_DEVELOPER
toString(SkString * str) const968 void SkDstInXfermode::toString(SkString* str) const {
969 this->INHERITED::toString(str);
970 }
971 #endif
972
973 ///////////////////////////////////////////////////////////////////////////////
974
975 class SkDstOutXfermode : public SkProcCoeffXfermode {
976 public:
SkDstOutXfermode(const ProcCoeff & rec)977 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
978
979 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
980
981 SK_DEVELOPER_TO_STRING()
982 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
983
984 private:
SkDstOutXfermode(SkFlattenableReadBuffer & buffer)985 SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
986 : INHERITED(buffer) {}
987
988 typedef SkProcCoeffXfermode INHERITED;
989 };
990
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const991 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
992 const SkPMColor* SK_RESTRICT src, int count,
993 const SkAlpha* SK_RESTRICT aa) const {
994 SkASSERT(dst && src);
995
996 if (count <= 0) {
997 return;
998 }
999 if (NULL != aa) {
1000 return this->INHERITED::xfer32(dst, src, count, aa);
1001 }
1002
1003 do {
1004 unsigned a = SkGetPackedA32(*src);
1005 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1006 dst++;
1007 src++;
1008 } while (--count != 0);
1009 }
1010
1011 #ifdef SK_DEVELOPER
toString(SkString * str) const1012 void SkDstOutXfermode::toString(SkString* str) const {
1013 this->INHERITED::toString(str);
1014 }
1015 #endif
1016
1017 ///////////////////////////////////////////////////////////////////////////////
1018
Create(Mode mode)1019 SkXfermode* SkXfermode::Create(Mode mode) {
1020 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1021 SkASSERT((unsigned)mode < kModeCount);
1022
1023 const ProcCoeff& rec = gProcCoeffs[mode];
1024
1025 switch (mode) {
1026 case kClear_Mode:
1027 return SkNEW_ARGS(SkClearXfermode, (rec));
1028 case kSrc_Mode:
1029 return SkNEW_ARGS(SkSrcXfermode, (rec));
1030 case kSrcOver_Mode:
1031 return NULL;
1032 case kDstIn_Mode:
1033 return SkNEW_ARGS(SkDstInXfermode, (rec));
1034 case kDstOut_Mode:
1035 return SkNEW_ARGS(SkDstOutXfermode, (rec));
1036 default:
1037 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1038 }
1039 }
1040
GetProc(Mode mode)1041 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1042 SkXfermodeProc proc = NULL;
1043 if ((unsigned)mode < kModeCount) {
1044 proc = gProcCoeffs[mode].fProc;
1045 }
1046 return proc;
1047 }
1048
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1049 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1050 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1051
1052 if ((unsigned)mode >= (unsigned)kModeCount) {
1053 // illegal mode parameter
1054 return false;
1055 }
1056
1057 const ProcCoeff& rec = gProcCoeffs[mode];
1058
1059 if (CANNOT_USE_COEFF == rec.fSC) {
1060 return false;
1061 }
1062
1063 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1064 if (src) {
1065 *src = rec.fSC;
1066 }
1067 if (dst) {
1068 *dst = rec.fDC;
1069 }
1070 return true;
1071 }
1072
AsMode(const SkXfermode * xfer,Mode * mode)1073 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1074 if (NULL == xfer) {
1075 if (mode) {
1076 *mode = kSrcOver_Mode;
1077 }
1078 return true;
1079 }
1080 return xfer->asMode(mode);
1081 }
1082
AsCoeff(const SkXfermode * xfer,Coeff * src,Coeff * dst)1083 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1084 if (NULL == xfer) {
1085 return ModeAsCoeff(kSrcOver_Mode, src, dst);
1086 }
1087 return xfer->asCoeff(src, dst);
1088 }
1089
IsMode(const SkXfermode * xfer,Mode mode)1090 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1091 // if xfer==null then the mode is srcover
1092 Mode m = kSrcOver_Mode;
1093 if (xfer && !xfer->asMode(&m)) {
1094 return false;
1095 }
1096 return mode == m;
1097 }
1098
1099 ///////////////////////////////////////////////////////////////////////////////
1100 //////////// 16bit xfermode procs
1101
1102 #ifdef SK_DEBUG
require_255(SkPMColor src)1103 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
require_0(SkPMColor src)1104 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1105 #endif
1106
src_modeproc16_255(SkPMColor src,uint16_t dst)1107 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1108 SkASSERT(require_255(src));
1109 return SkPixel32ToPixel16(src);
1110 }
1111
dst_modeproc16(SkPMColor src,uint16_t dst)1112 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1113 return dst;
1114 }
1115
srcover_modeproc16_0(SkPMColor src,uint16_t dst)1116 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1117 SkASSERT(require_0(src));
1118 return dst;
1119 }
1120
srcover_modeproc16_255(SkPMColor src,uint16_t dst)1121 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1122 SkASSERT(require_255(src));
1123 return SkPixel32ToPixel16(src);
1124 }
1125
dstover_modeproc16_0(SkPMColor src,uint16_t dst)1126 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1127 SkASSERT(require_0(src));
1128 return dst;
1129 }
1130
dstover_modeproc16_255(SkPMColor src,uint16_t dst)1131 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1132 SkASSERT(require_255(src));
1133 return dst;
1134 }
1135
srcin_modeproc16_255(SkPMColor src,uint16_t dst)1136 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1137 SkASSERT(require_255(src));
1138 return SkPixel32ToPixel16(src);
1139 }
1140
dstin_modeproc16_255(SkPMColor src,uint16_t dst)1141 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1142 SkASSERT(require_255(src));
1143 return dst;
1144 }
1145
dstout_modeproc16_0(SkPMColor src,uint16_t dst)1146 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1147 SkASSERT(require_0(src));
1148 return dst;
1149 }
1150
srcatop_modeproc16(SkPMColor src,uint16_t dst)1151 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1152 unsigned isa = 255 - SkGetPackedA32(src);
1153
1154 return SkPackRGB16(
1155 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1156 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1157 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1158 }
1159
srcatop_modeproc16_0(SkPMColor src,uint16_t dst)1160 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1161 SkASSERT(require_0(src));
1162 return dst;
1163 }
1164
srcatop_modeproc16_255(SkPMColor src,uint16_t dst)1165 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1166 SkASSERT(require_255(src));
1167 return SkPixel32ToPixel16(src);
1168 }
1169
dstatop_modeproc16_255(SkPMColor src,uint16_t dst)1170 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1171 SkASSERT(require_255(src));
1172 return dst;
1173 }
1174
1175 /*********
1176 darken and lighten boil down to this.
1177
1178 darken = (1 - Sa) * Dc + min(Sc, Dc)
1179 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1180
1181 if (Sa == 0) these become
1182 darken = Dc + min(0, Dc) = 0
1183 lighten = Dc + max(0, Dc) = Dc
1184
1185 if (Sa == 1) these become
1186 darken = min(Sc, Dc)
1187 lighten = max(Sc, Dc)
1188 */
1189
darken_modeproc16_0(SkPMColor src,uint16_t dst)1190 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1191 SkASSERT(require_0(src));
1192 return 0;
1193 }
1194
darken_modeproc16_255(SkPMColor src,uint16_t dst)1195 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1196 SkASSERT(require_255(src));
1197 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1198 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1199 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1200 return SkPackRGB16(r, g, b);
1201 }
1202
lighten_modeproc16_0(SkPMColor src,uint16_t dst)1203 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1204 SkASSERT(require_0(src));
1205 return dst;
1206 }
1207
lighten_modeproc16_255(SkPMColor src,uint16_t dst)1208 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1209 SkASSERT(require_255(src));
1210 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1211 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1212 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1213 return SkPackRGB16(r, g, b);
1214 }
1215
1216 struct Proc16Rec {
1217 SkXfermodeProc16 fProc16_0;
1218 SkXfermodeProc16 fProc16_255;
1219 SkXfermodeProc16 fProc16_General;
1220 };
1221
1222 static const Proc16Rec gModeProcs16[] = {
1223 { NULL, NULL, NULL }, // CLEAR
1224 { NULL, src_modeproc16_255, NULL },
1225 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1226 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1227 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1228 { NULL, srcin_modeproc16_255, NULL },
1229 { NULL, dstin_modeproc16_255, NULL },
1230 { NULL, NULL, NULL },// SRC_OUT
1231 { dstout_modeproc16_0, NULL, NULL },
1232 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1233 { NULL, dstatop_modeproc16_255, NULL },
1234 { NULL, NULL, NULL }, // XOR
1235
1236 { NULL, NULL, NULL }, // plus
1237 { NULL, NULL, NULL }, // modulate
1238 { NULL, NULL, NULL }, // screen
1239 { NULL, NULL, NULL }, // overlay
1240 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1241 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1242 { NULL, NULL, NULL }, // colordodge
1243 { NULL, NULL, NULL }, // colorburn
1244 { NULL, NULL, NULL }, // hardlight
1245 { NULL, NULL, NULL }, // softlight
1246 { NULL, NULL, NULL }, // difference
1247 { NULL, NULL, NULL }, // exclusion
1248 };
1249
GetProc16(Mode mode,SkColor srcColor)1250 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1251 SkXfermodeProc16 proc16 = NULL;
1252 if ((unsigned)mode < kModeCount) {
1253 const Proc16Rec& rec = gModeProcs16[mode];
1254 unsigned a = SkColorGetA(srcColor);
1255
1256 if (0 == a) {
1257 proc16 = rec.fProc16_0;
1258 } else if (255 == a) {
1259 proc16 = rec.fProc16_255;
1260 } else {
1261 proc16 = rec.fProc16_General;
1262 }
1263 }
1264 return proc16;
1265 }
1266
1267 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1268 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1269 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1270 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1271 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1272 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1273 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1274