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 #include "SkXfermode.h"
10 #include "SkXfermode_opts_SSE2.h"
11 #include "SkXfermode_proccoeff.h"
12 #include "Sk4px.h"
13 #include "SkColorPriv.h"
14 #include "SkLazyPtr.h"
15 #include "SkMathPriv.h"
16 #include "SkPMFloat.h"
17 #include "SkReadBuffer.h"
18 #include "SkString.h"
19 #include "SkUtilsArm.h"
20 #include "SkWriteBuffer.h"
21
22 // When implemented, the Sk4f and Sk4px xfermodes beat src/opts/SkXfermodes_opts_SSE2's.
23 // When implemented, the Sk4px, but not Sk4f, xfermodes beat src/opts/SkXfermodes_arm_neon's.
24 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
25 #define SK_4F_XFERMODES_ARE_FAST
26 #define SK_4PX_XFERMODES_ARE_FAST
27 #elif defined(SK_ARM_HAS_NEON)
28 #define SK_4PX_XFERMODES_ARE_FAST
29 #endif
30
31 #if !SK_ARM_NEON_IS_NONE
32 #include "SkXfermode_opts_arm_neon.h"
33 #endif
34
35 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
36
saturated_add(unsigned a,unsigned b)37 static inline unsigned saturated_add(unsigned a, unsigned b) {
38 SkASSERT(a <= 255);
39 SkASSERT(b <= 255);
40 unsigned sum = a + b;
41 if (sum > 255) {
42 sum = 255;
43 }
44 return sum;
45 }
46
clamp_signed_byte(int n)47 static inline int clamp_signed_byte(int n) {
48 if (n < 0) {
49 n = 0;
50 } else if (n > 255) {
51 n = 255;
52 }
53 return n;
54 }
55
clamp_div255round(int prod)56 static inline int clamp_div255round(int prod) {
57 if (prod <= 0) {
58 return 0;
59 } else if (prod >= 255*255) {
60 return 255;
61 } else {
62 return SkDiv255Round(prod);
63 }
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 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)181 static SkPMColor modulate_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
srcover_byte(int a,int b)189 static inline int srcover_byte(int a, int b) {
190 return a + b - SkAlphaMulAlpha(a, b);
191 }
192
193 // kMultiply_Mode
194 // B(Cb, Cs) = Cb x Cs
195 // multiply uses its own version of blendfunc_byte because sa and da are not needed
blendfunc_multiply_byte(int sc,int dc,int sa,int da)196 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
197 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
198 }
199
multiply_modeproc(SkPMColor src,SkPMColor dst)200 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
201 int sa = SkGetPackedA32(src);
202 int da = SkGetPackedA32(dst);
203 int a = srcover_byte(sa, da);
204 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
205 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
206 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
207 return SkPackARGB32(a, r, g, b);
208 }
209
210 // kScreen_Mode
screen_modeproc(SkPMColor src,SkPMColor dst)211 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
212 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
213 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
214 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
215 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
216 return SkPackARGB32(a, r, g, b);
217 }
218
219 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)220 static inline int overlay_byte(int sc, int dc, int sa, int da) {
221 int tmp = sc * (255 - da) + dc * (255 - sa);
222 int rc;
223 if (2 * dc <= da) {
224 rc = 2 * sc * dc;
225 } else {
226 rc = sa * da - 2 * (da - dc) * (sa - sc);
227 }
228 return clamp_div255round(rc + tmp);
229 }
overlay_modeproc(SkPMColor src,SkPMColor dst)230 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
231 int sa = SkGetPackedA32(src);
232 int da = SkGetPackedA32(dst);
233 int a = srcover_byte(sa, da);
234 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
235 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
236 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
237 return SkPackARGB32(a, r, g, b);
238 }
239
240 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)241 static inline int darken_byte(int sc, int dc, int sa, int da) {
242 int sd = sc * da;
243 int ds = dc * sa;
244 if (sd < ds) {
245 // srcover
246 return sc + dc - SkDiv255Round(ds);
247 } else {
248 // dstover
249 return dc + sc - SkDiv255Round(sd);
250 }
251 }
darken_modeproc(SkPMColor src,SkPMColor dst)252 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
253 int sa = SkGetPackedA32(src);
254 int da = SkGetPackedA32(dst);
255 int a = srcover_byte(sa, da);
256 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
257 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
258 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
259 return SkPackARGB32(a, r, g, b);
260 }
261
262 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)263 static inline int lighten_byte(int sc, int dc, int sa, int da) {
264 int sd = sc * da;
265 int ds = dc * sa;
266 if (sd > ds) {
267 // srcover
268 return sc + dc - SkDiv255Round(ds);
269 } else {
270 // dstover
271 return dc + sc - SkDiv255Round(sd);
272 }
273 }
lighten_modeproc(SkPMColor src,SkPMColor dst)274 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
275 int sa = SkGetPackedA32(src);
276 int da = SkGetPackedA32(dst);
277 int a = srcover_byte(sa, da);
278 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
279 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
280 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
281 return SkPackARGB32(a, r, g, b);
282 }
283
284 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)285 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
286 int diff = sa - sc;
287 int rc;
288 if (0 == dc) {
289 return SkAlphaMulAlpha(sc, 255 - da);
290 } else if (0 == diff) {
291 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
292 } else {
293 diff = dc * sa / diff;
294 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
295 }
296 return clamp_div255round(rc);
297 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)298 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
299 int sa = SkGetPackedA32(src);
300 int da = SkGetPackedA32(dst);
301 int a = srcover_byte(sa, da);
302 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
303 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
304 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
305 return SkPackARGB32(a, r, g, b);
306 }
307
308 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)309 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
310 int rc;
311 if (dc == da) {
312 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
313 } else if (0 == sc) {
314 return SkAlphaMulAlpha(dc, 255 - sa);
315 } else {
316 int tmp = (da - dc) * sa / sc;
317 rc = sa * (da - ((da < tmp) ? da : tmp))
318 + sc * (255 - da) + dc * (255 - sa);
319 }
320 return clamp_div255round(rc);
321 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)322 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
323 int sa = SkGetPackedA32(src);
324 int da = SkGetPackedA32(dst);
325 int a = srcover_byte(sa, da);
326 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
327 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
328 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
329 return SkPackARGB32(a, r, g, b);
330 }
331
332 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)333 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
334 int rc;
335 if (2 * sc <= sa) {
336 rc = 2 * sc * dc;
337 } else {
338 rc = sa * da - 2 * (da - dc) * (sa - sc);
339 }
340 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
341 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)342 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
343 int sa = SkGetPackedA32(src);
344 int da = SkGetPackedA32(dst);
345 int a = srcover_byte(sa, da);
346 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
347 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
348 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
349 return SkPackARGB32(a, r, g, b);
350 }
351
352 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)353 static U8CPU sqrt_unit_byte(U8CPU n) {
354 return SkSqrtBits(n, 15+4);
355 }
356
357 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)358 static inline int softlight_byte(int sc, int dc, int sa, int da) {
359 int m = da ? dc * 256 / da : 0;
360 int rc;
361 if (2 * sc <= sa) {
362 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
363 } else if (4 * dc <= da) {
364 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
365 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
366 } else {
367 int tmp = sqrt_unit_byte(m) - m;
368 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
369 }
370 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
371 }
softlight_modeproc(SkPMColor src,SkPMColor dst)372 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
373 int sa = SkGetPackedA32(src);
374 int da = SkGetPackedA32(dst);
375 int a = srcover_byte(sa, da);
376 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
377 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
378 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
379 return SkPackARGB32(a, r, g, b);
380 }
381
382 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)383 static inline int difference_byte(int sc, int dc, int sa, int da) {
384 int tmp = SkMin32(sc * da, dc * sa);
385 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
386 }
difference_modeproc(SkPMColor src,SkPMColor dst)387 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
388 int sa = SkGetPackedA32(src);
389 int da = SkGetPackedA32(dst);
390 int a = srcover_byte(sa, da);
391 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
392 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
393 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
394 return SkPackARGB32(a, r, g, b);
395 }
396
397 // kExclusion_Mode
exclusion_byte(int sc,int dc,int,int)398 static inline int exclusion_byte(int sc, int dc, int, int) {
399 // this equations is wacky, wait for SVG to confirm it
400 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
401
402 // The above equation can be simplified as follows
403 int r = 255*(sc + dc) - 2 * sc * dc;
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 // The CSS compositing spec introduces the following formulas:
417 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
418 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
419 // while PDF and CG uses the one from Rec. Rec. 601
420 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
Lum(int r,int g,int b)421 static inline int Lum(int r, int g, int b)
422 {
423 return SkDiv255Round(r * 77 + g * 150 + b * 28);
424 }
425
min2(int a,int b)426 static inline int min2(int a, int b) { return a < b ? a : b; }
max2(int a,int b)427 static inline int max2(int a, int b) { return a > b ? a : b; }
428 #define minimum(a, b, c) min2(min2(a, b), c)
429 #define maximum(a, b, c) max2(max2(a, b), c)
430
Sat(int r,int g,int b)431 static inline int Sat(int r, int g, int b) {
432 return maximum(r, g, b) - minimum(r, g, b);
433 }
434
setSaturationComponents(int * Cmin,int * Cmid,int * Cmax,int s)435 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
436 if(*Cmax > *Cmin) {
437 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
438 *Cmax = s;
439 } else {
440 *Cmax = 0;
441 *Cmid = 0;
442 }
443
444 *Cmin = 0;
445 }
446
SetSat(int * r,int * g,int * b,int s)447 static inline void SetSat(int* r, int* g, int* b, int s) {
448 if(*r <= *g) {
449 if(*g <= *b) {
450 setSaturationComponents(r, g, b, s);
451 } else if(*r <= *b) {
452 setSaturationComponents(r, b, g, s);
453 } else {
454 setSaturationComponents(b, r, g, s);
455 }
456 } else if(*r <= *b) {
457 setSaturationComponents(g, r, b, s);
458 } else if(*g <= *b) {
459 setSaturationComponents(g, b, r, s);
460 } else {
461 setSaturationComponents(b, g, r, s);
462 }
463 }
464
clipColor(int * r,int * g,int * b,int a)465 static inline void clipColor(int* r, int* g, int* b, int a) {
466 int L = Lum(*r, *g, *b);
467 int n = minimum(*r, *g, *b);
468 int x = maximum(*r, *g, *b);
469 int denom;
470 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
471 *r = L + SkMulDiv(*r - L, L, denom);
472 *g = L + SkMulDiv(*g - L, L, denom);
473 *b = L + SkMulDiv(*b - L, L, denom);
474 }
475
476 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
477 int numer = a - L;
478 *r = L + SkMulDiv(*r - L, numer, denom);
479 *g = L + SkMulDiv(*g - L, numer, denom);
480 *b = L + SkMulDiv(*b - L, numer, denom);
481 }
482 }
483
SetLum(int * r,int * g,int * b,int a,int l)484 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
485 int d = l - Lum(*r, *g, *b);
486 *r += d;
487 *g += d;
488 *b += d;
489
490 clipColor(r, g, b, a);
491 }
492
493 // non-separable blend modes are done in non-premultiplied alpha
494 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
495 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
496
497 // kHue_Mode
498 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
499 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
hue_modeproc(SkPMColor src,SkPMColor dst)500 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
501 int sr = SkGetPackedR32(src);
502 int sg = SkGetPackedG32(src);
503 int sb = SkGetPackedB32(src);
504 int sa = SkGetPackedA32(src);
505
506 int dr = SkGetPackedR32(dst);
507 int dg = SkGetPackedG32(dst);
508 int db = SkGetPackedB32(dst);
509 int da = SkGetPackedA32(dst);
510 int Sr, Sg, Sb;
511
512 if(sa && da) {
513 Sr = sr * sa;
514 Sg = sg * sa;
515 Sb = sb * sa;
516 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
517 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
518 } else {
519 Sr = 0;
520 Sg = 0;
521 Sb = 0;
522 }
523
524 int a = srcover_byte(sa, da);
525 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
526 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
527 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
528 return SkPackARGB32(a, r, g, b);
529 }
530
531 // kSaturation_Mode
532 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
533 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
saturation_modeproc(SkPMColor src,SkPMColor dst)534 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
535 int sr = SkGetPackedR32(src);
536 int sg = SkGetPackedG32(src);
537 int sb = SkGetPackedB32(src);
538 int sa = SkGetPackedA32(src);
539
540 int dr = SkGetPackedR32(dst);
541 int dg = SkGetPackedG32(dst);
542 int db = SkGetPackedB32(dst);
543 int da = SkGetPackedA32(dst);
544 int Dr, Dg, Db;
545
546 if(sa && da) {
547 Dr = dr * sa;
548 Dg = dg * sa;
549 Db = db * sa;
550 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
551 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
552 } else {
553 Dr = 0;
554 Dg = 0;
555 Db = 0;
556 }
557
558 int a = srcover_byte(sa, da);
559 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
560 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
561 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
562 return SkPackARGB32(a, r, g, b);
563 }
564
565 // kColor_Mode
566 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
567 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
color_modeproc(SkPMColor src,SkPMColor dst)568 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
569 int sr = SkGetPackedR32(src);
570 int sg = SkGetPackedG32(src);
571 int sb = SkGetPackedB32(src);
572 int sa = SkGetPackedA32(src);
573
574 int dr = SkGetPackedR32(dst);
575 int dg = SkGetPackedG32(dst);
576 int db = SkGetPackedB32(dst);
577 int da = SkGetPackedA32(dst);
578 int Sr, Sg, Sb;
579
580 if(sa && da) {
581 Sr = sr * da;
582 Sg = sg * da;
583 Sb = sb * da;
584 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
585 } else {
586 Sr = 0;
587 Sg = 0;
588 Sb = 0;
589 }
590
591 int a = srcover_byte(sa, da);
592 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
593 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
594 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
595 return SkPackARGB32(a, r, g, b);
596 }
597
598 // kLuminosity_Mode
599 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
600 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
luminosity_modeproc(SkPMColor src,SkPMColor dst)601 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
602 int sr = SkGetPackedR32(src);
603 int sg = SkGetPackedG32(src);
604 int sb = SkGetPackedB32(src);
605 int sa = SkGetPackedA32(src);
606
607 int dr = SkGetPackedR32(dst);
608 int dg = SkGetPackedG32(dst);
609 int db = SkGetPackedB32(dst);
610 int da = SkGetPackedA32(dst);
611 int Dr, Dg, Db;
612
613 if(sa && da) {
614 Dr = dr * sa;
615 Dg = dg * sa;
616 Db = db * sa;
617 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
618 } else {
619 Dr = 0;
620 Dg = 0;
621 Db = 0;
622 }
623
624 int a = srcover_byte(sa, da);
625 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
626 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
627 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
628 return SkPackARGB32(a, r, g, b);
629 }
630
631 const ProcCoeff gProcCoeffs[] = {
632 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
633 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
634 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
635 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
636 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
637 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
638 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
639 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
640 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
641 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
642 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
643 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
644
645 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
646 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
647 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
648 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
649 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
650 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
651 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
652 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
653 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
654 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
655 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
656 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
657 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
658 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
659 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
660 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
661 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
662 };
663
664 ///////////////////////////////////////////////////////////////////////////////
665
asMode(Mode * mode) const666 bool SkXfermode::asMode(Mode* mode) const {
667 return false;
668 }
669
asFragmentProcessor(GrFragmentProcessor **,GrTexture *) const670 bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
671 return false;
672 }
673
asXPFactory(GrXPFactory **) const674 bool SkXfermode::asXPFactory(GrXPFactory**) const {
675 return false;
676 }
677
678
679 #if SK_SUPPORT_GPU
680 #include "effects/GrPorterDuffXferProcessor.h"
681
AsXPFactory(SkXfermode * xfermode,GrXPFactory ** xpf)682 bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
683 if (NULL == xfermode) {
684 if (xpf) {
685 *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
686 }
687 return true;
688 } else {
689 return xfermode->asXPFactory(xpf);
690 }
691 }
692 #else
AsXPFactory(SkXfermode * xfermode,GrXPFactory ** xpf)693 bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
694 return false;
695 }
696 #endif
697
xferColor(SkPMColor src,SkPMColor dst) const698 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
699 // no-op. subclasses should override this
700 return dst;
701 }
702
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const703 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
704 const SkPMColor* SK_RESTRICT src, int count,
705 const SkAlpha* SK_RESTRICT aa) const {
706 SkASSERT(dst && src && count >= 0);
707
708 if (NULL == aa) {
709 for (int i = count - 1; i >= 0; --i) {
710 dst[i] = this->xferColor(src[i], dst[i]);
711 }
712 } else {
713 for (int i = count - 1; i >= 0; --i) {
714 unsigned a = aa[i];
715 if (0 != a) {
716 SkPMColor dstC = dst[i];
717 SkPMColor C = this->xferColor(src[i], dstC);
718 if (0xFF != a) {
719 C = SkFourByteInterp(C, dstC, a);
720 }
721 dst[i] = C;
722 }
723 }
724 }
725 }
726
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const727 void SkXfermode::xfer16(uint16_t* dst,
728 const SkPMColor* SK_RESTRICT src, int count,
729 const SkAlpha* SK_RESTRICT aa) const {
730 SkASSERT(dst && src && count >= 0);
731
732 if (NULL == aa) {
733 for (int i = count - 1; i >= 0; --i) {
734 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
735 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
736 }
737 } else {
738 for (int i = count - 1; i >= 0; --i) {
739 unsigned a = aa[i];
740 if (0 != a) {
741 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
742 SkPMColor C = this->xferColor(src[i], dstC);
743 if (0xFF != a) {
744 C = SkFourByteInterp(C, dstC, a);
745 }
746 dst[i] = SkPixel32ToPixel16_ToU16(C);
747 }
748 }
749 }
750 }
751
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const752 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
753 const SkPMColor src[], int count,
754 const SkAlpha* SK_RESTRICT aa) const {
755 SkASSERT(dst && src && count >= 0);
756
757 if (NULL == aa) {
758 for (int i = count - 1; i >= 0; --i) {
759 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
760 dst[i] = SkToU8(SkGetPackedA32(res));
761 }
762 } else {
763 for (int i = count - 1; i >= 0; --i) {
764 unsigned a = aa[i];
765 if (0 != a) {
766 SkAlpha dstA = dst[i];
767 unsigned A = SkGetPackedA32(this->xferColor(src[i],
768 (SkPMColor)(dstA << SK_A32_SHIFT)));
769 if (0xFF != a) {
770 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
771 }
772 dst[i] = SkToU8(A);
773 }
774 }
775 }
776 }
777
supportsCoverageAsAlpha() const778 bool SkXfermode::supportsCoverageAsAlpha() const {
779 return false;
780 }
781
isOpaque(SkXfermode::SrcColorOpacity opacityType) const782 bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
783 return false;
784 }
785
786 ///////////////////////////////////////////////////////////////////////////////
787 ///////////////////////////////////////////////////////////////////////////////
788
CreateProc(SkReadBuffer & buffer)789 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
790 uint32_t mode32 = buffer.read32();
791 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
792 return NULL;
793 }
794 return SkXfermode::Create((SkXfermode::Mode)mode32);
795 }
796
flatten(SkWriteBuffer & buffer) const797 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
798 buffer.write32(fMode);
799 }
800
asMode(Mode * mode) const801 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
802 if (mode) {
803 *mode = fMode;
804 }
805 return true;
806 }
807
supportsCoverageAsAlpha() const808 bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
809 if (CANNOT_USE_COEFF == fSrcCoeff) {
810 return false;
811 }
812
813 switch (fDstCoeff) {
814 case SkXfermode::kOne_Coeff:
815 case SkXfermode::kISA_Coeff:
816 case SkXfermode::kISC_Coeff:
817 return true;
818 default:
819 return false;
820 }
821 }
822
isOpaque(SkXfermode::SrcColorOpacity opacityType) const823 bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
824 if (CANNOT_USE_COEFF == fSrcCoeff) {
825 return false;
826 }
827
828 if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
829 SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
830 return false;
831 }
832
833 switch (fDstCoeff) {
834 case SkXfermode::kZero_Coeff:
835 return true;
836 case SkXfermode::kISA_Coeff:
837 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
838 case SkXfermode::kSA_Coeff:
839 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
840 SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
841 case SkXfermode::kSC_Coeff:
842 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
843 default:
844 return false;
845 }
846
847 }
848
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const849 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
850 const SkPMColor* SK_RESTRICT src, int count,
851 const SkAlpha* SK_RESTRICT aa) const {
852 SkASSERT(dst && src && count >= 0);
853
854 SkXfermodeProc proc = fProc;
855
856 if (proc) {
857 if (NULL == aa) {
858 for (int i = count - 1; i >= 0; --i) {
859 dst[i] = proc(src[i], dst[i]);
860 }
861 } else {
862 for (int i = count - 1; i >= 0; --i) {
863 unsigned a = aa[i];
864 if (0 != a) {
865 SkPMColor dstC = dst[i];
866 SkPMColor C = proc(src[i], dstC);
867 if (a != 0xFF) {
868 C = SkFourByteInterp(C, dstC, a);
869 }
870 dst[i] = C;
871 }
872 }
873 }
874 }
875 }
876
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const877 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
878 const SkPMColor* SK_RESTRICT src, int count,
879 const SkAlpha* SK_RESTRICT aa) const {
880 SkASSERT(dst && src && count >= 0);
881
882 SkXfermodeProc proc = fProc;
883
884 if (proc) {
885 if (NULL == aa) {
886 for (int i = count - 1; i >= 0; --i) {
887 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
888 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
889 }
890 } else {
891 for (int i = count - 1; i >= 0; --i) {
892 unsigned a = aa[i];
893 if (0 != a) {
894 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
895 SkPMColor C = proc(src[i], dstC);
896 if (0xFF != a) {
897 C = SkFourByteInterp(C, dstC, a);
898 }
899 dst[i] = SkPixel32ToPixel16_ToU16(C);
900 }
901 }
902 }
903 }
904 }
905
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const906 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
907 const SkPMColor* SK_RESTRICT src, int count,
908 const SkAlpha* SK_RESTRICT aa) const {
909 SkASSERT(dst && src && count >= 0);
910
911 SkXfermodeProc proc = fProc;
912
913 if (proc) {
914 if (NULL == aa) {
915 for (int i = count - 1; i >= 0; --i) {
916 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
917 dst[i] = SkToU8(SkGetPackedA32(res));
918 }
919 } else {
920 for (int i = count - 1; i >= 0; --i) {
921 unsigned a = aa[i];
922 if (0 != a) {
923 SkAlpha dstA = dst[i];
924 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
925 unsigned A = SkGetPackedA32(res);
926 if (0xFF != a) {
927 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
928 }
929 dst[i] = SkToU8(A);
930 }
931 }
932 }
933 }
934 }
935
936 #if SK_SUPPORT_GPU
937 #include "effects/GrCustomXfermode.h"
938
asFragmentProcessor(GrFragmentProcessor ** fp,GrTexture * background) const939 bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
940 GrTexture* background) const {
941 if (GrCustomXfermode::IsSupportedMode(fMode)) {
942 if (fp) {
943 *fp = GrCustomXfermode::CreateFP(fMode, background);
944 SkASSERT(*fp);
945 }
946 return true;
947 }
948 return false;
949 }
950
asXPFactory(GrXPFactory ** xp) const951 bool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
952 if (CANNOT_USE_COEFF != fSrcCoeff) {
953 if (xp) {
954 *xp = GrPorterDuffXPFactory::Create(fMode);
955 SkASSERT(*xp);
956 }
957 return true;
958 }
959
960 if (GrCustomXfermode::IsSupportedMode(fMode)) {
961 if (xp) {
962 *xp = GrCustomXfermode::CreateXPFactory(fMode);
963 SkASSERT(*xp);
964 }
965 return true;
966 }
967 return false;
968 }
969 #endif
970
ModeName(Mode mode)971 const char* SkXfermode::ModeName(Mode mode) {
972 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
973 const char* gModeStrings[] = {
974 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
975 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
976 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
977 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
978 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
979 };
980 return gModeStrings[mode];
981 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
982 }
983
984 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const985 void SkProcCoeffXfermode::toString(SkString* str) const {
986 str->append("SkProcCoeffXfermode: ");
987
988 str->append("mode: ");
989 str->append(ModeName(fMode));
990
991 static const char* gCoeffStrings[kCoeffCount] = {
992 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
993 };
994
995 str->append(" src: ");
996 if (CANNOT_USE_COEFF == fSrcCoeff) {
997 str->append("can't use");
998 } else {
999 str->append(gCoeffStrings[fSrcCoeff]);
1000 }
1001
1002 str->append(" dst: ");
1003 if (CANNOT_USE_COEFF == fDstCoeff) {
1004 str->append("can't use");
1005 } else {
1006 str->append(gCoeffStrings[fDstCoeff]);
1007 }
1008 }
1009 #endif
1010
1011 ///////////////////////////////////////////////////////////////////////////////
1012
1013 class SkClearXfermode : public SkProcCoeffXfermode {
1014 public:
Create(const ProcCoeff & rec)1015 static SkClearXfermode* Create(const ProcCoeff& rec) {
1016 return SkNEW_ARGS(SkClearXfermode, (rec));
1017 }
1018
1019 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1020 void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1021
1022 SK_TO_STRING_OVERRIDE()
1023
1024 private:
SkClearXfermode(const ProcCoeff & rec)1025 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1026
1027 typedef SkProcCoeffXfermode INHERITED;
1028 };
1029
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const1030 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1031 const SkPMColor* SK_RESTRICT, int count,
1032 const SkAlpha* SK_RESTRICT aa) const {
1033 SkASSERT(dst && count >= 0);
1034
1035 if (NULL == aa) {
1036 memset(dst, 0, count << 2);
1037 } else {
1038 for (int i = count - 1; i >= 0; --i) {
1039 unsigned a = aa[i];
1040 if (0xFF == a) {
1041 dst[i] = 0;
1042 } else if (a != 0) {
1043 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1044 }
1045 }
1046 }
1047 }
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const1048 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1049 const SkPMColor* SK_RESTRICT, int count,
1050 const SkAlpha* SK_RESTRICT aa) const {
1051 SkASSERT(dst && count >= 0);
1052
1053 if (NULL == aa) {
1054 memset(dst, 0, count);
1055 } else {
1056 for (int i = count - 1; i >= 0; --i) {
1057 unsigned a = aa[i];
1058 if (0xFF == a) {
1059 dst[i] = 0;
1060 } else if (0 != a) {
1061 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1062 }
1063 }
1064 }
1065 }
1066
1067 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1068 void SkClearXfermode::toString(SkString* str) const {
1069 this->INHERITED::toString(str);
1070 }
1071 #endif
1072
1073 ///////////////////////////////////////////////////////////////////////////////
1074
1075 class SkSrcXfermode : public SkProcCoeffXfermode {
1076 public:
Create(const ProcCoeff & rec)1077 static SkSrcXfermode* Create(const ProcCoeff& rec) {
1078 return SkNEW_ARGS(SkSrcXfermode, (rec));
1079 }
1080
1081 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1082 void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1083
1084 SK_TO_STRING_OVERRIDE()
1085
1086 private:
SkSrcXfermode(const ProcCoeff & rec)1087 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1088 typedef SkProcCoeffXfermode INHERITED;
1089 };
1090
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1091 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1092 const SkPMColor* SK_RESTRICT src, int count,
1093 const SkAlpha* SK_RESTRICT aa) const {
1094 SkASSERT(dst && src && count >= 0);
1095
1096 if (NULL == aa) {
1097 memcpy(dst, src, count << 2);
1098 } else {
1099 for (int i = count - 1; i >= 0; --i) {
1100 unsigned a = aa[i];
1101 if (a == 0xFF) {
1102 dst[i] = src[i];
1103 } else if (a != 0) {
1104 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1105 }
1106 }
1107 }
1108 }
1109
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1110 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1111 const SkPMColor* SK_RESTRICT src, int count,
1112 const SkAlpha* SK_RESTRICT aa) const {
1113 SkASSERT(dst && src && count >= 0);
1114
1115 if (NULL == aa) {
1116 for (int i = count - 1; i >= 0; --i) {
1117 dst[i] = SkToU8(SkGetPackedA32(src[i]));
1118 }
1119 } else {
1120 for (int i = count - 1; i >= 0; --i) {
1121 unsigned a = aa[i];
1122 if (0 != a) {
1123 unsigned srcA = SkGetPackedA32(src[i]);
1124 if (a == 0xFF) {
1125 dst[i] = SkToU8(srcA);
1126 } else {
1127 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1128 }
1129 }
1130 }
1131 }
1132 }
1133 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1134 void SkSrcXfermode::toString(SkString* str) const {
1135 this->INHERITED::toString(str);
1136 }
1137 #endif
1138
1139 ///////////////////////////////////////////////////////////////////////////////
1140
1141 class SkDstInXfermode : public SkProcCoeffXfermode {
1142 public:
Create(const ProcCoeff & rec)1143 static SkDstInXfermode* Create(const ProcCoeff& rec) {
1144 return SkNEW_ARGS(SkDstInXfermode, (rec));
1145 }
1146
1147 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1148
1149 SK_TO_STRING_OVERRIDE()
1150
1151 private:
SkDstInXfermode(const ProcCoeff & rec)1152 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1153
1154 typedef SkProcCoeffXfermode INHERITED;
1155 };
1156
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1157 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1158 const SkPMColor* SK_RESTRICT src, int count,
1159 const SkAlpha* SK_RESTRICT aa) const {
1160 SkASSERT(dst && src);
1161
1162 if (count <= 0) {
1163 return;
1164 }
1165 if (aa) {
1166 return this->INHERITED::xfer32(dst, src, count, aa);
1167 }
1168
1169 do {
1170 unsigned a = SkGetPackedA32(*src);
1171 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1172 dst++;
1173 src++;
1174 } while (--count != 0);
1175 }
1176
1177 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1178 void SkDstInXfermode::toString(SkString* str) const {
1179 this->INHERITED::toString(str);
1180 }
1181 #endif
1182
1183 ///////////////////////////////////////////////////////////////////////////////
1184
1185 /* These modes can merge coverage into src-alpha
1186 *
1187 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
1188 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
1189 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
1190 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
1191 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
1192 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
1193 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
1194 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
1195 */
1196
1197 static const float gInv255 = 0.0039215683f; // (1.0f / 255) - ULP == SkBits2Float(0x3B808080)
1198
ramp(const Sk4f & v0,const Sk4f & v1,const Sk4f & t)1199 static Sk4f ramp(const Sk4f& v0, const Sk4f& v1, const Sk4f& t) {
1200 return v0 + (v1 - v0) * t;
1201 }
1202
clamp_255(const Sk4f & value)1203 static Sk4f clamp_255(const Sk4f& value) {
1204 return Sk4f::Min(Sk4f(255), value);
1205 }
1206
clamp_0_255(const Sk4f & value)1207 static Sk4f clamp_0_255(const Sk4f& value) {
1208 return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value));
1209 }
1210
1211 /**
1212 * Some modes can, due to very slight numerical error, generate "invalid" pmcolors...
1213 *
1214 * e.g.
1215 * alpha = 100.9999
1216 * red = 101
1217 *
1218 * or
1219 * alpha = 255.0001
1220 *
1221 * If we know we're going to write-out the values as bytes, we can relax these somewhat,
1222 * since we only really need to enforce that the bytes are valid premul...
1223 *
1224 * To that end, this method asserts that the resulting pmcolor will be valid, but does not call
1225 * SkPMFloat::isValid(), as that would fire sometimes, but not result in a bad pixel.
1226 */
check_as_pmfloat(const Sk4f & value)1227 static inline SkPMFloat check_as_pmfloat(const Sk4f& value) {
1228 SkPMFloat pm = value;
1229 #ifdef SK_DEBUG
1230 (void)pm.round();
1231 #endif
1232 return pm;
1233 }
1234
1235 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
1236 struct SrcATop4f {
XferSrcATop4f1237 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1238 const Sk4f inv255(gInv255);
1239 return check_as_pmfloat(dst + (src * Sk4f(dst.a()) - dst * Sk4f(src.a())) * inv255);
1240 }
XferSrcATop4f1241 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1242 return Sk4px::Wide(src.mulWiden(dst.alphas()) + dst.mulWiden(src.alphas().inv()))
1243 .div255RoundNarrow();
1244 }
1245 static const bool kFoldCoverageIntoSrcAlpha = true;
1246 static const SkXfermode::Mode kMode = SkXfermode::kSrcATop_Mode;
1247 };
1248
1249 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
1250 struct DstATop4f {
XferDstATop4f1251 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1252 return SrcATop4f::Xfer(dst, src);
1253 }
XferDstATop4f1254 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1255 return SrcATop4f::Xfer(dst, src);
1256 }
1257 static const bool kFoldCoverageIntoSrcAlpha = false;
1258 static const SkXfermode::Mode kMode = SkXfermode::kDstATop_Mode;
1259 };
1260
1261 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
1262 struct Xor4f {
XferXor4f1263 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1264 const Sk4f inv255(gInv255);
1265 return check_as_pmfloat(src + dst - (src * Sk4f(dst.a()) + dst * Sk4f(src.a())) * inv255);
1266 }
XferXor4f1267 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1268 return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) + dst.mulWiden(src.alphas().inv()))
1269 .div255RoundNarrow();
1270 }
1271 static const bool kFoldCoverageIntoSrcAlpha = true;
1272 static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode;
1273 };
1274
1275 // kPlus_Mode [Sa + Da, Sc + Dc]
1276 struct Plus4f {
XferPlus4f1277 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1278 return check_as_pmfloat(clamp_255(src + dst));
1279 }
XferPlus4f1280 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1281 return src.saturatedAdd(dst);
1282 }
1283 static const bool kFoldCoverageIntoSrcAlpha = false;
1284 static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode;
1285 };
1286
1287 // kModulate_Mode [Sa * Da, Sc * Dc]
1288 struct Modulate4f {
XferModulate4f1289 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1290 const Sk4f inv255(gInv255);
1291 return check_as_pmfloat(src * dst * inv255);
1292 }
XferModulate4f1293 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1294 return src.mulWiden(dst).div255RoundNarrow();
1295 }
1296 static const bool kFoldCoverageIntoSrcAlpha = false;
1297 static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode;
1298 };
1299
1300 // kScreen_Mode [S + D - S * D]
1301 struct Screen4f {
XferScreen4f1302 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1303 const Sk4f inv255(gInv255);
1304 return check_as_pmfloat(src + dst - src * dst * inv255);
1305 }
XferScreen4f1306 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1307 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract can be done
1308 // in 8-bit space without overflow. S + (1-S)*D is a touch faster because inv() is cheap.
1309 return src + src.inv().mulWiden(dst).div255RoundNarrow();
1310 }
1311 static const bool kFoldCoverageIntoSrcAlpha = true;
1312 static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode;
1313 };
1314
1315 struct Multiply4f {
XferMultiply4f1316 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1317 const Sk4f inv255(gInv255);
1318 Sk4f sa = Sk4f(src.a());
1319 Sk4f da = Sk4f(dst.a());
1320 Sk4f sc = src;
1321 Sk4f dc = dst;
1322 Sk4f rc = sc + dc + (sc * (dc - da) - dc * sa) * inv255;
1323 // ra = srcover(sa, da), but the calc for rc happens to accomplish this for us
1324 return check_as_pmfloat(clamp_0_255(rc));
1325 }
XferMultiply4f1326 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1327 return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) +
1328 dst.mulWiden(src.alphas().inv()) +
1329 src.mulWiden(dst))
1330 .div255RoundNarrow();
1331 }
1332 static const bool kFoldCoverageIntoSrcAlpha = false;
1333 static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode;
1334 };
1335
1336 // [ sa + da - sa*da, sc + dc - 2*min(sc*da, dc*sa) ] (And notice sa*da == min(sa*da, da*sa).)
1337 struct Difference4f {
XferDifference4f1338 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1339 const Sk4f inv255(gInv255);
1340 Sk4f sa = Sk4f(src.a());
1341 Sk4f da = Sk4f(dst.a());
1342 Sk4f sc = src;
1343 Sk4f dc = dst;
1344 Sk4f min = Sk4f::Min(sc * da, dc * sa) * inv255;
1345 Sk4f ra = sc + dc - min;
1346 return check_as_pmfloat(ra - min * SkPMFloat(0, 1, 1, 1));
1347 }
XferDifference4f1348 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1349 auto m = Sk4px::Wide(Sk16h::Min(src.mulWiden(dst.alphas()), dst.mulWiden(src.alphas())))
1350 .div255RoundNarrow();
1351 // There's no chance of underflow, and if we subtract m before adding src+dst, no overflow.
1352 return (src - m) + (dst - m.zeroAlphas());
1353 }
1354 static const bool kFoldCoverageIntoSrcAlpha = false;
1355 static const SkXfermode::Mode kMode = SkXfermode::kDifference_Mode;
1356 };
1357
1358 // [ sa + da - sa*da, sc + dc - 2*sc*dc ]
1359 struct Exclusion4f {
XferExclusion4f1360 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1361 const Sk4f inv255(gInv255);
1362 Sk4f sc = src;
1363 Sk4f dc = dst;
1364 Sk4f prod = sc * dc * inv255;
1365 Sk4f ra = sc + dc - prod;
1366 return check_as_pmfloat(ra - prod * SkPMFloat(0, 1, 1, 1));
1367 }
XferExclusion4f1368 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1369 auto p = src.mulWiden(dst).div255RoundNarrow();
1370 // There's no chance of underflow, and if we subtract p before adding src+dst, no overflow.
1371 return (src - p) + (dst - p.zeroAlphas());
1372 }
1373 static const bool kFoldCoverageIntoSrcAlpha = false;
1374 static const SkXfermode::Mode kMode = SkXfermode::kExclusion_Mode;
1375 };
1376
1377 template <typename ProcType>
1378 class SkT4fXfermode : public SkProcCoeffXfermode {
1379 public:
Create(const ProcCoeff & rec)1380 static SkXfermode* Create(const ProcCoeff& rec) {
1381 return SkNEW_ARGS(SkT4fXfermode, (rec));
1382 }
1383
xfer32(SkPMColor dst[],const SkPMColor src[],int n,const SkAlpha aa[]) const1384 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
1385 if (NULL == aa) {
1386 for (int i = 0; i < n; ++i) {
1387 dst[i] = ProcType::Xfer(SkPMFloat(src[i]), SkPMFloat(dst[i])).round();
1388 }
1389 } else {
1390 for (int i = 0; i < n; ++i) {
1391 const Sk4f aa4 = Sk4f(aa[i] * gInv255);
1392 SkPMFloat dstF(dst[i]);
1393 SkPMFloat srcF(src[i]);
1394 Sk4f res;
1395 if (ProcType::kFoldCoverageIntoSrcAlpha) {
1396 Sk4f src4 = srcF;
1397 res = ProcType::Xfer(src4 * aa4, dstF);
1398 } else {
1399 res = ramp(dstF, ProcType::Xfer(srcF, dstF), aa4);
1400 }
1401 dst[i] = SkPMFloat(res).round();
1402 }
1403 }
1404 }
1405
1406 private:
SkT4fXfermode(const ProcCoeff & rec)1407 SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
1408
1409 typedef SkProcCoeffXfermode INHERITED;
1410 };
1411
1412 template <typename ProcType>
1413 class SkT4pxXfermode : public SkProcCoeffXfermode {
1414 public:
Create(const ProcCoeff & rec)1415 static SkXfermode* Create(const ProcCoeff& rec) {
1416 return SkNEW_ARGS(SkT4pxXfermode, (rec));
1417 }
1418
xfer32(SkPMColor dst[],const SkPMColor src[],int n,const SkAlpha aa[]) const1419 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
1420 if (NULL == aa) {
1421 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& src4) {
1422 return ProcType::Xfer(src4, dst4);
1423 });
1424 } else {
1425 Sk4px::MapDstSrcAlpha(n, dst, src, aa,
1426 [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha) {
1427 // We can't exploit kFoldCoverageIntoSrcAlpha. That requires >=24-bit intermediates.
1428 Sk4px res4 = ProcType::Xfer(src4, dst4);
1429 return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk4px(alpha).inv()))
1430 .div255RoundNarrow();
1431 });
1432 }
1433 }
1434
1435 private:
SkT4pxXfermode(const ProcCoeff & rec)1436 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
1437
1438 typedef SkProcCoeffXfermode INHERITED;
1439 };
1440
1441 ///////////////////////////////////////////////////////////////////////////////
1442
1443 class SkDstOutXfermode : public SkProcCoeffXfermode {
1444 public:
Create(const ProcCoeff & rec)1445 static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1446 return SkNEW_ARGS(SkDstOutXfermode, (rec));
1447 }
1448
1449 void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1450
1451 SK_TO_STRING_OVERRIDE()
1452
1453 private:
SkDstOutXfermode(const ProcCoeff & rec)1454 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1455
1456 typedef SkProcCoeffXfermode INHERITED;
1457 };
1458
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1459 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1460 const SkPMColor* SK_RESTRICT src, int count,
1461 const SkAlpha* SK_RESTRICT aa) const {
1462 SkASSERT(dst && src);
1463
1464 if (count <= 0) {
1465 return;
1466 }
1467 if (aa) {
1468 return this->INHERITED::xfer32(dst, src, count, aa);
1469 }
1470
1471 do {
1472 unsigned a = SkGetPackedA32(*src);
1473 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1474 dst++;
1475 src++;
1476 } while (--count != 0);
1477 }
1478
1479 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1480 void SkDstOutXfermode::toString(SkString* str) const {
1481 this->INHERITED::toString(str);
1482 }
1483 #endif
1484
1485 ///////////////////////////////////////////////////////////////////////////////
1486
1487 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1488 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1489
1490 // Technically, can't be static and passed as a template parameter. So we use anonymous namespace.
1491 namespace {
create_mode(int iMode)1492 SkXfermode* create_mode(int iMode) {
1493 SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1494
1495 ProcCoeff rec = gProcCoeffs[mode];
1496 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1497 if (pp != NULL) {
1498 rec.fProc = pp;
1499 }
1500
1501 #if defined(SK_4PX_XFERMODES_ARE_FAST) && !defined(SK_PREFER_LEGACY_FLOAT_XFERMODES)
1502 switch (mode) {
1503 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop4f>::Create(rec);
1504 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop4f>::Create(rec);
1505 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor4f>::Create(rec);
1506 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus4f>::Create(rec);
1507 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate4f>::Create(rec);
1508 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen4f>::Create(rec);
1509 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply4f>::Create(rec);
1510 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference4f>::Create(rec);
1511 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion4f>::Create(rec);
1512 default: break;
1513 }
1514 #endif
1515
1516 #if defined(SK_4F_XFERMODES_ARE_FAST)
1517 switch (mode) {
1518 case SkXfermode::kSrcATop_Mode: return SkT4fXfermode<SrcATop4f>::Create(rec);
1519 case SkXfermode::kDstATop_Mode: return SkT4fXfermode<DstATop4f>::Create(rec);
1520 case SkXfermode::kXor_Mode: return SkT4fXfermode<Xor4f>::Create(rec);
1521 case SkXfermode::kPlus_Mode: return SkT4fXfermode<Plus4f>::Create(rec);
1522 case SkXfermode::kModulate_Mode: return SkT4fXfermode<Modulate4f>::Create(rec);
1523 case SkXfermode::kScreen_Mode: return SkT4fXfermode<Screen4f>::Create(rec);
1524 case SkXfermode::kMultiply_Mode: return SkT4fXfermode<Multiply4f>::Create(rec);
1525 case SkXfermode::kDifference_Mode: return SkT4fXfermode<Difference4f>::Create(rec);
1526 case SkXfermode::kExclusion_Mode: return SkT4fXfermode<Exclusion4f>::Create(rec);
1527 default: break;
1528 }
1529 #endif
1530
1531 SkXfermode* xfer = NULL;
1532
1533 // check if we have a platform optim for that
1534 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1535 if (xfm != NULL) {
1536 xfer = xfm;
1537 } else {
1538 // All modes can in theory be represented by the ProcCoeff rec, since
1539 // it contains function ptrs. However, a few modes are both simple and
1540 // commonly used, so we call those out for their own subclasses here.
1541 switch (mode) {
1542 case SkXfermode::kClear_Mode:
1543 xfer = SkClearXfermode::Create(rec);
1544 break;
1545 case SkXfermode::kSrc_Mode:
1546 xfer = SkSrcXfermode::Create(rec);
1547 break;
1548 case SkXfermode::kSrcOver_Mode:
1549 SkASSERT(false); // should not land here
1550 break;
1551 case SkXfermode::kDstIn_Mode:
1552 xfer = SkDstInXfermode::Create(rec);
1553 break;
1554 case SkXfermode::kDstOut_Mode:
1555 xfer = SkDstOutXfermode::Create(rec);
1556 break;
1557 default:
1558 // no special-case, just rely in the rec and its function-ptrs
1559 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1560 break;
1561 }
1562 }
1563 return xfer;
1564 }
1565 } // namespace
1566
1567 SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1568
Create(Mode mode)1569 SkXfermode* SkXfermode::Create(Mode mode) {
1570 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1571
1572 if ((unsigned)mode >= kModeCount) {
1573 // report error
1574 return NULL;
1575 }
1576
1577 // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1578 // so we can just return NULL from the factory.
1579 if (kSrcOver_Mode == mode) {
1580 return NULL;
1581 }
1582
1583 return SkSafeRef(cached[mode]);
1584 }
1585
GetProc(Mode mode)1586 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1587 SkXfermodeProc proc = NULL;
1588 if ((unsigned)mode < kModeCount) {
1589 proc = gProcCoeffs[mode].fProc;
1590 }
1591 return proc;
1592 }
1593
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1594 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1595 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1596
1597 if ((unsigned)mode >= (unsigned)kModeCount) {
1598 // illegal mode parameter
1599 return false;
1600 }
1601
1602 const ProcCoeff& rec = gProcCoeffs[mode];
1603
1604 if (CANNOT_USE_COEFF == rec.fSC) {
1605 return false;
1606 }
1607
1608 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1609 if (src) {
1610 *src = rec.fSC;
1611 }
1612 if (dst) {
1613 *dst = rec.fDC;
1614 }
1615 return true;
1616 }
1617
AsMode(const SkXfermode * xfer,Mode * mode)1618 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1619 if (NULL == xfer) {
1620 if (mode) {
1621 *mode = kSrcOver_Mode;
1622 }
1623 return true;
1624 }
1625 return xfer->asMode(mode);
1626 }
1627
IsMode(const SkXfermode * xfer,Mode mode)1628 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1629 // if xfer==null then the mode is srcover
1630 Mode m = kSrcOver_Mode;
1631 if (xfer && !xfer->asMode(&m)) {
1632 return false;
1633 }
1634 return mode == m;
1635 }
1636
SupportsCoverageAsAlpha(const SkXfermode * xfer)1637 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1638 // if xfer is NULL we treat it as srcOver which always supports coverageAsAlpha
1639 if (!xfer) {
1640 return true;
1641 }
1642
1643 return xfer->supportsCoverageAsAlpha();
1644 }
1645
IsOpaque(const SkXfermode * xfer,SrcColorOpacity opacityType)1646 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1647 // if xfer is NULL we treat it as srcOver which is opaque if our src is opaque
1648 if (!xfer) {
1649 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1650 }
1651
1652 return xfer->isOpaque(opacityType);
1653 }
1654
1655 ///////////////////////////////////////////////////////////////////////////////
1656 //////////// 16bit xfermode procs
1657
1658 #ifdef SK_DEBUG
require_255(SkPMColor src)1659 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
require_0(SkPMColor src)1660 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1661 #endif
1662
src_modeproc16_255(SkPMColor src,uint16_t dst)1663 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1664 SkASSERT(require_255(src));
1665 return SkPixel32ToPixel16(src);
1666 }
1667
dst_modeproc16(SkPMColor src,uint16_t dst)1668 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1669 return dst;
1670 }
1671
srcover_modeproc16_0(SkPMColor src,uint16_t dst)1672 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1673 SkASSERT(require_0(src));
1674 return dst;
1675 }
1676
srcover_modeproc16_255(SkPMColor src,uint16_t dst)1677 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1678 SkASSERT(require_255(src));
1679 return SkPixel32ToPixel16(src);
1680 }
1681
dstover_modeproc16_0(SkPMColor src,uint16_t dst)1682 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1683 SkASSERT(require_0(src));
1684 return dst;
1685 }
1686
dstover_modeproc16_255(SkPMColor src,uint16_t dst)1687 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1688 SkASSERT(require_255(src));
1689 return dst;
1690 }
1691
srcin_modeproc16_255(SkPMColor src,uint16_t dst)1692 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1693 SkASSERT(require_255(src));
1694 return SkPixel32ToPixel16(src);
1695 }
1696
dstin_modeproc16_255(SkPMColor src,uint16_t dst)1697 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1698 SkASSERT(require_255(src));
1699 return dst;
1700 }
1701
dstout_modeproc16_0(SkPMColor src,uint16_t dst)1702 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1703 SkASSERT(require_0(src));
1704 return dst;
1705 }
1706
srcatop_modeproc16(SkPMColor src,uint16_t dst)1707 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1708 unsigned isa = 255 - SkGetPackedA32(src);
1709
1710 return SkPackRGB16(
1711 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1712 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1713 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1714 }
1715
srcatop_modeproc16_0(SkPMColor src,uint16_t dst)1716 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1717 SkASSERT(require_0(src));
1718 return dst;
1719 }
1720
srcatop_modeproc16_255(SkPMColor src,uint16_t dst)1721 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1722 SkASSERT(require_255(src));
1723 return SkPixel32ToPixel16(src);
1724 }
1725
dstatop_modeproc16_255(SkPMColor src,uint16_t dst)1726 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1727 SkASSERT(require_255(src));
1728 return dst;
1729 }
1730
1731 /*********
1732 darken and lighten boil down to this.
1733
1734 darken = (1 - Sa) * Dc + min(Sc, Dc)
1735 lighten = (1 - Sa) * Dc + max(Sc, Dc)
1736
1737 if (Sa == 0) these become
1738 darken = Dc + min(0, Dc) = 0
1739 lighten = Dc + max(0, Dc) = Dc
1740
1741 if (Sa == 1) these become
1742 darken = min(Sc, Dc)
1743 lighten = max(Sc, Dc)
1744 */
1745
darken_modeproc16_0(SkPMColor src,uint16_t dst)1746 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1747 SkASSERT(require_0(src));
1748 return 0;
1749 }
1750
darken_modeproc16_255(SkPMColor src,uint16_t dst)1751 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1752 SkASSERT(require_255(src));
1753 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1754 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1755 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1756 return SkPackRGB16(r, g, b);
1757 }
1758
lighten_modeproc16_0(SkPMColor src,uint16_t dst)1759 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1760 SkASSERT(require_0(src));
1761 return dst;
1762 }
1763
lighten_modeproc16_255(SkPMColor src,uint16_t dst)1764 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1765 SkASSERT(require_255(src));
1766 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1767 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1768 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1769 return SkPackRGB16(r, g, b);
1770 }
1771
1772 struct Proc16Rec {
1773 SkXfermodeProc16 fProc16_0;
1774 SkXfermodeProc16 fProc16_255;
1775 SkXfermodeProc16 fProc16_General;
1776 };
1777
1778 static const Proc16Rec gModeProcs16[] = {
1779 { NULL, NULL, NULL }, // CLEAR
1780 { NULL, src_modeproc16_255, NULL },
1781 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
1782 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
1783 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
1784 { NULL, srcin_modeproc16_255, NULL },
1785 { NULL, dstin_modeproc16_255, NULL },
1786 { NULL, NULL, NULL },// SRC_OUT
1787 { dstout_modeproc16_0, NULL, NULL },
1788 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
1789 { NULL, dstatop_modeproc16_255, NULL },
1790 { NULL, NULL, NULL }, // XOR
1791
1792 { NULL, NULL, NULL }, // plus
1793 { NULL, NULL, NULL }, // modulate
1794 { NULL, NULL, NULL }, // screen
1795 { NULL, NULL, NULL }, // overlay
1796 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken
1797 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten
1798 { NULL, NULL, NULL }, // colordodge
1799 { NULL, NULL, NULL }, // colorburn
1800 { NULL, NULL, NULL }, // hardlight
1801 { NULL, NULL, NULL }, // softlight
1802 { NULL, NULL, NULL }, // difference
1803 { NULL, NULL, NULL }, // exclusion
1804 { NULL, NULL, NULL }, // multiply
1805 { NULL, NULL, NULL }, // hue
1806 { NULL, NULL, NULL }, // saturation
1807 { NULL, NULL, NULL }, // color
1808 { NULL, NULL, NULL }, // luminosity
1809 };
1810
GetProc16(Mode mode,SkColor srcColor)1811 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1812 SkXfermodeProc16 proc16 = NULL;
1813 if ((unsigned)mode < kModeCount) {
1814 const Proc16Rec& rec = gModeProcs16[mode];
1815 unsigned a = SkColorGetA(srcColor);
1816
1817 if (0 == a) {
1818 proc16 = rec.fProc16_0;
1819 } else if (255 == a) {
1820 proc16 = rec.fProc16_255;
1821 } else {
1822 proc16 = rec.fProc16_General;
1823 }
1824 }
1825 return proc16;
1826 }
1827
1828 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1829 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1830 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1831