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