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