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