SkBlitter_ARGB32.cpp revision a8ec4805db3a3cfd34926b89d6963700fb0ff0c1
1/* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkCoreBlitters.h" 9#include "SkColorPriv.h" 10#include "SkShader.h" 11#include "SkUtils.h" 12#include "SkXfermode.h" 13#include "SkBlitMask.h" 14 15/////////////////////////////////////////////////////////////////////////////// 16 17static void SkARGB32_Blit32(const 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 43SkARGB32_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 fColor32Proc = SkBlitRow::ColorProcFactory(); 56} 57 58const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) { 59 if (255 == fSrcA) { 60 *value = fPMColor; 61 return &fDevice; 62 } 63 return NULL; 64} 65 66#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 67#pragma warning ( push ) 68#pragma warning ( disable : 4701 ) 69#endif 70 71void SkARGB32_Blitter::blitH(int x, int y, int width) { 72 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 73 74 uint32_t* device = fDevice.getAddr32(x, y); 75 fColor32Proc(device, device, width, fPMColor); 76} 77 78void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 79 const int16_t runs[]) { 80 if (fSrcA == 0) { 81 return; 82 } 83 84 uint32_t color = fPMColor; 85 uint32_t* device = fDevice.getAddr32(x, y); 86 unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case 87 88 for (;;) { 89 int count = runs[0]; 90 SkASSERT(count >= 0); 91 if (count <= 0) { 92 return; 93 } 94 unsigned aa = antialias[0]; 95 if (aa) { 96 if ((opaqueMask & aa) == 255) { 97 sk_memset32(device, color, count); 98 } else { 99 uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa)); 100 fColor32Proc(device, device, count, sc); 101 } 102 } 103 runs += count; 104 antialias += count; 105 device += count; 106 } 107} 108 109void SkARGB32_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 110 uint32_t* device = fDevice.getAddr32(x, y); 111 SkDEBUGCODE((void)fDevice.getAddr32(x + 1, y);) 112 113 device[0] = SkBlendARGB32(fPMColor, device[0], a0); 114 device[1] = SkBlendARGB32(fPMColor, device[1], a1); 115} 116 117void SkARGB32_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 118 uint32_t* device = fDevice.getAddr32(x, y); 119 SkDEBUGCODE((void)fDevice.getAddr32(x, y + 1);) 120 121 device[0] = SkBlendARGB32(fPMColor, device[0], a0); 122 device = (uint32_t*)((char*)device + fDevice.rowBytes()); 123 device[0] = SkBlendARGB32(fPMColor, device[0], a1); 124} 125 126////////////////////////////////////////////////////////////////////////////////////// 127 128#define solid_8_pixels(mask, dst, color) \ 129 do { \ 130 if (mask & 0x80) dst[0] = color; \ 131 if (mask & 0x40) dst[1] = color; \ 132 if (mask & 0x20) dst[2] = color; \ 133 if (mask & 0x10) dst[3] = color; \ 134 if (mask & 0x08) dst[4] = color; \ 135 if (mask & 0x04) dst[5] = color; \ 136 if (mask & 0x02) dst[6] = color; \ 137 if (mask & 0x01) dst[7] = color; \ 138 } while (0) 139 140#define SK_BLITBWMASK_NAME SkARGB32_BlitBW 141#define SK_BLITBWMASK_ARGS , SkPMColor color 142#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 143#define SK_BLITBWMASK_GETADDR getAddr32 144#define SK_BLITBWMASK_DEVTYPE uint32_t 145#include "SkBlitBWMaskTemplate.h" 146 147#define blend_8_pixels(mask, dst, sc, dst_scale) \ 148 do { \ 149 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \ 150 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \ 151 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \ 152 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \ 153 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \ 154 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \ 155 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \ 156 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \ 157 } while (0) 158 159#define SK_BLITBWMASK_NAME SkARGB32_BlendBW 160#define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale 161#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_scale) 162#define SK_BLITBWMASK_GETADDR getAddr32 163#define SK_BLITBWMASK_DEVTYPE uint32_t 164#include "SkBlitBWMaskTemplate.h" 165 166void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 167 SkASSERT(mask.fBounds.contains(clip)); 168 SkASSERT(fSrcA != 0xFF); 169 170 if (fSrcA == 0) { 171 return; 172 } 173 174 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) { 175 return; 176 } 177 178 if (mask.fFormat == SkMask::kBW_Format) { 179 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA)); 180 } else if (SkMask::kARGB32_Format == mask.fFormat) { 181 SkARGB32_Blit32(fDevice, mask, clip, fPMColor); 182 } 183} 184 185void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, 186 const SkIRect& clip) { 187 SkASSERT(mask.fBounds.contains(clip)); 188 189 if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) { 190 return; 191 } 192 193 if (mask.fFormat == SkMask::kBW_Format) { 194 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor); 195 } else if (SkMask::kARGB32_Format == mask.fFormat) { 196 SkARGB32_Blit32(fDevice, mask, clip, fPMColor); 197 } 198} 199 200void SkARGB32_Opaque_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 201 uint32_t* device = fDevice.getAddr32(x, y); 202 SkDEBUGCODE((void)fDevice.getAddr32(x + 1, y);) 203 204 device[0] = SkFastFourByteInterp(fPMColor, device[0], a0); 205 device[1] = SkFastFourByteInterp(fPMColor, device[1], a1); 206} 207 208void SkARGB32_Opaque_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 209 uint32_t* device = fDevice.getAddr32(x, y); 210 SkDEBUGCODE((void)fDevice.getAddr32(x, y + 1);) 211 212 device[0] = SkFastFourByteInterp(fPMColor, device[0], a0); 213 device = (uint32_t*)((char*)device + fDevice.rowBytes()); 214 device[0] = SkFastFourByteInterp(fPMColor, device[0], a1); 215} 216 217/////////////////////////////////////////////////////////////////////////////// 218 219void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 220 if (alpha == 0 || fSrcA == 0) { 221 return; 222 } 223 224 uint32_t* device = fDevice.getAddr32(x, y); 225 uint32_t color = fPMColor; 226 227 if (alpha != 255) { 228 color = SkAlphaMulQ(color, SkAlpha255To256(alpha)); 229 } 230 231 unsigned dst_scale = 255 - SkGetPackedA32(color); 232 size_t rowBytes = fDevice.rowBytes(); 233 while (--height >= 0) { 234 device[0] = color + SkAlphaMulQ(device[0], dst_scale); 235 device = (uint32_t*)((char*)device + rowBytes); 236 } 237} 238 239void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) { 240 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height()); 241 242 if (fSrcA == 0) { 243 return; 244 } 245 246 uint32_t* device = fDevice.getAddr32(x, y); 247 uint32_t color = fPMColor; 248 size_t rowBytes = fDevice.rowBytes(); 249 250 while (--height >= 0) { 251 fColor32Proc(device, device, width, color); 252 device = (uint32_t*)((char*)device + rowBytes); 253 } 254} 255 256#if defined _WIN32 && _MSC_VER >= 1300 257#pragma warning ( pop ) 258#endif 259 260/////////////////////////////////////////////////////////////////////// 261 262void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 263 const int16_t runs[]) { 264 uint32_t* device = fDevice.getAddr32(x, y); 265 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); 266 267 for (;;) { 268 int count = runs[0]; 269 SkASSERT(count >= 0); 270 if (count <= 0) { 271 return; 272 } 273 unsigned aa = antialias[0]; 274 if (aa) { 275 if (aa == 255) { 276 sk_memset32(device, black, count); 277 } else { 278 SkPMColor src = aa << SK_A32_SHIFT; 279 unsigned dst_scale = 256 - aa; 280 int n = count; 281 do { 282 --n; 283 device[n] = src + SkAlphaMulQ(device[n], dst_scale); 284 } while (n > 0); 285 } 286 } 287 runs += count; 288 antialias += count; 289 device += count; 290 } 291} 292 293void SkARGB32_Black_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 294 uint32_t* device = fDevice.getAddr32(x, y); 295 SkDEBUGCODE((void)fDevice.getAddr32(x + 1, y);) 296 297 device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0); 298 device[1] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[1], 256 - a1); 299} 300 301void SkARGB32_Black_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 302 uint32_t* device = fDevice.getAddr32(x, y); 303 SkDEBUGCODE((void)fDevice.getAddr32(x, y + 1);) 304 305 device[0] = (a0 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a0); 306 device = (uint32_t*)((char*)device + fDevice.rowBytes()); 307 device[0] = (a1 << SK_A32_SHIFT) + SkAlphaMulQ(device[0], 256 - a1); 308} 309 310/////////////////////////////////////////////////////////////////////////////// 311 312// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode, 313// instead of kSrcOver_Mode 314static void blend_srcmode(SkPMColor* SK_RESTRICT device, 315 const SkPMColor* SK_RESTRICT span, 316 int count, U8CPU aa) { 317 int aa256 = SkAlpha255To256(aa); 318 for (int i = 0; i < count; ++i) { 319 device[i] = SkFourByteInterp256(span[i], device[i], aa256); 320 } 321} 322 323SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, 324 const SkPaint& paint, SkShader::Context* shaderContext) 325 : INHERITED(device, paint, shaderContext) 326{ 327 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); 328 329 fXfermode = paint.getXfermode(); 330 SkSafeRef(fXfermode); 331 332 int flags = 0; 333 if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 334 flags |= SkBlitRow::kSrcPixelAlpha_Flag32; 335 } 336 // we call this on the output from the shader 337 fProc32 = SkBlitRow::Factory32(flags); 338 // we call this on the output from the shader + alpha from the aa buffer 339 fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32); 340 341 fShadeDirectlyIntoDevice = false; 342 if (fXfermode == NULL) { 343 if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) { 344 fShadeDirectlyIntoDevice = true; 345 } 346 } else { 347 SkXfermode::Mode mode; 348 if (fXfermode->asMode(&mode)) { 349 if (SkXfermode::kSrc_Mode == mode) { 350 fShadeDirectlyIntoDevice = true; 351 fProc32Blend = blend_srcmode; 352 } 353 } 354 } 355 356 fConstInY = SkToBool(shaderContext->getFlags() & SkShader::kConstInY32_Flag); 357} 358 359SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { 360 SkSafeUnref(fXfermode); 361 sk_free(fBuffer); 362} 363 364void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { 365 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 366 367 uint32_t* device = fDevice.getAddr32(x, y); 368 369 if (fShadeDirectlyIntoDevice) { 370 fShaderContext->shadeSpan(x, y, device, width); 371 } else { 372 SkPMColor* span = fBuffer; 373 fShaderContext->shadeSpan(x, y, span, width); 374 if (fXfermode) { 375 fXfermode->xfer32(device, span, width, NULL); 376 } else { 377 fProc32(device, span, width, 255); 378 } 379 } 380} 381 382void SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) { 383 SkASSERT(x >= 0 && y >= 0 && 384 x + width <= fDevice.width() && y + height <= fDevice.height()); 385 386 uint32_t* device = fDevice.getAddr32(x, y); 387 size_t deviceRB = fDevice.rowBytes(); 388 SkShader::Context* shaderContext = fShaderContext; 389 SkPMColor* span = fBuffer; 390 391 if (fConstInY) { 392 if (fShadeDirectlyIntoDevice) { 393 // shade the first row directly into the device 394 shaderContext->shadeSpan(x, y, device, width); 395 span = device; 396 while (--height > 0) { 397 device = (uint32_t*)((char*)device + deviceRB); 398 memcpy(device, span, width << 2); 399 } 400 } else { 401 shaderContext->shadeSpan(x, y, span, width); 402 SkXfermode* xfer = fXfermode; 403 if (xfer) { 404 do { 405 xfer->xfer32(device, span, width, NULL); 406 y += 1; 407 device = (uint32_t*)((char*)device + deviceRB); 408 } while (--height > 0); 409 } else { 410 SkBlitRow::Proc32 proc = fProc32; 411 do { 412 proc(device, span, width, 255); 413 y += 1; 414 device = (uint32_t*)((char*)device + deviceRB); 415 } while (--height > 0); 416 } 417 } 418 return; 419 } 420 421 if (fShadeDirectlyIntoDevice) { 422 void* ctx; 423 SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx); 424 if (shadeProc) { 425 do { 426 shadeProc(ctx, x, y, device, width); 427 y += 1; 428 device = (uint32_t*)((char*)device + deviceRB); 429 } while (--height > 0); 430 } else { 431 do { 432 shaderContext->shadeSpan(x, y, device, width); 433 y += 1; 434 device = (uint32_t*)((char*)device + deviceRB); 435 } while (--height > 0); 436 } 437 } else { 438 SkXfermode* xfer = fXfermode; 439 if (xfer) { 440 do { 441 shaderContext->shadeSpan(x, y, span, width); 442 xfer->xfer32(device, span, width, NULL); 443 y += 1; 444 device = (uint32_t*)((char*)device + deviceRB); 445 } while (--height > 0); 446 } else { 447 SkBlitRow::Proc32 proc = fProc32; 448 do { 449 shaderContext->shadeSpan(x, y, span, width); 450 proc(device, span, width, 255); 451 y += 1; 452 device = (uint32_t*)((char*)device + deviceRB); 453 } while (--height > 0); 454 } 455 } 456} 457 458void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 459 const int16_t runs[]) { 460 SkPMColor* span = fBuffer; 461 uint32_t* device = fDevice.getAddr32(x, y); 462 SkShader::Context* shaderContext = fShaderContext; 463 464 if (fXfermode && !fShadeDirectlyIntoDevice) { 465 for (;;) { 466 SkXfermode* xfer = fXfermode; 467 468 int count = *runs; 469 if (count <= 0) 470 break; 471 int aa = *antialias; 472 if (aa) { 473 shaderContext->shadeSpan(x, y, span, count); 474 if (aa == 255) { 475 xfer->xfer32(device, span, count, NULL); 476 } else { 477 // count is almost always 1 478 for (int i = count - 1; i >= 0; --i) { 479 xfer->xfer32(&device[i], &span[i], 1, antialias); 480 } 481 } 482 } 483 device += count; 484 runs += count; 485 antialias += count; 486 x += count; 487 } 488 } else if (fShadeDirectlyIntoDevice || 489 (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 490 for (;;) { 491 int count = *runs; 492 if (count <= 0) { 493 break; 494 } 495 int aa = *antialias; 496 if (aa) { 497 if (aa == 255) { 498 // cool, have the shader draw right into the device 499 shaderContext->shadeSpan(x, y, device, count); 500 } else { 501 shaderContext->shadeSpan(x, y, span, count); 502 fProc32Blend(device, span, count, aa); 503 } 504 } 505 device += count; 506 runs += count; 507 antialias += count; 508 x += count; 509 } 510 } else { 511 for (;;) { 512 int count = *runs; 513 if (count <= 0) { 514 break; 515 } 516 int aa = *antialias; 517 if (aa) { 518 shaderContext->shadeSpan(x, y, span, count); 519 if (aa == 255) { 520 fProc32(device, span, count, 255); 521 } else { 522 fProc32Blend(device, span, count, aa); 523 } 524 } 525 device += count; 526 runs += count; 527 antialias += count; 528 x += count; 529 } 530 } 531} 532 533void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 534 // we only handle kA8 with an xfermode 535 if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) { 536 this->INHERITED::blitMask(mask, clip); 537 return; 538 } 539 540 SkASSERT(mask.fBounds.contains(clip)); 541 542 SkShader::Context* shaderContext = fShaderContext; 543 SkBlitMask::RowProc proc = NULL; 544 if (!fXfermode) { 545 unsigned flags = 0; 546 if (shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) { 547 flags |= SkBlitMask::kSrcIsOpaque_RowFlag; 548 } 549 proc = SkBlitMask::RowFactory(kN32_SkColorType, mask.fFormat, 550 (SkBlitMask::RowFlags)flags); 551 if (NULL == proc) { 552 this->INHERITED::blitMask(mask, clip); 553 return; 554 } 555 } 556 557 const int x = clip.fLeft; 558 const int width = clip.width(); 559 int y = clip.fTop; 560 int height = clip.height(); 561 562 char* dstRow = (char*)fDevice.getAddr32(x, y); 563 const size_t dstRB = fDevice.rowBytes(); 564 const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); 565 const size_t maskRB = mask.fRowBytes; 566 567 SkPMColor* span = fBuffer; 568 569 if (fXfermode) { 570 SkASSERT(SkMask::kA8_Format == mask.fFormat); 571 SkXfermode* xfer = fXfermode; 572 do { 573 shaderContext->shadeSpan(x, y, span, width); 574 xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow); 575 dstRow += dstRB; 576 maskRow += maskRB; 577 y += 1; 578 } while (--height > 0); 579 } else { 580 do { 581 shaderContext->shadeSpan(x, y, span, width); 582 proc(dstRow, maskRow, span, width); 583 dstRow += dstRB; 584 maskRow += maskRB; 585 y += 1; 586 } while (--height > 0); 587 } 588} 589 590void SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 591 SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height()); 592 593 uint32_t* device = fDevice.getAddr32(x, y); 594 size_t deviceRB = fDevice.rowBytes(); 595 SkShader::Context* shaderContext = fShaderContext; 596 597 if (fConstInY) { 598 SkPMColor c; 599 shaderContext->shadeSpan(x, y, &c, 1); 600 601 if (fShadeDirectlyIntoDevice) { 602 if (255 == alpha) { 603 do { 604 *device = c; 605 device = (uint32_t*)((char*)device + deviceRB); 606 } while (--height > 0); 607 } else { 608 do { 609 *device = SkFourByteInterp(c, *device, alpha); 610 device = (uint32_t*)((char*)device + deviceRB); 611 } while (--height > 0); 612 } 613 } else { 614 SkXfermode* xfer = fXfermode; 615 if (xfer) { 616 do { 617 xfer->xfer32(device, &c, 1, &alpha); 618 device = (uint32_t*)((char*)device + deviceRB); 619 } while (--height > 0); 620 } else { 621 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend; 622 do { 623 proc(device, &c, 1, alpha); 624 device = (uint32_t*)((char*)device + deviceRB); 625 } while (--height > 0); 626 } 627 } 628 return; 629 } 630 631 if (fShadeDirectlyIntoDevice) { 632 void* ctx; 633 SkShader::Context::ShadeProc shadeProc = shaderContext->asAShadeProc(&ctx); 634 if (255 == alpha) { 635 if (shadeProc) { 636 do { 637 shadeProc(ctx, x, y, device, 1); 638 y += 1; 639 device = (uint32_t*)((char*)device + deviceRB); 640 } while (--height > 0); 641 } else { 642 do { 643 shaderContext->shadeSpan(x, y, device, 1); 644 y += 1; 645 device = (uint32_t*)((char*)device + deviceRB); 646 } while (--height > 0); 647 } 648 } else { // alpha < 255 649 SkPMColor c; 650 if (shadeProc) { 651 do { 652 shadeProc(ctx, x, y, &c, 1); 653 *device = SkFourByteInterp(c, *device, alpha); 654 y += 1; 655 device = (uint32_t*)((char*)device + deviceRB); 656 } while (--height > 0); 657 } else { 658 do { 659 shaderContext->shadeSpan(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 } 665 } 666 } else { 667 SkPMColor* span = fBuffer; 668 SkXfermode* xfer = fXfermode; 669 if (xfer) { 670 do { 671 shaderContext->shadeSpan(x, y, span, 1); 672 xfer->xfer32(device, span, 1, &alpha); 673 y += 1; 674 device = (uint32_t*)((char*)device + deviceRB); 675 } while (--height > 0); 676 } else { 677 SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend; 678 do { 679 shaderContext->shadeSpan(x, y, span, 1); 680 proc(device, span, 1, alpha); 681 y += 1; 682 device = (uint32_t*)((char*)device + deviceRB); 683 } while (--height > 0); 684 } 685 } 686} 687