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