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