Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 "SkCoreBlitters.h"
      9 #include "SkColorPriv.h"
     10 #include "SkShader.h"
     11 #include "SkUtils.h"
     12 #include "SkXfermode.h"
     13 #include "SkBlitMask.h"
     14 
     15 ///////////////////////////////////////////////////////////////////////////////
     16 
     17 static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
     18                             const SkIRect& clip, SkPMColor srcColor) {
     19     U8CPU alpha = SkGetPackedA32(srcColor);
     20     unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
     21     if (alpha != 255) {
     22         flags |= SkBlitRow::kGlobalAlpha_Flag32;
     23     }
     24     SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
     25 
     26     int x = clip.fLeft;
     27     int y = clip.fTop;
     28     int width = clip.width();
     29     int height = clip.height();
     30 
     31     SkPMColor*         dstRow = device.getAddr32(x, y);
     32     const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
     33 
     34     do {
     35         proc(dstRow, srcRow, width, alpha);
     36         dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
     37         srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
     38     } while (--height != 0);
     39 }
     40 
     41 //////////////////////////////////////////////////////////////////////////////////////
     42 
     43 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
     44         : INHERITED(device) {
     45     SkColor color = paint.getColor();
     46     fColor = color;
     47 
     48     fSrcA = SkColorGetA(color);
     49     unsigned scale = SkAlpha255To256(fSrcA);
     50     fSrcR = SkAlphaMul(SkColorGetR(color), scale);
     51     fSrcG = SkAlphaMul(SkColorGetG(color), scale);
     52     fSrcB = SkAlphaMul(SkColorGetB(color), scale);
     53 
     54     fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
     55     fColor32Proc = SkBlitRow::ColorProcFactory();
     56     fColorRect32Proc = SkBlitRow::ColorRectProcFactory();
     57 }
     58 
     59 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
     60     if (255 == fSrcA) {
     61         *value = fPMColor;
     62         return &fDevice;
     63     }
     64     return NULL;
     65 }
     66 
     67 #if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
     68 #pragma warning ( push )
     69 #pragma warning ( disable : 4701 )
     70 #endif
     71 
     72 void SkARGB32_Blitter::blitH(int x, int y, int width) {
     73     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
     74 
     75     uint32_t*   device = fDevice.getAddr32(x, y);
     76     fColor32Proc(device, device, width, fPMColor);
     77 }
     78 
     79 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
     80                                  const int16_t runs[]) {
     81     if (fSrcA == 0) {
     82         return;
     83     }
     84 
     85     uint32_t    color = fPMColor;
     86     uint32_t*   device = fDevice.getAddr32(x, y);
     87     unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
     88 
     89     for (;;) {
     90         int count = runs[0];
     91         SkASSERT(count >= 0);
     92         if (count <= 0) {
     93             return;
     94         }
     95         unsigned aa = antialias[0];
     96         if (aa) {
     97             if ((opaqueMask & aa) == 255) {
     98                 sk_memset32(device, color, count);
     99             } else {
    100                 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
    101                 fColor32Proc(device, device, count, sc);
    102             }
    103         }
    104         runs += count;
    105         antialias += count;
    106         device += count;
    107     }
    108 }
    109 
    110 //////////////////////////////////////////////////////////////////////////////////////
    111 
    112 #define solid_8_pixels(mask, dst, color)    \
    113     do {                                    \
    114         if (mask & 0x80) dst[0] = color;    \
    115         if (mask & 0x40) dst[1] = color;    \
    116         if (mask & 0x20) dst[2] = color;    \
    117         if (mask & 0x10) dst[3] = color;    \
    118         if (mask & 0x08) dst[4] = color;    \
    119         if (mask & 0x04) dst[5] = color;    \
    120         if (mask & 0x02) dst[6] = color;    \
    121         if (mask & 0x01) dst[7] = color;    \
    122     } while (0)
    123 
    124 #define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
    125 #define SK_BLITBWMASK_ARGS                  , SkPMColor color
    126 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
    127 #define SK_BLITBWMASK_GETADDR               getAddr32
    128 #define SK_BLITBWMASK_DEVTYPE               uint32_t
    129 #include "SkBlitBWMaskTemplate.h"
    130 
    131 #define blend_8_pixels(mask, dst, sc, dst_scale)                            \
    132     do {                                                                    \
    133         if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
    134         if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
    135         if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
    136         if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
    137         if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
    138         if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
    139         if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
    140         if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
    141     } while (0)
    142 
    143 #define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
    144 #define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
    145 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
    146 #define SK_BLITBWMASK_GETADDR               getAddr32
    147 #define SK_BLITBWMASK_DEVTYPE               uint32_t
    148 #include "SkBlitBWMaskTemplate.h"
    149 
    150 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    151     SkASSERT(mask.fBounds.contains(clip));
    152     SkASSERT(fSrcA != 0xFF);
    153 
    154     if (fSrcA == 0) {
    155         return;
    156     }
    157 
    158     if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
    159         return;
    160     }
    161 
    162     if (mask.fFormat == SkMask::kBW_Format) {
    163         SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
    164     } else if (SkMask::kARGB32_Format == mask.fFormat) {
    165         SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
    166     }
    167 }
    168 
    169 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
    170                                        const SkIRect& clip) {
    171     SkASSERT(mask.fBounds.contains(clip));
    172 
    173     if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
    174         return;
    175     }
    176 
    177     if (mask.fFormat == SkMask::kBW_Format) {
    178         SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
    179     } else if (SkMask::kARGB32_Format == mask.fFormat) {
    180         SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
    181     }
    182 }
    183 
    184 ///////////////////////////////////////////////////////////////////////////////
    185 
    186 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    187     if (alpha == 0 || fSrcA == 0) {
    188         return;
    189     }
    190 
    191     uint32_t* device = fDevice.getAddr32(x, y);
    192     uint32_t  color = fPMColor;
    193 
    194     if (alpha != 255) {
    195         color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
    196     }
    197 
    198     unsigned dst_scale = 255 - SkGetPackedA32(color);
    199     size_t rowBytes = fDevice.rowBytes();
    200     while (--height >= 0) {
    201         device[0] = color + SkAlphaMulQ(device[0], dst_scale);
    202         device = (uint32_t*)((char*)device + rowBytes);
    203     }
    204 }
    205 
    206 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
    207     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
    208 
    209     if (fSrcA == 0) {
    210         return;
    211     }
    212 
    213     uint32_t*   device = fDevice.getAddr32(x, y);
    214     uint32_t    color = fPMColor;
    215     size_t      rowBytes = fDevice.rowBytes();
    216 
    217     if (255 == SkGetPackedA32(color)) {
    218         fColorRect32Proc(device, width, height, rowBytes, color);
    219     } else {
    220         while (--height >= 0) {
    221             fColor32Proc(device, device, width, color);
    222             device = (uint32_t*)((char*)device + rowBytes);
    223         }
    224     }
    225 }
    226 
    227 #if defined _WIN32 && _MSC_VER >= 1300
    228 #pragma warning ( pop )
    229 #endif
    230 
    231 ///////////////////////////////////////////////////////////////////////
    232 
    233 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    234                                        const int16_t runs[]) {
    235     uint32_t*   device = fDevice.getAddr32(x, y);
    236     SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
    237 
    238     for (;;) {
    239         int count = runs[0];
    240         SkASSERT(count >= 0);
    241         if (count <= 0) {
    242             return;
    243         }
    244         unsigned aa = antialias[0];
    245         if (aa) {
    246             if (aa == 255) {
    247                 sk_memset32(device, black, count);
    248             } else {
    249                 SkPMColor src = aa << SK_A32_SHIFT;
    250                 unsigned dst_scale = 256 - aa;
    251                 int n = count;
    252                 do {
    253                     --n;
    254                     device[n] = src + SkAlphaMulQ(device[n], dst_scale);
    255                 } while (n > 0);
    256             }
    257         }
    258         runs += count;
    259         antialias += count;
    260         device += count;
    261     }
    262 }
    263 
    264 ///////////////////////////////////////////////////////////////////////////////
    265 
    266 // Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
    267 // instead of kSrcOver_Mode
    268 static void blend_srcmode(SkPMColor* SK_RESTRICT device,
    269                           const SkPMColor* SK_RESTRICT span,
    270                           int count, U8CPU aa) {
    271     int aa256 = SkAlpha255To256(aa);
    272     for (int i = 0; i < count; ++i) {
    273         device[i] = SkFourByteInterp256(span[i], device[i], aa256);
    274     }
    275 }
    276 
    277 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
    278         const SkPaint& paint, SkShader::Context* shaderContext)
    279     : INHERITED(device, paint, shaderContext)
    280 {
    281     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
    282 
    283     fXfermode = paint.getXfermode();
    284     SkSafeRef(fXfermode);
    285 
    286     int flags = 0;
    287     if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
    288         flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
    289     }
    290     // we call this on the output from the shader
    291     fProc32 = SkBlitRow::Factory32(flags);
    292     // we call this on the output from the shader + alpha from the aa buffer
    293     fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
    294 
    295     fShadeDirectlyIntoDevice = false;
    296     if (fXfermode == NULL) {
    297         if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
    298             fShadeDirectlyIntoDevice = true;
    299         }
    300     } else {
    301         SkXfermode::Mode mode;
    302         if (fXfermode->asMode(&mode)) {
    303             if (SkXfermode::kSrc_Mode == mode) {
    304                 fShadeDirectlyIntoDevice = true;
    305                 fProc32Blend = blend_srcmode;
    306             }
    307         }
    308     }
    309 
    310     fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag);
    311 }
    312 
    313 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
    314     SkSafeUnref(fXfermode);
    315     sk_free(fBuffer);
    316 }
    317 
    318 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
    319     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
    320 
    321     uint32_t*   device = fDevice.getAddr32(x, y);
    322 
    323     if (fShadeDirectlyIntoDevice) {
    324         fShaderContext->shadeSpan(x, y, device, width);
    325     } else {
    326         SkPMColor*  span = fBuffer;
    327         fShaderContext->shadeSpan(x, y, span, width);
    328         if (fXfermode) {
    329             fXfermode->xfer32(device, span, width, NULL);
    330         } else {
    331             fProc32(device, span, width, 255);
    332         }
    333     }
    334 }
    335 
    336 void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
    337     SkASSERT(x >= 0 && y >= 0 &&
    338              x + width <= fDevice.width() && y + height <= fDevice.height());
    339 
    340     uint32_t*          device = fDevice.getAddr32(x, y);
    341     size_t             deviceRB = fDevice.rowBytes();
    342     SkShader::Context* shaderContext = fShaderContext;
    343     SkPMColor*         span = fBuffer;
    344 
    345     if (fConstInY) {
    346         if (fShadeDirectlyIntoDevice) {
    347             // shade the first row directly into the device
    348             shaderContext->shadeSpan(x, y, device, width);
    349             span = device;
    350             while (--height > 0) {
    351                 device = (uint32_t*)((char*)device + deviceRB);
    352                 memcpy(device, span, width << 2);
    353             }
    354         } else {
    355             shaderContext->shadeSpan(x, y, span, width);
    356             SkXfermode* xfer = fXfermode;
    357             if (xfer) {
    358                 do {
    359                     xfer->xfer32(device, span, width, NULL);
    360                     y += 1;
    361                     device = (uint32_t*)((char*)device + deviceRB);
    362                 } while (--height > 0);
    363             } else {
    364                 SkBlitRow::Proc32 proc = fProc32;
    365                 do {
    366                     proc(device, span, width, 255);
    367                     y += 1;
    368                     device = (uint32_t*)((char*)device + deviceRB);
    369                 } while (--height > 0);
    370             }
    371         }
    372         return;
    373     }
    374 
    375     if (fShadeDirectlyIntoDevice) {
    376         void* ctx;
    377         SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
    378         if (shadeProc) {
    379             do {
    380                 shadeProc(ctx, x, y, device, width);
    381                 y += 1;
    382                 device = (uint32_t*)((char*)device + deviceRB);
    383             } while (--height > 0);
    384         } else {
    385             do {
    386                 shaderContext->shadeSpan(x, y, device, width);
    387                 y += 1;
    388                 device = (uint32_t*)((char*)device + deviceRB);
    389             } while (--height > 0);
    390         }
    391     } else {
    392         SkXfermode* xfer = fXfermode;
    393         if (xfer) {
    394             do {
    395                 shaderContext->shadeSpan(x, y, span, width);
    396                 xfer->xfer32(device, span, width, NULL);
    397                 y += 1;
    398                 device = (uint32_t*)((char*)device + deviceRB);
    399             } while (--height > 0);
    400         } else {
    401             SkBlitRow::Proc32 proc = fProc32;
    402             do {
    403                 shaderContext->shadeSpan(x, y, span, width);
    404                 proc(device, span, width, 255);
    405                 y += 1;
    406                 device = (uint32_t*)((char*)device + deviceRB);
    407             } while (--height > 0);
    408         }
    409     }
    410 }
    411 
    412 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    413                                         const int16_t runs[]) {
    414     SkPMColor*         span = fBuffer;
    415     uint32_t*          device = fDevice.getAddr32(x, y);
    416     SkShader::Context* shaderContext = fShaderContext;
    417 
    418     if (fXfermode && !fShadeDirectlyIntoDevice) {
    419         for (;;) {
    420             SkXfermode* xfer = fXfermode;
    421 
    422             int count = *runs;
    423             if (count <= 0)
    424                 break;
    425             int aa = *antialias;
    426             if (aa) {
    427                 shaderContext->shadeSpan(x, y, span, count);
    428                 if (aa == 255) {
    429                     xfer->xfer32(device, span, count, NULL);
    430                 } else {
    431                     // count is almost always 1
    432                     for (int i = count - 1; i >= 0; --i) {
    433                         xfer->xfer32(&device[i], &span[i], 1, antialias);
    434                     }
    435                 }
    436             }
    437             device += count;
    438             runs += count;
    439             antialias += count;
    440             x += count;
    441         }
    442     } else if (fShadeDirectlyIntoDevice ||
    443                (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
    444         for (;;) {
    445             int count = *runs;
    446             if (count <= 0) {
    447                 break;
    448             }
    449             int aa = *antialias;
    450             if (aa) {
    451                 if (aa == 255) {
    452                     // cool, have the shader draw right into the device
    453                     shaderContext->shadeSpan(x, y, device, count);
    454                 } else {
    455                     shaderContext->shadeSpan(x, y, span, count);
    456                     fProc32Blend(device, span, count, aa);
    457                 }
    458             }
    459             device += count;
    460             runs += count;
    461             antialias += count;
    462             x += count;
    463         }
    464     } else {
    465         for (;;) {
    466             int count = *runs;
    467             if (count <= 0) {
    468                 break;
    469             }
    470             int aa = *antialias;
    471             if (aa) {
    472                 shaderContext->shadeSpan(x, y, span, count);
    473                 if (aa == 255) {
    474                     fProc32(device, span, count, 255);
    475                 } else {
    476                     fProc32Blend(device, span, count, aa);
    477                 }
    478             }
    479             device += count;
    480             runs += count;
    481             antialias += count;
    482             x += count;
    483         }
    484     }
    485 }
    486 
    487 void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    488     // we only handle kA8 with an xfermode
    489     if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
    490         this->INHERITED::blitMask(mask, clip);
    491         return;
    492     }
    493 
    494     SkASSERT(mask.fBounds.contains(clip));
    495 
    496     SkShader::Context*  shaderContext = fShaderContext;
    497     SkBlitMask::RowProc proc = NULL;
    498     if (!fXfermode) {
    499         unsigned flags = 0;
    500         if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
    501             flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
    502         }
    503         proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat,
    504                                       (SkBlitMask::RowFlags)flags);
    505         if (NULL == proc) {
    506             this->INHERITED::blitMask(mask, clip);
    507             return;
    508         }
    509     }
    510 
    511     const int x = clip.fLeft;
    512     const int width = clip.width();
    513     int y = clip.fTop;
    514     int height = clip.height();
    515 
    516     char* dstRow = (char*)fDevice.getAddr32(x, y);
    517     const size_t dstRB = fDevice.rowBytes();
    518     const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
    519     const size_t maskRB = mask.fRowBytes;
    520 
    521     SkPMColor* span = fBuffer;
    522 
    523     if (fXfermode) {
    524         SkASSERT(SkMask::kA8_Format == mask.fFormat);
    525         SkXfermode* xfer = fXfermode;
    526         do {
    527             shaderContext->shadeSpan(x, y, span, width);
    528             xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
    529             dstRow += dstRB;
    530             maskRow += maskRB;
    531             y += 1;
    532         } while (--height > 0);
    533     } else {
    534         do {
    535             shaderContext->shadeSpan(x, y, span, width);
    536             proc(dstRow, maskRow, span, width);
    537             dstRow += dstRB;
    538             maskRow += maskRB;
    539             y += 1;
    540         } while (--height > 0);
    541     }
    542 }
    543 
    544 void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    545     SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
    546 
    547     uint32_t*          device = fDevice.getAddr32(x, y);
    548     size_t             deviceRB = fDevice.rowBytes();
    549     SkShader::Context* shaderContext = fShaderContext;
    550 
    551     if (fConstInY) {
    552         SkPMColor c;
    553         shaderContext->shadeSpan(x, y, &c, 1);
    554 
    555         if (fShadeDirectlyIntoDevice) {
    556             if (255 == alpha) {
    557                 do {
    558                     *device = c;
    559                     device = (uint32_t*)((char*)device + deviceRB);
    560                 } while (--height > 0);
    561             } else {
    562                 do {
    563                     *device = SkFourByteInterp(c, *device, alpha);
    564                     device = (uint32_t*)((char*)device + deviceRB);
    565                 } while (--height > 0);
    566             }
    567         } else {
    568             SkXfermode* xfer = fXfermode;
    569             if (xfer) {
    570                 do {
    571                     xfer->xfer32(device, &c, 1, &alpha);
    572                     device = (uint32_t*)((char*)device + deviceRB);
    573                 } while (--height > 0);
    574             } else {
    575                 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
    576                 do {
    577                     proc(device, &c, 1, alpha);
    578                     device = (uint32_t*)((char*)device + deviceRB);
    579                 } while (--height > 0);
    580             }
    581         }
    582         return;
    583     }
    584 
    585     if (fShadeDirectlyIntoDevice) {
    586         void* ctx;
    587         SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
    588         if (255 == alpha) {
    589             if (shadeProc) {
    590                 do {
    591                     shadeProc(ctx, x, y, device, 1);
    592                     y += 1;
    593                     device = (uint32_t*)((char*)device + deviceRB);
    594                 } while (--height > 0);
    595             } else {
    596                 do {
    597                     shaderContext->shadeSpan(x, y, device, 1);
    598                     y += 1;
    599                     device = (uint32_t*)((char*)device + deviceRB);
    600                 } while (--height > 0);
    601             }
    602         } else {    // alpha < 255
    603             SkPMColor c;
    604             if (shadeProc) {
    605                 do {
    606                     shadeProc(ctx, x, y, &c, 1);
    607                     *device = SkFourByteInterp(c, *device, alpha);
    608                     y += 1;
    609                     device = (uint32_t*)((char*)device + deviceRB);
    610                 } while (--height > 0);
    611             } else {
    612                 do {
    613                     shaderContext->shadeSpan(x, y, &c, 1);
    614                     *device = SkFourByteInterp(c, *device, alpha);
    615                     y += 1;
    616                     device = (uint32_t*)((char*)device + deviceRB);
    617                 } while (--height > 0);
    618             }
    619         }
    620     } else {
    621         SkPMColor* span = fBuffer;
    622         SkXfermode* xfer = fXfermode;
    623         if (xfer) {
    624             do {
    625                 shaderContext->shadeSpan(x, y, span, 1);
    626                 xfer->xfer32(device, span, 1, &alpha);
    627                 y += 1;
    628                 device = (uint32_t*)((char*)device + deviceRB);
    629             } while (--height > 0);
    630         } else {
    631             SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
    632             do {
    633                 shaderContext->shadeSpan(x, y, span, 1);
    634                 proc(device, span, 1, alpha);
    635                 y += 1;
    636                 device = (uint32_t*)((char*)device + deviceRB);
    637             } while (--height > 0);
    638         }
    639     }
    640 }
    641