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