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