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