Home | History | Annotate | Download | only in core
      1 #include "SkBlitMask.h"
      2 #include "SkColor.h"
      3 #include "SkColorPriv.h"
      4 
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    229 static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
    230     return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
    231 }
    232 
    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 
    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 
    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 
    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 
    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 
    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 
    379 static int upscale31To255(int value) {
    380     value = (value << 3) | (value >> 2);
    381     return value;
    382 }
    383 
    384 static int mul(int a, int b) {
    385     return a * b >> 8;
    386 }
    387 
    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 
    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 
    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 
    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 
    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 
    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