blob: 80bafcedc7130f408e65a1d59f0c39df8354d0c5 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "SkXfermode.h"
18#include "SkColorPriv.h"
19
20#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
21
22static SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, U8CPU alpha) {
23 unsigned scale = SkAlpha255To256(alpha);
24
25 unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
26 unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
27 unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
28 unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
29
30 return SkPackARGB32(a, r, g, b);
31}
32
reed@android.comfc25abd2009-01-15 14:38:33 +000033#if 0
reed@android.com8a1c16f2008-12-17 15:59:43 +000034// idea for higher precision blends in xfer procs (and slightly faster)
35// see DstATop as a probable caller
36static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
37 SkASSERT(a <= 255);
38 SkASSERT(b <= 255);
39 SkASSERT(c <= 255);
40 SkASSERT(d <= 255);
41 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
42 unsigned result = (prod + (prod >> 8)) >> 8;
43 SkASSERT(result <= 255);
44 return result;
45}
reed@android.comfc25abd2009-01-15 14:38:33 +000046#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +000047
48///////////////////////////////////////////////////////////////////////////////
49
50bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
51 return false;
52}
53
54SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) {
55 // no-op. subclasses should override this
56 return dst;
57}
58
59void SkXfermode::xfer32(SK_RESTRICT SkPMColor dst[],
60 const SK_RESTRICT SkPMColor src[], int count,
61 const SK_RESTRICT SkAlpha aa[]) {
62 SkASSERT(dst && src && count >= 0);
63
64 if (NULL == aa) {
65 for (int i = count - 1; i >= 0; --i) {
66 dst[i] = this->xferColor(src[i], dst[i]);
67 }
68 } else {
69 for (int i = count - 1; i >= 0; --i) {
70 unsigned a = aa[i];
71 if (0 != a) {
72 SkPMColor dstC = dst[i];
73 SkPMColor C = this->xferColor(src[i], dstC);
74 if (0xFF != a) {
75 C = SkFourByteInterp(C, dstC, a);
76 }
77 dst[i] = C;
78 }
79 }
80 }
81}
82
83void SkXfermode::xfer16(SK_RESTRICT uint16_t dst[],
84 const SK_RESTRICT SkPMColor src[], int count,
85 const SK_RESTRICT SkAlpha aa[]) {
86 SkASSERT(dst && src && count >= 0);
87
88 if (NULL == aa) {
89 for (int i = count - 1; i >= 0; --i) {
90 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
91 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
92 }
93 } else {
94 for (int i = count - 1; i >= 0; --i) {
95 unsigned a = aa[i];
96 if (0 != a) {
97 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
98 SkPMColor C = this->xferColor(src[i], dstC);
99 if (0xFF != a) {
100 C = SkFourByteInterp(C, dstC, a);
101 }
102 dst[i] = SkPixel32ToPixel16_ToU16(C);
103 }
104 }
105 }
106}
107
108void SkXfermode::xfer4444(SK_RESTRICT SkPMColor16 dst[],
109 const SK_RESTRICT SkPMColor src[], int count,
110 const SK_RESTRICT SkAlpha aa[])
111{
112 SkASSERT(dst && src && count >= 0);
113
114 if (NULL == aa) {
115 for (int i = count - 1; i >= 0; --i) {
116 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
117 dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
118 }
119 } else {
120 for (int i = count - 1; i >= 0; --i) {
121 unsigned a = aa[i];
122 if (0 != a) {
123 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
124 SkPMColor C = this->xferColor(src[i], dstC);
125 if (0xFF != a) {
126 C = SkFourByteInterp(C, dstC, a);
127 }
128 dst[i] = SkPixel32ToPixel4444(C);
129 }
130 }
131 }
132}
133
134void SkXfermode::xferA8(SK_RESTRICT SkAlpha dst[],
135 const SkPMColor src[], int count,
136 const SK_RESTRICT SkAlpha aa[])
137{
138 SkASSERT(dst && src && count >= 0);
139
140 if (NULL == aa) {
141 for (int i = count - 1; i >= 0; --i) {
142 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
143 dst[i] = SkToU8(SkGetPackedA32(res));
144 }
145 } else {
146 for (int i = count - 1; i >= 0; --i) {
147 unsigned a = aa[i];
148 if (0 != a) {
149 SkAlpha dstA = dst[i];
150 unsigned A = SkGetPackedA32(this->xferColor(src[i],
151 (SkPMColor)(dstA << SK_A32_SHIFT)));
152 if (0xFF != a) {
153 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
154 }
155 dst[i] = SkToU8(A);
156 }
157 }
158 }
159}
160
161///////////////////////////////////////////////////////////////////////////////
162
163void SkProcXfermode::xfer32(SK_RESTRICT SkPMColor dst[],
164 const SK_RESTRICT SkPMColor src[], int count,
165 const SK_RESTRICT SkAlpha aa[]) {
166 SkASSERT(dst && src && count >= 0);
167
168 SkXfermodeProc proc = fProc;
169
170 if (NULL != proc) {
171 if (NULL == aa) {
172 for (int i = count - 1; i >= 0; --i) {
173 dst[i] = proc(src[i], dst[i]);
174 }
175 } else {
176 for (int i = count - 1; i >= 0; --i) {
177 unsigned a = aa[i];
178 if (0 != a) {
179 SkPMColor dstC = dst[i];
180 SkPMColor C = proc(src[i], dstC);
181 if (a != 0xFF) {
182 C = SkFourByteInterp(C, dstC, a);
183 }
184 dst[i] = C;
185 }
186 }
187 }
188 }
189}
190
191void SkProcXfermode::xfer16(SK_RESTRICT uint16_t dst[],
192 const SK_RESTRICT SkPMColor src[], int count,
193 const SK_RESTRICT SkAlpha aa[]) {
194 SkASSERT(dst && src && count >= 0);
195
196 SkXfermodeProc proc = fProc;
197
198 if (NULL != proc) {
199 if (NULL == aa) {
200 for (int i = count - 1; i >= 0; --i) {
201 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
202 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
203 }
204 } else {
205 for (int i = count - 1; i >= 0; --i) {
206 unsigned a = aa[i];
207 if (0 != a) {
208 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
209 SkPMColor C = proc(src[i], dstC);
210 if (0xFF != a) {
211 C = SkFourByteInterp(C, dstC, a);
212 }
213 dst[i] = SkPixel32ToPixel16_ToU16(C);
214 }
215 }
216 }
217 }
218}
219
220void SkProcXfermode::xfer4444(SK_RESTRICT SkPMColor16 dst[],
221 const SK_RESTRICT SkPMColor src[], int count,
222 const SK_RESTRICT SkAlpha aa[]) {
223 SkASSERT(dst && src && count >= 0);
224
225 SkXfermodeProc proc = fProc;
226
227 if (NULL != proc) {
228 if (NULL == aa) {
229 for (int i = count - 1; i >= 0; --i) {
230 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
231 dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
232 }
233 } else {
234 for (int i = count - 1; i >= 0; --i) {
235 unsigned a = aa[i];
236 if (0 != a) {
237 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
238 SkPMColor C = proc(src[i], dstC);
239 if (0xFF != a) {
240 C = SkFourByteInterp(C, dstC, a);
241 }
242 dst[i] = SkPixel32ToPixel4444(C);
243 }
244 }
245 }
246 }
247}
248
249void SkProcXfermode::xferA8(SK_RESTRICT SkAlpha dst[],
250 const SK_RESTRICT SkPMColor src[], int count,
251 const SK_RESTRICT SkAlpha aa[]) {
252 SkASSERT(dst && src && count >= 0);
253
254 SkXfermodeProc proc = fProc;
255
256 if (NULL != proc) {
257 if (NULL == aa) {
258 for (int i = count - 1; i >= 0; --i) {
259 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
260 dst[i] = SkToU8(SkGetPackedA32(res));
261 }
262 } else {
263 for (int i = count - 1; i >= 0; --i) {
264 unsigned a = aa[i];
265 if (0 != a) {
266 SkAlpha dstA = dst[i];
267 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
268 unsigned A = SkGetPackedA32(res);
269 if (0xFF != a) {
270 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
271 }
272 dst[i] = SkToU8(A);
273 }
274 }
275 }
276 }
277}
278
279SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
280 : SkXfermode(buffer) {
281 fProc = (SkXfermodeProc)buffer.readFunctionPtr();
282}
283
284void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
285 buffer.writeFunctionPtr((void*)fProc);
286}
287
288///////////////////////////////////////////////////////////////////////////////
289///////////////////////////////////////////////////////////////////////////////
290
291class SkProcCoeffXfermode : public SkProcXfermode {
292public:
293 SkProcCoeffXfermode(SkXfermodeProc proc, Coeff sc, Coeff dc)
294 : INHERITED(proc), fSrcCoeff(sc), fDstCoeff(dc) {
295 }
296
297 virtual bool asCoeff(Coeff* sc, Coeff* dc) {
298 if (sc) {
299 *sc = fSrcCoeff;
300 }
301 if (dc) {
302 *dc = fDstCoeff;
303 }
304 return true;
305 }
306
307 virtual Factory getFactory() { return CreateProc; }
308 virtual void flatten(SkFlattenableWriteBuffer& buffer) {
309 this->INHERITED::flatten(buffer);
310 buffer.write32(fSrcCoeff);
311 buffer.write32(fDstCoeff);
312 }
313
314protected:
315 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
316 : INHERITED(buffer) {
317 fSrcCoeff = (Coeff)buffer.readU32();
318 fDstCoeff = (Coeff)buffer.readU32();
319 }
320
321private:
322 Coeff fSrcCoeff, fDstCoeff;
323
324 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
325 return SkNEW_ARGS(SkProcCoeffXfermode, (buffer)); }
326
327 typedef SkProcXfermode INHERITED;
328};
329
330///////////////////////////////////////////////////////////////////////////////
331
332// kClear_Mode, //!< [0, 0]
333static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
334 return 0;
335}
336
337// kSrc_Mode, //!< [Sa, Sc]
338static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
339 return src;
340}
341
342// kDst_Mode, //!< [Da, Dc]
343static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
344 return dst;
345}
346
347// kSrcOver_Mode, //!< [Sa + (1 - Sa)*Da, Sc + (1 - Sa)*Dc]
348static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
349 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
350}
351
352// kDstOver_Mode, //!< [Sa + (1 - Sa)*Da, Dc + (1 - Da)*Sc]
353static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
354 unsigned sa = SkGetPackedA32(src);
355 unsigned da = SkGetPackedA32(dst);
356 unsigned ida = 255 - da;
357
358 return SkPackARGB32(sa + da - SkAlphaMulAlpha(sa, da),
359 SkGetPackedR32(dst) + SkAlphaMulAlpha(ida, SkGetPackedR32(src)),
360 SkGetPackedG32(dst) + SkAlphaMulAlpha(ida, SkGetPackedG32(src)),
361 SkGetPackedB32(dst) + SkAlphaMulAlpha(ida, SkGetPackedB32(src)));
362}
363
364// kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
365static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
366 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
367}
368
369// kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
370static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
371 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
372}
373
374// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
375static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
376 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
377}
378
379// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
380static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
381 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
382}
383
384// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
385static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
386 unsigned sa = SkGetPackedA32(src);
387 unsigned da = SkGetPackedA32(dst);
388 unsigned isa = 255 - sa;
389
390 return SkPackARGB32(da,
391 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
392 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
393 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
394 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
395 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
396 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
397}
398
399// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
400static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
401 unsigned sa = SkGetPackedA32(src);
402 unsigned da = SkGetPackedA32(dst);
403 unsigned ida = 255 - da;
404
405 return SkPackARGB32(sa,
406 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
407 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
408 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
409 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
410 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
411 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
412}
413
414// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
415static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
416 unsigned sa = SkGetPackedA32(src);
417 unsigned da = SkGetPackedA32(dst);
418 unsigned isa = 255 - sa;
419 unsigned ida = 255 - da;
420
421 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
422 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
423 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
424 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
425 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
426 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
427 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
428}
429
430
431// kDarken_Mode, [Sa + Da - Sa·Da, Sc·(1 - Da) + Dc·(1 - Sa) + min(Sc, Dc)]
432
433static inline unsigned darken_p(unsigned src, unsigned dst,
434 unsigned src_mul, unsigned dst_mul) {
435 return ((dst_mul * src + src_mul * dst) >> 8) + SkMin32(src, dst);
436}
437
438static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
439 unsigned sa = SkGetPackedA32(src);
440 unsigned da = SkGetPackedA32(dst);
441 unsigned src_scale = SkAlpha255To256(255 - sa);
442 unsigned dst_scale = SkAlpha255To256(255 - da);
443
444 unsigned ra = sa + da - SkAlphaMulAlpha(sa, da);
445 unsigned rr = darken_p(SkGetPackedR32(src), SkGetPackedR32(dst),
446 src_scale, dst_scale);
447 unsigned rg = darken_p(SkGetPackedG32(src), SkGetPackedG32(dst),
448 src_scale, dst_scale);
449 unsigned rb = darken_p(SkGetPackedB32(src), SkGetPackedB32(dst),
450 src_scale, dst_scale);
451
452 return SkPackARGB32(ra, SkFastMin32(rr, ra),
453 SkFastMin32(rg, ra), SkFastMin32(rb, ra));
454}
455
456// kLighten_Mode, [Sa + Da - Sa·Da, Sc·(1 - Da) + Dc·(1 - Sa) + max(Sc, Dc)]
457static inline unsigned lighten_p(unsigned src, unsigned dst,
458 unsigned src_mul, unsigned dst_mul) {
459 return ((dst_mul * src + src_mul * dst) >> 8) + SkMax32(src, dst);
460}
461
462static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
463 unsigned sa = SkGetPackedA32(src);
464 unsigned da = SkGetPackedA32(dst);
465 unsigned src_scale = SkAlpha255To256(255 - sa);
466 unsigned dst_scale = SkAlpha255To256(255 - da);
467
468 unsigned ra = sa + da - SkAlphaMulAlpha(sa, da);
469 unsigned rr = lighten_p(SkGetPackedR32(src), SkGetPackedR32(dst),
470 src_scale, dst_scale);
471 unsigned rg = lighten_p(SkGetPackedG32(src), SkGetPackedG32(dst),
472 src_scale, dst_scale);
473 unsigned rb = lighten_p(SkGetPackedB32(src), SkGetPackedB32(dst),
474 src_scale, dst_scale);
475
476 return SkPackARGB32(ra, SkFastMin32(rr, ra),
477 SkFastMin32(rg, ra), SkFastMin32(rb, ra));
478}
479
480static SkPMColor mult_modeproc(SkPMColor src, SkPMColor dst) {
481 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
482 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
483 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
484 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
485 return SkPackARGB32(a, r, g, b);
486}
487
488static inline int screen_byte(int a, int b) {
489 return a + b - SkAlphaMulAlpha(a, b);
490}
491
492static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
493 int a = screen_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
494 int r = screen_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
495 int g = screen_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
496 int b = screen_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
497 return SkPackARGB32(a, r, g, b);
498}
499
500///////////////////////////////////////////////////////////////////////////////
501
502class SkClearXfermode : public SkProcCoeffXfermode {
503public:
504 SkClearXfermode() : SkProcCoeffXfermode(clear_modeproc,
505 kZero_Coeff, kZero_Coeff) {}
506
507 virtual void xfer32(SK_RESTRICT SkPMColor dst[],
508 const SK_RESTRICT SkPMColor[], int count,
509 const SK_RESTRICT SkAlpha aa[]) {
510 SkASSERT(dst && count >= 0);
511
512 if (NULL == aa) {
513 memset(dst, 0, count << 2);
514 } else {
515 for (int i = count - 1; i >= 0; --i) {
516 unsigned a = aa[i];
517 if (0xFF == a) {
518 dst[i] = 0;
519 } else if (a != 0) {
520 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
521 }
522 }
523 }
524 }
525 virtual void xferA8(SK_RESTRICT SkAlpha dst[],
526 const SK_RESTRICT SkPMColor[], int count,
527 const SK_RESTRICT SkAlpha aa[]) {
528 SkASSERT(dst && count >= 0);
529
530 if (NULL == aa) {
531 memset(dst, 0, count);
532 } else {
533 for (int i = count - 1; i >= 0; --i) {
534 unsigned a = aa[i];
535 if (0xFF == a) {
536 dst[i] = 0;
537 } else if (0 != a) {
538 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
539 }
540 }
541 }
542 }
543
544 virtual Factory getFactory() { return CreateProc; }
545
546private:
547 SkClearXfermode(SkFlattenableReadBuffer& buffer)
548 : SkProcCoeffXfermode(buffer) {}
549
550 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
551 return SkNEW_ARGS(SkClearXfermode, (buffer));
552 }
553};
554
555///////////////////////////////////////////////////////////////////////////////
556
557class SkSrcXfermode : public SkProcCoeffXfermode {
558public:
559 SkSrcXfermode() : SkProcCoeffXfermode(src_modeproc,
560 kOne_Coeff, kZero_Coeff) {}
561
562 virtual void xfer32(SK_RESTRICT SkPMColor dst[],
563 const SK_RESTRICT SkPMColor src[], int count,
564 const SK_RESTRICT SkAlpha aa[]) {
565 SkASSERT(dst && src && count >= 0);
566
567 if (NULL == aa) {
568 memcpy(dst, src, count << 2);
569 } else {
570 for (int i = count - 1; i >= 0; --i) {
571 unsigned a = aa[i];
572 if (a == 0xFF) {
573 dst[i] = src[i];
574 } else if (a != 0) {
575 dst[i] = SkFourByteInterp(src[i], dst[i], a);
576 }
577 }
578 }
579 }
580
581 virtual void xferA8(SK_RESTRICT SkAlpha dst[],
582 const SK_RESTRICT SkPMColor src[], int count,
583 const SK_RESTRICT SkAlpha aa[]) {
584 SkASSERT(dst && src && count >= 0);
585
586 if (NULL == aa) {
587 for (int i = count - 1; i >= 0; --i) {
588 dst[i] = SkToU8(SkGetPackedA32(src[i]));
589 }
590 } else {
591 for (int i = count - 1; i >= 0; --i) {
592 unsigned a = aa[i];
593 if (0 != a) {
594 unsigned srcA = SkGetPackedA32(src[i]);
595 if (a == 0xFF) {
596 dst[i] = SkToU8(srcA);
597 } else {
598 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
599 }
600 }
601 }
602 }
603 }
604
605 virtual Factory getFactory() { return CreateProc; }
606
607private:
608 SkSrcXfermode(SkFlattenableReadBuffer& buffer)
609 : SkProcCoeffXfermode(buffer) {}
610
611 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
612 return SkNEW_ARGS(SkSrcXfermode, (buffer));
613 }
614};
615
616class SkDstInXfermode : public SkProcCoeffXfermode {
617public:
618 SkDstInXfermode() : SkProcCoeffXfermode(dstin_modeproc,
619 kZero_Coeff, kSA_Coeff) {}
620
621 virtual void xfer32(SK_RESTRICT SkPMColor dst[],
622 const SK_RESTRICT SkPMColor src[], int count,
623 const SK_RESTRICT SkAlpha aa[]) {
624 SkASSERT(dst && src);
625
626 if (count <= 0) {
627 return;
628 }
629 if (NULL != aa) {
630 return this->INHERITED::xfer32(dst, src, count, aa);
631 }
632
633 do {
634 unsigned a = SkGetPackedA32(*src);
635 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
636 dst++;
637 src++;
638 } while (--count != 0);
639 }
640
641 virtual Factory getFactory() { return CreateProc; }
642
643private:
644 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
645
646 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
647 return SkNEW_ARGS(SkDstInXfermode, (buffer));
648 }
649
650 typedef SkProcCoeffXfermode INHERITED;
651};
652
653class SkDstOutXfermode : public SkProcCoeffXfermode {
654public:
655 SkDstOutXfermode() : SkProcCoeffXfermode(dstout_modeproc,
656 kZero_Coeff, kISA_Coeff) {}
657
658 virtual void xfer32(SK_RESTRICT SkPMColor dst[],
659 const SK_RESTRICT SkPMColor src[], int count,
660 const SK_RESTRICT SkAlpha aa[]) {
661 SkASSERT(dst && src);
662
663 if (count <= 0) {
664 return;
665 }
666 if (NULL != aa) {
667 return this->INHERITED::xfer32(dst, src, count, aa);
668 }
669
670 do {
671 unsigned a = SkGetPackedA32(*src);
672 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
673 dst++;
674 src++;
675 } while (--count != 0);
676 }
677
678 virtual Factory getFactory() { return CreateProc; }
679
680private:
681 SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
682 : INHERITED(buffer) {}
683
684 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
685 return SkNEW_ARGS(SkDstOutXfermode, (buffer));
686 }
687
688 typedef SkProcCoeffXfermode INHERITED;
689};
690
691///////////////////////////////////////////////////////////////////////////////
692
693#include "SkPorterDuff.h"
694
695struct ProcCoeff {
696 SkXfermodeProc fProc;
697 SkXfermode::Coeff fSC;
698 SkXfermode::Coeff fDC;
699};
700
701static const ProcCoeff gProcCoeffs[] = {
702 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
703 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
704 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
705 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
706 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
707 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
708 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
709 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
710 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
711 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
712 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
713 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
714 // these two can't be represented as coefficients
715 { darken_modeproc, SkXfermode::Coeff(-1), SkXfermode::Coeff(-1) },
716 { lighten_modeproc, SkXfermode::Coeff(-1), SkXfermode::Coeff(-1) },
717 // these can use coefficients
718 { mult_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
719 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }
720};
721
722SkXfermode* SkPorterDuff::CreateXfermode(SkPorterDuff::Mode mode) {
723 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == SkPorterDuff::kModeCount);
724 SkASSERT((unsigned)mode < SkPorterDuff::kModeCount);
725
726 switch (mode) {
727 case kClear_Mode:
728 return SkNEW(SkClearXfermode);
729 case kSrc_Mode:
730 return SkNEW(SkSrcXfermode);
731 case kSrcOver_Mode:
732 return NULL;
733 case kDstIn_Mode:
734 return SkNEW(SkDstInXfermode);
735 case kDstOut_Mode:
736 return SkNEW(SkDstOutXfermode);
737 // these two can't be represented with Coeff
738 case kDarken_Mode:
739 return SkNEW_ARGS(SkProcXfermode, (darken_modeproc));
740 case kLighten_Mode:
741 return SkNEW_ARGS(SkProcXfermode, (lighten_modeproc));
742 // use the table
743 default: {
744 const ProcCoeff& rec = gProcCoeffs[mode];
745 SkASSERT((unsigned)rec.fSC < SkXfermode::kCoeffCount);
746 SkASSERT((unsigned)rec.fDC < SkXfermode::kCoeffCount);
747 return SkNEW_ARGS(SkProcCoeffXfermode, (rec.fProc,
748 rec.fSC, rec.fDC));
749 }
750 }
751}
752
753bool SkPorterDuff::IsMode(SkXfermode* xfer, Mode* mode) {
754 if (NULL == xfer) {
755 if (mode) {
756 *mode = kSrcOver_Mode;
757 }
758 return true;
759 }
760
761 SkXfermode::Coeff sc, dc;
762 if (xfer->asCoeff(&sc, &dc)) {
763 SkASSERT((unsigned)sc < (unsigned)SkXfermode::kCoeffCount);
764 SkASSERT((unsigned)dc < (unsigned)SkXfermode::kCoeffCount);
765
766 const ProcCoeff* rec = gProcCoeffs;
767 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcCoeffs); i++) {
768 if (rec[i].fSC == sc && rec[i].fDC == dc) {
769 if (mode) {
770 *mode = SkPorterDuff::Mode(i);
771 }
772 return true;
773 }
774 }
775 }
776
777 // no coefficients, or not found in our table
778 return false;
779}
780
781///////////////////////////////////////////////////////////////////////////////
782
reed@android.comfc25abd2009-01-15 14:38:33 +0000783#ifdef SK_DEBUGx
reed@android.com8a1c16f2008-12-17 15:59:43 +0000784static void unit_test() {
785 for (unsigned a = 0; a <= 255; a++) {
786 for (unsigned c = 0; c <= a; c++) {
787 SkPMColor pm = SkPackARGB32(a, c, c, c);
788 for (unsigned aa = 0; aa <= 255; aa++) {
789 for (unsigned cc = 0; cc <= aa; cc++) {
790 SkPMColor pm2 = SkPackARGB32(aa, cc, cc, cc);
791
792 const size_t N = SK_ARRAY_COUNT(gProcCoeffs);
793 for (size_t i = 0; i < N; i++) {
794 gProcCoeffs[i].fProc(pm, pm2);
795 }
796 }
797 }
798 }
799 }
800}
801#endif
802
803SkXfermodeProc SkPorterDuff::GetXfermodeProc(Mode mode) {
804#ifdef SK_DEBUGx
805 static bool gUnitTest;
806 if (!gUnitTest) {
807 gUnitTest = true;
808 unit_test();
809 }
810#endif
811
812 SkXfermodeProc proc = NULL;
813
814 if ((unsigned)mode < SkPorterDuff::kModeCount) {
815 proc = gProcCoeffs[mode].fProc;
816 }
817 return proc;
818}
819
820///////////////////////////////////////////////////////////////////////////////
821//////////// 16bit xfermode procs
822
823#ifdef SK_DEBUG
824static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
825static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
826#endif
827
828static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
829 SkASSERT(require_255(src));
830 return SkPixel32ToPixel16(src);
831}
832
833static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
834 return dst;
835}
836
837static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
838 SkASSERT(require_0(src));
839 return dst;
840}
841
842static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
843 SkASSERT(require_255(src));
844 return SkPixel32ToPixel16(src);
845}
846
847static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
848 SkASSERT(require_0(src));
849 return dst;
850}
851
852static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
853 SkASSERT(require_255(src));
854 return dst;
855}
856
857static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
858 SkASSERT(require_255(src));
859 return SkPixel32ToPixel16(src);
860}
861
862static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
863 SkASSERT(require_255(src));
864 return dst;
865}
866
867static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
868 SkASSERT(require_0(src));
869 return dst;
870}
871
872static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
873 unsigned isa = 255 - SkGetPackedA32(src);
874
875 return SkPackRGB16(
876 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
877 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
878 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
879}
880
881static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
882 SkASSERT(require_0(src));
883 return dst;
884}
885
886static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
887 SkASSERT(require_255(src));
888 return SkPixel32ToPixel16(src);
889}
890
891static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
892 SkASSERT(require_255(src));
893 return dst;
894}
895
896/*********
897 darken and lighten boil down to this.
898
899 darken = (1 - Sa) * Dc + min(Sc, Dc)
900 lighten = (1 - Sa) * Dc + max(Sc, Dc)
901
902 if (Sa == 0) these become
903 darken = Dc + min(0, Dc) = 0
904 lighten = Dc + max(0, Dc) = Dc
905
906 if (Sa == 1) these become
907 darken = min(Sc, Dc)
908 lighten = max(Sc, Dc)
909*/
910
911static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
912 SkASSERT(require_0(src));
913 return 0;
914}
915
916static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
917 SkASSERT(require_255(src));
918 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
919 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
920 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
921 return SkPackRGB16(r, g, b);
922}
923
924static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
925 SkASSERT(require_0(src));
926 return dst;
927}
928
929static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
930 SkASSERT(require_255(src));
931 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
932 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
933 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
934 return SkPackRGB16(r, g, b);
935}
936
937struct Proc16Rec {
938 SkXfermodeProc16 fProc16_0;
939 SkXfermodeProc16 fProc16_255;
940 SkXfermodeProc16 fProc16_General;
941};
942
943static const Proc16Rec gPorterDuffModeProcs16[] = {
944 { NULL, NULL, NULL }, // CLEAR
945 { NULL, src_modeproc16_255, NULL },
946 { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
947 { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
948 { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
949 { NULL, srcin_modeproc16_255, NULL },
950 { NULL, dstin_modeproc16_255, NULL },
951 { NULL, NULL, NULL },// SRC_OUT
952 { dstout_modeproc16_0, NULL, NULL },
953 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
954 { NULL, dstatop_modeproc16_255, NULL },
955 { NULL, NULL, NULL }, // XOR
956 { darken_modeproc16_0, darken_modeproc16_255, NULL },
957 { lighten_modeproc16_0, lighten_modeproc16_255, NULL },
958 { NULL, NULL, NULL },//multiply
959 { NULL, NULL, NULL }// screen
960};
961
962SkXfermodeProc16 SkPorterDuff::GetXfermodeProc16(Mode mode, SkColor srcColor) {
963 SkXfermodeProc16 proc16 = NULL;
964
965 if ((unsigned)mode < SkPorterDuff::kModeCount) {
966 const Proc16Rec& rec = gPorterDuffModeProcs16[mode];
967
968 unsigned a = SkColorGetA(srcColor);
969
970 if (0 == a) {
971 proc16 = rec.fProc16_0;
972 } else if (255 == a) {
973 proc16 = rec.fProc16_255;
974 } else {
975 proc16 = rec.fProc16_General;
976 }
977 }
978 return proc16;
979}
980