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 }
56 
justAnOpaqueColor(uint32_t * value)57 const 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 
blitH(int x,int y,int width)70 void 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 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])77 void 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 
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)108 void 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 
blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)116 void 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 
blitMask(const SkMask & mask,const SkIRect & clip)165 void 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 
blitMask(const SkMask & mask,const SkIRect & clip)184 void 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 
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)199 void 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 
blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)207 void 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 
blitV(int x,int y,int height,SkAlpha alpha)218 void 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 
blitRect(int x,int y,int width,int height)238 void 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 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])261 void 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 
blitAntiH2(int x,int y,U8CPU a0,U8CPU a1)292 void 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 
blitAntiV2(int x,int y,U8CPU a0,U8CPU a1)300 void 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
blend_srcmode(SkPMColor * SK_RESTRICT device,const SkPMColor * SK_RESTRICT span,int count,U8CPU aa)313 static 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 
SkARGB32_Shader_Blitter(const SkBitmap & device,const SkPaint & paint,SkShader::Context * shaderContext)322 SkARGB32_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 
~SkARGB32_Shader_Blitter()358 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
359     SkSafeUnref(fXfermode);
360     sk_free(fBuffer);
361 }
362 
blitH(int x,int y,int width)363 void 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 
blitRect(int x,int y,int width,int height)381 void 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 
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])457 void 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 
blitMask(const SkMask & mask,const SkIRect & clip)532 void 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 
blitV(int x,int y,int height,SkAlpha alpha)589 void 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