SkBlitter_ARGB32.cpp revision 2cbcd12281ee807214df094964c584c78932e10b
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 SkPixmap& 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.writable_addr32(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 SkPixmap& 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 SkPixmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
58    if (255 == fSrcA) {
59        *value = fPMColor;
60        return &fDevice;
61    }
62    return nullptr;
63}
64
65#if defined _WIN32  // 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.writable_addr32(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.writable_addr32(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.writable_addr32(x, y);
110    SkDEBUGCODE((void)fDevice.writable_addr32(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.writable_addr32(x, y);
118    SkDEBUGCODE((void)fDevice.writable_addr32(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               writable_addr32
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               writable_addr32
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    switch (mask.fFormat) {
178        case SkMask::kBW_Format:
179            SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
180            break;
181        case SkMask::kARGB32_Format:
182            SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
183            break;
184        default:
185            SkFAIL("Mask format not handled.");
186    }
187}
188
189void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
190                                       const SkIRect& clip) {
191    SkASSERT(mask.fBounds.contains(clip));
192
193    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
194        return;
195    }
196
197    switch (mask.fFormat) {
198        case SkMask::kBW_Format:
199            SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
200            break;
201        case SkMask::kARGB32_Format:
202            SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
203            break;
204        default:
205            SkFAIL("Mask format not handled.");
206    }
207}
208
209void SkARGB32_Opaque_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
210    uint32_t* device = fDevice.writable_addr32(x, y);
211    SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
212
213    device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
214    device[1] = SkFastFourByteInterp(fPMColor, device[1], a1);
215}
216
217void SkARGB32_Opaque_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
218    uint32_t* device = fDevice.writable_addr32(x, y);
219    SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
220
221    device[0] = SkFastFourByteInterp(fPMColor, device[0], a0);
222    device = (uint32_t*)((char*)device + fDevice.rowBytes());
223    device[0] = SkFastFourByteInterp(fPMColor, device[0], a1);
224}
225
226///////////////////////////////////////////////////////////////////////////////
227
228void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
229    if (alpha == 0 || fSrcA == 0) {
230        return;
231    }
232
233    uint32_t* device = fDevice.writable_addr32(x, y);
234    uint32_t  color = fPMColor;
235
236    if (alpha != 255) {
237        color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
238    }
239
240#ifdef SK_SUPPORT_LEGACY_BROKEN_LERP
241    unsigned dst_scale = 255 - SkGetPackedA32(color);
242#else
243    unsigned dst_scale = SkAlpha255To256(255 - SkGetPackedA32(color));
244#endif
245    size_t rowBytes = fDevice.rowBytes();
246    while (--height >= 0) {
247        device[0] = color + SkAlphaMulQ(device[0], dst_scale);
248        device = (uint32_t*)((char*)device + rowBytes);
249    }
250}
251
252void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
253    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
254
255    if (fSrcA == 0) {
256        return;
257    }
258
259    uint32_t*   device = fDevice.writable_addr32(x, y);
260    uint32_t    color = fPMColor;
261    size_t      rowBytes = fDevice.rowBytes();
262
263    while (--height >= 0) {
264        SkBlitRow::Color32(device, device, width, color);
265        device = (uint32_t*)((char*)device + rowBytes);
266    }
267}
268
269#if defined _WIN32
270#pragma warning ( pop )
271#endif
272
273///////////////////////////////////////////////////////////////////////
274
275void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
276                                       const int16_t runs[]) {
277    uint32_t*   device = fDevice.writable_addr32(x, y);
278    SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
279
280    for (;;) {
281        int count = runs[0];
282        SkASSERT(count >= 0);
283        if (count <= 0) {
284            return;
285        }
286        unsigned aa = antialias[0];
287        if (aa) {
288            if (aa == 255) {
289                sk_memset32(device, black, count);
290            } else {
291                SkPMColor src = aa << SK_A32_SHIFT;
292                unsigned dst_scale = 256 - aa;
293                int n = count;
294                do {
295                    --n;
296                    device[n] = src + SkAlphaMulQ(device[n], dst_scale);
297                } while (n > 0);
298            }
299        }
300        runs += count;
301        antialias += count;
302        device += count;
303    }
304}
305
306void SkARGB32_Black_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
307    uint32_t* device = fDevice.writable_addr32(x, y);
308    SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);)
309
310    device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
311    device[1] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[1], 256 - a1);
312}
313
314void SkARGB32_Black_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
315    uint32_t* device = fDevice.writable_addr32(x, y);
316    SkDEBUGCODE((void)fDevice.writable_addr32(x, y + 1);)
317
318    device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0);
319    device = (uint32_t*)((char*)device + fDevice.rowBytes());
320    device[0] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a1);
321}
322
323///////////////////////////////////////////////////////////////////////////////
324
325// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
326// instead of kSrcOver_Mode
327static void blend_srcmode(SkPMColor* SK_RESTRICT device,
328                          const SkPMColor* SK_RESTRICT span,
329                          int count, U8CPU aa) {
330    int aa256 = SkAlpha255To256(aa);
331    for (int i = 0; i < count; ++i) {
332        device[i] = SkFourByteInterp256(span[i], device[i], aa256);
333    }
334}
335
336SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkPixmap& device,
337        const SkPaint& paint, SkShader::Context* shaderContext)
338    : INHERITED(device, paint, shaderContext)
339{
340    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
341
342    fXfermode = paint.getXfermode();
343    SkSafeRef(fXfermode);
344
345    int flags = 0;
346    if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
347        flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
348    }
349    // we call this on the output from the shader
350    fProc32 = SkBlitRow::Factory32(flags);
351    // we call this on the output from the shader + alpha from the aa buffer
352    fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
353
354    fShadeDirectlyIntoDevice = false;
355    if (fXfermode == nullptr) {
356        if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
357            fShadeDirectlyIntoDevice = true;
358        }
359    } else {
360        SkXfermode::Mode mode;
361        if (fXfermode->asMode(&mode)) {
362            if (SkXfermode::kSrc_Mode == mode) {
363                fShadeDirectlyIntoDevice = true;
364                fProc32Blend = blend_srcmode;
365            }
366        }
367    }
368
369    fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag);
370}
371
372SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
373    SkSafeUnref(fXfermode);
374    sk_free(fBuffer);
375}
376
377void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
378    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
379
380    uint32_t* device = fDevice.writable_addr32(x, y);
381
382    if (fShadeDirectlyIntoDevice) {
383        fShaderContext->shadeSpan(x, y, device, width);
384    } else {
385        SkPMColor*  span = fBuffer;
386        fShaderContext->shadeSpan(x, y, span, width);
387        if (fXfermode) {
388            fXfermode->xfer32(device, span, width, nullptr);
389        } else {
390            fProc32(device, span, width, 255);
391        }
392    }
393}
394
395void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
396    SkASSERT(x >= 0 && y >= 0 &&
397             x + width <= fDevice.width() && y + height <= fDevice.height());
398
399    uint32_t*          device = fDevice.writable_addr32(x, y);
400    size_t             deviceRB = fDevice.rowBytes();
401    SkShader::Context* shaderContext = fShaderContext;
402    SkPMColor*         span = fBuffer;
403
404    if (fConstInY) {
405        if (fShadeDirectlyIntoDevice) {
406            // shade the first row directly into the device
407            shaderContext->shadeSpan(x, y, device, width);
408            span = device;
409            while (--height > 0) {
410                device = (uint32_t*)((char*)device + deviceRB);
411                memcpy(device, span, width << 2);
412            }
413        } else {
414            shaderContext->shadeSpan(x, y, span, width);
415            SkXfermode* xfer = fXfermode;
416            if (xfer) {
417                do {
418                    xfer->xfer32(device, span, width, nullptr);
419                    y += 1;
420                    device = (uint32_t*)((char*)device + deviceRB);
421                } while (--height > 0);
422            } else {
423                SkBlitRow::Proc32 proc = fProc32;
424                do {
425                    proc(device, span, width, 255);
426                    y += 1;
427                    device = (uint32_t*)((char*)device + deviceRB);
428                } while (--height > 0);
429            }
430        }
431        return;
432    }
433
434    if (fShadeDirectlyIntoDevice) {
435        void* ctx;
436        SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
437        if (shadeProc) {
438            do {
439                shadeProc(ctx, x, y, device, width);
440                y += 1;
441                device = (uint32_t*)((char*)device + deviceRB);
442            } while (--height > 0);
443        } else {
444            do {
445                shaderContext->shadeSpan(x, y, device, width);
446                y += 1;
447                device = (uint32_t*)((char*)device + deviceRB);
448            } while (--height > 0);
449        }
450    } else {
451        SkXfermode* xfer = fXfermode;
452        if (xfer) {
453            do {
454                shaderContext->shadeSpan(x, y, span, width);
455                xfer->xfer32(device, span, width, nullptr);
456                y += 1;
457                device = (uint32_t*)((char*)device + deviceRB);
458            } while (--height > 0);
459        } else {
460            SkBlitRow::Proc32 proc = fProc32;
461            do {
462                shaderContext->shadeSpan(x, y, span, width);
463                proc(device, span, width, 255);
464                y += 1;
465                device = (uint32_t*)((char*)device + deviceRB);
466            } while (--height > 0);
467        }
468    }
469}
470
471void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
472                                        const int16_t runs[]) {
473    SkPMColor*         span = fBuffer;
474    uint32_t*          device = fDevice.writable_addr32(x, y);
475    SkShader::Context* shaderContext = fShaderContext;
476
477    if (fXfermode && !fShadeDirectlyIntoDevice) {
478        for (;;) {
479            SkXfermode* xfer = fXfermode;
480
481            int count = *runs;
482            if (count <= 0)
483                break;
484            int aa = *antialias;
485            if (aa) {
486                shaderContext->shadeSpan(x, y, span, count);
487                if (aa == 255) {
488                    xfer->xfer32(device, span, count, nullptr);
489                } else {
490                    // count is almost always 1
491                    for (int i = count - 1; i >= 0; --i) {
492                        xfer->xfer32(&device[i], &span[i], 1, antialias);
493                    }
494                }
495            }
496            device += count;
497            runs += count;
498            antialias += count;
499            x += count;
500        }
501    } else if (fShadeDirectlyIntoDevice ||
502               (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
503        for (;;) {
504            int count = *runs;
505            if (count <= 0) {
506                break;
507            }
508            int aa = *antialias;
509            if (aa) {
510                if (aa == 255) {
511                    // cool, have the shader draw right into the device
512                    shaderContext->shadeSpan(x, y, device, count);
513                } else {
514                    shaderContext->shadeSpan(x, y, span, count);
515                    fProc32Blend(device, span, count, aa);
516                }
517            }
518            device += count;
519            runs += count;
520            antialias += count;
521            x += count;
522        }
523    } else {
524        for (;;) {
525            int count = *runs;
526            if (count <= 0) {
527                break;
528            }
529            int aa = *antialias;
530            if (aa) {
531                shaderContext->shadeSpan(x, y, span, count);
532                if (aa == 255) {
533                    fProc32(device, span, count, 255);
534                } else {
535                    fProc32Blend(device, span, count, aa);
536                }
537            }
538            device += count;
539            runs += count;
540            antialias += count;
541            x += count;
542        }
543    }
544}
545
546void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
547    // we only handle kA8 with an xfermode
548    if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
549        this->INHERITED::blitMask(mask, clip);
550        return;
551    }
552
553    SkASSERT(mask.fBounds.contains(clip));
554
555    SkShader::Context*  shaderContext = fShaderContext;
556    SkBlitMask::RowProc proc = nullptr;
557    if (!fXfermode) {
558        unsigned flags = 0;
559        if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) {
560            flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
561        }
562        proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat,
563                                      (SkBlitMask::RowFlags)flags);
564        if (nullptr == proc) {
565            this->INHERITED::blitMask(mask, clip);
566            return;
567        }
568    }
569
570    const int x = clip.fLeft;
571    const int width = clip.width();
572    int y = clip.fTop;
573    int height = clip.height();
574
575    char* dstRow = (char*)fDevice.writable_addr32(x, y);
576    const size_t dstRB = fDevice.rowBytes();
577    const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
578    const size_t maskRB = mask.fRowBytes;
579
580    SkPMColor* span = fBuffer;
581
582    if (fXfermode) {
583        SkASSERT(SkMask::kA8_Format == mask.fFormat);
584        SkXfermode* xfer = fXfermode;
585        do {
586            shaderContext->shadeSpan(x, y, span, width);
587            xfer->xfer32(reinterpret_cast<SkPMColor*>(dstRow), span, width, maskRow);
588            dstRow += dstRB;
589            maskRow += maskRB;
590            y += 1;
591        } while (--height > 0);
592    } else {
593        do {
594            shaderContext->shadeSpan(x, y, span, width);
595            proc(reinterpret_cast<SkPMColor*>(dstRow), maskRow, span, width);
596            dstRow += dstRB;
597            maskRow += maskRB;
598            y += 1;
599        } while (--height > 0);
600    }
601}
602
603void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
604    SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
605
606    uint32_t*          device = fDevice.writable_addr32(x, y);
607    size_t             deviceRB = fDevice.rowBytes();
608    SkShader::Context* shaderContext = fShaderContext;
609
610    if (fConstInY) {
611        SkPMColor c;
612        shaderContext->shadeSpan(x, y, &c, 1);
613
614        if (fShadeDirectlyIntoDevice) {
615            if (255 == alpha) {
616                do {
617                    *device = c;
618                    device = (uint32_t*)((char*)device + deviceRB);
619                } while (--height > 0);
620            } else {
621                do {
622                    *device = SkFourByteInterp(c, *device, alpha);
623                    device = (uint32_t*)((char*)device + deviceRB);
624                } while (--height > 0);
625            }
626        } else {
627            SkXfermode* xfer = fXfermode;
628            if (xfer) {
629                do {
630                    xfer->xfer32(device, &c, 1, &alpha);
631                    device = (uint32_t*)((char*)device + deviceRB);
632                } while (--height > 0);
633            } else {
634                SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
635                do {
636                    proc(device, &c, 1, alpha);
637                    device = (uint32_t*)((char*)device + deviceRB);
638                } while (--height > 0);
639            }
640        }
641        return;
642    }
643
644    if (fShadeDirectlyIntoDevice) {
645        void* ctx;
646        SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx);
647        if (255 == alpha) {
648            if (shadeProc) {
649                do {
650                    shadeProc(ctx, x, y, device, 1);
651                    y += 1;
652                    device = (uint32_t*)((char*)device + deviceRB);
653                } while (--height > 0);
654            } else {
655                do {
656                    shaderContext->shadeSpan(x, y, device, 1);
657                    y += 1;
658                    device = (uint32_t*)((char*)device + deviceRB);
659                } while (--height > 0);
660            }
661        } else {    // alpha < 255
662            SkPMColor c;
663            if (shadeProc) {
664                do {
665                    shadeProc(ctx, x, y, &c, 1);
666                    *device = SkFourByteInterp(c, *device, alpha);
667                    y += 1;
668                    device = (uint32_t*)((char*)device + deviceRB);
669                } while (--height > 0);
670            } else {
671                do {
672                    shaderContext->shadeSpan(x, y, &c, 1);
673                    *device = SkFourByteInterp(c, *device, alpha);
674                    y += 1;
675                    device = (uint32_t*)((char*)device + deviceRB);
676                } while (--height > 0);
677            }
678        }
679    } else {
680        SkPMColor* span = fBuffer;
681        SkXfermode* xfer = fXfermode;
682        if (xfer) {
683            do {
684                shaderContext->shadeSpan(x, y, span, 1);
685                xfer->xfer32(device, span, 1, &alpha);
686                y += 1;
687                device = (uint32_t*)((char*)device + deviceRB);
688            } while (--height > 0);
689        } else {
690            SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
691            do {
692                shaderContext->shadeSpan(x, y, span, 1);
693                proc(device, span, 1, alpha);
694                y += 1;
695                device = (uint32_t*)((char*)device + deviceRB);
696            } while (--height > 0);
697        }
698    }
699}
700