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