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 (NULL != 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 Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) { 718 fProxy = buffer.readShader(); 719 // Leaving this here until we bump the picture version, though this 720 // shader should never be recorded. 721 buffer.readColor(); 722 } 723 724 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { 725 this->INHERITED::flatten(buffer); 726 buffer.writeFlattenable(fProxy); 727 // Leaving this here until we bump the picture version, though this 728 // shader should never be recorded. 729 buffer.writeColor(SkColor()); 730 } 731 732 private: 733 SkShader* fProxy; 734 735 typedef SkShader INHERITED; 736 }; 737 738 class Sk3DBlitter : public SkBlitter { 739 public: 740 Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext) 741 : fProxy(proxy) 742 , fShaderContext(shaderContext) 743 {} 744 745 virtual void blitH(int x, int y, int width) { 746 fProxy->blitH(x, y, width); 747 } 748 749 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 750 const int16_t runs[]) { 751 fProxy->blitAntiH(x, y, antialias, runs); 752 } 753 754 virtual void blitV(int x, int y, int height, SkAlpha alpha) { 755 fProxy->blitV(x, y, height, alpha); 756 } 757 758 virtual void blitRect(int x, int y, int width, int height) { 759 fProxy->blitRect(x, y, width, height); 760 } 761 762 virtual void blitMask(const SkMask& mask, const SkIRect& clip) { 763 if (mask.fFormat == SkMask::k3D_Format) { 764 fShaderContext->set3DMask(&mask); 765 766 ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; 767 fProxy->blitMask(mask, clip); 768 ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; 769 770 fShaderContext->set3DMask(NULL); 771 } else { 772 fProxy->blitMask(mask, clip); 773 } 774 } 775 776 private: 777 // Both pointers are unowned. They will be deleted by SkSmallAllocator. 778 SkBlitter* fProxy; 779 SkShader::Context* fShaderContext; 780 }; 781 782 /////////////////////////////////////////////////////////////////////////////// 783 784 #include "SkCoreBlitters.h" 785 786 static bool just_solid_color(const SkPaint& paint) { 787 if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) { 788 SkShader* shader = paint.getShader(); 789 if (NULL == shader) { 790 return true; 791 } 792 } 793 return false; 794 } 795 796 /** By analyzing the paint (with an xfermode), we may decide we can take 797 special action. This enum lists our possible actions 798 */ 799 enum XferInterp { 800 kNormal_XferInterp, // no special interpretation, draw normally 801 kSrcOver_XferInterp, // draw as if in srcover mode 802 kSkipDrawing_XferInterp // draw nothing 803 }; 804 805 static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer, 806 SkColorType deviceCT) { 807 SkXfermode::Mode mode; 808 809 if (SkXfermode::AsMode(xfer, &mode)) { 810 switch (mode) { 811 case SkXfermode::kSrc_Mode: 812 if (just_solid_color(paint)) { 813 return kSrcOver_XferInterp; 814 } 815 break; 816 case SkXfermode::kDst_Mode: 817 return kSkipDrawing_XferInterp; 818 case SkXfermode::kSrcOver_Mode: 819 return kSrcOver_XferInterp; 820 case SkXfermode::kDstOver_Mode: 821 if (kRGB_565_SkColorType == deviceCT) { 822 return kSkipDrawing_XferInterp; 823 } 824 break; 825 case SkXfermode::kSrcIn_Mode: 826 if (kRGB_565_SkColorType == deviceCT && 827 just_solid_color(paint)) { 828 return kSrcOver_XferInterp; 829 } 830 break; 831 case SkXfermode::kDstIn_Mode: 832 if (just_solid_color(paint)) { 833 return kSkipDrawing_XferInterp; 834 } 835 break; 836 default: 837 break; 838 } 839 } 840 return kNormal_XferInterp; 841 } 842 843 SkBlitter* SkBlitter::Choose(const SkBitmap& device, 844 const SkMatrix& matrix, 845 const SkPaint& origPaint, 846 SkTBlitterAllocator* allocator, 847 bool drawCoverage) { 848 SkASSERT(allocator != NULL); 849 850 SkBlitter* blitter = NULL; 851 852 // which check, in case we're being called by a client with a dummy device 853 // (e.g. they have a bounder that always aborts the draw) 854 if (kUnknown_SkColorType == device.colorType() || 855 (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) { 856 blitter = allocator->createT<SkNullBlitter>(); 857 return blitter; 858 } 859 860 SkShader* shader = origPaint.getShader(); 861 SkColorFilter* cf = origPaint.getColorFilter(); 862 SkXfermode* mode = origPaint.getXfermode(); 863 Sk3DShader* shader3D = NULL; 864 865 SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 866 867 if (origPaint.getMaskFilter() != NULL && 868 origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) { 869 shader3D = SkNEW_ARGS(Sk3DShader, (shader)); 870 // we know we haven't initialized lazyPaint yet, so just do it 871 paint.writable()->setShader(shader3D)->unref(); 872 shader = shader3D; 873 } 874 875 if (NULL != mode) { 876 switch (interpret_xfermode(*paint, mode, device.colorType())) { 877 case kSrcOver_XferInterp: 878 mode = NULL; 879 paint.writable()->setXfermode(NULL); 880 break; 881 case kSkipDrawing_XferInterp:{ 882 blitter = allocator->createT<SkNullBlitter>(); 883 return blitter; 884 } 885 default: 886 break; 887 } 888 } 889 890 /* 891 * If the xfermode is CLEAR, then we can completely ignore the installed 892 * color/shader/colorfilter, and just pretend we're SRC + color==0. This 893 * will fall into our optimizations for SRC mode. 894 */ 895 if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) { 896 SkPaint* p = paint.writable(); 897 shader = p->setShader(NULL); 898 cf = p->setColorFilter(NULL); 899 mode = p->setXfermodeMode(SkXfermode::kSrc_Mode); 900 p->setColor(0); 901 } 902 903 if (NULL == shader) { 904 if (mode) { 905 // xfermodes (and filters) require shaders for our current blitters 906 shader = SkNEW_ARGS(SkColorShader, (paint->getColor())); 907 paint.writable()->setShader(shader)->unref(); 908 paint.writable()->setAlpha(0xFF); 909 } else if (cf) { 910 // if no shader && no xfermode, we just apply the colorfilter to 911 // our color and move on. 912 SkPaint* writablePaint = paint.writable(); 913 writablePaint->setColor(cf->filterColor(paint->getColor())); 914 writablePaint->setColorFilter(NULL); 915 cf = NULL; 916 } 917 } 918 919 if (cf) { 920 SkASSERT(shader); 921 shader = SkNEW_ARGS(SkFilterShader, (shader, cf)); 922 paint.writable()->setShader(shader)->unref(); 923 // blitters should ignore the presence/absence of a filter, since 924 // if there is one, the shader will take care of it. 925 } 926 927 /* 928 * We create a SkShader::Context object, and store it on the blitter. 929 */ 930 SkShader::Context* shaderContext; 931 if (shader) { 932 SkShader::ContextRec rec(device, *paint, matrix); 933 // Try to create the ShaderContext 934 void* storage = allocator->reserveT<SkShader::Context>(shader->contextSize()); 935 shaderContext = shader->createContext(rec, storage); 936 if (!shaderContext) { 937 allocator->freeLast(); 938 blitter = allocator->createT<SkNullBlitter>(); 939 return blitter; 940 } 941 SkASSERT(shaderContext); 942 SkASSERT((void*) shaderContext == storage); 943 } else { 944 shaderContext = NULL; 945 } 946 947 948 switch (device.colorType()) { 949 case kAlpha_8_SkColorType: 950 if (drawCoverage) { 951 SkASSERT(NULL == shader); 952 SkASSERT(NULL == paint->getXfermode()); 953 blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint); 954 } else if (shader) { 955 blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext); 956 } else { 957 blitter = allocator->createT<SkA8_Blitter>(device, *paint); 958 } 959 break; 960 961 case kRGB_565_SkColorType: 962 blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator); 963 break; 964 965 case kN32_SkColorType: 966 if (shader) { 967 blitter = allocator->createT<SkARGB32_Shader_Blitter>( 968 device, *paint, shaderContext); 969 } else if (paint->getColor() == SK_ColorBLACK) { 970 blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint); 971 } else if (paint->getAlpha() == 0xFF) { 972 blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint); 973 } else { 974 blitter = allocator->createT<SkARGB32_Blitter>(device, *paint); 975 } 976 break; 977 978 default: 979 SkDEBUGFAIL("unsupported device config"); 980 blitter = allocator->createT<SkNullBlitter>(); 981 break; 982 } 983 984 if (shader3D) { 985 SkBlitter* innerBlitter = blitter; 986 // innerBlitter was allocated by allocator, which will delete it. 987 // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to 988 // wrapper the blitter to notify it when we see an emboss mask. 989 blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext); 990 } 991 return blitter; 992 } 993 994 /////////////////////////////////////////////////////////////////////////////// 995 996 class SkTransparentShaderContext : public SkShader::Context { 997 public: 998 SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec) 999 // Override rec with the identity matrix, so it is guaranteed to be invertible. 1000 : INHERITED(shader, SkShader::ContextRec(*rec.fDevice, *rec.fPaint, SkMatrix::I())) {} 1001 1002 virtual void shadeSpan(int x, int y, SkPMColor colors[], int count) SK_OVERRIDE { 1003 sk_bzero(colors, count * sizeof(SkPMColor)); 1004 } 1005 1006 private: 1007 typedef SkShader::Context INHERITED; 1008 }; 1009 1010 SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, 1011 SkShader::Context* shaderContext) 1012 : INHERITED(device) 1013 , fShader(paint.getShader()) 1014 , fShaderContext(shaderContext) { 1015 SkASSERT(fShader); 1016 SkASSERT(fShaderContext); 1017 1018 fShader->ref(); 1019 fShaderFlags = fShaderContext->getFlags(); 1020 } 1021 1022 SkShaderBlitter::~SkShaderBlitter() { 1023 fShader->unref(); 1024 } 1025 1026 bool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) { 1027 // Only destroy the old context if we have a new one. We need to ensure to have a 1028 // live context in fShaderContext because the storage is owned by an SkSmallAllocator 1029 // outside of this class. 1030 // The new context will be of the same size as the old one because we use the same 1031 // shader to create it. It is therefore safe to re-use the storage. 1032 fShaderContext->~Context(); 1033 SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext); 1034 if (NULL == ctx) { 1035 // Need a valid context in fShaderContext's storage, so we can later (or our caller) call 1036 // the in-place destructor. 1037 SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec)); 1038 return false; 1039 } 1040 return true; 1041 } 1042