Home | History | Annotate | Download | only in core
      1 /* libs/graphics/sgl/SkBlitter_ARGB32.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkCoreBlitters.h"
     19 #include "SkColorPriv.h"
     20 #include "SkShader.h"
     21 #include "SkUtils.h"
     22 #include "SkXfermode.h"
     23 
     24 #if defined(SK_SUPPORT_LCDTEXT)
     25 namespace skia_blitter_support {
     26 // subpixel helper functions from SkBlitter_ARGB32_Subpixel.cpp
     27 uint32_t* adjustForSubpixelClip(const SkMask& mask,
     28                                 const SkIRect& clip, const SkBitmap& device,
     29                                 int* widthAdjustment, int* heightAdjustment,
     30                                 const uint32_t** alpha32);
     31 extern uint32_t BlendLCDPixelWithColor(const uint32_t alphaPixel, const uint32_t originalPixel,
     32                                        const uint32_t sourcePixel);
     33 extern uint32_t BlendLCDPixelWithOpaqueColor(const uint32_t alphaPixel, const uint32_t originalPixel,
     34                                              const uint32_t sourcePixel);
     35 extern uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t originalPixel);
     36 }
     37 
     38 using namespace skia_blitter_support;
     39 #endif
     40 
     41 ///////////////////////////////////////////////////////////////////////////////
     42 
     43 static inline int upscale31To32(int value) {
     44     SkASSERT((unsigned)value <= 31);
     45     return value + (value >> 4);
     46 }
     47 
     48 static inline int blend32(int src, int dst, int scale) {
     49     SkASSERT((unsigned)src <= 0xFF);
     50     SkASSERT((unsigned)dst <= 0xFF);
     51     SkASSERT((unsigned)scale <= 32);
     52     return dst + ((src - dst) * scale >> 5);
     53 }
     54 
     55 static void blit_lcd16_opaque(SkPMColor dst[], const uint16_t src[],
     56                               SkPMColor color, int width) {
     57     int srcR = SkGetPackedR32(color);
     58     int srcG = SkGetPackedG32(color);
     59     int srcB = SkGetPackedB32(color);
     60 
     61     for (int i = 0; i < width; i++) {
     62         uint16_t mask = src[i];
     63         if (0 == mask) {
     64             continue;
     65         }
     66 
     67         SkPMColor d = dst[i];
     68 
     69         /*  We want all of these in 5bits, hence the shifts in case one of them
     70          *  (green) is 6bits.
     71          */
     72         int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
     73         int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
     74         int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
     75 
     76         // Now upscale them to 0..256, so we can use SkAlphaBlend
     77         maskR = upscale31To32(maskR);
     78         maskG = upscale31To32(maskG);
     79         maskB = upscale31To32(maskB);
     80 
     81         int maskA = SkMax32(SkMax32(maskR, maskG), maskB);
     82 
     83         int dstA = SkGetPackedA32(d);
     84         int dstR = SkGetPackedR32(d);
     85         int dstG = SkGetPackedG32(d);
     86         int dstB = SkGetPackedB32(d);
     87 
     88         dst[i] = SkPackARGB32(blend32(0xFF, dstA, maskA),
     89                               blend32(srcR, dstR, maskR),
     90                               blend32(srcG, dstG, maskG),
     91                               blend32(srcB, dstB, maskB));
     92     }
     93 }
     94 
     95 static void blitmask_lcd16(const SkBitmap& device, const SkMask& mask,
     96                            const SkIRect& clip, SkPMColor srcColor) {
     97     int x = clip.fLeft;
     98     int y = clip.fTop;
     99     int width = clip.width();
    100     int height = clip.height();
    101 
    102     SkPMColor*		dstRow = device.getAddr32(x, y);
    103     const uint16_t* srcRow = mask.getAddrLCD16(x, y);
    104 
    105     do {
    106         blit_lcd16_opaque(dstRow, srcRow, srcColor, width);
    107         dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
    108         srcRow = (const uint16_t*)((const char*)srcRow + mask.fRowBytes);
    109     } while (--height != 0);
    110 }
    111 
    112 //////////////////////////////////////////////////////////////////////////////////////
    113 
    114 static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
    115 							const SkIRect& clip, SkPMColor srcColor) {
    116 	U8CPU alpha = SkGetPackedA32(srcColor);
    117 	unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
    118 	if (alpha != 255) {
    119 		flags |= SkBlitRow::kGlobalAlpha_Flag32;
    120 	}
    121 	SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
    122 
    123     int x = clip.fLeft;
    124     int y = clip.fTop;
    125     int width = clip.width();
    126     int height = clip.height();
    127 
    128     SkPMColor*		 dstRow = device.getAddr32(x, y);
    129     const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr(x, y));
    130 
    131     do {
    132 		proc(dstRow, srcRow, width, alpha);
    133         dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
    134         srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
    135     } while (--height != 0);
    136 }
    137 
    138 //////////////////////////////////////////////////////////////////////////////////////
    139 
    140 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
    141         : INHERITED(device) {
    142     SkColor color = paint.getColor();
    143     fColor = color;
    144 
    145     fSrcA = SkColorGetA(color);
    146     unsigned scale = SkAlpha255To256(fSrcA);
    147     fSrcR = SkAlphaMul(SkColorGetR(color), scale);
    148     fSrcG = SkAlphaMul(SkColorGetG(color), scale);
    149     fSrcB = SkAlphaMul(SkColorGetB(color), scale);
    150 
    151     fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
    152     fColor32Proc = SkBlitRow::ColorProcFactory();
    153 
    154     // init the pro for blitmask
    155     fBlitMaskProc = SkBlitMask::Factory(SkBitmap::kARGB_8888_Config, color);
    156 }
    157 
    158 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
    159     if (255 == fSrcA) {
    160         *value = fPMColor;
    161         return &fDevice;
    162     }
    163     return NULL;
    164 }
    165 
    166 #if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
    167 #pragma warning ( push )
    168 #pragma warning ( disable : 4701 )
    169 #endif
    170 
    171 void SkARGB32_Blitter::blitH(int x, int y, int width) {
    172     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
    173 
    174     uint32_t*   device = fDevice.getAddr32(x, y);
    175     fColor32Proc(device, device, width, fPMColor);
    176 }
    177 
    178 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    179                                  const int16_t runs[]) {
    180     if (fSrcA == 0) {
    181         return;
    182     }
    183 
    184     uint32_t    color = fPMColor;
    185     uint32_t*   device = fDevice.getAddr32(x, y);
    186     unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
    187 
    188     for (;;) {
    189         int count = runs[0];
    190         SkASSERT(count >= 0);
    191         if (count <= 0) {
    192             return;
    193         }
    194         unsigned aa = antialias[0];
    195         if (aa) {
    196             if ((opaqueMask & aa) == 255) {
    197                 sk_memset32(device, color, count);
    198             } else {
    199                 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
    200                 fColor32Proc(device, device, count, sc);
    201             }
    202         }
    203         runs += count;
    204         antialias += count;
    205         device += count;
    206     }
    207 }
    208 
    209 //////////////////////////////////////////////////////////////////////////////////////
    210 
    211 #define solid_8_pixels(mask, dst, color)    \
    212     do {                                    \
    213         if (mask & 0x80) dst[0] = color;    \
    214         if (mask & 0x40) dst[1] = color;    \
    215         if (mask & 0x20) dst[2] = color;    \
    216         if (mask & 0x10) dst[3] = color;    \
    217         if (mask & 0x08) dst[4] = color;    \
    218         if (mask & 0x04) dst[5] = color;    \
    219         if (mask & 0x02) dst[6] = color;    \
    220         if (mask & 0x01) dst[7] = color;    \
    221     } while (0)
    222 
    223 #define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
    224 #define SK_BLITBWMASK_ARGS                  , SkPMColor color
    225 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
    226 #define SK_BLITBWMASK_GETADDR               getAddr32
    227 #define SK_BLITBWMASK_DEVTYPE               uint32_t
    228 #include "SkBlitBWMaskTemplate.h"
    229 
    230 #define blend_8_pixels(mask, dst, sc, dst_scale)                            \
    231     do {                                                                    \
    232         if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
    233         if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
    234         if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
    235         if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
    236         if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
    237         if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
    238         if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
    239         if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
    240     } while (0)
    241 
    242 #define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
    243 #define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
    244 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
    245 #define SK_BLITBWMASK_GETADDR               getAddr32
    246 #define SK_BLITBWMASK_DEVTYPE               uint32_t
    247 #include "SkBlitBWMaskTemplate.h"
    248 
    249 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    250     SkASSERT(mask.fBounds.contains(clip));
    251     SkASSERT(fSrcA != 0xFF);
    252 
    253     if (fSrcA == 0) {
    254         return;
    255     }
    256 
    257     if (mask.fFormat == SkMask::kBW_Format) {
    258         SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
    259         return;
    260     } else if (SkMask::kARGB32_Format == mask.fFormat) {
    261 		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
    262 		return;
    263     } else if (SkMask::kLCD16_Format == mask.fFormat) {
    264         blitmask_lcd16(fDevice, mask, clip, fPMColor);
    265         return;
    266     }
    267 
    268     int x = clip.fLeft;
    269     int y = clip.fTop;
    270 
    271     fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(),
    272                   SkBitmap::kARGB_8888_Config,
    273                   mask.getAddr(x, y), mask.fRowBytes,
    274                   fColor, clip.width(), clip.height());
    275 }
    276 
    277 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
    278                                        const SkIRect& clip) {
    279     SkASSERT(mask.fBounds.contains(clip));
    280 
    281     if (mask.fFormat == SkMask::kBW_Format) {
    282         SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
    283         return;
    284     } else if (SkMask::kARGB32_Format == mask.fFormat) {
    285 		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
    286 		return;
    287     } else if (SkMask::kLCD16_Format == mask.fFormat) {
    288         blitmask_lcd16(fDevice, mask, clip, fPMColor);
    289         return;
    290 	}
    291 
    292     int x = clip.fLeft;
    293     int y = clip.fTop;
    294     int width = clip.width();
    295     int height = clip.height();
    296 
    297 #if defined(SK_SUPPORT_LCDTEXT)
    298     const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
    299     const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format;
    300 
    301     // In LCD mode the masks have either an extra couple of rows or columns on the edges.
    302     if (lcdMode || verticalLCDMode) {
    303         int widthAdjustment, heightAdjustment;
    304         const uint32_t* alpha32;
    305         uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32);
    306 
    307         width += widthAdjustment;
    308         height += heightAdjustment;
    309 
    310         unsigned devRB = fDevice.rowBytes() - (width << 2);
    311         unsigned alphaExtraRowWords = mask.rowWordsLCD() - width;
    312         SkPMColor srcColor = fPMColor;
    313 
    314         do {
    315             unsigned w = width;
    316             do {
    317                 const uint32_t alphaPixel = *alpha32++;
    318                 const uint32_t originalPixel = *device;
    319                 *device++ = BlendLCDPixelWithOpaqueColor(alphaPixel, originalPixel, srcColor);
    320             } while (--w != 0);
    321             device = (uint32_t*)((char*)device + devRB);
    322             alpha32 += alphaExtraRowWords;
    323         } while (--height != 0);
    324 
    325         return;
    326     }
    327 #endif
    328 
    329     fBlitMaskProc(fDevice.getAddr32(x, y), fDevice.rowBytes(),
    330                   SkBitmap::kARGB_8888_Config,
    331                   mask.getAddr(x, y), mask.fRowBytes, fColor, width, height);
    332 }
    333 
    334 //////////////////////////////////////////////////////////////////////////////////////
    335 
    336 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    337     if (alpha == 0 || fSrcA == 0) {
    338         return;
    339     }
    340 
    341     uint32_t* device = fDevice.getAddr32(x, y);
    342     uint32_t  color = fPMColor;
    343 
    344     if (alpha != 255) {
    345         color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
    346     }
    347 
    348     unsigned dst_scale = 255 - SkGetPackedA32(color);
    349     uint32_t prevDst = ~device[0];
    350     uint32_t result  SK_INIT_TO_AVOID_WARNING;
    351     uint32_t rowBytes = fDevice.rowBytes();
    352 
    353     while (--height >= 0) {
    354         uint32_t dst = device[0];
    355         if (dst != prevDst) {
    356             result = color + SkAlphaMulQ(dst, dst_scale);
    357             prevDst = dst;
    358         }
    359         device[0] = result;
    360         device = (uint32_t*)((char*)device + rowBytes);
    361     }
    362 }
    363 
    364 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
    365     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
    366 
    367     if (fSrcA == 0) {
    368         return;
    369     }
    370 
    371     uint32_t*   device = fDevice.getAddr32(x, y);
    372     uint32_t    color = fPMColor;
    373     size_t      rowBytes = fDevice.rowBytes();
    374 
    375     while (--height >= 0) {
    376         fColor32Proc(device, device, width, color);
    377         device = (uint32_t*)((char*)device + rowBytes);
    378     }
    379 }
    380 
    381 #if defined _WIN32 && _MSC_VER >= 1300
    382 #pragma warning ( pop )
    383 #endif
    384 
    385 ///////////////////////////////////////////////////////////////////////
    386 
    387 void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    388     SkASSERT(mask.fBounds.contains(clip));
    389 
    390     if (mask.fFormat == SkMask::kBW_Format) {
    391         SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
    392 
    393         SkARGB32_BlitBW(fDevice, mask, clip, black);
    394     } else if (SkMask::kARGB32_Format == mask.fFormat) {
    395 		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
    396     } else if (SkMask::kLCD16_Format == mask.fFormat) {
    397         blitmask_lcd16(fDevice, mask, clip, fPMColor);
    398     } else {
    399 #if defined(SK_SUPPORT_LCDTEXT)
    400         const bool      lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
    401         const bool      verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format;
    402 #endif
    403 
    404         // In LCD mode the masks have either an extra couple of rows or columns on the edges.
    405         unsigned        width = clip.width();
    406         unsigned        height = clip.height();
    407 
    408         SkASSERT((int)height > 0);
    409         SkASSERT((int)width > 0);
    410 
    411 #if defined(SK_SUPPORT_LCDTEXT)
    412         if (lcdMode || verticalLCDMode) {
    413             int widthAdjustment, heightAdjustment;
    414             const uint32_t* alpha32;
    415             uint32_t* device = adjustForSubpixelClip(mask, clip, fDevice, &widthAdjustment, &heightAdjustment, &alpha32);
    416 
    417             width += widthAdjustment;
    418             height += heightAdjustment;
    419 
    420             unsigned deviceRB = fDevice.rowBytes() - (width << 2);
    421             unsigned alphaExtraRowWords = mask.rowWordsLCD() - width;
    422 
    423             do {
    424                 unsigned w = width;
    425                 do {
    426                     const uint32_t alphaPixel = *alpha32++;
    427                     const uint32_t originalPixel = *device;
    428                     *device++ = BlendLCDPixelWithBlack(alphaPixel, originalPixel);
    429                 } while (--w != 0);
    430                 device = (uint32_t*)((char*)device + deviceRB);
    431                 alpha32 += alphaExtraRowWords;
    432             } while (--height != 0);
    433 
    434             return;
    435         }
    436 #endif
    437 
    438         uint32_t*      device = fDevice.getAddr32(clip.fLeft, clip.fTop);
    439         unsigned       maskRB = mask.fRowBytes - width;
    440         unsigned       deviceRB = fDevice.rowBytes() - (width << 2);
    441         const uint8_t* alpha = mask.getAddr(clip.fLeft, clip.fTop);
    442         do {
    443             unsigned w = width;
    444             do {
    445                 unsigned aa = *alpha++;
    446                 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
    447                 device += 1;
    448             } while (--w != 0);
    449             device = (uint32_t*)((char*)device + deviceRB);
    450             alpha += maskRB;
    451         } while (--height != 0);
    452     }
    453 }
    454 
    455 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    456                                        const int16_t runs[]) {
    457     uint32_t*   device = fDevice.getAddr32(x, y);
    458     SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
    459 
    460     for (;;) {
    461         int count = runs[0];
    462         SkASSERT(count >= 0);
    463         if (count <= 0) {
    464             return;
    465         }
    466         unsigned aa = antialias[0];
    467         if (aa) {
    468             if (aa == 255) {
    469                 sk_memset32(device, black, count);
    470             } else {
    471                 SkPMColor src = aa << SK_A32_SHIFT;
    472                 unsigned dst_scale = 256 - aa;
    473                 int n = count;
    474                 do {
    475                     --n;
    476                     device[n] = src + SkAlphaMulQ(device[n], dst_scale);
    477                 } while (n > 0);
    478             }
    479         }
    480         runs += count;
    481         antialias += count;
    482         device += count;
    483     }
    484 }
    485 
    486 //////////////////////////////////////////////////////////////////////////////////////////
    487 
    488 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
    489                             const SkPaint& paint) : INHERITED(device, paint) {
    490     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
    491 
    492     fXfermode = paint.getXfermode();
    493     SkSafeRef(fXfermode);
    494 
    495     int flags = 0;
    496     if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
    497         flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
    498     }
    499     // we call this on the output from the shader
    500     fProc32 = SkBlitRow::Factory32(flags);
    501     // we call this on the output from the shader + alpha from the aa buffer
    502     fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
    503 }
    504 
    505 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
    506     SkSafeUnref(fXfermode);
    507     sk_free(fBuffer);
    508 }
    509 
    510 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
    511     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
    512 
    513     uint32_t*   device = fDevice.getAddr32(x, y);
    514 
    515     if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
    516         fShader->shadeSpan(x, y, device, width);
    517     } else {
    518         SkPMColor*  span = fBuffer;
    519         fShader->shadeSpan(x, y, span, width);
    520         if (fXfermode) {
    521             fXfermode->xfer32(device, span, width, NULL);
    522         } else {
    523             fProc32(device, span, width, 255);
    524         }
    525     }
    526 }
    527 
    528 ///////////////////////////////////////////////////////////////////////////////////////////////
    529 
    530 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    531                                         const int16_t runs[]) {
    532     SkPMColor*  span = fBuffer;
    533     uint32_t*   device = fDevice.getAddr32(x, y);
    534     SkShader*   shader = fShader;
    535 
    536     if (fXfermode) {
    537         for (;;) {
    538             SkXfermode* xfer = fXfermode;
    539 
    540             int count = *runs;
    541             if (count <= 0)
    542                 break;
    543             int aa = *antialias;
    544             if (aa) {
    545                 shader->shadeSpan(x, y, span, count);
    546                 if (aa == 255) {
    547                     xfer->xfer32(device, span, count, NULL);
    548                 } else {
    549                     // count is almost always 1
    550                     for (int i = count - 1; i >= 0; --i) {
    551                         xfer->xfer32(&device[i], &span[i], 1, antialias);
    552                     }
    553                 }
    554             }
    555             device += count;
    556             runs += count;
    557             antialias += count;
    558             x += count;
    559         }
    560     } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
    561         for (;;) {
    562             int count = *runs;
    563             if (count <= 0) {
    564                 break;
    565             }
    566             int aa = *antialias;
    567             if (aa) {
    568                 if (aa == 255) {
    569                     // cool, have the shader draw right into the device
    570                     shader->shadeSpan(x, y, device, count);
    571                 } else {
    572                     shader->shadeSpan(x, y, span, count);
    573                     fProc32Blend(device, span, count, aa);
    574                 }
    575             }
    576             device += count;
    577             runs += count;
    578             antialias += count;
    579             x += count;
    580         }
    581     } else {    // no xfermode but the shader not opaque
    582         for (;;) {
    583             int count = *runs;
    584             if (count <= 0) {
    585                 break;
    586             }
    587             int aa = *antialias;
    588             if (aa) {
    589                 fShader->shadeSpan(x, y, span, count);
    590                 if (aa == 255) {
    591                     fProc32(device, span, count, 255);
    592                 } else {
    593                     fProc32Blend(device, span, count, aa);
    594                 }
    595             }
    596             device += count;
    597             runs += count;
    598             antialias += count;
    599             x += count;
    600         }
    601     }
    602 }
    603