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