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