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 "SkBlitter.h" 9 #include "SkAntiRun.h" 10 #include "SkColor.h" 11 #include "SkColorFilter.h" 12 #include "SkCoreBlitters.h" 13 #include "SkFilterShader.h" 14 #include "SkReadBuffer.h" 15 #include "SkWriteBuffer.h" 16 #include "SkMask.h" 17 #include "SkMaskFilter.h" 18 #include "SkString.h" 19 #include "SkTLazy.h" 20 #include "SkUtils.h" 21 #include "SkXfermode.h" 22 #include "SkXfermodeInterpretation.h" 23 24 SkBlitter::~SkBlitter() {} 25 26 bool SkBlitter::isNullBlitter() const { return false; } 27 28 bool SkBlitter::resetShaderContext(const SkShader::ContextRec&) { 29 return true; 30 } 31 32 SkShader::Context* SkBlitter::getShaderContext() const { 33 return NULL; 34 } 35 36 const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) { 37 return NULL; 38 } 39 40 void SkBlitter::blitH(int x, int y, int width) { 41 SkDEBUGFAIL("unimplemented"); 42 } 43 44 void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 45 const int16_t runs[]) { 46 SkDEBUGFAIL("unimplemented"); 47 } 48 49 void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 50 if (alpha == 255) { 51 this->blitRect(x, y, 1, height); 52 } else { 53 int16_t runs[2]; 54 runs[0] = 1; 55 runs[1] = 0; 56 57 while (--height >= 0) { 58 this->blitAntiH(x, y++, &alpha, runs); 59 } 60 } 61 } 62 63 void SkBlitter::blitRect(int x, int y, int width, int height) { 64 SkASSERT(width > 0); 65 while (--height >= 0) { 66 this->blitH(x, y++, width); 67 } 68 } 69 70 /// Default implementation doesn't check for any easy optimizations 71 /// such as alpha == 0 or 255; also uses blitV(), which some subclasses 72 /// may not support. 73 void SkBlitter::blitAntiRect(int x, int y, int width, int height, 74 SkAlpha leftAlpha, SkAlpha rightAlpha) { 75 this->blitV(x++, y, height, leftAlpha); 76 if (width > 0) { 77 this->blitRect(x, y, width, height); 78 x += width; 79 } 80 this->blitV(x, y, height, rightAlpha); 81 } 82 83 ////////////////////////////////////////////////////////////////////////////// 84 85 static inline void bits_to_runs(SkBlitter* blitter, int x, int y, 86 const uint8_t bits[], 87 U8CPU left_mask, int rowBytes, 88 U8CPU right_mask) { 89 int inFill = 0; 90 int pos = 0; 91 92 while (--rowBytes >= 0) { 93 unsigned b = *bits++ & left_mask; 94 if (rowBytes == 0) { 95 b &= right_mask; 96 } 97 98 for (unsigned test = 0x80; test != 0; test >>= 1) { 99 if (b & test) { 100 if (!inFill) { 101 pos = x; 102 inFill = true; 103 } 104 } else { 105 if (inFill) { 106 blitter->blitH(pos, y, x - pos); 107 inFill = false; 108 } 109 } 110 x += 1; 111 } 112 left_mask = 0xFF; 113 } 114 115 // final cleanup 116 if (inFill) { 117 blitter->blitH(pos, y, x - pos); 118 } 119 } 120 121 void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 122 SkASSERT(mask.fBounds.contains(clip)); 123 124 if (mask.fFormat == SkMask::kBW_Format) { 125 int cx = clip.fLeft; 126 int cy = clip.fTop; 127 int maskLeft = mask.fBounds.fLeft; 128 int mask_rowBytes = mask.fRowBytes; 129 int height = clip.height(); 130 131 const uint8_t* bits = mask.getAddr1(cx, cy); 132 133 if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) { 134 while (--height >= 0) { 135 bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF); 136 bits += mask_rowBytes; 137 cy += 1; 138 } 139 } else { 140 int left_edge = cx - maskLeft; 141 SkASSERT(left_edge >= 0); 142 int rite_edge = clip.fRight - maskLeft; 143 SkASSERT(rite_edge > left_edge); 144 145 int left_mask = 0xFF >> (left_edge & 7); 146 int rite_mask = 0xFF << (8 - (rite_edge & 7)); 147 int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3); 148 149 // check for empty right mask, so we don't read off the end (or go slower than we need to) 150 if (rite_mask == 0) { 151 SkASSERT(full_runs >= 0); 152 full_runs -= 1; 153 rite_mask = 0xFF; 154 } 155 if (left_mask == 0xFF) { 156 full_runs -= 1; 157 } 158 159 // back up manually so we can keep in sync with our byte-aligned src 160 // have cx reflect our actual starting x-coord 161 cx -= left_edge & 7; 162 163 if (full_runs < 0) { 164 SkASSERT((left_mask & rite_mask) != 0); 165 while (--height >= 0) { 166 bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask); 167 bits += mask_rowBytes; 168 cy += 1; 169 } 170 } else { 171 while (--height >= 0) { 172 bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask); 173 bits += mask_rowBytes; 174 cy += 1; 175 } 176 } 177 } 178 } else { 179 int width = clip.width(); 180 SkAutoSTMalloc<64, int16_t> runStorage(width + 1); 181 int16_t* runs = runStorage.get(); 182 const uint8_t* aa = mask.getAddr8(clip.fLeft, clip.fTop); 183 184 sk_memset16((uint16_t*)runs, 1, width); 185 runs[width] = 0; 186 187 int height = clip.height(); 188 int y = clip.fTop; 189 while (--height >= 0) { 190 this->blitAntiH(clip.fLeft, y, aa, runs); 191 aa += mask.fRowBytes; 192 y += 1; 193 } 194 } 195 } 196 197 /////////////////////// these guys are not virtual, just a helpers 198 199 void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) { 200 if (clip.quickReject(mask.fBounds)) { 201 return; 202 } 203 204 SkRegion::Cliperator clipper(clip, mask.fBounds); 205 206 while (!clipper.done()) { 207 const SkIRect& cr = clipper.rect(); 208 this->blitMask(mask, cr); 209 clipper.next(); 210 } 211 } 212 213 void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) { 214 SkRegion::Cliperator clipper(clip, rect); 215 216 while (!clipper.done()) { 217 const SkIRect& cr = clipper.rect(); 218 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 219 clipper.next(); 220 } 221 } 222 223 void SkBlitter::blitRegion(const SkRegion& clip) { 224 SkRegion::Iterator iter(clip); 225 226 while (!iter.done()) { 227 const SkIRect& cr = iter.rect(); 228 this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 229 iter.next(); 230 } 231 } 232 233 /////////////////////////////////////////////////////////////////////////////// 234 235 void SkNullBlitter::blitH(int x, int y, int width) {} 236 237 void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 238 const int16_t runs[]) {} 239 240 void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {} 241 242 void SkNullBlitter::blitRect(int x, int y, int width, int height) {} 243 244 void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {} 245 246 const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) { 247 return NULL; 248 } 249 250 bool SkNullBlitter::isNullBlitter() const { return true; } 251 252 /////////////////////////////////////////////////////////////////////////////// 253 254 static int compute_anti_width(const int16_t runs[]) { 255 int width = 0; 256 257 for (;;) { 258 int count = runs[0]; 259 260 SkASSERT(count >= 0); 261 if (count == 0) { 262 break; 263 } 264 width += count; 265 runs += count; 266 } 267 return width; 268 } 269 270 static inline bool y_in_rect(int y, const SkIRect& rect) { 271 return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 272 } 273 274 static inline bool x_in_rect(int x, const SkIRect& rect) { 275 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 276 } 277 278 void SkRectClipBlitter::blitH(int left, int y, int width) { 279 SkASSERT(width > 0); 280 281 if (!y_in_rect(y, fClipRect)) { 282 return; 283 } 284 285 int right = left + width; 286 287 if (left < fClipRect.fLeft) { 288 left = fClipRect.fLeft; 289 } 290 if (right > fClipRect.fRight) { 291 right = fClipRect.fRight; 292 } 293 294 width = right - left; 295 if (width > 0) { 296 fBlitter->blitH(left, y, width); 297 } 298 } 299 300 void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], 301 const int16_t runs[]) { 302 if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) { 303 return; 304 } 305 306 int x0 = left; 307 int x1 = left + compute_anti_width(runs); 308 309 if (x1 <= fClipRect.fLeft) { 310 return; 311 } 312 313 SkASSERT(x0 < x1); 314 if (x0 < fClipRect.fLeft) { 315 int dx = fClipRect.fLeft - x0; 316 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx); 317 runs += dx; 318 aa += dx; 319 x0 = fClipRect.fLeft; 320 } 321 322 SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 323 if (x1 > fClipRect.fRight) { 324 x1 = fClipRect.fRight; 325 SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0); 326 ((int16_t*)runs)[x1 - x0] = 0; 327 } 328 329 SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 330 SkASSERT(compute_anti_width(runs) == x1 - x0); 331 332 fBlitter->blitAntiH(x0, y, aa, runs); 333 } 334 335 void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 336 SkASSERT(height > 0); 337 338 if (!x_in_rect(x, fClipRect)) { 339 return; 340 } 341 342 int y0 = y; 343 int y1 = y + height; 344 345 if (y0 < fClipRect.fTop) { 346 y0 = fClipRect.fTop; 347 } 348 if (y1 > fClipRect.fBottom) { 349 y1 = fClipRect.fBottom; 350 } 351 352 if (y0 < y1) { 353 fBlitter->blitV(x, y0, y1 - y0, alpha); 354 } 355 } 356 357 void SkRectClipBlitter::blitRect(int left, int y, int width, int height) { 358 SkIRect r; 359 360 r.set(left, y, left + width, y + height); 361 if (r.intersect(fClipRect)) { 362 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 363 } 364 } 365 366 void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height, 367 SkAlpha leftAlpha, SkAlpha rightAlpha) { 368 SkIRect r; 369 370 // The *true* width of the rectangle blitted is width+2: 371 r.set(left, y, left + width + 2, y + height); 372 if (r.intersect(fClipRect)) { 373 if (r.fLeft != left) { 374 SkASSERT(r.fLeft > left); 375 leftAlpha = 255; 376 } 377 if (r.fRight != left + width + 2) { 378 SkASSERT(r.fRight < left + width + 2); 379 rightAlpha = 255; 380 } 381 if (255 == leftAlpha && 255 == rightAlpha) { 382 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 383 } else if (1 == r.width()) { 384 if (r.fLeft == left) { 385 fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha); 386 } else { 387 SkASSERT(r.fLeft == left + width + 1); 388 fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha); 389 } 390 } else { 391 fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 392 leftAlpha, rightAlpha); 393 } 394 } 395 } 396 397 void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 398 SkASSERT(mask.fBounds.contains(clip)); 399 400 SkIRect r = clip; 401 402 if (r.intersect(fClipRect)) { 403 fBlitter->blitMask(mask, r); 404 } 405 } 406 407 const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) { 408 return fBlitter->justAnOpaqueColor(value); 409 } 410 411 /////////////////////////////////////////////////////////////////////////////// 412 413 void SkRgnClipBlitter::blitH(int x, int y, int width) { 414 SkRegion::Spanerator span(*fRgn, y, x, x + width); 415 int left, right; 416 417 while (span.next(&left, &right)) { 418 SkASSERT(left < right); 419 fBlitter->blitH(left, y, right - left); 420 } 421 } 422 423 void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 424 const int16_t runs[]) { 425 int width = compute_anti_width(runs); 426 SkRegion::Spanerator span(*fRgn, y, x, x + width); 427 int left, right; 428 SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();) 429 430 int prevRite = x; 431 while (span.next(&left, &right)) { 432 SkASSERT(x <= left); 433 SkASSERT(left < right); 434 SkASSERT(left >= bounds.fLeft && right <= bounds.fRight); 435 436 SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left); 437 438 // now zero before left 439 if (left > prevRite) { 440 int index = prevRite - x; 441 ((uint8_t*)aa)[index] = 0; // skip runs after right 442 ((int16_t*)runs)[index] = SkToS16(left - prevRite); 443 } 444 445 prevRite = right; 446 } 447 448 if (prevRite > x) { 449 ((int16_t*)runs)[prevRite - x] = 0; 450 451 if (x < 0) { 452 int skip = runs[0]; 453 SkASSERT(skip >= -x); 454 aa += skip; 455 runs += skip; 456 x += skip; 457 } 458 fBlitter->blitAntiH(x, y, aa, runs); 459 } 460 } 461 462 void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 463 SkIRect bounds; 464 bounds.set(x, y, x + 1, y + height); 465 466 SkRegion::Cliperator iter(*fRgn, bounds); 467 468 while (!iter.done()) { 469 const SkIRect& r = iter.rect(); 470 SkASSERT(bounds.contains(r)); 471 472 fBlitter->blitV(x, r.fTop, r.height(), alpha); 473 iter.next(); 474 } 475 } 476 477 void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) { 478 SkIRect bounds; 479 bounds.set(x, y, x + width, y + height); 480 481 SkRegion::Cliperator iter(*fRgn, bounds); 482 483 while (!iter.done()) { 484 const SkIRect& r = iter.rect(); 485 SkASSERT(bounds.contains(r)); 486 487 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 488 iter.next(); 489 } 490 } 491 492 void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height, 493 SkAlpha leftAlpha, SkAlpha rightAlpha) { 494 // The *true* width of the rectangle to blit is width + 2 495 SkIRect bounds; 496 bounds.set(x, y, x + width + 2, y + height); 497 498 SkRegion::Cliperator iter(*fRgn, bounds); 499 500 while (!iter.done()) { 501 const SkIRect& r = iter.rect(); 502 SkASSERT(bounds.contains(r)); 503 SkASSERT(r.fLeft >= x); 504 SkASSERT(r.fRight <= x + width + 2); 505 506 SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255; 507 SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ? 508 rightAlpha : 255; 509 510 if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) { 511 fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 512 } else if (1 == r.width()) { 513 if (r.fLeft == x) { 514 fBlitter->blitV(r.fLeft, r.fTop, r.height(), 515 effectiveLeftAlpha); 516 } else { 517 SkASSERT(r.fLeft == x + width + 1); 518 fBlitter->blitV(r.fLeft, r.fTop, r.height(), 519 effectiveRightAlpha); 520 } 521 } else { 522 fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 523 effectiveLeftAlpha, effectiveRightAlpha); 524 } 525 iter.next(); 526 } 527 } 528 529 530 void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 531 SkASSERT(mask.fBounds.contains(clip)); 532 533 SkRegion::Cliperator iter(*fRgn, clip); 534 const SkIRect& r = iter.rect(); 535 SkBlitter* blitter = fBlitter; 536 537 while (!iter.done()) { 538 blitter->blitMask(mask, r); 539 iter.next(); 540 } 541 } 542 543 const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) { 544 return fBlitter->justAnOpaqueColor(value); 545 } 546 547 /////////////////////////////////////////////////////////////////////////////// 548 549 SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, 550 const SkIRect* ir) { 551 if (clip) { 552 const SkIRect& clipR = clip->getBounds(); 553 554 if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) { 555 blitter = &fNullBlitter; 556 } else if (clip->isRect()) { 557 if (ir == NULL || !clipR.contains(*ir)) { 558 fRectBlitter.init(blitter, clipR); 559 blitter = &fRectBlitter; 560 } 561 } else { 562 fRgnBlitter.init(blitter, clip); 563 blitter = &fRgnBlitter; 564 } 565 } 566 return blitter; 567 } 568 569 /////////////////////////////////////////////////////////////////////////////// 570 571 #include "SkColorShader.h" 572 #include "SkColorPriv.h" 573 574 class Sk3DShader : public SkShader { 575 public: 576 Sk3DShader(SkShader* proxy) : fProxy(proxy) { 577 SkSafeRef(proxy); 578 } 579 580 virtual ~Sk3DShader() { 581 SkSafeUnref(fProxy); 582 } 583 584 size_t contextSize() const override { 585 size_t size = sizeof(Sk3DShaderContext); 586 if (fProxy) { 587 size += fProxy->contextSize(); 588 } 589 return size; 590 } 591 592 Context* onCreateContext(const ContextRec& rec, void* storage) const override { 593 SkShader::Context* proxyContext = NULL; 594 if (fProxy) { 595 char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext); 596 proxyContext = fProxy->createContext(rec, proxyContextStorage); 597 if (!proxyContext) { 598 return NULL; 599 } 600 } 601 return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, rec, proxyContext)); 602 } 603 604 class Sk3DShaderContext : public SkShader::Context { 605 public: 606 // Calls proxyContext's destructor but will NOT free its memory. 607 Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec, 608 SkShader::Context* proxyContext) 609 : INHERITED(shader, rec) 610 , fMask(NULL) 611 , fProxyContext(proxyContext) 612 { 613 if (!fProxyContext) { 614 fPMColor = SkPreMultiplyColor(rec.fPaint->getColor()); 615 } 616 } 617 618 virtual ~Sk3DShaderContext() { 619 if (fProxyContext) { 620 fProxyContext->~Context(); 621 } 622 } 623 624 void set3DMask(const SkMask* mask) override { fMask = mask; } 625 626 void shadeSpan(int x, int y, SkPMColor span[], int count) override { 627 if (fProxyContext) { 628 fProxyContext->shadeSpan(x, y, span, count); 629 } 630 631 if (fMask == NULL) { 632 if (fProxyContext == NULL) { 633 sk_memset32(span, fPMColor, count); 634 } 635 return; 636 } 637 638 SkASSERT(fMask->fBounds.contains(x, y)); 639 SkASSERT(fMask->fBounds.contains(x + count - 1, y)); 640 641 size_t size = fMask->computeImageSize(); 642 const uint8_t* alpha = fMask->getAddr8(x, y); 643 const uint8_t* mulp = alpha + size; 644 const uint8_t* addp = mulp + size; 645 646 if (fProxyContext) { 647 for (int i = 0; i < count; i++) { 648 if (alpha[i]) { 649 SkPMColor c = span[i]; 650 if (c) { 651 unsigned a = SkGetPackedA32(c); 652 unsigned r = SkGetPackedR32(c); 653 unsigned g = SkGetPackedG32(c); 654 unsigned b = SkGetPackedB32(c); 655 656 unsigned mul = SkAlpha255To256(mulp[i]); 657 unsigned add = addp[i]; 658 659 r = SkFastMin32(SkAlphaMul(r, mul) + add, a); 660 g = SkFastMin32(SkAlphaMul(g, mul) + add, a); 661 b = SkFastMin32(SkAlphaMul(b, mul) + add, a); 662 663 span[i] = SkPackARGB32(a, r, g, b); 664 } 665 } else { 666 span[i] = 0; 667 } 668 } 669 } else { // color 670 unsigned a = SkGetPackedA32(fPMColor); 671 unsigned r = SkGetPackedR32(fPMColor); 672 unsigned g = SkGetPackedG32(fPMColor); 673 unsigned b = SkGetPackedB32(fPMColor); 674 for (int i = 0; i < count; i++) { 675 if (alpha[i]) { 676 unsigned mul = SkAlpha255To256(mulp[i]); 677 unsigned add = addp[i]; 678 679 span[i] = SkPackARGB32( a, 680 SkFastMin32(SkAlphaMul(r, mul) + add, a), 681 SkFastMin32(SkAlphaMul(g, mul) + add, a), 682 SkFastMin32(SkAlphaMul(b, mul) + add, a)); 683 } else { 684 span[i] = 0; 685 } 686 } 687 } 688 } 689 690 private: 691 // Unowned. 692 const SkMask* fMask; 693 // Memory is unowned, but we need to call the destructor. 694 SkShader::Context* fProxyContext; 695 SkPMColor fPMColor; 696 697 typedef SkShader::Context INHERITED; 698 }; 699 700 #ifndef SK_IGNORE_TO_STRING 701 void toString(SkString* str) const override { 702 str->append("Sk3DShader: ("); 703 704 if (fProxy) { 705 str->append("Proxy: "); 706 fProxy->toString(str); 707 } 708 709 this->INHERITED::toString(str); 710 711 str->append(")"); 712 } 713 #endif 714 715 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader) 716 717 protected: 718 void flatten(SkWriteBuffer& buffer) const override { 719 buffer.writeFlattenable(fProxy); 720 } 721 722 private: 723 SkShader* fProxy; 724 725 typedef SkShader INHERITED; 726 }; 727 728 SkFlattenable* Sk3DShader::CreateProc(SkReadBuffer& buffer) { 729 SkAutoTUnref<SkShader> shader(buffer.readShader()); 730 return SkNEW_ARGS(Sk3DShader, (shader)); 731 } 732 733 class Sk3DBlitter : public SkBlitter { 734 public: 735 Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext) 736 : fProxy(proxy) 737 , fShaderContext(shaderContext) 738 {} 739 740 void blitH(int x, int y, int width) override { 741 fProxy->blitH(x, y, width); 742 } 743 744 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 745 const int16_t runs[]) override { 746 fProxy->blitAntiH(x, y, antialias, runs); 747 } 748 749 void blitV(int x, int y, int height, SkAlpha alpha) override { 750 fProxy->blitV(x, y, height, alpha); 751 } 752 753 void blitRect(int x, int y, int width, int height) override { 754 fProxy->blitRect(x, y, width, height); 755 } 756 757 void blitMask(const SkMask& mask, const SkIRect& clip) override { 758 if (mask.fFormat == SkMask::k3D_Format) { 759 fShaderContext->set3DMask(&mask); 760 761 ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; 762 fProxy->blitMask(mask, clip); 763 ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; 764 765 fShaderContext->set3DMask(NULL); 766 } else { 767 fProxy->blitMask(mask, clip); 768 } 769 } 770 771 private: 772 // Both pointers are unowned. They will be deleted by SkSmallAllocator. 773 SkBlitter* fProxy; 774 SkShader::Context* fShaderContext; 775 }; 776 777 /////////////////////////////////////////////////////////////////////////////// 778 779 #include "SkCoreBlitters.h" 780 781 SkBlitter* SkBlitter::Choose(const SkBitmap& device, 782 const SkMatrix& matrix, 783 const SkPaint& origPaint, 784 SkTBlitterAllocator* allocator, 785 bool drawCoverage) { 786 SkASSERT(allocator != NULL); 787 788 // which check, in case we're being called by a client with a dummy device 789 // (e.g. they have a bounder that always aborts the draw) 790 if (kUnknown_SkColorType == device.colorType() || 791 (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) { 792 return allocator->createT<SkNullBlitter>(); 793 } 794 795 SkShader* shader = origPaint.getShader(); 796 SkColorFilter* cf = origPaint.getColorFilter(); 797 SkXfermode* mode = origPaint.getXfermode(); 798 Sk3DShader* shader3D = NULL; 799 800 SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 801 802 if (origPaint.getMaskFilter() != NULL && 803 origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) { 804 shader3D = SkNEW_ARGS(Sk3DShader, (shader)); 805 // we know we haven't initialized lazyPaint yet, so just do it 806 paint.writable()->setShader(shader3D)->unref(); 807 shader = shader3D; 808 } 809 810 if (mode) { 811 bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType(); 812 switch (SkInterpretXfermode(*paint, deviceIsOpaque)) { 813 case kSrcOver_SkXfermodeInterpretation: 814 mode = NULL; 815 paint.writable()->setXfermode(NULL); 816 break; 817 case kSkipDrawing_SkXfermodeInterpretation:{ 818 return allocator->createT<SkNullBlitter>(); 819 } 820 default: 821 break; 822 } 823 } 824 825 /* 826 * If the xfermode is CLEAR, then we can completely ignore the installed 827 * color/shader/colorfilter, and just pretend we're SRC + color==0. This 828 * will fall into our optimizations for SRC mode. 829 */ 830 if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) { 831 SkPaint* p = paint.writable(); 832 shader = p->setShader(NULL); 833 cf = p->setColorFilter(NULL); 834 mode = p->setXfermodeMode(SkXfermode::kSrc_Mode); 835 p->setColor(0); 836 } 837 838 if (NULL == shader) { 839 if (mode) { 840 // xfermodes (and filters) require shaders for our current blitters 841 shader = SkNEW_ARGS(SkColorShader, (paint->getColor())); 842 paint.writable()->setShader(shader)->unref(); 843 paint.writable()->setAlpha(0xFF); 844 } else if (cf) { 845 // if no shader && no xfermode, we just apply the colorfilter to 846 // our color and move on. 847 SkPaint* writablePaint = paint.writable(); 848 writablePaint->setColor(cf->filterColor(paint->getColor())); 849 writablePaint->setColorFilter(NULL); 850 cf = NULL; 851 } 852 } 853 854 if (cf) { 855 SkASSERT(shader); 856 shader = SkNEW_ARGS(SkFilterShader, (shader, cf)); 857 paint.writable()->setShader(shader)->unref(); 858 // blitters should ignore the presence/absence of a filter, since 859 // if there is one, the shader will take care of it. 860 } 861 862 /* 863 * We create a SkShader::Context object, and store it on the blitter. 864 */ 865 SkShader::Context* shaderContext = NULL; 866 if (shader) { 867 SkShader::ContextRec rec(device, *paint, matrix); 868 size_t contextSize = shader->contextSize(); 869 if (contextSize) { 870 // Try to create the ShaderContext 871 void* storage = allocator->reserveT<SkShader::Context>(contextSize); 872 shaderContext = shader->createContext(rec, storage); 873 if (!shaderContext) { 874 allocator->freeLast(); 875 return allocator->createT<SkNullBlitter>(); 876 } 877 SkASSERT(shaderContext); 878 SkASSERT((void*) shaderContext == storage); 879 } else { 880 return allocator->createT<SkNullBlitter>(); 881 } 882 } 883 884 SkBlitter* blitter = NULL; 885 switch (device.colorType()) { 886 case kAlpha_8_SkColorType: 887 if (drawCoverage) { 888 SkASSERT(NULL == shader); 889 SkASSERT(NULL == paint->getXfermode()); 890 blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint); 891 } else if (shader) { 892 blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext); 893 } else { 894 blitter = allocator->createT<SkA8_Blitter>(device, *paint); 895 } 896 break; 897 898 case kRGB_565_SkColorType: 899 blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator); 900 break; 901 902 case kN32_SkColorType: 903 if (shader) { 904 blitter = allocator->createT<SkARGB32_Shader_Blitter>( 905 device, *paint, shaderContext); 906 } else if (paint->getColor() == SK_ColorBLACK) { 907 blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint); 908 } else if (paint->getAlpha() == 0xFF) { 909 blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint); 910 } else { 911 blitter = allocator->createT<SkARGB32_Blitter>(device, *paint); 912 } 913 break; 914 915 default: 916 SkDEBUGFAIL("unsupported device config"); 917 blitter = allocator->createT<SkNullBlitter>(); 918 break; 919 } 920 921 if (shader3D) { 922 SkBlitter* innerBlitter = blitter; 923 // innerBlitter was allocated by allocator, which will delete it. 924 // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to 925 // wrapper the blitter to notify it when we see an emboss mask. 926 blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext); 927 } 928 return blitter; 929 } 930 931 /////////////////////////////////////////////////////////////////////////////// 932 933 class SkTransparentShaderContext : public SkShader::Context { 934 public: 935 SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec) 936 // Override rec with the identity matrix, so it is guaranteed to be invertible. 937 : INHERITED(shader, SkShader::ContextRec(*rec.fDevice, *rec.fPaint, SkMatrix::I())) {} 938 939 void shadeSpan(int x, int y, SkPMColor colors[], int count) override { 940 sk_bzero(colors, count * sizeof(SkPMColor)); 941 } 942 943 private: 944 typedef SkShader::Context INHERITED; 945 }; 946 947 SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, 948 SkShader::Context* shaderContext) 949 : INHERITED(device) 950 , fShader(paint.getShader()) 951 , fShaderContext(shaderContext) { 952 SkASSERT(fShader); 953 SkASSERT(fShaderContext); 954 955 fShader->ref(); 956 fShaderFlags = fShaderContext->getFlags(); 957 } 958 959 SkShaderBlitter::~SkShaderBlitter() { 960 fShader->unref(); 961 } 962 963 bool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) { 964 // Only destroy the old context if we have a new one. We need to ensure to have a 965 // live context in fShaderContext because the storage is owned by an SkSmallAllocator 966 // outside of this class. 967 // The new context will be of the same size as the old one because we use the same 968 // shader to create it. It is therefore safe to re-use the storage. 969 fShaderContext->~Context(); 970 SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext); 971 if (NULL == ctx) { 972 // Need a valid context in fShaderContext's storage, so we can later (or our caller) call 973 // the in-place destructor. 974 SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec)); 975 return false; 976 } 977 return true; 978 } 979