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 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 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 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 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 66 #pragma warning ( push ) 67 #pragma warning ( disable : 4701 ) 68 #endif 69 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 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 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 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 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 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 199 void SkARGB32_Opaque_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 200 uint32_t* device = fDevice.writable_addr32(x, y); 201 SkDEBUGCODE((void)fDevice.writable_addr32(x + 1, y);) 202 203 device[0] = SkFastFourByteInterp(fPMColor, device[0], a0); 204 device[1] = SkFastFourByteInterp(fPMColor, device[1], a1); 205 } 206 207 void SkARGB32_Opaque_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 208 uint32_t* device = fDevice.writable_addr32(x, y); 209 SkDEBUGCODE((void)fDevice.writable_addr32(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 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.writable_addr32(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 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.writable_addr32(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 261 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 262 const int16_t runs[]) { 263 uint32_t* device = fDevice.writable_addr32(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 292 void SkARGB32_Black_Blitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) { 293 uint32_t* device = fDevice.writable_addr32(x, y); 294 SkDEBUGCODE((void)fDevice.writable_addr32(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 300 void SkARGB32_Black_Blitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) { 301 uint32_t* device = fDevice.writable_addr32(x, y); 302 SkDEBUGCODE((void)fDevice.writable_addr32(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 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 322 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkPixmap& 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 == nullptr) { 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 358 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { 359 SkSafeUnref(fXfermode); 360 sk_free(fBuffer); 361 } 362 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.writable_addr32(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, nullptr); 375 } else { 376 fProc32(device, span, width, 255); 377 } 378 } 379 } 380 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.writable_addr32(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, nullptr); 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, nullptr); 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 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.writable_addr32(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, nullptr); 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 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 = nullptr; 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 (nullptr == 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.writable_addr32(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(reinterpret_cast<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(reinterpret_cast<SkPMColor*>(dstRow), maskRow, span, width); 582 dstRow += dstRB; 583 maskRow += maskRB; 584 y += 1; 585 } while (--height > 0); 586 } 587 } 588 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.writable_addr32(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