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