Home | History | Annotate | Download | only in core
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    236 static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
    237     return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
    238 }
    239 
    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 
    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 
    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 
    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 
    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 
    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 
    385 static int upscale31To255(int value) {
    386     value = (value << 3) | (value >> 2);
    387     return value;
    388 }
    389 
    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 
    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 
    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 
    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 
    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 
    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