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