1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkXfermode.h"
9 #include "SkXfermode_proccoeff.h"
10 #include "SkColorPriv.h"
11 #include "SkMathPriv.h"
12 #include "SkOncePtr.h"
13 #include "SkOpts.h"
14 #include "SkReadBuffer.h"
15 #include "SkString.h"
16 #include "SkWriteBuffer.h"
17 #include "SkPM4f.h"
18
19 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
20
saturated_add(unsigned a,unsigned b)21 static inline unsigned saturated_add(unsigned a, unsigned b) {
22 SkASSERT(a <= 255);
23 SkASSERT(b <= 255);
24 unsigned sum = a + b;
25 if (sum > 255) {
26 sum = 255;
27 }
28 return sum;
29 }
30
clamp_signed_byte(int n)31 static inline int clamp_signed_byte(int n) {
32 if (n < 0) {
33 n = 0;
34 } else if (n > 255) {
35 n = 255;
36 }
37 return n;
38 }
39
clamp_div255round(int prod)40 static inline int clamp_div255round(int prod) {
41 if (prod <= 0) {
42 return 0;
43 } else if (prod >= 255*255) {
44 return 255;
45 } else {
46 return SkDiv255Round(prod);
47 }
48 }
49
50 ///////////////////////////////////////////////////////////////////////////////
51 #include "SkNx.h"
52
alpha(const Sk4f & color)53 static Sk4f alpha(const Sk4f& color) { return Sk4f(color[3]); }
inv_alpha(const Sk4f & color)54 static Sk4f inv_alpha(const Sk4f& color) { return Sk4f(1 - color[3]); }
pin_1(const Sk4f & value)55 static Sk4f pin_1(const Sk4f& value) { return Sk4f::Min(value, Sk4f(1)); }
56
color_alpha(const Sk4f & color,float newAlpha)57 static Sk4f color_alpha(const Sk4f& color, float newAlpha) {
58 return Sk4f(color[0], color[1], color[2], newAlpha);
59 }
color_alpha(const Sk4f & color,const Sk4f & newAlpha)60 static Sk4f color_alpha(const Sk4f& color, const Sk4f& newAlpha) {
61 return color_alpha(color, newAlpha[3]);
62 }
63
set_argb(float a,float r,float g,float b)64 static Sk4f set_argb(float a, float r, float g, float b) {
65 if (0 == SkPM4f::R) {
66 return Sk4f(r, g, b, a);
67 } else {
68 return Sk4f(b, g, r, a);
69 }
70 }
71
clear_4f(const Sk4f & s,const Sk4f & d)72 static Sk4f clear_4f(const Sk4f& s, const Sk4f& d) { return Sk4f(0); }
src_4f(const Sk4f & s,const Sk4f & d)73 static Sk4f src_4f(const Sk4f& s, const Sk4f& d) { return s; }
dst_4f(const Sk4f & s,const Sk4f & d)74 static Sk4f dst_4f(const Sk4f& s, const Sk4f& d) { return d; }
srcover_4f(const Sk4f & s,const Sk4f & d)75 static Sk4f srcover_4f(const Sk4f& s, const Sk4f& d) { return s + inv_alpha(s) * d; }
dstover_4f(const Sk4f & s,const Sk4f & d)76 static Sk4f dstover_4f(const Sk4f& s, const Sk4f& d) { return d + inv_alpha(d) * s; }
srcin_4f(const Sk4f & s,const Sk4f & d)77 static Sk4f srcin_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d); }
dstin_4f(const Sk4f & s,const Sk4f & d)78 static Sk4f dstin_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s); }
srcout_4f(const Sk4f & s,const Sk4f & d)79 static Sk4f srcout_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d); }
dstout_4f(const Sk4f & s,const Sk4f & d)80 static Sk4f dstout_4f(const Sk4f& s, const Sk4f& d) { return d * inv_alpha(s); }
srcatop_4f(const Sk4f & s,const Sk4f & d)81 static Sk4f srcatop_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d) + d * inv_alpha(s); }
dstatop_4f(const Sk4f & s,const Sk4f & d)82 static Sk4f dstatop_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s) + s * inv_alpha(d); }
xor_4f(const Sk4f & s,const Sk4f & d)83 static Sk4f xor_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d) + d * inv_alpha(s);}
plus_4f(const Sk4f & s,const Sk4f & d)84 static Sk4f plus_4f(const Sk4f& s, const Sk4f& d) { return pin_1(s + d); }
modulate_4f(const Sk4f & s,const Sk4f & d)85 static Sk4f modulate_4f(const Sk4f& s, const Sk4f& d) { return s * d; }
screen_4f(const Sk4f & s,const Sk4f & d)86 static Sk4f screen_4f(const Sk4f& s, const Sk4f& d) { return s + d - s * d; }
87
multiply_4f(const Sk4f & s,const Sk4f & d)88 static Sk4f multiply_4f(const Sk4f& s, const Sk4f& d) {
89 return s * inv_alpha(d) + d * inv_alpha(s) + s * d;
90 }
91
overlay_4f(const Sk4f & s,const Sk4f & d)92 static Sk4f overlay_4f(const Sk4f& s, const Sk4f& d) {
93 Sk4f sa = alpha(s);
94 Sk4f da = alpha(d);
95 Sk4f two = Sk4f(2);
96 Sk4f rc = (two * d <= da).thenElse(two * s * d,
97 sa * da - two * (da - d) * (sa - s));
98 return pin_1(s + d - s * da + color_alpha(rc - d * sa, 0));
99 }
100
hardlight_4f(const Sk4f & s,const Sk4f & d)101 static Sk4f hardlight_4f(const Sk4f& s, const Sk4f& d) {
102 return overlay_4f(d, s);
103 }
104
darken_4f(const Sk4f & s,const Sk4f & d)105 static Sk4f darken_4f(const Sk4f& s, const Sk4f& d) {
106 Sk4f sa = alpha(s);
107 Sk4f da = alpha(d);
108 return s + d - Sk4f::Max(s * da, d * sa);
109 }
110
lighten_4f(const Sk4f & s,const Sk4f & d)111 static Sk4f lighten_4f(const Sk4f& s, const Sk4f& d) {
112 Sk4f sa = alpha(s);
113 Sk4f da = alpha(d);
114 return s + d - Sk4f::Min(s * da, d * sa);
115 }
116
colordodge_4f(const Sk4f & s,const Sk4f & d)117 static Sk4f colordodge_4f(const Sk4f& s, const Sk4f& d) {
118 Sk4f sa = alpha(s);
119 Sk4f da = alpha(d);
120 Sk4f isa = Sk4f(1) - sa;
121 Sk4f ida = Sk4f(1) - da;
122
123 Sk4f srcover = s + d * isa;
124 Sk4f dstover = d + s * ida;
125 Sk4f otherwise = sa * Sk4f::Min(da, (d * sa) / (sa - s)) + s * ida + d * isa;
126
127 // Order matters here, preferring d==0 over s==sa.
128 auto colors = (d == Sk4f(0)).thenElse(dstover,
129 (s == sa).thenElse(srcover,
130 otherwise));
131 return color_alpha(colors, srcover);
132 }
133
colorburn_4f(const Sk4f & s,const Sk4f & d)134 static Sk4f colorburn_4f(const Sk4f& s, const Sk4f& d) {
135 Sk4f sa = alpha(s);
136 Sk4f da = alpha(d);
137 Sk4f isa = Sk4f(1) - sa;
138 Sk4f ida = Sk4f(1) - da;
139
140 Sk4f srcover = s + d * isa;
141 Sk4f dstover = d + s * ida;
142 Sk4f otherwise = sa * (da - Sk4f::Min(da, (da - d) * sa / s)) + s * ida + d * isa;
143
144 // Order matters here, preferring d==da over s==0.
145 auto colors = (d == da).thenElse(dstover,
146 (s == Sk4f(0)).thenElse(srcover,
147 otherwise));
148 return color_alpha(colors, srcover);
149 }
150
softlight_4f(const Sk4f & s,const Sk4f & d)151 static Sk4f softlight_4f(const Sk4f& s, const Sk4f& d) {
152 Sk4f sa = alpha(s);
153 Sk4f da = alpha(d);
154 Sk4f isa = Sk4f(1) - sa;
155 Sk4f ida = Sk4f(1) - da;
156
157 // Some common terms.
158 Sk4f m = (da > Sk4f(0)).thenElse(d / da, Sk4f(0));
159 Sk4f s2 = Sk4f(2) * s;
160 Sk4f m4 = Sk4f(4) * m;
161
162 // The logic forks three ways:
163 // 1. dark src?
164 // 2. light src, dark dst?
165 // 3. light src, light dst?
166 Sk4f darkSrc = d * (sa + (s2 - sa) * (Sk4f(1) - m)); // Used in case 1.
167 Sk4f darkDst = (m4 * m4 + m4) * (m - Sk4f(1)) + Sk4f(7) * m; // Used in case 2.
168 Sk4f liteDst = m.sqrt() - m; // Used in case 3.
169 Sk4f liteSrc = d * sa + da * (s2 - sa) * (Sk4f(4) * d <= da).thenElse(darkDst,
170 liteDst); // Case 2 or 3?
171
172 return color_alpha(s * ida + d * isa + (s2 <= sa).thenElse(darkSrc, liteSrc), // Case 1 or 2/3?
173 s + d * isa);
174 }
175
difference_4f(const Sk4f & s,const Sk4f & d)176 static Sk4f difference_4f(const Sk4f& s, const Sk4f& d) {
177 Sk4f min = Sk4f::Min(s * alpha(d), d * alpha(s));
178 return s + d - min - color_alpha(min, 0);
179 }
180
exclusion_4f(const Sk4f & s,const Sk4f & d)181 static Sk4f exclusion_4f(const Sk4f& s, const Sk4f& d) {
182 Sk4f product = s * d;
183 return s + d - product - color_alpha(product, 0);
184 }
185
186 ////////////////////////////////////////////////////
187
188 // The CSS compositing spec introduces the following formulas:
189 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
190 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
191 // while PDF and CG uses the one from Rec. Rec. 601
192 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
Lum(float r,float g,float b)193 static inline float Lum(float r, float g, float b) {
194 return r * 0.2126f + g * 0.7152f + b * 0.0722f;
195 }
196
max(float a,float b,float c)197 static inline float max(float a, float b, float c) {
198 return SkTMax(a, SkTMax(b, c));
199 }
200
min(float a,float b,float c)201 static inline float min(float a, float b, float c) {
202 return SkTMin(a, SkTMin(b, c));
203 }
204
Sat(float r,float g,float b)205 static inline float Sat(float r, float g, float b) {
206 return max(r, g, b) - min(r, g, b);
207 }
208
setSaturationComponents(float * Cmin,float * Cmid,float * Cmax,float s)209 static inline void setSaturationComponents(float* Cmin, float* Cmid, float* Cmax, float s) {
210 if(*Cmax > *Cmin) {
211 *Cmid = (*Cmid - *Cmin) * s / (*Cmax - *Cmin);
212 *Cmax = s;
213 } else {
214 *Cmax = 0;
215 *Cmid = 0;
216 }
217 *Cmin = 0;
218 }
219
SetSat(float * r,float * g,float * b,float s)220 static inline void SetSat(float* r, float* g, float* b, float s) {
221 if(*r <= *g) {
222 if(*g <= *b) {
223 setSaturationComponents(r, g, b, s);
224 } else if(*r <= *b) {
225 setSaturationComponents(r, b, g, s);
226 } else {
227 setSaturationComponents(b, r, g, s);
228 }
229 } else if(*r <= *b) {
230 setSaturationComponents(g, r, b, s);
231 } else if(*g <= *b) {
232 setSaturationComponents(g, b, r, s);
233 } else {
234 setSaturationComponents(b, g, r, s);
235 }
236 }
237
clipColor(float * r,float * g,float * b,float a)238 static inline void clipColor(float* r, float* g, float* b, float a) {
239 float L = Lum(*r, *g, *b);
240 float n = min(*r, *g, *b);
241 float x = max(*r, *g, *b);
242 float denom;
243 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
244 float scale = L / denom;
245 *r = L + (*r - L) * scale;
246 *g = L + (*g - L) * scale;
247 *b = L + (*b - L) * scale;
248 }
249
250 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
251 float scale = (a - L) / denom;
252 *r = L + (*r - L) * scale;
253 *g = L + (*g - L) * scale;
254 *b = L + (*b - L) * scale;
255 }
256 }
257
SetLum(float * r,float * g,float * b,float a,float l)258 static inline void SetLum(float* r, float* g, float* b, float a, float l) {
259 float d = l - Lum(*r, *g, *b);
260 *r += d;
261 *g += d;
262 *b += d;
263 clipColor(r, g, b, a);
264 }
265
hue_4f(const Sk4f & s,const Sk4f & d)266 static Sk4f hue_4f(const Sk4f& s, const Sk4f& d) {
267 float sa = s[SkPM4f::A];
268 float sr = s[SkPM4f::R];
269 float sg = s[SkPM4f::G];
270 float sb = s[SkPM4f::B];
271
272 float da = d[SkPM4f::A];
273 float dr = d[SkPM4f::R];
274 float dg = d[SkPM4f::G];
275 float db = d[SkPM4f::B];
276
277 float Sr = sr;
278 float Sg = sg;
279 float Sb = sb;
280 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
281 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
282
283 return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
284 sa + da - sa * da);
285 }
286
saturation_4f(const Sk4f & s,const Sk4f & d)287 static Sk4f saturation_4f(const Sk4f& s, const Sk4f& d) {
288 float sa = s[SkPM4f::A];
289 float sr = s[SkPM4f::R];
290 float sg = s[SkPM4f::G];
291 float sb = s[SkPM4f::B];
292
293 float da = d[SkPM4f::A];
294 float dr = d[SkPM4f::R];
295 float dg = d[SkPM4f::G];
296 float db = d[SkPM4f::B];
297
298 float Dr = dr;
299 float Dg = dg;
300 float Db = db;
301 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
302 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
303
304 return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
305 sa + da - sa * da);
306 }
307
color_4f(const Sk4f & s,const Sk4f & d)308 static Sk4f color_4f(const Sk4f& s, const Sk4f& d) {
309 float sa = s[SkPM4f::A];
310 float sr = s[SkPM4f::R];
311 float sg = s[SkPM4f::G];
312 float sb = s[SkPM4f::B];
313
314 float da = d[SkPM4f::A];
315 float dr = d[SkPM4f::R];
316 float dg = d[SkPM4f::G];
317 float db = d[SkPM4f::B];
318
319 float Sr = sr;
320 float Sg = sg;
321 float Sb = sb;
322 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
323
324 Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
325 sa + da - sa * da);
326 // Can return tiny negative values ...
327 return Sk4f::Max(res, Sk4f(0));
328 }
329
luminosity_4f(const Sk4f & s,const Sk4f & d)330 static Sk4f luminosity_4f(const Sk4f& s, const Sk4f& d) {
331 float sa = s[SkPM4f::A];
332 float sr = s[SkPM4f::R];
333 float sg = s[SkPM4f::G];
334 float sb = s[SkPM4f::B];
335
336 float da = d[SkPM4f::A];
337 float dr = d[SkPM4f::R];
338 float dg = d[SkPM4f::G];
339 float db = d[SkPM4f::B];
340
341 float Dr = dr;
342 float Dg = dg;
343 float Db = db;
344 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
345
346 Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
347 sa + da - sa * da);
348 // Can return tiny negative values ...
349 return Sk4f::Max(res, Sk4f(0));
350 }
351
352 ///////////////////////////////////////////////////////////////////////////////
353
354 // kClear_Mode, //!< [0, 0]
clear_modeproc(SkPMColor src,SkPMColor dst)355 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
356 return 0;
357 }
358
359 // kSrc_Mode, //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)360 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
361 return src;
362 }
363
364 // kDst_Mode, //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)365 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
366 return dst;
367 }
368
369 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
srcover_modeproc(SkPMColor src,SkPMColor dst)370 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
371 #if 0
372 // this is the old, more-correct way, but it doesn't guarantee that dst==255
373 // will always stay opaque
374 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
375 #else
376 // this is slightly faster, but more importantly guarantees that dst==255
377 // will always stay opaque
378 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
379 #endif
380 }
381
382 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
dstover_modeproc(SkPMColor src,SkPMColor dst)383 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
384 // this is the reverse of srcover, just flipping src and dst
385 // see srcover's comment about the 256 for opaqueness guarantees
386 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
387 }
388
389 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
srcin_modeproc(SkPMColor src,SkPMColor dst)390 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
391 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
392 }
393
394 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
dstin_modeproc(SkPMColor src,SkPMColor dst)395 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
396 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
397 }
398
399 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
srcout_modeproc(SkPMColor src,SkPMColor dst)400 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
401 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
402 }
403
404 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
dstout_modeproc(SkPMColor src,SkPMColor dst)405 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
406 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
407 }
408
409 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
srcatop_modeproc(SkPMColor src,SkPMColor dst)410 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
411 unsigned sa = SkGetPackedA32(src);
412 unsigned da = SkGetPackedA32(dst);
413 unsigned isa = 255 - sa;
414
415 return SkPackARGB32(da,
416 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
417 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
418 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
419 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
420 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
421 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
422 }
423
424 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)425 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
426 unsigned sa = SkGetPackedA32(src);
427 unsigned da = SkGetPackedA32(dst);
428 unsigned ida = 255 - da;
429
430 return SkPackARGB32(sa,
431 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
432 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
433 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
434 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
435 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
436 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
437 }
438
439 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
xor_modeproc(SkPMColor src,SkPMColor dst)440 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
441 unsigned sa = SkGetPackedA32(src);
442 unsigned da = SkGetPackedA32(dst);
443 unsigned isa = 255 - sa;
444 unsigned ida = 255 - da;
445
446 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
447 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
448 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
449 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
450 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
451 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
452 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
453 }
454
455 ///////////////////////////////////////////////////////////////////////////////
456
457 // kPlus_Mode
plus_modeproc(SkPMColor src,SkPMColor dst)458 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
459 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
460 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
461 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
462 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
463 return SkPackARGB32(a, r, g, b);
464 }
465
466 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)467 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
468 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
469 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
470 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
471 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
472 return SkPackARGB32(a, r, g, b);
473 }
474
srcover_byte(int a,int b)475 static inline int srcover_byte(int a, int b) {
476 return a + b - SkAlphaMulAlpha(a, b);
477 }
478
479 // kMultiply_Mode
480 // B(Cb, Cs) = Cb x Cs
481 // 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)482 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
483 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
484 }
485
multiply_modeproc(SkPMColor src,SkPMColor dst)486 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
487 int sa = SkGetPackedA32(src);
488 int da = SkGetPackedA32(dst);
489 int a = srcover_byte(sa, da);
490 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
491 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
492 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
493 return SkPackARGB32(a, r, g, b);
494 }
495
496 // kScreen_Mode
screen_modeproc(SkPMColor src,SkPMColor dst)497 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
498 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
499 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
500 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
501 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
502 return SkPackARGB32(a, r, g, b);
503 }
504
505 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)506 static inline int overlay_byte(int sc, int dc, int sa, int da) {
507 int tmp = sc * (255 - da) + dc * (255 - sa);
508 int rc;
509 if (2 * dc <= da) {
510 rc = 2 * sc * dc;
511 } else {
512 rc = sa * da - 2 * (da - dc) * (sa - sc);
513 }
514 return clamp_div255round(rc + tmp);
515 }
overlay_modeproc(SkPMColor src,SkPMColor dst)516 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
517 int sa = SkGetPackedA32(src);
518 int da = SkGetPackedA32(dst);
519 int a = srcover_byte(sa, da);
520 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
521 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
522 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
523 return SkPackARGB32(a, r, g, b);
524 }
525
526 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)527 static inline int darken_byte(int sc, int dc, int sa, int da) {
528 int sd = sc * da;
529 int ds = dc * sa;
530 if (sd < ds) {
531 // srcover
532 return sc + dc - SkDiv255Round(ds);
533 } else {
534 // dstover
535 return dc + sc - SkDiv255Round(sd);
536 }
537 }
darken_modeproc(SkPMColor src,SkPMColor dst)538 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
539 int sa = SkGetPackedA32(src);
540 int da = SkGetPackedA32(dst);
541 int a = srcover_byte(sa, da);
542 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
543 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
544 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
545 return SkPackARGB32(a, r, g, b);
546 }
547
548 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)549 static inline int lighten_byte(int sc, int dc, int sa, int da) {
550 int sd = sc * da;
551 int ds = dc * sa;
552 if (sd > ds) {
553 // srcover
554 return sc + dc - SkDiv255Round(ds);
555 } else {
556 // dstover
557 return dc + sc - SkDiv255Round(sd);
558 }
559 }
lighten_modeproc(SkPMColor src,SkPMColor dst)560 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
561 int sa = SkGetPackedA32(src);
562 int da = SkGetPackedA32(dst);
563 int a = srcover_byte(sa, da);
564 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
565 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
566 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
567 return SkPackARGB32(a, r, g, b);
568 }
569
570 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)571 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
572 int diff = sa - sc;
573 int rc;
574 if (0 == dc) {
575 return SkAlphaMulAlpha(sc, 255 - da);
576 } else if (0 == diff) {
577 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
578 } else {
579 diff = dc * sa / diff;
580 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
581 }
582 return clamp_div255round(rc);
583 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)584 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
585 int sa = SkGetPackedA32(src);
586 int da = SkGetPackedA32(dst);
587 int a = srcover_byte(sa, da);
588 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
589 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
590 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
591 return SkPackARGB32(a, r, g, b);
592 }
593
594 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)595 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
596 int rc;
597 if (dc == da) {
598 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
599 } else if (0 == sc) {
600 return SkAlphaMulAlpha(dc, 255 - sa);
601 } else {
602 int tmp = (da - dc) * sa / sc;
603 rc = sa * (da - ((da < tmp) ? da : tmp))
604 + sc * (255 - da) + dc * (255 - sa);
605 }
606 return clamp_div255round(rc);
607 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)608 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
609 int sa = SkGetPackedA32(src);
610 int da = SkGetPackedA32(dst);
611 int a = srcover_byte(sa, da);
612 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
613 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
614 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
615 return SkPackARGB32(a, r, g, b);
616 }
617
618 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)619 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
620 int rc;
621 if (2 * sc <= sa) {
622 rc = 2 * sc * dc;
623 } else {
624 rc = sa * da - 2 * (da - dc) * (sa - sc);
625 }
626 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
627 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)628 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
629 int sa = SkGetPackedA32(src);
630 int da = SkGetPackedA32(dst);
631 int a = srcover_byte(sa, da);
632 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
633 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
634 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
635 return SkPackARGB32(a, r, g, b);
636 }
637
638 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)639 static U8CPU sqrt_unit_byte(U8CPU n) {
640 return SkSqrtBits(n, 15+4);
641 }
642
643 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)644 static inline int softlight_byte(int sc, int dc, int sa, int da) {
645 int m = da ? dc * 256 / da : 0;
646 int rc;
647 if (2 * sc <= sa) {
648 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
649 } else if (4 * dc <= da) {
650 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
651 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
652 } else {
653 int tmp = sqrt_unit_byte(m) - m;
654 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
655 }
656 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
657 }
softlight_modeproc(SkPMColor src,SkPMColor dst)658 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
659 int sa = SkGetPackedA32(src);
660 int da = SkGetPackedA32(dst);
661 int a = srcover_byte(sa, da);
662 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
663 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
664 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
665 return SkPackARGB32(a, r, g, b);
666 }
667
668 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)669 static inline int difference_byte(int sc, int dc, int sa, int da) {
670 int tmp = SkMin32(sc * da, dc * sa);
671 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
672 }
difference_modeproc(SkPMColor src,SkPMColor dst)673 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
674 int sa = SkGetPackedA32(src);
675 int da = SkGetPackedA32(dst);
676 int a = srcover_byte(sa, da);
677 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
678 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
679 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
680 return SkPackARGB32(a, r, g, b);
681 }
682
683 // kExclusion_Mode
exclusion_byte(int sc,int dc,int,int)684 static inline int exclusion_byte(int sc, int dc, int, int) {
685 // this equations is wacky, wait for SVG to confirm it
686 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
687
688 // The above equation can be simplified as follows
689 int r = 255*(sc + dc) - 2 * sc * dc;
690 return clamp_div255round(r);
691 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)692 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
693 int sa = SkGetPackedA32(src);
694 int da = SkGetPackedA32(dst);
695 int a = srcover_byte(sa, da);
696 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
697 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
698 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
699 return SkPackARGB32(a, r, g, b);
700 }
701
702 // The CSS compositing spec introduces the following formulas:
703 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
704 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
705 // while PDF and CG uses the one from Rec. Rec. 601
706 // 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)707 static inline int Lum(int r, int g, int b)
708 {
709 return SkDiv255Round(r * 77 + g * 150 + b * 28);
710 }
711
min2(int a,int b)712 static inline int min2(int a, int b) { return a < b ? a : b; }
max2(int a,int b)713 static inline int max2(int a, int b) { return a > b ? a : b; }
714 #define minimum(a, b, c) min2(min2(a, b), c)
715 #define maximum(a, b, c) max2(max2(a, b), c)
716
Sat(int r,int g,int b)717 static inline int Sat(int r, int g, int b) {
718 return maximum(r, g, b) - minimum(r, g, b);
719 }
720
setSaturationComponents(int * Cmin,int * Cmid,int * Cmax,int s)721 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
722 if(*Cmax > *Cmin) {
723 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
724 *Cmax = s;
725 } else {
726 *Cmax = 0;
727 *Cmid = 0;
728 }
729
730 *Cmin = 0;
731 }
732
SetSat(int * r,int * g,int * b,int s)733 static inline void SetSat(int* r, int* g, int* b, int s) {
734 if(*r <= *g) {
735 if(*g <= *b) {
736 setSaturationComponents(r, g, b, s);
737 } else if(*r <= *b) {
738 setSaturationComponents(r, b, g, s);
739 } else {
740 setSaturationComponents(b, r, g, s);
741 }
742 } else if(*r <= *b) {
743 setSaturationComponents(g, r, b, s);
744 } else if(*g <= *b) {
745 setSaturationComponents(g, b, r, s);
746 } else {
747 setSaturationComponents(b, g, r, s);
748 }
749 }
750
clipColor(int * r,int * g,int * b,int a)751 static inline void clipColor(int* r, int* g, int* b, int a) {
752 int L = Lum(*r, *g, *b);
753 int n = minimum(*r, *g, *b);
754 int x = maximum(*r, *g, *b);
755 int denom;
756 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
757 *r = L + SkMulDiv(*r - L, L, denom);
758 *g = L + SkMulDiv(*g - L, L, denom);
759 *b = L + SkMulDiv(*b - L, L, denom);
760 }
761
762 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
763 int numer = a - L;
764 *r = L + SkMulDiv(*r - L, numer, denom);
765 *g = L + SkMulDiv(*g - L, numer, denom);
766 *b = L + SkMulDiv(*b - L, numer, denom);
767 }
768 }
769
SetLum(int * r,int * g,int * b,int a,int l)770 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
771 int d = l - Lum(*r, *g, *b);
772 *r += d;
773 *g += d;
774 *b += d;
775
776 clipColor(r, g, b, a);
777 }
778
779 // non-separable blend modes are done in non-premultiplied alpha
780 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
781 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
782
783 // kHue_Mode
784 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
785 // 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)786 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
787 int sr = SkGetPackedR32(src);
788 int sg = SkGetPackedG32(src);
789 int sb = SkGetPackedB32(src);
790 int sa = SkGetPackedA32(src);
791
792 int dr = SkGetPackedR32(dst);
793 int dg = SkGetPackedG32(dst);
794 int db = SkGetPackedB32(dst);
795 int da = SkGetPackedA32(dst);
796 int Sr, Sg, Sb;
797
798 if(sa && da) {
799 Sr = sr * sa;
800 Sg = sg * sa;
801 Sb = sb * sa;
802 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
803 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
804 } else {
805 Sr = 0;
806 Sg = 0;
807 Sb = 0;
808 }
809
810 int a = srcover_byte(sa, da);
811 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
812 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
813 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
814 return SkPackARGB32(a, r, g, b);
815 }
816
817 // kSaturation_Mode
818 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
819 // 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)820 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
821 int sr = SkGetPackedR32(src);
822 int sg = SkGetPackedG32(src);
823 int sb = SkGetPackedB32(src);
824 int sa = SkGetPackedA32(src);
825
826 int dr = SkGetPackedR32(dst);
827 int dg = SkGetPackedG32(dst);
828 int db = SkGetPackedB32(dst);
829 int da = SkGetPackedA32(dst);
830 int Dr, Dg, Db;
831
832 if(sa && da) {
833 Dr = dr * sa;
834 Dg = dg * sa;
835 Db = db * sa;
836 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
837 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
838 } else {
839 Dr = 0;
840 Dg = 0;
841 Db = 0;
842 }
843
844 int a = srcover_byte(sa, da);
845 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
846 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
847 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
848 return SkPackARGB32(a, r, g, b);
849 }
850
851 // kColor_Mode
852 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
853 // 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)854 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
855 int sr = SkGetPackedR32(src);
856 int sg = SkGetPackedG32(src);
857 int sb = SkGetPackedB32(src);
858 int sa = SkGetPackedA32(src);
859
860 int dr = SkGetPackedR32(dst);
861 int dg = SkGetPackedG32(dst);
862 int db = SkGetPackedB32(dst);
863 int da = SkGetPackedA32(dst);
864 int Sr, Sg, Sb;
865
866 if(sa && da) {
867 Sr = sr * da;
868 Sg = sg * da;
869 Sb = sb * da;
870 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
871 } else {
872 Sr = 0;
873 Sg = 0;
874 Sb = 0;
875 }
876
877 int a = srcover_byte(sa, da);
878 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
879 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
880 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
881 return SkPackARGB32(a, r, g, b);
882 }
883
884 // kLuminosity_Mode
885 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
886 // 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)887 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
888 int sr = SkGetPackedR32(src);
889 int sg = SkGetPackedG32(src);
890 int sb = SkGetPackedB32(src);
891 int sa = SkGetPackedA32(src);
892
893 int dr = SkGetPackedR32(dst);
894 int dg = SkGetPackedG32(dst);
895 int db = SkGetPackedB32(dst);
896 int da = SkGetPackedA32(dst);
897 int Dr, Dg, Db;
898
899 if(sa && da) {
900 Dr = dr * sa;
901 Dg = dg * sa;
902 Db = db * sa;
903 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
904 } else {
905 Dr = 0;
906 Dg = 0;
907 Db = 0;
908 }
909
910 int a = srcover_byte(sa, da);
911 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
912 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
913 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
914 return SkPackARGB32(a, r, g, b);
915 }
916
917 ///////////////////////////////////////////////////////////////////////////////////////////////////
918
as_pm4f(const Sk4f & x)919 static SkPM4f as_pm4f(const Sk4f& x) {
920 SkPM4f pm4;
921 x.store(pm4.fVec);
922 return pm4;
923 }
924
as_4f(const SkPM4f & pm4)925 static Sk4f as_4f(const SkPM4f& pm4) {
926 return Sk4f::Load(pm4.fVec);
927 }
928
assert_unit(const SkPM4f & r)929 static void assert_unit(const SkPM4f& r) {
930 #ifdef SK_DEBUG
931 const float eps = 0.00001f;
932 const float min = 0 - eps;
933 const float max = 1 + eps;
934 for (int i = 0; i < 4; ++i) {
935 SkASSERT(r.fVec[i] >= min && r.fVec[i] <= max);
936 }
937 #endif
938 }
939
proc_4f(const SkPM4f & s,const SkPM4f & d)940 template <Sk4f (blend)(const Sk4f&, const Sk4f&)> SkPM4f proc_4f(const SkPM4f& s, const SkPM4f& d) {
941 assert_unit(s);
942 assert_unit(d);
943 SkPM4f r = as_pm4f(blend(as_4f(s), as_4f(d)));
944 assert_unit(r);
945 return r;
946 }
947
948 const ProcCoeff gProcCoeffs[] = {
949 { clear_modeproc, proc_4f<clear_4f>, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
950 { src_modeproc, proc_4f<src_4f>, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
951 { dst_modeproc, proc_4f<dst_4f>, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
952 { srcover_modeproc, proc_4f<srcover_4f>, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
953 { dstover_modeproc, proc_4f<dstover_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
954 { srcin_modeproc, proc_4f<srcin_4f>, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
955 { dstin_modeproc, proc_4f<dstin_4f>, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
956 { srcout_modeproc, proc_4f<srcout_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
957 { dstout_modeproc, proc_4f<dstout_4f>, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
958 { srcatop_modeproc, proc_4f<srcatop_4f>, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
959 { dstatop_modeproc, proc_4f<dstatop_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
960 { xor_modeproc, proc_4f<xor_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
961
962 { plus_modeproc, proc_4f<plus_4f>, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
963 { modulate_modeproc, proc_4f<modulate_4f>, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
964 { screen_modeproc, proc_4f<screen_4f>, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
965 { overlay_modeproc, proc_4f<overlay_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
966 { darken_modeproc, proc_4f<darken_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
967 { lighten_modeproc, proc_4f<lighten_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
968 { colordodge_modeproc, proc_4f<colordodge_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
969 { colorburn_modeproc, proc_4f<colorburn_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
970 { hardlight_modeproc, proc_4f<hardlight_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
971 { softlight_modeproc, proc_4f<softlight_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
972 { difference_modeproc, proc_4f<difference_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
973 { exclusion_modeproc, proc_4f<exclusion_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
974 { multiply_modeproc, proc_4f<multiply_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
975 { hue_modeproc, proc_4f<hue_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
976 { saturation_modeproc, proc_4f<saturation_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
977 { color_modeproc, proc_4f<color_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
978 { luminosity_modeproc, proc_4f<luminosity_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
979 };
980
981 ///////////////////////////////////////////////////////////////////////////////
982
asMode(Mode * mode) const983 bool SkXfermode::asMode(Mode* mode) const {
984 return false;
985 }
986
987 #if SK_SUPPORT_GPU
getFragmentProcessorForImageFilter(const GrFragmentProcessor *) const988 const GrFragmentProcessor* SkXfermode::getFragmentProcessorForImageFilter(
989 const GrFragmentProcessor*) const {
990 // This should never be called.
991 // TODO: make pure virtual in SkXfermode once Android update lands
992 SkASSERT(0);
993 return nullptr;
994 }
995
asXPFactory() const996 GrXPFactory* SkXfermode::asXPFactory() const {
997 // This should never be called.
998 // TODO: make pure virtual in SkXfermode once Android update lands
999 SkASSERT(0);
1000 return nullptr;
1001 }
1002 #endif
1003
xferColor(SkPMColor src,SkPMColor dst) const1004 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
1005 // no-op. subclasses should override this
1006 return dst;
1007 }
1008
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1009 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1010 const SkPMColor* SK_RESTRICT src, int count,
1011 const SkAlpha* SK_RESTRICT aa) const {
1012 SkASSERT(dst && src && count >= 0);
1013
1014 if (nullptr == aa) {
1015 for (int i = count - 1; i >= 0; --i) {
1016 dst[i] = this->xferColor(src[i], dst[i]);
1017 }
1018 } else {
1019 for (int i = count - 1; i >= 0; --i) {
1020 unsigned a = aa[i];
1021 if (0 != a) {
1022 SkPMColor dstC = dst[i];
1023 SkPMColor C = this->xferColor(src[i], dstC);
1024 if (0xFF != a) {
1025 C = SkFourByteInterp(C, dstC, a);
1026 }
1027 dst[i] = C;
1028 }
1029 }
1030 }
1031 }
1032
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1033 void SkXfermode::xfer16(uint16_t* dst,
1034 const SkPMColor* SK_RESTRICT src, int count,
1035 const SkAlpha* SK_RESTRICT aa) const {
1036 SkASSERT(dst && src && count >= 0);
1037
1038 if (nullptr == aa) {
1039 for (int i = count - 1; i >= 0; --i) {
1040 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1041 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
1042 }
1043 } else {
1044 for (int i = count - 1; i >= 0; --i) {
1045 unsigned a = aa[i];
1046 if (0 != a) {
1047 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1048 SkPMColor C = this->xferColor(src[i], dstC);
1049 if (0xFF != a) {
1050 C = SkFourByteInterp(C, dstC, a);
1051 }
1052 dst[i] = SkPixel32ToPixel16_ToU16(C);
1053 }
1054 }
1055 }
1056 }
1057
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const1058 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1059 const SkPMColor src[], int count,
1060 const SkAlpha* SK_RESTRICT aa) const {
1061 SkASSERT(dst && src && count >= 0);
1062
1063 if (nullptr == aa) {
1064 for (int i = count - 1; i >= 0; --i) {
1065 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
1066 dst[i] = SkToU8(SkGetPackedA32(res));
1067 }
1068 } else {
1069 for (int i = count - 1; i >= 0; --i) {
1070 unsigned a = aa[i];
1071 if (0 != a) {
1072 SkAlpha dstA = dst[i];
1073 unsigned A = SkGetPackedA32(this->xferColor(src[i],
1074 (SkPMColor)(dstA << SK_A32_SHIFT)));
1075 if (0xFF != a) {
1076 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1077 }
1078 dst[i] = SkToU8(A);
1079 }
1080 }
1081 }
1082 }
1083
supportsCoverageAsAlpha() const1084 bool SkXfermode::supportsCoverageAsAlpha() const {
1085 return false;
1086 }
1087
isOpaque(SkXfermode::SrcColorOpacity opacityType) const1088 bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
1089 return false;
1090 }
1091
1092 ///////////////////////////////////////////////////////////////////////////////
1093 ///////////////////////////////////////////////////////////////////////////////
1094
CreateProc(SkReadBuffer & buffer)1095 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
1096 uint32_t mode32 = buffer.read32();
1097 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
1098 return nullptr;
1099 }
1100 return SkXfermode::Create((SkXfermode::Mode)mode32);
1101 }
1102
flatten(SkWriteBuffer & buffer) const1103 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1104 buffer.write32(fMode);
1105 }
1106
asMode(Mode * mode) const1107 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1108 if (mode) {
1109 *mode = fMode;
1110 }
1111 return true;
1112 }
1113
supportsCoverageAsAlpha() const1114 bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
1115 if (CANNOT_USE_COEFF == fSrcCoeff) {
1116 return false;
1117 }
1118
1119 switch (fDstCoeff) {
1120 case SkXfermode::kOne_Coeff:
1121 case SkXfermode::kISA_Coeff:
1122 case SkXfermode::kISC_Coeff:
1123 return true;
1124 default:
1125 return false;
1126 }
1127 }
1128
isOpaque(SkXfermode::SrcColorOpacity opacityType) const1129 bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
1130 if (CANNOT_USE_COEFF == fSrcCoeff) {
1131 return false;
1132 }
1133
1134 if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
1135 SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
1136 return false;
1137 }
1138
1139 switch (fDstCoeff) {
1140 case SkXfermode::kZero_Coeff:
1141 return true;
1142 case SkXfermode::kISA_Coeff:
1143 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1144 case SkXfermode::kSA_Coeff:
1145 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
1146 SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
1147 case SkXfermode::kSC_Coeff:
1148 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
1149 default:
1150 return false;
1151 }
1152
1153 }
1154
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1155 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1156 const SkPMColor* SK_RESTRICT src, int count,
1157 const SkAlpha* SK_RESTRICT aa) const {
1158 SkASSERT(dst && src && count >= 0);
1159
1160 SkXfermodeProc proc = fProc;
1161
1162 if (proc) {
1163 if (nullptr == aa) {
1164 for (int i = count - 1; i >= 0; --i) {
1165 dst[i] = proc(src[i], dst[i]);
1166 }
1167 } else {
1168 for (int i = count - 1; i >= 0; --i) {
1169 unsigned a = aa[i];
1170 if (0 != a) {
1171 SkPMColor dstC = dst[i];
1172 SkPMColor C = proc(src[i], dstC);
1173 if (a != 0xFF) {
1174 C = SkFourByteInterp(C, dstC, a);
1175 }
1176 dst[i] = C;
1177 }
1178 }
1179 }
1180 }
1181 }
1182
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1183 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1184 const SkPMColor* SK_RESTRICT src, int count,
1185 const SkAlpha* SK_RESTRICT aa) const {
1186 SkASSERT(dst && src && count >= 0);
1187
1188 SkXfermodeProc proc = fProc;
1189
1190 if (proc) {
1191 if (nullptr == aa) {
1192 for (int i = count - 1; i >= 0; --i) {
1193 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1194 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1195 }
1196 } else {
1197 for (int i = count - 1; i >= 0; --i) {
1198 unsigned a = aa[i];
1199 if (0 != a) {
1200 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1201 SkPMColor C = proc(src[i], dstC);
1202 if (0xFF != a) {
1203 C = SkFourByteInterp(C, dstC, a);
1204 }
1205 dst[i] = SkPixel32ToPixel16_ToU16(C);
1206 }
1207 }
1208 }
1209 }
1210 }
1211
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1212 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1213 const SkPMColor* SK_RESTRICT src, int count,
1214 const SkAlpha* SK_RESTRICT aa) const {
1215 SkASSERT(dst && src && count >= 0);
1216
1217 SkXfermodeProc proc = fProc;
1218
1219 if (proc) {
1220 if (nullptr == aa) {
1221 for (int i = count - 1; i >= 0; --i) {
1222 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1223 dst[i] = SkToU8(SkGetPackedA32(res));
1224 }
1225 } else {
1226 for (int i = count - 1; i >= 0; --i) {
1227 unsigned a = aa[i];
1228 if (0 != a) {
1229 SkAlpha dstA = dst[i];
1230 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1231 unsigned A = SkGetPackedA32(res);
1232 if (0xFF != a) {
1233 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1234 }
1235 dst[i] = SkToU8(A);
1236 }
1237 }
1238 }
1239 }
1240 }
1241
1242 #if SK_SUPPORT_GPU
1243 #include "effects/GrCustomXfermode.h"
1244 #include "effects/GrPorterDuffXferProcessor.h"
1245 #include "effects/GrXfermodeFragmentProcessor.h"
1246
getFragmentProcessorForImageFilter(const GrFragmentProcessor * dst) const1247 const GrFragmentProcessor* SkProcCoeffXfermode::getFragmentProcessorForImageFilter(
1248 const GrFragmentProcessor* dst) const {
1249 SkASSERT(dst);
1250 return GrXfermodeFragmentProcessor::CreateFromDstProcessor(dst, fMode);
1251 }
1252
asXPFactory() const1253 GrXPFactory* SkProcCoeffXfermode::asXPFactory() const {
1254 if (CANNOT_USE_COEFF != fSrcCoeff) {
1255 GrXPFactory* result = GrPorterDuffXPFactory::Create(fMode);
1256 SkASSERT(result);
1257 return result;
1258 }
1259
1260 SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
1261 return GrCustomXfermode::CreateXPFactory(fMode);
1262 }
1263 #endif
1264
ModeName(Mode mode)1265 const char* SkXfermode::ModeName(Mode mode) {
1266 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1267 const char* gModeStrings[] = {
1268 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1269 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1270 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1271 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1272 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
1273 };
1274 return gModeStrings[mode];
1275 static_assert(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, "mode_count");
1276 }
1277
1278 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1279 void SkProcCoeffXfermode::toString(SkString* str) const {
1280 str->append("SkProcCoeffXfermode: ");
1281
1282 str->append("mode: ");
1283 str->append(ModeName(fMode));
1284
1285 static const char* gCoeffStrings[kCoeffCount] = {
1286 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1287 };
1288
1289 str->append(" src: ");
1290 if (CANNOT_USE_COEFF == fSrcCoeff) {
1291 str->append("can't use");
1292 } else {
1293 str->append(gCoeffStrings[fSrcCoeff]);
1294 }
1295
1296 str->append(" dst: ");
1297 if (CANNOT_USE_COEFF == fDstCoeff) {
1298 str->append("can't use");
1299 } else {
1300 str->append(gCoeffStrings[fDstCoeff]);
1301 }
1302 }
1303 #endif
1304
1305
1306 SK_DECLARE_STATIC_ONCE_PTR(SkXfermode, cached[SkXfermode::kLastMode + 1]);
1307
Create(Mode mode)1308 SkXfermode* SkXfermode::Create(Mode mode) {
1309 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1310
1311 if ((unsigned)mode >= kModeCount) {
1312 // report error
1313 return nullptr;
1314 }
1315
1316 // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
1317 // so we can just return nullptr from the factory.
1318 if (kSrcOver_Mode == mode) {
1319 return nullptr;
1320 }
1321
1322 return SkSafeRef(cached[mode].get([=]{
1323 ProcCoeff rec = gProcCoeffs[mode];
1324 if (auto xfermode = SkOpts::create_xfermode(rec, mode)) {
1325 return xfermode;
1326 }
1327 return (SkXfermode*) new SkProcCoeffXfermode(rec, mode);
1328 }));
1329 }
1330
GetProc(Mode mode)1331 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1332 SkXfermodeProc proc = nullptr;
1333 if ((unsigned)mode < kModeCount) {
1334 proc = gProcCoeffs[mode].fProc;
1335 }
1336 return proc;
1337 }
1338
GetProc4f(Mode mode)1339 SkXfermodeProc4f SkXfermode::GetProc4f(Mode mode) {
1340 SkXfermodeProc4f proc = nullptr;
1341 if ((unsigned)mode < kModeCount) {
1342 proc = gProcCoeffs[mode].fProc4f;
1343 }
1344 return proc;
1345 }
1346
missing_proc4f(const SkPM4f & src,const SkPM4f & dst)1347 static SkPM4f missing_proc4f(const SkPM4f& src, const SkPM4f& dst) {
1348 return src;
1349 }
1350
getProc4f() const1351 SkXfermodeProc4f SkXfermode::getProc4f() const {
1352 Mode mode;
1353 return this->asMode(&mode) ? GetProc4f(mode) : missing_proc4f;
1354 }
1355
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1356 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1357 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1358
1359 if ((unsigned)mode >= (unsigned)kModeCount) {
1360 // illegal mode parameter
1361 return false;
1362 }
1363
1364 const ProcCoeff& rec = gProcCoeffs[mode];
1365
1366 if (CANNOT_USE_COEFF == rec.fSC) {
1367 return false;
1368 }
1369
1370 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1371 if (src) {
1372 *src = rec.fSC;
1373 }
1374 if (dst) {
1375 *dst = rec.fDC;
1376 }
1377 return true;
1378 }
1379
AsMode(const SkXfermode * xfer,Mode * mode)1380 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1381 if (nullptr == xfer) {
1382 if (mode) {
1383 *mode = kSrcOver_Mode;
1384 }
1385 return true;
1386 }
1387 return xfer->asMode(mode);
1388 }
1389
IsMode(const SkXfermode * xfer,Mode mode)1390 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1391 // if xfer==null then the mode is srcover
1392 Mode m = kSrcOver_Mode;
1393 if (xfer && !xfer->asMode(&m)) {
1394 return false;
1395 }
1396 return mode == m;
1397 }
1398
SupportsCoverageAsAlpha(const SkXfermode * xfer)1399 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1400 // if xfer is nullptr we treat it as srcOver which always supports coverageAsAlpha
1401 if (!xfer) {
1402 return true;
1403 }
1404
1405 return xfer->supportsCoverageAsAlpha();
1406 }
1407
IsOpaque(const SkXfermode * xfer,SrcColorOpacity opacityType)1408 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1409 // if xfer is nullptr we treat it as srcOver which is opaque if our src is opaque
1410 if (!xfer) {
1411 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1412 }
1413
1414 return xfer->isOpaque(opacityType);
1415 }
1416
1417 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1418 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1419 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1420