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