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