blob: 81522ff5917b252a7c355bcdacf9b0c9051ce2bc [file] [log] [blame]
reed@google.comedb606c2011-10-18 13:56:50 +00001#include "SkBlitMask.h"
2#include "SkColor.h"
3#include "SkColorPriv.h"
4
5static void D32_A8_Color(void* SK_RESTRICT dst, size_t dstRB,
6 const void* SK_RESTRICT maskPtr, size_t maskRB,
7 SkColor color, int width, int height) {
8 SkPMColor pmc = SkPreMultiplyColor(color);
9 size_t dstOffset = dstRB - (width << 2);
10 size_t maskOffset = maskRB - width;
11 SkPMColor* SK_RESTRICT device = (SkPMColor *)dst;
12 const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
13
14 do {
15 int w = width;
16 do {
17 unsigned aa = *mask++;
18 *device = SkBlendARGB32(pmc, *device, aa);
19 device += 1;
20 } while (--w != 0);
21 device = (uint32_t*)((char*)device + dstOffset);
22 mask += maskOffset;
23 } while (--height != 0);
24}
25
26static void D32_A8_Opaque(void* SK_RESTRICT dst, size_t dstRB,
27 const void* SK_RESTRICT maskPtr, size_t maskRB,
28 SkColor color, int width, int height) {
29 SkPMColor pmc = SkPreMultiplyColor(color);
30 SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
31 const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
32
33 maskRB -= width;
34 dstRB -= (width << 2);
35 do {
36 int w = width;
37 do {
38 unsigned aa = *mask++;
39 *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
40 device += 1;
41 } while (--w != 0);
42 device = (uint32_t*)((char*)device + dstRB);
43 mask += maskRB;
44 } while (--height != 0);
45}
46
47static void D32_A8_Black(void* SK_RESTRICT dst, size_t dstRB,
48 const void* SK_RESTRICT maskPtr, size_t maskRB,
49 SkColor, int width, int height) {
50 SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
51 const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
52
53 maskRB -= width;
54 dstRB -= (width << 2);
55 do {
56 int w = width;
57 do {
58 unsigned aa = *mask++;
59 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
60 device += 1;
61 } while (--w != 0);
62 device = (uint32_t*)((char*)device + dstRB);
63 mask += maskRB;
64 } while (--height != 0);
65}
66
67///////////////////////////////////////////////////////////////////////////////
68
69static inline int upscale31To32(int value) {
70 SkASSERT((unsigned)value <= 31);
71 return value + (value >> 4);
72}
73
74static inline int blend32(int src, int dst, int scale) {
75 SkASSERT((unsigned)src <= 0xFF);
76 SkASSERT((unsigned)dst <= 0xFF);
77 SkASSERT((unsigned)scale <= 32);
78 return dst + ((src - dst) * scale >> 5);
79}
80
81static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[],
82 SkColor color, int width, SkPMColor) {
83 int srcA = SkColorGetA(color);
84 int srcR = SkColorGetR(color);
85 int srcG = SkColorGetG(color);
86 int srcB = SkColorGetB(color);
87
88 srcA = SkAlpha255To256(srcA);
89
90 for (int i = 0; i < width; i++) {
91 uint16_t mask = src[i];
92 if (0 == mask) {
93 continue;
94 }
95
96 SkPMColor d = dst[i];
97
98 /* We want all of these in 5bits, hence the shifts in case one of them
99 * (green) is 6bits.
100 */
101 int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
102 int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
103 int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
104
105 // Now upscale them to 0..32, so we can use blend32
106 maskR = upscale31To32(maskR);
107 maskG = upscale31To32(maskG);
108 maskB = upscale31To32(maskB);
109
110 maskR = maskR * srcA >> 8;
111 maskG = maskG * srcA >> 8;
112 maskB = maskB * srcA >> 8;
113
114 int dstR = SkGetPackedR32(d);
115 int dstG = SkGetPackedG32(d);
116 int dstB = SkGetPackedB32(d);
117
tomhudson@google.com83a44462011-10-27 15:27:51 +0000118 // LCD blitting is only supported if the dst is known/required
reed@google.comedb606c2011-10-18 13:56:50 +0000119 // to be opaque
120 dst[i] = SkPackARGB32(0xFF,
121 blend32(srcR, dstR, maskR),
122 blend32(srcG, dstG, maskG),
123 blend32(srcB, dstB, maskB));
124 }
125}
126
127static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[],
128 SkColor color, int width, SkPMColor opaqueDst) {
129 int srcR = SkColorGetR(color);
130 int srcG = SkColorGetG(color);
131 int srcB = SkColorGetB(color);
132
133 for (int i = 0; i < width; i++) {
134 uint16_t mask = src[i];
135 if (0 == mask) {
136 continue;
137 }
138 if (0xFFFF == mask) {
139 dst[i] = opaqueDst;
140 continue;
141 }
142
143 SkPMColor d = dst[i];
144
145 /* We want all of these in 5bits, hence the shifts in case one of them
146 * (green) is 6bits.
147 */
148 int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
149 int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
150 int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
151
152 // Now upscale them to 0..32, so we can use blend32
153 maskR = upscale31To32(maskR);
154 maskG = upscale31To32(maskG);
155 maskB = upscale31To32(maskB);
156
157 int dstR = SkGetPackedR32(d);
158 int dstG = SkGetPackedG32(d);
159 int dstB = SkGetPackedB32(d);
160
161 // LCD blitting is only supported if the dst is known/required
162 // to be opaque
163 dst[i] = SkPackARGB32(0xFF,
164 blend32(srcR, dstR, maskR),
165 blend32(srcG, dstG, maskG),
166 blend32(srcB, dstB, maskB));
167 }
168}
169
170static void D32_LCD16_Proc(void* SK_RESTRICT dst, size_t dstRB,
171 const void* SK_RESTRICT mask, size_t maskRB,
172 SkColor color, int width, int height) {
173
174 SkPMColor* dstRow = (SkPMColor*)dst;
175 const uint16_t* srcRow = (const uint16_t*)mask;
176 SkPMColor opaqueDst;
177
178 void (*proc)(SkPMColor dst[], const uint16_t src[],
179 SkColor color, int width, SkPMColor);
180 if (0xFF == SkColorGetA(color)) {
181 proc = blit_lcd16_opaque_row;
182 opaqueDst = SkPreMultiplyColor(color);
183 } else {
184 proc = blit_lcd16_row;
185 opaqueDst = 0; // ignored
186 }
187
188 do {
189 proc(dstRow, srcRow, color, width, opaqueDst);
190 dstRow = (SkPMColor*)((char*)dstRow + dstRB);
191 srcRow = (const uint16_t*)((const char*)srcRow + maskRB);
192 } while (--height != 0);
193}
194
195///////////////////////////////////////////////////////////////////////////////
196
197static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst,
198 const SkPMColor* SK_RESTRICT src,
199 SkColor color, int width) {
200 int srcR = SkColorGetR(color);
201 int srcG = SkColorGetG(color);
202 int srcB = SkColorGetB(color);
203
204 for (int i = 0; i < width; i++) {
205 SkPMColor mask = src[i];
206 if (0 == mask) {
207 continue;
208 }
209
210 SkPMColor d = dst[i];
211
212 int maskR = SkGetPackedR32(mask);
213 int maskG = SkGetPackedG32(mask);
214 int maskB = SkGetPackedB32(mask);
215
216 // Now upscale them to 0..256, so we can use SkAlphaBlend
217 maskR = SkAlpha255To256(maskR);
218 maskG = SkAlpha255To256(maskG);
219 maskB = SkAlpha255To256(maskB);
220
221 int dstR = SkGetPackedR32(d);
222 int dstG = SkGetPackedG32(d);
223 int dstB = SkGetPackedB32(d);
224
225 // LCD blitting is only supported if the dst is known/required
226 // to be opaque
227 dst[i] = SkPackARGB32(0xFF,
228 SkAlphaBlend(srcR, dstR, maskR),
229 SkAlphaBlend(srcG, dstG, maskG),
230 SkAlphaBlend(srcB, dstB, maskB));
231 }
232}
233
234static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst,
235 const SkPMColor* SK_RESTRICT src,
236 SkColor color, int width) {
237 int srcA = SkColorGetA(color);
238 int srcR = SkColorGetR(color);
239 int srcG = SkColorGetG(color);
240 int srcB = SkColorGetB(color);
241
242 srcA = SkAlpha255To256(srcA);
243
244 for (int i = 0; i < width; i++) {
245 SkPMColor mask = src[i];
246 if (0 == mask) {
247 continue;
248 }
249
250 SkPMColor d = dst[i];
251
252 int maskR = SkGetPackedR32(mask);
253 int maskG = SkGetPackedG32(mask);
254 int maskB = SkGetPackedB32(mask);
255
256 // Now upscale them to 0..256, so we can use SkAlphaBlend
257 maskR = SkAlpha255To256(maskR);
258 maskG = SkAlpha255To256(maskG);
259 maskB = SkAlpha255To256(maskB);
260
261 maskR = maskR * srcA >> 8;
262 maskG = maskG * srcA >> 8;
263 maskB = maskB * srcA >> 8;
264
265 int dstR = SkGetPackedR32(d);
266 int dstG = SkGetPackedG32(d);
267 int dstB = SkGetPackedB32(d);
268
269 // LCD blitting is only supported if the dst is known/required
270 // to be opaque
271 dst[i] = SkPackARGB32(0xFF,
272 SkAlphaBlend(srcR, dstR, maskR),
273 SkAlphaBlend(srcG, dstG, maskG),
274 SkAlphaBlend(srcB, dstB, maskB));
275 }
276}
277
278static void D32_LCD32_Blend(void* SK_RESTRICT dst, size_t dstRB,
279 const void* SK_RESTRICT mask, size_t maskRB,
280 SkColor color, int width, int height) {
281 SkASSERT(height > 0);
282 SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
283 const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
284
285 do {
286 blit_lcd32_row(dstRow, srcRow, color, width);
287 dstRow = (SkPMColor*)((char*)dstRow + dstRB);
288 srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
289 } while (--height != 0);
290}
291
292static void D32_LCD32_Opaque(void* SK_RESTRICT dst, size_t dstRB,
293 const void* SK_RESTRICT mask, size_t maskRB,
294 SkColor color, int width, int height) {
295 SkASSERT(height > 0);
296 SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
297 const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
298
299 do {
300 blit_lcd32_opaque_row(dstRow, srcRow, color, width);
301 dstRow = (SkPMColor*)((char*)dstRow + dstRB);
302 srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
303 } while (--height != 0);
304}
305
306///////////////////////////////////////////////////////////////////////////////
307
reed@google.come901b4c2011-11-14 21:56:45 +0000308static SkBlitMask::ColorProc D32_A8_Factory(SkColor color) {
reed@google.comedb606c2011-10-18 13:56:50 +0000309 if (SK_ColorBLACK == color) {
310 return D32_A8_Black;
311 } else if (0xFF == SkColorGetA(color)) {
312 return D32_A8_Opaque;
313 } else {
314 return D32_A8_Color;
315 }
316}
317
reed@google.come901b4c2011-11-14 21:56:45 +0000318static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
reed@google.comedb606c2011-10-18 13:56:50 +0000319 return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
320}
321
reed@google.come901b4c2011-11-14 21:56:45 +0000322SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkBitmap::Config config,
323 SkMask::Format format,
324 SkColor color) {
325 ColorProc proc = PlatformColorProcs(config, format, color);
reed@google.comedb606c2011-10-18 13:56:50 +0000326 if (proc) {
327 return proc;
328 }
329
330 switch (config) {
331 case SkBitmap::kARGB_8888_Config:
332 switch (format) {
333 case SkMask::kA8_Format:
334 return D32_A8_Factory(color);
335 case SkMask::kLCD16_Format:
336 return D32_LCD16_Proc;
337 case SkMask::kLCD32_Format:
338 return D32_LCD32_Factory(color);
reed@google.com5344a1a2011-10-18 14:03:23 +0000339 default:
340 break;
reed@google.comedb606c2011-10-18 13:56:50 +0000341 }
342 break;
343 default:
344 break;
345 }
346 return NULL;
347}
348
reed@google.comedb606c2011-10-18 13:56:50 +0000349bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
350 const SkIRect& clip, SkColor color) {
reed@google.come901b4c2011-11-14 21:56:45 +0000351 ColorProc proc = ColorFactory(device.config(), mask.fFormat, color);
reed@google.comedb606c2011-10-18 13:56:50 +0000352 if (proc) {
353 int x = clip.fLeft;
354 int y = clip.fTop;
reed@google.comf52e5552011-10-18 17:29:44 +0000355 proc(device.getAddr32(x, y), device.rowBytes(), mask.getAddr(x, y),
reed@google.comedb606c2011-10-18 13:56:50 +0000356 mask.fRowBytes, color, clip.width(), clip.height());
357 return true;
358 }
359 return false;
360}
361
reed@google.com1750bf12011-11-15 19:51:02 +0000362///////////////////////////////////////////////////////////////////////////////
363///////////////////////////////////////////////////////////////////////////////
364
365static void BW_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
366 const uint8_t* SK_RESTRICT mask,
367 const SkPMColor* SK_RESTRICT src, int count) {
368 int i, octuple = (count + 7) >> 3;
369 for (i = 0; i < octuple; ++i) {
370 int m = *mask++;
371 if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
372 if (m & 0x40) { dst[1] = SkPMSrcOver(src[1], dst[1]); }
373 if (m & 0x20) { dst[2] = SkPMSrcOver(src[2], dst[2]); }
374 if (m & 0x10) { dst[3] = SkPMSrcOver(src[3], dst[3]); }
375 if (m & 0x08) { dst[4] = SkPMSrcOver(src[4], dst[4]); }
376 if (m & 0x04) { dst[5] = SkPMSrcOver(src[5], dst[5]); }
377 if (m & 0x02) { dst[6] = SkPMSrcOver(src[6], dst[6]); }
378 if (m & 0x01) { dst[7] = SkPMSrcOver(src[7], dst[7]); }
379 src += 8;
380 dst += 8;
381 }
382 count &= 7;
383 if (count > 0) {
384 int m = *mask;
385 do {
386 if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
387 m <<= 1;
388 src += 1;
389 dst += 1;
390 } while (--count > 0);
391 }
392}
393
394static void BW_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
395 const uint8_t* SK_RESTRICT mask,
396 const SkPMColor* SK_RESTRICT src, int count) {
397 int i, octuple = (count + 7) >> 3;
398 for (i = 0; i < octuple; ++i) {
399 int m = *mask++;
400 if (m & 0x80) { dst[0] = src[0]; }
401 if (m & 0x40) { dst[1] = src[1]; }
402 if (m & 0x20) { dst[2] = src[2]; }
403 if (m & 0x10) { dst[3] = src[3]; }
404 if (m & 0x08) { dst[4] = src[4]; }
405 if (m & 0x04) { dst[5] = src[5]; }
406 if (m & 0x02) { dst[6] = src[6]; }
407 if (m & 0x01) { dst[7] = src[7]; }
408 src += 8;
409 dst += 8;
410 }
411 count &= 7;
412 if (count > 0) {
413 int m = *mask;
414 do {
415 if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
416 m <<= 1;
417 src += 1;
418 dst += 1;
419 } while (--count > 0);
420 }
421}
422
423static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
424 const uint8_t* SK_RESTRICT mask,
425 const SkPMColor* SK_RESTRICT src, int count) {
426 for (int i = 0; i < count; ++i) {
427 if (mask[i]) {
428 dst[i] = SkBlendARGB32(src[i], dst[i], mask[i]);
429 }
430 }
431}
432
433// expand the steps that SkAlphaMulQ performs, but this way we can
434// exand.. add.. combine
435// instead of
436// expand..combine add expand..combine
437//
438#define EXPAND0(v, m, s) ((v) & (m)) * (s)
439#define EXPAND1(v, m, s) (((v) >> 8) & (m)) * (s)
440#define COMBINE(e0, e1, m) ((((e0) >> 8) & (m)) | ((e1) & ~(m)))
441
442static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
443 const uint8_t* SK_RESTRICT mask,
444 const SkPMColor* SK_RESTRICT src, int count) {
445 const uint32_t rbmask = gMask_00FF00FF;
446 for (int i = 0; i < count; ++i) {
447 int m = mask[i];
448 if (m) {
449 m += (m >> 7);
450#if 0
451 dst[i] = SkAlphaMulQ(src[i], m) + SkAlphaMulQ(dst[i], 256 - m);
452#else
453 uint32_t v = src[i];
454 uint32_t s0 = EXPAND0(v, rbmask, m);
455 uint32_t s1 = EXPAND1(v, rbmask, m);
456 v = dst[i];
457 uint32_t d0 = EXPAND0(v, rbmask, m);
458 uint32_t d1 = EXPAND1(v, rbmask, m);
459 dst[i] = COMBINE(s0 + d0, s1 + d1, rbmask);
460#endif
461 }
462 }
463}
464
465static void LCD16_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
466 const SkPMColor* SK_RESTRICT mask,
467 const SkPMColor* SK_RESTRICT src, int count) {
468 for (int i = 0; i < count; ++i) {
469 uint16_t m = mask[i];
470 if (0 == m) {
471 continue;
472 }
473
474 SkPMColor s = src[i];
475 SkPMColor d = dst[i];
476
477 int srcA = SkGetPackedA32(s);
478 int srcR = SkGetPackedR32(s);
479 int srcG = SkGetPackedB32(s);
480 int srcB = SkGetPackedB32(s);
481
482 /* We want all of these in 5bits, hence the shifts in case one of them
483 * (green) is 6bits.
484 */
485 int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
486 int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
487 int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
488
489 // Now upscale them to 0..32, so we can use blend32
490 maskR = upscale31To32(maskR);
491 maskG = upscale31To32(maskG);
492 maskB = upscale31To32(maskB);
493
494 maskR = maskR * srcA >> 8;
495 maskG = maskG * srcA >> 8;
496 maskB = maskB * srcA >> 8;
497
498 int dstR = SkGetPackedR32(d);
499 int dstG = SkGetPackedG32(d);
500 int dstB = SkGetPackedB32(d);
501
502 // LCD blitting is only supported if the dst is known/required
503 // to be opaque
504 dst[i] = SkPackARGB32(0xFF,
505 blend32(srcR, dstR, maskR),
506 blend32(srcG, dstG, maskG),
507 blend32(srcB, dstB, maskB));
508 }
509}
510
511static void LCD16_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
512 const SkPMColor* SK_RESTRICT mask,
513 const SkPMColor* SK_RESTRICT src, int count) {
514 for (int i = 0; i < count; ++i) {
515 uint16_t m = mask[i];
516 if (0 == m) {
517 continue;
518 }
519
520 SkPMColor s = src[i];
521 SkPMColor d = dst[i];
522
523 int srcR = SkGetPackedR32(s);
524 int srcG = SkGetPackedB32(s);
525 int srcB = SkGetPackedB32(s);
526
527 /* We want all of these in 5bits, hence the shifts in case one of them
528 * (green) is 6bits.
529 */
530 int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
531 int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
532 int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
533
534 // Now upscale them to 0..32, so we can use blend32
535 maskR = upscale31To32(maskR);
536 maskG = upscale31To32(maskG);
537 maskB = upscale31To32(maskB);
538
539 int dstR = SkGetPackedR32(d);
540 int dstG = SkGetPackedG32(d);
541 int dstB = SkGetPackedB32(d);
542
543 // LCD blitting is only supported if the dst is known/required
544 // to be opaque
545 dst[i] = SkPackARGB32(0xFF,
546 blend32(srcR, dstR, maskR),
547 blend32(srcG, dstG, maskG),
548 blend32(srcB, dstB, maskB));
549 }
550}
551
552static void LCD32_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
553 const SkPMColor* SK_RESTRICT mask,
554 const SkPMColor* SK_RESTRICT src, int count) {
555 for (int i = 0; i < count; ++i) {
556 SkPMColor m = mask[i];
557 if (0 == m) {
558 continue;
559 }
560
561 SkPMColor s = src[i];
562 int srcA = SkGetPackedA32(s);
563 int srcR = SkGetPackedR32(s);
564 int srcG = SkGetPackedB32(s);
565 int srcB = SkGetPackedB32(s);
566
567 srcA = SkAlpha255To256(srcA);
568
569 SkPMColor d = dst[i];
570
571 int maskR = SkGetPackedR32(m);
572 int maskG = SkGetPackedG32(m);
573 int maskB = SkGetPackedB32(m);
574
575 // Now upscale them to 0..256, so we can use SkAlphaBlend
576 maskR = SkAlpha255To256(maskR);
577 maskG = SkAlpha255To256(maskG);
578 maskB = SkAlpha255To256(maskB);
579
580 maskR = maskR * srcA >> 8;
581 maskG = maskG * srcA >> 8;
582 maskB = maskB * srcA >> 8;
583
584 int dstR = SkGetPackedR32(d);
585 int dstG = SkGetPackedG32(d);
586 int dstB = SkGetPackedB32(d);
587
588 // LCD blitting is only supported if the dst is known/required
589 // to be opaque
590 dst[i] = SkPackARGB32(0xFF,
591 SkAlphaBlend(srcR, dstR, maskR),
592 SkAlphaBlend(srcG, dstG, maskG),
593 SkAlphaBlend(srcB, dstB, maskB));
594 }
595}
596
597static void LCD32_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
598 const SkPMColor* SK_RESTRICT mask,
599 const SkPMColor* SK_RESTRICT src, int count) {
600 for (int i = 0; i < count; ++i) {
601 SkPMColor m = mask[i];
602 if (0 == m) {
603 continue;
604 }
605
606 SkPMColor s = src[i];
607 SkPMColor d = dst[i];
608
609 int maskR = SkGetPackedR32(m);
610 int maskG = SkGetPackedG32(m);
611 int maskB = SkGetPackedB32(m);
612 int srcR = SkGetPackedR32(s);
613 int srcG = SkGetPackedB32(s);
614 int srcB = SkGetPackedB32(s);
615 int dstR = SkGetPackedR32(d);
616 int dstG = SkGetPackedG32(d);
617 int dstB = SkGetPackedB32(d);
618
619 // Now upscale them to 0..256, so we can use SkAlphaBlend
620 maskR = SkAlpha255To256(maskR);
621 maskG = SkAlpha255To256(maskG);
622 maskB = SkAlpha255To256(maskB);
623
624 // LCD blitting is only supported if the dst is known/required
625 // to be opaque
626 dst[i] = SkPackARGB32(0xFF,
627 SkAlphaBlend(srcR, dstR, maskR),
628 SkAlphaBlend(srcG, dstG, maskG),
629 SkAlphaBlend(srcB, dstB, maskB));
630 }
631}
632
633SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
634 SkMask::Format format,
635 RowFlags flags) {
636 RowProc proc = PlatformRowProcs(config, format, flags);
637 if (proc) {
638 return proc;
639 }
640
641 static const RowProc gProcs[] = {
642 // need X coordinate to handle BW
643 NULL, NULL, //(RowProc)BW_RowProc_Blend, (RowProc)BW_RowProc_Opaque,
644 (RowProc)A8_RowProc_Blend, (RowProc)A8_RowProc_Opaque,
645 (RowProc)LCD16_RowProc_Blend, (RowProc)LCD16_RowProc_Opaque,
646 (RowProc)LCD32_RowProc_Blend, (RowProc)LCD32_RowProc_Opaque,
647 };
648
649 int index;
650 switch (config) {
651 case SkBitmap::kARGB_8888_Config:
652 switch (format) {
653 case SkMask::kBW_Format: index = 0; break;
654 case SkMask::kA8_Format: index = 2; break;
655 case SkMask::kLCD16_Format: index = 4; break;
656 case SkMask::kLCD32_Format: index = 6; break;
657 default:
658 return NULL;
659 }
660 if (flags & kSrcIsOpaque_RowFlag) {
661 index |= 1;
662 }
663 SkASSERT((size_t)index < SK_ARRAY_COUNT(gProcs));
664 return gProcs[index];
665 default:
666 break;
667 }
668 return NULL;
669}
reed@google.comedb606c2011-10-18 13:56:50 +0000670