• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkBlitMask.h"
2 #include "SkColor.h"
3 #include "SkColorPriv.h"
4 
D32_A8_Color(void * SK_RESTRICT dst,size_t dstRB,const void * SK_RESTRICT maskPtr,size_t maskRB,SkColor color,int width,int height)5 static 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 
D32_A8_Opaque(void * SK_RESTRICT dst,size_t dstRB,const void * SK_RESTRICT maskPtr,size_t maskRB,SkColor color,int width,int height)26 static 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 
D32_A8_Black(void * SK_RESTRICT dst,size_t dstRB,const void * SK_RESTRICT maskPtr,size_t maskRB,SkColor,int width,int height)47 static 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 
BlitLCD16RowFactory(bool isOpaque)67 SkBlitMask::BlitLCD16RowProc SkBlitMask::BlitLCD16RowFactory(bool isOpaque) {
68     BlitLCD16RowProc proc = PlatformBlitRowProcs16(isOpaque);
69     if (proc) {
70         return proc;
71     }
72 
73     if (isOpaque) {
74         return  SkBlitLCD16OpaqueRow;
75     } else {
76         return  SkBlitLCD16Row;
77     }
78 }
79 
D32_LCD16_Proc(void * SK_RESTRICT dst,size_t dstRB,const void * SK_RESTRICT mask,size_t maskRB,SkColor color,int width,int height)80 static void D32_LCD16_Proc(void* SK_RESTRICT dst, size_t dstRB,
81                            const void* SK_RESTRICT mask, size_t maskRB,
82                            SkColor color, int width, int height) {
83 
84     SkPMColor*		dstRow = (SkPMColor*)dst;
85     const uint16_t* srcRow = (const uint16_t*)mask;
86     SkPMColor       opaqueDst;
87 
88     SkBlitMask::BlitLCD16RowProc proc = NULL;
89     bool isOpaque = (0xFF == SkColorGetA(color));
90     proc = SkBlitMask::BlitLCD16RowFactory(isOpaque);
91     SkASSERT(proc != NULL);
92 
93     if (isOpaque) {
94         opaqueDst = SkPreMultiplyColor(color);
95     } else {
96         opaqueDst = 0;  // ignored
97     }
98 
99     do {
100         proc(dstRow, srcRow, color, width, opaqueDst);
101         dstRow = (SkPMColor*)((char*)dstRow + dstRB);
102         srcRow = (const uint16_t*)((const char*)srcRow + maskRB);
103     } while (--height != 0);
104 }
105 
106 ///////////////////////////////////////////////////////////////////////////////
107 
blit_lcd32_opaque_row(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,SkColor color,int width)108 static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst,
109                                   const SkPMColor* SK_RESTRICT src,
110                                   SkColor color, int width) {
111     int srcR = SkColorGetR(color);
112     int srcG = SkColorGetG(color);
113     int srcB = SkColorGetB(color);
114 
115     for (int i = 0; i < width; i++) {
116         SkPMColor mask = src[i];
117         if (0 == mask) {
118             continue;
119         }
120 
121         SkPMColor d = dst[i];
122 
123         int maskR = SkGetPackedR32(mask);
124         int maskG = SkGetPackedG32(mask);
125         int maskB = SkGetPackedB32(mask);
126 
127         // Now upscale them to 0..256, so we can use SkAlphaBlend
128         maskR = SkAlpha255To256(maskR);
129         maskG = SkAlpha255To256(maskG);
130         maskB = SkAlpha255To256(maskB);
131 
132         int dstR = SkGetPackedR32(d);
133         int dstG = SkGetPackedG32(d);
134         int dstB = SkGetPackedB32(d);
135 
136         // LCD blitting is only supported if the dst is known/required
137         // to be opaque
138         dst[i] = SkPackARGB32(0xFF,
139                               SkAlphaBlend(srcR, dstR, maskR),
140                               SkAlphaBlend(srcG, dstG, maskG),
141                               SkAlphaBlend(srcB, dstB, maskB));
142     }
143 }
144 
blit_lcd32_row(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,SkColor color,int width)145 static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst,
146                            const SkPMColor* SK_RESTRICT src,
147                            SkColor color, int width) {
148     int srcA = SkColorGetA(color);
149     int srcR = SkColorGetR(color);
150     int srcG = SkColorGetG(color);
151     int srcB = SkColorGetB(color);
152 
153     srcA = SkAlpha255To256(srcA);
154 
155     for (int i = 0; i < width; i++) {
156         SkPMColor mask = src[i];
157         if (0 == mask) {
158             continue;
159         }
160 
161         SkPMColor d = dst[i];
162 
163         int maskR = SkGetPackedR32(mask);
164         int maskG = SkGetPackedG32(mask);
165         int maskB = SkGetPackedB32(mask);
166 
167         // Now upscale them to 0..256, so we can use SkAlphaBlend
168         maskR = SkAlpha255To256(maskR);
169         maskG = SkAlpha255To256(maskG);
170         maskB = SkAlpha255To256(maskB);
171 
172         maskR = maskR * srcA >> 8;
173         maskG = maskG * srcA >> 8;
174         maskB = maskB * srcA >> 8;
175 
176         int dstR = SkGetPackedR32(d);
177         int dstG = SkGetPackedG32(d);
178         int dstB = SkGetPackedB32(d);
179 
180         // LCD blitting is only supported if the dst is known/required
181         // to be opaque
182         dst[i] = SkPackARGB32(0xFF,
183                               SkAlphaBlend(srcR, dstR, maskR),
184                               SkAlphaBlend(srcG, dstG, maskG),
185                               SkAlphaBlend(srcB, dstB, maskB));
186     }
187 }
188 
D32_LCD32_Blend(void * SK_RESTRICT dst,size_t dstRB,const void * SK_RESTRICT mask,size_t maskRB,SkColor color,int width,int height)189 static void D32_LCD32_Blend(void* SK_RESTRICT dst, size_t dstRB,
190                             const void* SK_RESTRICT mask, size_t maskRB,
191                             SkColor color, int width, int height) {
192     SkASSERT(height > 0);
193     SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
194     const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
195 
196     do {
197         blit_lcd32_row(dstRow, srcRow, color, width);
198         dstRow = (SkPMColor*)((char*)dstRow + dstRB);
199         srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
200     } while (--height != 0);
201 }
202 
D32_LCD32_Opaque(void * SK_RESTRICT dst,size_t dstRB,const void * SK_RESTRICT mask,size_t maskRB,SkColor color,int width,int height)203 static void D32_LCD32_Opaque(void* SK_RESTRICT dst, size_t dstRB,
204                              const void* SK_RESTRICT mask, size_t maskRB,
205                              SkColor color, int width, int height) {
206     SkASSERT(height > 0);
207     SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
208     const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
209 
210     do {
211         blit_lcd32_opaque_row(dstRow, srcRow, color, width);
212         dstRow = (SkPMColor*)((char*)dstRow + dstRB);
213         srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
214     } while (--height != 0);
215 }
216 
217 ///////////////////////////////////////////////////////////////////////////////
218 
D32_A8_Factory(SkColor color)219 static SkBlitMask::ColorProc D32_A8_Factory(SkColor color) {
220     if (SK_ColorBLACK == color) {
221         return D32_A8_Black;
222     } else if (0xFF == SkColorGetA(color)) {
223         return D32_A8_Opaque;
224     } else {
225         return D32_A8_Color;
226     }
227 }
228 
D32_LCD32_Factory(SkColor color)229 static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
230     return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
231 }
232 
ColorFactory(SkBitmap::Config config,SkMask::Format format,SkColor color)233 SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkBitmap::Config config,
234                                                SkMask::Format format,
235                                                SkColor color) {
236     ColorProc proc = PlatformColorProcs(config, format, color);
237     if (proc) {
238         return proc;
239     }
240 
241     switch (config) {
242         case SkBitmap::kARGB_8888_Config:
243             switch (format) {
244                 case SkMask::kA8_Format:
245                     return D32_A8_Factory(color);
246                 case SkMask::kLCD16_Format:
247                     return D32_LCD16_Proc;
248                 case SkMask::kLCD32_Format:
249                     return D32_LCD32_Factory(color);
250                 default:
251                     break;
252             }
253             break;
254         default:
255             break;
256     }
257     return NULL;
258 }
259 
BlitColor(const SkBitmap & device,const SkMask & mask,const SkIRect & clip,SkColor color)260 bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
261                            const SkIRect& clip, SkColor color) {
262     ColorProc proc = ColorFactory(device.config(), mask.fFormat, color);
263     if (proc) {
264         int x = clip.fLeft;
265         int y = clip.fTop;
266         proc(device.getAddr32(x, y), device.rowBytes(), mask.getAddr(x, y),
267              mask.fRowBytes, color, clip.width(), clip.height());
268         return true;
269     }
270     return false;
271 }
272 
273 ///////////////////////////////////////////////////////////////////////////////
274 ///////////////////////////////////////////////////////////////////////////////
275 
BW_RowProc_Blend(SkPMColor * SK_RESTRICT dst,const uint8_t * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)276 static void BW_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
277                              const uint8_t* SK_RESTRICT mask,
278                              const SkPMColor* SK_RESTRICT src, int count) {
279     int i, octuple = (count + 7) >> 3;
280     for (i = 0; i < octuple; ++i) {
281         int m = *mask++;
282         if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
283         if (m & 0x40) { dst[1] = SkPMSrcOver(src[1], dst[1]); }
284         if (m & 0x20) { dst[2] = SkPMSrcOver(src[2], dst[2]); }
285         if (m & 0x10) { dst[3] = SkPMSrcOver(src[3], dst[3]); }
286         if (m & 0x08) { dst[4] = SkPMSrcOver(src[4], dst[4]); }
287         if (m & 0x04) { dst[5] = SkPMSrcOver(src[5], dst[5]); }
288         if (m & 0x02) { dst[6] = SkPMSrcOver(src[6], dst[6]); }
289         if (m & 0x01) { dst[7] = SkPMSrcOver(src[7], dst[7]); }
290         src += 8;
291         dst += 8;
292     }
293     count &= 7;
294     if (count > 0) {
295         int m = *mask;
296         do {
297             if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
298             m <<= 1;
299             src += 1;
300             dst += 1;
301         } while (--count > 0);
302     }
303 }
304 
BW_RowProc_Opaque(SkPMColor * SK_RESTRICT dst,const uint8_t * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)305 static void BW_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
306                               const uint8_t* SK_RESTRICT mask,
307                               const SkPMColor* SK_RESTRICT src, int count) {
308     int i, octuple = (count + 7) >> 3;
309     for (i = 0; i < octuple; ++i) {
310         int m = *mask++;
311         if (m & 0x80) { dst[0] = src[0]; }
312         if (m & 0x40) { dst[1] = src[1]; }
313         if (m & 0x20) { dst[2] = src[2]; }
314         if (m & 0x10) { dst[3] = src[3]; }
315         if (m & 0x08) { dst[4] = src[4]; }
316         if (m & 0x04) { dst[5] = src[5]; }
317         if (m & 0x02) { dst[6] = src[6]; }
318         if (m & 0x01) { dst[7] = src[7]; }
319         src += 8;
320         dst += 8;
321     }
322     count &= 7;
323     if (count > 0) {
324         int m = *mask;
325         do {
326             if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
327             m <<= 1;
328             src += 1;
329             dst += 1;
330         } while (--count > 0);
331     }
332 }
333 
A8_RowProc_Blend(SkPMColor * SK_RESTRICT dst,const uint8_t * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)334 static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
335                              const uint8_t* SK_RESTRICT mask,
336                              const SkPMColor* SK_RESTRICT src, int count) {
337     for (int i = 0; i < count; ++i) {
338         if (mask[i]) {
339             dst[i] = SkBlendARGB32(src[i], dst[i], mask[i]);
340         }
341     }
342 }
343 
344 // expand the steps that SkAlphaMulQ performs, but this way we can
345 //  exand.. add.. combine
346 // instead of
347 // expand..combine add expand..combine
348 //
349 #define EXPAND0(v, m, s)    ((v) & (m)) * (s)
350 #define EXPAND1(v, m, s)    (((v) >> 8) & (m)) * (s)
351 #define COMBINE(e0, e1, m)  ((((e0) >> 8) & (m)) | ((e1) & ~(m)))
352 
A8_RowProc_Opaque(SkPMColor * SK_RESTRICT dst,const uint8_t * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)353 static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
354                               const uint8_t* SK_RESTRICT mask,
355                               const SkPMColor* SK_RESTRICT src, int count) {
356     const uint32_t rbmask = gMask_00FF00FF;
357     for (int i = 0; i < count; ++i) {
358         int m = mask[i];
359         if (m) {
360             m += (m >> 7);
361 #if 1
362             // this is slightly slower than the expand/combine version, but it
363             // is much closer to the old results, so we use it for now to reduce
364             // rebaselining.
365             dst[i] = SkAlphaMulQ(src[i], m) + SkAlphaMulQ(dst[i], 256 - m);
366 #else
367             uint32_t v = src[i];
368             uint32_t s0 = EXPAND0(v, rbmask, m);
369             uint32_t s1 = EXPAND1(v, rbmask, m);
370             v = dst[i];
371             uint32_t d0 = EXPAND0(v, rbmask, m);
372             uint32_t d1 = EXPAND1(v, rbmask, m);
373             dst[i] = COMBINE(s0 + d0, s1 + d1, rbmask);
374 #endif
375         }
376     }
377 }
378 
upscale31To255(int value)379 static int upscale31To255(int value) {
380     value = (value << 3) | (value >> 2);
381     return value;
382 }
383 
mul(int a,int b)384 static int mul(int a, int b) {
385     return a * b >> 8;
386 }
387 
src_alpha_blend(int src,int dst,int srcA,int mask)388 static int src_alpha_blend(int src, int dst, int srcA, int mask) {
389 
390     return dst + mul(src - mul(srcA, dst), mask);
391 }
392 
LCD16_RowProc_Blend(SkPMColor * SK_RESTRICT dst,const uint16_t * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)393 static void LCD16_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
394                                 const uint16_t* SK_RESTRICT mask,
395                                 const SkPMColor* SK_RESTRICT src, int count) {
396     for (int i = 0; i < count; ++i) {
397         uint16_t m = mask[i];
398         if (0 == m) {
399             continue;
400         }
401 
402         SkPMColor s = src[i];
403         SkPMColor d = dst[i];
404 
405         int srcA = SkGetPackedA32(s);
406         int srcR = SkGetPackedR32(s);
407         int srcG = SkGetPackedG32(s);
408         int srcB = SkGetPackedB32(s);
409 
410         srcA += srcA >> 7;
411 
412         /*  We want all of these in 5bits, hence the shifts in case one of them
413          *  (green) is 6bits.
414          */
415         int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
416         int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
417         int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
418 
419         maskR = upscale31To255(maskR);
420         maskG = upscale31To255(maskG);
421         maskB = upscale31To255(maskB);
422 
423         int dstR = SkGetPackedR32(d);
424         int dstG = SkGetPackedG32(d);
425         int dstB = SkGetPackedB32(d);
426 
427         // LCD blitting is only supported if the dst is known/required
428         // to be opaque
429         dst[i] = SkPackARGB32(0xFF,
430                               src_alpha_blend(srcR, dstR, srcA, maskR),
431                               src_alpha_blend(srcG, dstG, srcA, maskG),
432                               src_alpha_blend(srcB, dstB, srcA, maskB));
433     }
434 }
435 
LCD16_RowProc_Opaque(SkPMColor * SK_RESTRICT dst,const uint16_t * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)436 static void LCD16_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
437                                  const uint16_t* SK_RESTRICT mask,
438                                  const SkPMColor* SK_RESTRICT src, int count) {
439     for (int i = 0; i < count; ++i) {
440         uint16_t m = mask[i];
441         if (0 == m) {
442             continue;
443         }
444 
445         SkPMColor s = src[i];
446         SkPMColor d = dst[i];
447 
448         int srcR = SkGetPackedR32(s);
449         int srcG = SkGetPackedG32(s);
450         int srcB = SkGetPackedB32(s);
451 
452         /*  We want all of these in 5bits, hence the shifts in case one of them
453          *  (green) is 6bits.
454          */
455         int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
456         int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
457         int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
458 
459         // Now upscale them to 0..32, so we can use blend32
460         maskR = SkUpscale31To32(maskR);
461         maskG = SkUpscale31To32(maskG);
462         maskB = SkUpscale31To32(maskB);
463 
464         int dstR = SkGetPackedR32(d);
465         int dstG = SkGetPackedG32(d);
466         int dstB = SkGetPackedB32(d);
467 
468         // LCD blitting is only supported if the dst is known/required
469         // to be opaque
470         dst[i] = SkPackARGB32(0xFF,
471                               SkBlend32(srcR, dstR, maskR),
472                               SkBlend32(srcG, dstG, maskG),
473                               SkBlend32(srcB, dstB, maskB));
474     }
475 }
476 
LCD32_RowProc_Blend(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)477 static void LCD32_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
478                                 const SkPMColor* SK_RESTRICT mask,
479                                 const SkPMColor* SK_RESTRICT src, int count) {
480     for (int i = 0; i < count; ++i) {
481         SkPMColor m = mask[i];
482         if (0 == m) {
483             continue;
484         }
485 
486         SkPMColor s = src[i];
487         int srcA = SkGetPackedA32(s);
488         int srcR = SkGetPackedR32(s);
489         int srcG = SkGetPackedG32(s);
490         int srcB = SkGetPackedB32(s);
491 
492         srcA = SkAlpha255To256(srcA);
493 
494         SkPMColor d = dst[i];
495 
496         int maskR = SkGetPackedR32(m);
497         int maskG = SkGetPackedG32(m);
498         int maskB = SkGetPackedB32(m);
499 
500         // Now upscale them to 0..256
501         maskR = SkAlpha255To256(maskR);
502         maskG = SkAlpha255To256(maskG);
503         maskB = SkAlpha255To256(maskB);
504 
505         int dstR = SkGetPackedR32(d);
506         int dstG = SkGetPackedG32(d);
507         int dstB = SkGetPackedB32(d);
508 
509         // LCD blitting is only supported if the dst is known/required
510         // to be opaque
511         dst[i] = SkPackARGB32(0xFF,
512                               src_alpha_blend(srcR, dstR, srcA, maskR),
513                               src_alpha_blend(srcG, dstG, srcA, maskG),
514                               src_alpha_blend(srcB, dstB, srcA, maskB));
515     }
516 }
517 
LCD32_RowProc_Opaque(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT mask,const SkPMColor * SK_RESTRICT src,int count)518 static void LCD32_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
519                                  const SkPMColor* SK_RESTRICT mask,
520                                  const SkPMColor* SK_RESTRICT src, int count) {
521     for (int i = 0; i < count; ++i) {
522         SkPMColor m = mask[i];
523         if (0 == m) {
524             continue;
525         }
526 
527         SkPMColor s = src[i];
528         SkPMColor d = dst[i];
529 
530         int maskR = SkGetPackedR32(m);
531         int maskG = SkGetPackedG32(m);
532         int maskB = SkGetPackedB32(m);
533 
534         int srcR = SkGetPackedR32(s);
535         int srcG = SkGetPackedG32(s);
536         int srcB = SkGetPackedB32(s);
537 
538         int dstR = SkGetPackedR32(d);
539         int dstG = SkGetPackedG32(d);
540         int dstB = SkGetPackedB32(d);
541 
542         // Now upscale them to 0..256, so we can use SkAlphaBlend
543         maskR = SkAlpha255To256(maskR);
544         maskG = SkAlpha255To256(maskG);
545         maskB = SkAlpha255To256(maskB);
546 
547         // LCD blitting is only supported if the dst is known/required
548         // to be opaque
549         dst[i] = SkPackARGB32(0xFF,
550                               SkAlphaBlend(srcR, dstR, maskR),
551                               SkAlphaBlend(srcG, dstG, maskG),
552                               SkAlphaBlend(srcB, dstB, maskB));
553     }
554 }
555 
RowFactory(SkBitmap::Config config,SkMask::Format format,RowFlags flags)556 SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
557                                            SkMask::Format format,
558                                            RowFlags flags) {
559 // make this opt-in until chrome can rebaseline
560     RowProc proc = PlatformRowProcs(config, format, flags);
561     if (proc) {
562         return proc;
563     }
564 
565     static const RowProc gProcs[] = {
566         // need X coordinate to handle BW
567         NULL, NULL, //(RowProc)BW_RowProc_Blend,      (RowProc)BW_RowProc_Opaque,
568         (RowProc)A8_RowProc_Blend,      (RowProc)A8_RowProc_Opaque,
569         (RowProc)LCD16_RowProc_Blend,   (RowProc)LCD16_RowProc_Opaque,
570         (RowProc)LCD32_RowProc_Blend,   (RowProc)LCD32_RowProc_Opaque,
571     };
572 
573     int index;
574     switch (config) {
575         case SkBitmap::kARGB_8888_Config:
576             switch (format) {
577                 case SkMask::kBW_Format:    index = 0; break;
578                 case SkMask::kA8_Format:    index = 2; break;
579                 case SkMask::kLCD16_Format: index = 4; break;
580                 case SkMask::kLCD32_Format: index = 6; break;
581                 default:
582                     return NULL;
583             }
584             if (flags & kSrcIsOpaque_RowFlag) {
585                 index |= 1;
586             }
587             SkASSERT((size_t)index < SK_ARRAY_COUNT(gProcs));
588             return gProcs[index];
589         default:
590             break;
591     }
592     return NULL;
593 }
594 
595