• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkARGB32_Blit32(const SkBitmap & device,const SkMask & mask,const SkIRect & clip,SkPMColor srcColor)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 
SkARGB32_Blitter(const SkBitmap & device,const SkPaint & paint)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 
justAnOpaqueColor(uint32_t * value)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 
blitH(int x,int y,int width)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 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])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 
blitMask(const SkMask & mask,const SkIRect & clip)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 
blitMask(const SkMask & mask,const SkIRect & clip)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 
blitV(int x,int y,int height,SkAlpha alpha)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 
blitRect(int x,int y,int width,int height)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 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])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
blend_srcmode(SkPMColor * SK_RESTRICT device,const SkPMColor * SK_RESTRICT span,int count,U8CPU aa)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 
SkARGB32_Shader_Blitter(const SkBitmap & device,const SkPaint & paint,SkShader::Context * shaderContext)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 
~SkARGB32_Shader_Blitter()313 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
314     SkSafeUnref(fXfermode);
315     sk_free(fBuffer);
316 }
317 
blitH(int x,int y,int width)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 
blitRect(int x,int y,int width,int height)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 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])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 
blitMask(const SkMask & mask,const SkIRect & clip)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 
blitV(int x,int y,int height,SkAlpha alpha)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