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