SkAAClip.cpp revision 209c41511eb0d06f8c19f8fb1fc0393c502a1b18
1 2/* 3 * Copyright 2011 Google Inc. 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#include "SkAAClip.h" 10#include "SkBlitter.h" 11#include "SkColorPriv.h" 12#include "SkPath.h" 13#include "SkScan.h" 14#include "SkThread.h" 15#include "SkUtils.h" 16 17class AutoAAClipValidate { 18public: 19 AutoAAClipValidate(const SkAAClip& clip) : fClip(clip) { 20 fClip.validate(); 21 } 22 ~AutoAAClipValidate() { 23 fClip.validate(); 24 } 25private: 26 const SkAAClip& fClip; 27}; 28 29#ifdef SK_DEBUG 30 #define AUTO_AACLIP_VALIDATE(clip) AutoAAClipValidate acv(clip) 31#else 32 #define AUTO_AACLIP_VALIDATE(clip) 33#endif 34 35/////////////////////////////////////////////////////////////////////////////// 36 37#define kMaxInt32 0x7FFFFFFF 38 39static inline bool x_in_rect(int x, const SkIRect& rect) { 40 return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 41} 42 43static inline bool y_in_rect(int y, const SkIRect& rect) { 44 return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 45} 46 47/* 48 * Data runs are packed [count, alpha] 49 */ 50 51struct SkAAClip::YOffset { 52 int32_t fY; 53 uint32_t fOffset; 54}; 55 56struct SkAAClip::RunHead { 57 int32_t fRefCnt; 58 int32_t fRowCount; 59 int32_t fDataSize; 60 61 YOffset* yoffsets() { 62 return (YOffset*)((char*)this + sizeof(RunHead)); 63 } 64 const YOffset* yoffsets() const { 65 return (const YOffset*)((const char*)this + sizeof(RunHead)); 66 } 67 uint8_t* data() { 68 return (uint8_t*)(this->yoffsets() + fRowCount); 69 } 70 const uint8_t* data() const { 71 return (const uint8_t*)(this->yoffsets() + fRowCount); 72 } 73 74 static RunHead* Alloc(int rowCount, size_t dataSize) { 75 size_t size = sizeof(RunHead) + rowCount * sizeof(YOffset) + dataSize; 76 RunHead* head = (RunHead*)sk_malloc_throw(size); 77 head->fRefCnt = 1; 78 head->fRowCount = rowCount; 79 head->fDataSize = dataSize; 80 return head; 81 } 82 83 static int ComputeRowSizeForWidth(int width) { 84 // 2 bytes per segment, where each segment can store up to 255 for count 85 int segments = 0; 86 while (width > 0) { 87 segments += 1; 88 int n = SkMin32(width, 255); 89 width -= n; 90 } 91 return segments * 2; // each segment is row[0] + row[1] (n + alpha) 92 } 93 94 static RunHead* AllocRect(const SkIRect& bounds) { 95 SkASSERT(!bounds.isEmpty()); 96 int width = bounds.width(); 97 size_t rowSize = ComputeRowSizeForWidth(width); 98 RunHead* head = RunHead::Alloc(1, rowSize); 99 YOffset* yoff = head->yoffsets(); 100 yoff->fY = bounds.height() - 1; 101 yoff->fOffset = 0; 102 uint8_t* row = head->data(); 103 while (width > 0) { 104 int n = SkMin32(width, 255); 105 row[0] = n; 106 row[1] = 0xFF; 107 width -= n; 108 row += 2; 109 } 110 return head; 111 } 112}; 113 114class SkAAClip::Iter { 115public: 116 Iter(const SkAAClip&); 117 118 bool done() const { return fDone; } 119 int top() const { return fTop; } 120 int bottom() const { return fBottom; } 121 const uint8_t* data() const { return fData; } 122 void next(); 123 124private: 125 const YOffset* fCurrYOff; 126 const YOffset* fStopYOff; 127 const uint8_t* fData; 128 129 int fTop, fBottom; 130 bool fDone; 131}; 132 133SkAAClip::Iter::Iter(const SkAAClip& clip) { 134 if (clip.isEmpty()) { 135 fDone = true; 136 fTop = fBottom = clip.fBounds.fBottom; 137 fData = NULL; 138 return; 139 } 140 141 const RunHead* head = clip.fRunHead; 142 fCurrYOff = head->yoffsets(); 143 fStopYOff = fCurrYOff + head->fRowCount; 144 fData = head->data() + fCurrYOff->fOffset; 145 146 // setup first value 147 fTop = clip.fBounds.fTop; 148 fBottom = clip.fBounds.fTop + fCurrYOff->fY + 1; 149 fDone = false; 150} 151 152void SkAAClip::Iter::next() { 153 if (!fDone) { 154 const YOffset* prev = fCurrYOff; 155 const YOffset* curr = prev + 1; 156 SkASSERT(curr <= fStopYOff); 157 158 fTop = fBottom; 159 if (curr >= fStopYOff) { 160 fDone = true; 161 fBottom = kMaxInt32; 162 fData = NULL; 163 } else { 164 fBottom += curr->fY - prev->fY; 165 fData += curr->fOffset - prev->fOffset; 166 fCurrYOff = curr; 167 } 168 } 169} 170 171#ifdef SK_DEBUG 172static size_t compute_row_length(const uint8_t row[], int width) { 173 const uint8_t* origRow = row; 174 while (width > 0) { 175 int n = row[0]; 176 SkASSERT(n <= width); 177 row += 2; 178 width -= n; 179 } 180 SkASSERT(0 == width); 181 return row - origRow; 182} 183 184void SkAAClip::validate() const { 185 if (NULL == fRunHead) { 186 SkASSERT(fBounds.isEmpty()); 187 return; 188 } 189 190 const RunHead* head = fRunHead; 191 SkASSERT(head->fRefCnt > 0); 192 SkASSERT(head->fRowCount > 0); 193 SkASSERT(head->fDataSize > 0); 194 195 const YOffset* yoff = head->yoffsets(); 196 const YOffset* ystop = yoff + head->fRowCount; 197 const uint8_t* row = head->data(); 198 SkASSERT(0 == yoff->fOffset); 199 // y values must be monotonic 200 int y = -1; 201 int32_t offset = -1; 202 size_t computedOffset = 0; 203 while (yoff < ystop) { 204 SkASSERT(y < yoff->fY); 205 y = yoff->fY; 206 SkASSERT(offset < (int32_t)yoff->fOffset); 207 offset = yoff->fOffset; 208 SkASSERT(yoff->fOffset == computedOffset); 209 yoff += 1; 210 211 size_t rowLength = compute_row_length(row, fBounds.width()); 212 row += rowLength; 213 computedOffset += rowLength; 214 } 215 SkASSERT(head->fDataSize == computedOffset); 216 // check the last entry; 217 --yoff; 218 SkASSERT(yoff->fY == fBounds.height() - 1); 219 220} 221#endif 222 223/////////////////////////////////////////////////////////////////////////////// 224 225// can't validate before we're done, since trimming is part of the process of 226// making us valid after the Builder. Since we build from top to bottom, its 227// possible our fBounds.fBottom is bigger than our last scanline of data, so 228// we trim fBounds.fBottom back up. 229// 230// TODO: look to trim our bounds on top, left, right. 231// TODO: check for duplicates in X and Y to further compress our data 232// 233bool SkAAClip::trimBounds() { 234 if (this->isEmpty()) { 235 return false; 236 } 237 238 const RunHead* head = fRunHead; 239 const YOffset* yoff = head->yoffsets(); 240 241 SkASSERT(head->fRowCount > 0); 242 const YOffset& lastY = yoff[head->fRowCount - 1]; 243 SkASSERT(lastY.fY + 1 <= fBounds.height()); 244 fBounds.fBottom = fBounds.fTop + lastY.fY + 1; 245 SkASSERT(lastY.fY + 1 == fBounds.height()); 246 return true; 247} 248 249/////////////////////////////////////////////////////////////////////////////// 250 251void SkAAClip::freeRuns() { 252 if (fRunHead) { 253 SkASSERT(fRunHead->fRefCnt >= 1); 254 if (1 == sk_atomic_dec(&fRunHead->fRefCnt)) { 255 sk_free(fRunHead); 256 } 257 } 258} 259 260SkAAClip::SkAAClip() { 261 fBounds.setEmpty(); 262 fRunHead = NULL; 263} 264 265SkAAClip::SkAAClip(const SkAAClip& src) { 266 SkDEBUGCODE(fBounds.setEmpty();) // need this for validate 267 fRunHead = NULL; 268 *this = src; 269} 270 271SkAAClip::~SkAAClip() { 272 this->freeRuns(); 273} 274 275SkAAClip& SkAAClip::operator=(const SkAAClip& src) { 276 AUTO_AACLIP_VALIDATE(*this); 277 src.validate(); 278 279 if (this != &src) { 280 this->freeRuns(); 281 fBounds = src.fBounds; 282 fRunHead = src.fRunHead; 283 if (fRunHead) { 284 sk_atomic_inc(&fRunHead->fRefCnt); 285 } 286 } 287 return *this; 288} 289 290bool operator==(const SkAAClip& a, const SkAAClip& b) { 291 a.validate(); 292 b.validate(); 293 294 if (&a == &b) { 295 return true; 296 } 297 if (a.fBounds != b.fBounds) { 298 return false; 299 } 300 301 const SkAAClip::RunHead* ah = a.fRunHead; 302 const SkAAClip::RunHead* bh = b.fRunHead; 303 304 // this catches empties and rects being equal 305 if (ah == bh) { 306 return true; 307 } 308 309 // now we insist that both are complex (but different ptrs) 310 if (!a.fRunHead || !b.fRunHead) { 311 return false; 312 } 313 314 return ah->fRowCount == bh->fRowCount && 315 ah->fDataSize == bh->fDataSize && 316 !memcmp(ah->data(), bh->data(), ah->fDataSize); 317} 318 319void SkAAClip::swap(SkAAClip& other) { 320 AUTO_AACLIP_VALIDATE(*this); 321 other.validate(); 322 323 SkTSwap(fBounds, other.fBounds); 324 SkTSwap(fRunHead, other.fRunHead); 325} 326 327bool SkAAClip::set(const SkAAClip& src) { 328 *this = src; 329 return !this->isEmpty(); 330} 331 332bool SkAAClip::setEmpty() { 333 this->freeRuns(); 334 fBounds.setEmpty(); 335 fRunHead = NULL; 336 return false; 337} 338 339bool SkAAClip::setRect(const SkIRect& bounds) { 340 if (bounds.isEmpty()) { 341 return this->setEmpty(); 342 } 343 344 AUTO_AACLIP_VALIDATE(*this); 345 346#if 0 347 SkRect r; 348 r.set(bounds); 349 SkPath path; 350 path.addRect(r); 351 return this->setPath(path); 352#else 353 this->freeRuns(); 354 fBounds = bounds; 355 fRunHead = RunHead::AllocRect(bounds); 356 SkASSERT(!this->isEmpty()); 357 return true; 358#endif 359} 360 361bool SkAAClip::setRect(const SkRect& r, bool doAA) { 362 if (r.isEmpty()) { 363 return this->setEmpty(); 364 } 365 366 AUTO_AACLIP_VALIDATE(*this); 367 368 // TODO: special case this 369 370 SkPath path; 371 path.addRect(r); 372 return this->setPath(path, NULL, doAA); 373} 374 375bool SkAAClip::setRegion(const SkRegion& rgn) { 376 if (rgn.isEmpty()) { 377 return this->setEmpty(); 378 } 379 if (rgn.isRect()) { 380 return this->setRect(rgn.getBounds()); 381 } 382 383 SkAAClip clip; 384 SkRegion::Iterator iter(rgn); 385 for (; !iter.done(); iter.next()) { 386 clip.op(iter.rect(), SkRegion::kUnion_Op); 387 } 388 this->swap(clip); 389 return !this->isEmpty(); 390} 391 392/////////////////////////////////////////////////////////////////////////////// 393 394const uint8_t* SkAAClip::findRow(int y, int* lastYForRow) const { 395 SkASSERT(fRunHead); 396 397 if (!y_in_rect(y, fBounds)) { 398 return NULL; 399 } 400 y -= fBounds.y(); // our yoffs values are relative to the top 401 402 const YOffset* yoff = fRunHead->yoffsets(); 403 while (yoff->fY < y) { 404 yoff += 1; 405 SkASSERT(yoff - fRunHead->yoffsets() < fRunHead->fRowCount); 406 } 407 408 if (lastYForRow) { 409 *lastYForRow = fBounds.y() + yoff->fY; 410 } 411 return fRunHead->data() + yoff->fOffset; 412} 413 414const uint8_t* SkAAClip::findX(const uint8_t data[], int x, int* initialCount) const { 415 SkASSERT(x_in_rect(x, fBounds)); 416 x -= fBounds.x(); 417 418 // first skip up to X 419 for (;;) { 420 int n = data[0]; 421 if (x < n) { 422 *initialCount = n - x; 423 break; 424 } 425 data += 2; 426 x -= n; 427 } 428 return data; 429} 430 431bool SkAAClip::quickContains(int left, int top, int right, int bottom) const { 432 if (this->isEmpty()) { 433 return false; 434 } 435 if (!fBounds.contains(left, top, right, bottom)) { 436 return false; 437 } 438#if 0 439 if (this->isRect()) { 440 return true; 441 } 442#endif 443 444 int lastY; 445 const uint8_t* row = this->findRow(top, &lastY); 446 if (lastY < bottom) { 447 return false; 448 } 449 // now just need to check in X 450 int count; 451 row = this->findX(row, left, &count); 452#if 0 453 return count >= (right - left) && 0xFF == row[1]; 454#else 455 int rectWidth = right - left; 456 while (0xFF == row[1]) { 457 if (count >= rectWidth) { 458 return true; 459 } 460 rectWidth -= count; 461 row += 2; 462 count = row[0]; 463 } 464 return false; 465#endif 466} 467 468/////////////////////////////////////////////////////////////////////////////// 469 470class SkAAClip::Builder { 471 SkIRect fBounds; 472 struct Row { 473 int fY; 474 int fWidth; 475 SkTDArray<uint8_t>* fData; 476 }; 477 SkTDArray<Row> fRows; 478 Row* fCurrRow; 479 int fPrevY; 480 int fWidth; 481 int fMinY; 482 483public: 484 Builder(const SkIRect& bounds) : fBounds(bounds) { 485 fPrevY = -1; 486 fWidth = bounds.width(); 487 fCurrRow = NULL; 488 fMinY = bounds.fTop; 489 } 490 491 ~Builder() { 492 Row* row = fRows.begin(); 493 Row* stop = fRows.end(); 494 while (row < stop) { 495 delete row->fData; 496 row += 1; 497 } 498 } 499 500 const SkIRect& getBounds() const { return fBounds; } 501 502 void addRun(int x, int y, U8CPU alpha, int count) { 503 SkASSERT(count > 0); 504 SkASSERT(fBounds.contains(x, y)); 505 SkASSERT(fBounds.contains(x + count - 1, y)); 506 507 x -= fBounds.left(); 508 y -= fBounds.top(); 509 510 Row* row = fCurrRow; 511 if (y != fPrevY) { 512 SkASSERT(y > fPrevY); 513 fPrevY = y; 514 row = this->flushRow(true); 515 row->fY = y; 516 row->fWidth = 0; 517 SkASSERT(row->fData); 518 SkASSERT(0 == row->fData->count()); 519 fCurrRow = row; 520 } 521 522 SkASSERT(row->fWidth <= x); 523 SkASSERT(row->fWidth < fBounds.width()); 524 525 SkTDArray<uint8_t>& data = *row->fData; 526 527 int gap = x - row->fWidth; 528 if (gap) { 529 AppendRun(data, 0, gap); 530 row->fWidth += gap; 531 SkASSERT(row->fWidth < fBounds.width()); 532 } 533 534 AppendRun(data, alpha, count); 535 row->fWidth += count; 536 SkASSERT(row->fWidth <= fBounds.width()); 537 } 538 539 bool finish(SkAAClip* target) { 540 this->flushRow(false); 541 542 const Row* row = fRows.begin(); 543 const Row* stop = fRows.end(); 544 545 size_t dataSize = 0; 546 while (row < stop) { 547 dataSize += row->fData->count(); 548 row += 1; 549 } 550 551 if (0 == dataSize) { 552 return target->setEmpty(); 553 } 554 555 SkASSERT(fMinY >= fBounds.fTop); 556 SkASSERT(fMinY < fBounds.fBottom); 557 int adjustY = fMinY - fBounds.fTop; 558 fBounds.fTop = fMinY; 559 560 RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 561 YOffset* yoffset = head->yoffsets(); 562 uint8_t* data = head->data(); 563 uint8_t* baseData = data; 564 565 row = fRows.begin(); 566 while (row < stop) { 567 yoffset->fY = row->fY - adjustY; 568 yoffset->fOffset = data - baseData; 569 yoffset += 1; 570 571 size_t n = row->fData->count(); 572 memcpy(data, row->fData->begin(), n); 573 data += n; 574 575 row += 1; 576 } 577 578 target->freeRuns(); 579 target->fBounds = fBounds; 580 target->fRunHead = head; 581 return target->trimBounds(); 582 } 583 584 void dump() { 585 this->validate(); 586 int y; 587 for (y = 0; y < fRows.count(); ++y) { 588 const Row& row = fRows[y]; 589 SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 590 const SkTDArray<uint8_t>& data = *row.fData; 591 int count = data.count(); 592 SkASSERT(!(count & 1)); 593 const uint8_t* ptr = data.begin(); 594 for (int x = 0; x < count; x += 2) { 595 SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 596 ptr += 2; 597 } 598 SkDebugf("\n"); 599 } 600 } 601 602 void validate() { 603#ifdef SK_DEBUG 604 int prevY = -1; 605 for (int i = 0; i < fRows.count(); ++i) { 606 const Row& row = fRows[i]; 607 SkASSERT(prevY < row.fY); 608 SkASSERT(fWidth == row.fWidth); 609 int count = row.fData->count(); 610 const uint8_t* ptr = row.fData->begin(); 611 SkASSERT(!(count & 1)); 612 int w = 0; 613 for (int x = 0; x < count; x += 2) { 614 w += ptr[0]; 615 SkASSERT(w <= fWidth); 616 ptr += 2; 617 } 618 SkASSERT(w == fWidth); 619 prevY = row.fY; 620 } 621#endif 622 } 623 624 // only called by BuilderBlitter 625 void setMinY(int y) { 626 fMinY = y; 627 } 628 629private: 630 631 Row* flushRow(bool readyForAnother) { 632 Row* next = NULL; 633 int count = fRows.count(); 634 if (count > 0) { 635 // flush current row if needed 636 Row* curr = &fRows[count - 1]; 637 if (curr->fWidth < fWidth) { 638 AppendRun(*curr->fData, 0, fWidth - curr->fWidth); 639 curr->fWidth = fWidth; 640 } 641 } 642 if (count > 1) { 643 // are our last two runs the same? 644 Row* prev = &fRows[count - 2]; 645 Row* curr = &fRows[count - 1]; 646 SkASSERT(prev->fWidth == fWidth); 647 SkASSERT(curr->fWidth == fWidth); 648 if (*prev->fData == *curr->fData) { 649 prev->fY = curr->fY; 650 if (readyForAnother) { 651 curr->fData->rewind(); 652 next = curr; 653 } else { 654 delete curr->fData; 655 fRows.removeShuffle(count - 1); 656 } 657 } else { 658 if (readyForAnother) { 659 next = fRows.append(); 660 next->fData = new SkTDArray<uint8_t>; 661 } 662 } 663 } else { 664 if (readyForAnother) { 665 next = fRows.append(); 666 next->fData = new SkTDArray<uint8_t>; 667 } 668 } 669 return next; 670 } 671 672 static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 673 do { 674 int n = count; 675 if (n > 255) { 676 n = 255; 677 } 678 uint8_t* ptr = data.append(2); 679 ptr[0] = n; 680 ptr[1] = alpha; 681 count -= n; 682 } while (count > 0); 683 } 684}; 685 686class SkAAClip::BuilderBlitter : public SkBlitter { 687public: 688 BuilderBlitter(Builder* builder) { 689 fBuilder = builder; 690 fLeft = builder->getBounds().fLeft; 691 fRight = builder->getBounds().fRight; 692 fMinY = SK_MaxS32; 693 } 694 695 void finish() { 696 if (fMinY < SK_MaxS32) { 697 fBuilder->setMinY(fMinY); 698 } 699 } 700 701 virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE 702 { unexpected(); } 703 704 // let the default impl call blitH 705// virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE 706 707 virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE 708 { unexpected(); } 709 710 virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE { 711 return NULL; 712 } 713 714 virtual void blitH(int x, int y, int width) SK_OVERRIDE { 715 this->recordMinY(y); 716 fBuilder->addRun(x, y, 0xFF, width); 717 } 718 719 virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 720 const int16_t runs[]) SK_OVERRIDE { 721 this->recordMinY(y); 722 for (;;) { 723 int count = *runs; 724 if (count <= 0) { 725 return; 726 } 727 728 // The supersampler's buffer can be the width of the device, so 729 // we may have to trim the run to our bounds. If so, we assert that 730 // the extra spans are always alpha==0 731 int localX = x; 732 int localCount = count; 733 if (x < fLeft) { 734 SkASSERT(0 == *alpha); 735 int gap = fLeft - x; 736 SkASSERT(gap <= count); 737 localX += gap; 738 localCount -= gap; 739 } 740 int right = x + count; 741 if (right > fRight) { 742 SkASSERT(0 == *alpha); 743 localCount -= right - fRight; 744 SkASSERT(localCount >= 0); 745 } 746 747 if (localCount) { 748 fBuilder->addRun(localX, y, *alpha, localCount); 749 } 750 // Next run 751 runs += count; 752 alpha += count; 753 x += count; 754 } 755 } 756 757private: 758 Builder* fBuilder; 759 int fLeft; // cache of builder's bounds' left edge 760 int fRight; 761 int fMinY; 762 763 /* 764 * We track this, in case the scan converter skipped some number of 765 * scanlines at the (relative to the bounds it was given). This allows 766 * the builder, during its finish, to trip its bounds down to the "real" 767 * top. 768 */ 769 void recordMinY(int y) { 770 if (y < fMinY) { 771 fMinY = y; 772 } 773 } 774 775 void unexpected() { 776 SkDebugf("---- did not expect to get called here"); 777 sk_throw(); 778 } 779}; 780 781bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 782 AUTO_AACLIP_VALIDATE(*this); 783 784 if (clip && clip->isEmpty()) { 785 return this->setEmpty(); 786 } 787 788 SkIRect ibounds; 789 path.getBounds().roundOut(&ibounds); 790 791 SkRegion tmpClip; 792 if (NULL == clip) { 793 tmpClip.setRect(ibounds); 794 clip = &tmpClip; 795 } 796 797 if (path.isInverseFillType()) { 798 ibounds = clip->getBounds(); 799 } else { 800 if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 801 return this->setEmpty(); 802 } 803 } 804 805 Builder builder(ibounds); 806 BuilderBlitter blitter(&builder); 807 808 if (doAA) { 809 SkScan::AntiFillPath(path, *clip, &blitter, true); 810 } else { 811 SkScan::FillPath(path, *clip, &blitter); 812 } 813 814 blitter.finish(); 815 return builder.finish(this); 816} 817 818/////////////////////////////////////////////////////////////////////////////// 819 820typedef void (*RowProc)(SkAAClip::Builder&, int bottom, 821 const uint8_t* rowA, const SkIRect& rectA, 822 const uint8_t* rowB, const SkIRect& rectB); 823 824static void sectRowProc(SkAAClip::Builder& builder, int bottom, 825 const uint8_t* rowA, const SkIRect& rectA, 826 const uint8_t* rowB, const SkIRect& rectB) { 827 828} 829 830typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 831 832static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 833 // Multiply 834 return SkMulDiv255Round(alphaA, alphaB); 835} 836 837static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 838 // SrcOver 839 return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 840} 841 842static U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 843 // SrcOut 844 return SkMulDiv255Round(alphaA, 0xFF - alphaB); 845} 846 847static U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 848 // XOR 849 return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 850} 851 852static AlphaProc find_alpha_proc(SkRegion::Op op) { 853 switch (op) { 854 case SkRegion::kIntersect_Op: 855 return sectAlphaProc; 856 case SkRegion::kDifference_Op: 857 return diffAlphaProc; 858 case SkRegion::kUnion_Op: 859 return unionAlphaProc; 860 case SkRegion::kXOR_Op: 861 return xorAlphaProc; 862 default: 863 SkASSERT(!"unexpected region op"); 864 return sectAlphaProc; 865 } 866} 867 868static const uint8_t gEmptyRow[] = { 869 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 870 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 871 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 872 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 873 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 874 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 875 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 876 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 877}; 878 879class RowIter { 880public: 881 RowIter(const uint8_t* row, const SkIRect& bounds) { 882 fRow = row; 883 fLeft = bounds.fLeft; 884 fBoundsRight = bounds.fRight; 885 if (row) { 886 fRight = bounds.fLeft + row[0]; 887 SkASSERT(fRight <= fBoundsRight); 888 fAlpha = row[1]; 889 fDone = false; 890 } else { 891 fDone = true; 892 fRight = kMaxInt32; 893 fAlpha = 0; 894 } 895 } 896 897 bool done() const { return fDone; } 898 int left() const { return fLeft; } 899 int right() const { return fRight; } 900 U8CPU alpha() const { return fAlpha; } 901 void next() { 902 if (!fDone) { 903 fLeft = fRight; 904 if (fRight == fBoundsRight) { 905 fDone = true; 906 fRight = kMaxInt32; 907 fAlpha = 0; 908 } else { 909 fRow += 2; 910 fRight += fRow[0]; 911 fAlpha = fRow[1]; 912 SkASSERT(fRight <= fBoundsRight); 913 } 914 } 915 } 916 917private: 918 const uint8_t* fRow; 919 int fLeft; 920 int fRight; 921 int fBoundsRight; 922 bool fDone; 923 uint8_t fAlpha; 924}; 925 926static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 927 if (rite == riteA) { 928 iter.next(); 929 leftA = iter.left(); 930 riteA = iter.right(); 931 } 932} 933 934static bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 935 SkASSERT(min < max); 936 SkASSERT(boundsMin < boundsMax); 937 if (min >= boundsMax || max <= boundsMin) { 938 return false; 939 } 940 if (min < boundsMin) { 941 min = boundsMin; 942 } 943 if (max > boundsMax) { 944 max = boundsMax; 945 } 946 return true; 947} 948 949static void operatorX(SkAAClip::Builder& builder, int lastY, 950 RowIter& iterA, RowIter& iterB, 951 AlphaProc proc, const SkIRect& bounds) { 952 int leftA = iterA.left(); 953 int riteA = iterA.right(); 954 int leftB = iterB.left(); 955 int riteB = iterB.right(); 956 957 int prevRite = bounds.fLeft; 958 959 do { 960 U8CPU alphaA = 0; 961 U8CPU alphaB = 0; 962 int left, rite; 963 964 if (leftA < leftB) { 965 left = leftA; 966 alphaA = iterA.alpha(); 967 if (riteA <= leftB) { 968 rite = riteA; 969 } else { 970 rite = leftA = leftB; 971 } 972 } else if (leftB < leftA) { 973 left = leftB; 974 alphaB = iterB.alpha(); 975 if (riteB <= leftA) { 976 rite = riteB; 977 } else { 978 rite = leftB = leftA; 979 } 980 } else { 981 left = leftA; // or leftB, since leftA == leftB 982 rite = leftA = leftB = SkMin32(riteA, riteB); 983 alphaA = iterA.alpha(); 984 alphaB = iterB.alpha(); 985 } 986 987 if (left >= bounds.fRight) { 988 break; 989 } 990 if (rite > bounds.fRight) { 991 rite = bounds.fRight; 992 } 993 994 if (left >= bounds.fLeft) { 995 SkASSERT(rite > left); 996 builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 997 prevRite = rite; 998 } 999 1000 adjust_row(iterA, leftA, riteA, rite); 1001 adjust_row(iterB, leftB, riteB, rite); 1002 } while (!iterA.done() || !iterB.done()); 1003 1004 if (prevRite < bounds.fRight) { 1005 builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 1006 } 1007} 1008 1009static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 1010 if (bot == botA) { 1011 iter.next(); 1012 topA = botA; 1013 SkASSERT(botA == iter.top()); 1014 botA = iter.bottom(); 1015 } 1016} 1017 1018static void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 1019 const SkAAClip& B, SkRegion::Op op) { 1020 AlphaProc proc = find_alpha_proc(op); 1021 const SkIRect& bounds = builder.getBounds(); 1022 1023 SkAAClip::Iter iterA(A); 1024 SkAAClip::Iter iterB(B); 1025 1026 SkASSERT(!iterA.done()); 1027 int topA = iterA.top(); 1028 int botA = iterA.bottom(); 1029 SkASSERT(!iterB.done()); 1030 int topB = iterB.top(); 1031 int botB = iterB.bottom(); 1032 1033 do { 1034 const uint8_t* rowA = NULL; 1035 const uint8_t* rowB = NULL; 1036 int top, bot; 1037 1038 if (topA < topB) { 1039 top = topA; 1040 rowA = iterA.data(); 1041 if (botA <= topB) { 1042 bot = botA; 1043 } else { 1044 bot = topA = topB; 1045 } 1046 1047 } else if (topB < topA) { 1048 top = topB; 1049 rowB = iterB.data(); 1050 if (botB <= topA) { 1051 bot = botB; 1052 } else { 1053 bot = topB = topA; 1054 } 1055 } else { 1056 top = topA; // or topB, since topA == topB 1057 bot = topA = topB = SkMin32(botA, botB); 1058 rowA = iterA.data(); 1059 rowB = iterB.data(); 1060 } 1061 1062 if (top >= bounds.fBottom) { 1063 break; 1064 } 1065 1066 if (bot > bounds.fBottom) { 1067 bot = bounds.fBottom; 1068 } 1069 SkASSERT(top < bot); 1070 1071 if (!rowA && !rowB) { 1072 builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 1073 } else if (top >= bounds.fTop) { 1074 SkASSERT(bot <= bounds.fBottom); 1075 RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 1076 RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1077 operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1078 } 1079 1080 adjust_iter(iterA, topA, botA, bot); 1081 adjust_iter(iterB, topB, botB, bot); 1082 } while (!iterA.done() || !iterB.done()); 1083} 1084 1085bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1086 SkRegion::Op op) { 1087 AUTO_AACLIP_VALIDATE(*this); 1088 1089 if (SkRegion::kReplace_Op == op) { 1090 return this->set(clipBOrig); 1091 } 1092 1093 const SkAAClip* clipA = &clipAOrig; 1094 const SkAAClip* clipB = &clipBOrig; 1095 1096 if (SkRegion::kReverseDifference_Op == op) { 1097 SkTSwap(clipA, clipB); 1098 op = SkRegion::kDifference_Op; 1099 } 1100 1101 bool a_empty = clipA->isEmpty(); 1102 bool b_empty = clipB->isEmpty(); 1103 1104 SkIRect bounds; 1105 switch (op) { 1106 case SkRegion::kDifference_Op: 1107 if (a_empty) { 1108 return this->setEmpty(); 1109 } 1110 if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1111 return this->set(*clipA); 1112 } 1113 bounds = clipA->fBounds; 1114 break; 1115 1116 case SkRegion::kIntersect_Op: 1117 if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1118 clipB->fBounds)) { 1119 return this->setEmpty(); 1120 } 1121 break; 1122 1123 case SkRegion::kUnion_Op: 1124 case SkRegion::kXOR_Op: 1125 if (a_empty) { 1126 return this->set(*clipB); 1127 } 1128 if (b_empty) { 1129 return this->set(*clipA); 1130 } 1131 bounds = clipA->fBounds; 1132 bounds.join(clipB->fBounds); 1133 break; 1134 1135 default: 1136 SkASSERT(!"unknown region op"); 1137 return !this->isEmpty(); 1138 } 1139 1140 SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1141 SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1142 1143 Builder builder(bounds); 1144 operateY(builder, *clipA, *clipB, op); 1145 1146 return builder.finish(this); 1147} 1148 1149/* 1150 * It can be expensive to build a local aaclip before applying the op, so 1151 * we first see if we can restrict the bounds of new rect to our current 1152 * bounds, or note that the new rect subsumes our current clip. 1153 */ 1154 1155bool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1156 SkIRect rStorage; 1157 const SkIRect* r = &rOrig; 1158 1159 switch (op) { 1160 case SkRegion::kIntersect_Op: 1161 if (!rStorage.intersect(rOrig, fBounds)) { 1162 // no overlap, so we're empty 1163 return this->setEmpty(); 1164 } 1165 if (rStorage == fBounds) { 1166 // we were wholly inside the rect, no change 1167 return !this->isEmpty(); 1168 } 1169 if (this->quickContains(rStorage)) { 1170 // the intersection is wholly inside us, we're a rect 1171 return this->setRect(rStorage); 1172 } 1173 r = &rStorage; // use the intersected bounds 1174 break; 1175 case SkRegion::kDifference_Op: 1176 break; 1177 case SkRegion::kUnion_Op: 1178 if (rOrig.contains(fBounds)) { 1179 return this->setRect(rOrig); 1180 } 1181 break; 1182 default: 1183 break; 1184 } 1185 1186 SkAAClip clip; 1187 clip.setRect(*r); 1188 return this->op(*this, clip, op); 1189} 1190 1191bool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1192 SkRect rStorage, boundsStorage; 1193 const SkRect* r = &rOrig; 1194 1195 boundsStorage.set(fBounds); 1196 switch (op) { 1197 case SkRegion::kIntersect_Op: 1198 case SkRegion::kDifference_Op: 1199 if (!rStorage.intersect(rOrig, boundsStorage)) { 1200 return this->setEmpty(); 1201 } 1202 r = &rStorage; // use the intersected bounds 1203 break; 1204 case SkRegion::kUnion_Op: 1205 if (rOrig.contains(boundsStorage)) { 1206 return this->setRect(rOrig); 1207 } 1208 break; 1209 default: 1210 break; 1211 } 1212 1213 SkAAClip clip; 1214 clip.setRect(*r, doAA); 1215 return this->op(*this, clip, op); 1216} 1217 1218bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 1219 return this->op(*this, clip, op); 1220} 1221 1222/////////////////////////////////////////////////////////////////////////////// 1223 1224bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 1225 if (NULL == dst) { 1226 return !this->isEmpty(); 1227 } 1228 1229 if (this->isEmpty()) { 1230 return dst->setEmpty(); 1231 } 1232 1233 if (this != dst) { 1234 sk_atomic_inc(&fRunHead->fRefCnt); 1235 dst->fRunHead = fRunHead; 1236 dst->fBounds = fBounds; 1237 } 1238 dst->fBounds.offset(dx, dy); 1239 return true; 1240} 1241 1242static void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1243 const uint8_t* SK_RESTRICT row, 1244 int width) { 1245 while (width > 0) { 1246 int n = row[0]; 1247 SkASSERT(width >= n); 1248 memset(mask, row[1], n); 1249 mask += n; 1250 row += 2; 1251 width -= n; 1252 } 1253} 1254 1255void SkAAClip::copyToMask(SkMask* mask) const { 1256 mask->fFormat = SkMask::kA8_Format; 1257 if (this->isEmpty()) { 1258 mask->fBounds.setEmpty(); 1259 mask->fImage = NULL; 1260 mask->fRowBytes = 0; 1261 return; 1262 } 1263 1264 mask->fBounds = fBounds; 1265 mask->fRowBytes = fBounds.width(); 1266 size_t size = mask->computeImageSize(); 1267 mask->fImage = SkMask::AllocImage(size); 1268 1269 Iter iter(*this); 1270 uint8_t* dst = mask->fImage; 1271 const int width = fBounds.width(); 1272 1273 int y = fBounds.fTop; 1274 while (!iter.done()) { 1275 do { 1276 expand_row_to_mask(dst, iter.data(), width); 1277 dst += mask->fRowBytes; 1278 } while (++y < iter.bottom()); 1279 iter.next(); 1280 } 1281} 1282 1283/////////////////////////////////////////////////////////////////////////////// 1284/////////////////////////////////////////////////////////////////////////////// 1285 1286static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1287 int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1288 // we don't read our initial n from data, since the caller may have had to 1289 // clip it, hence the initialCount parameter. 1290 int n = initialCount; 1291 for (;;) { 1292 if (n > width) { 1293 n = width; 1294 } 1295 SkASSERT(n > 0); 1296 runs[0] = n; 1297 runs += n; 1298 1299 aa[0] = data[1]; 1300 aa += n; 1301 1302 data += 2; 1303 width -= n; 1304 if (0 == width) { 1305 break; 1306 } 1307 // load the next count 1308 n = data[0]; 1309 } 1310 runs[0] = 0; // sentinel 1311} 1312 1313SkAAClipBlitter::~SkAAClipBlitter() { 1314 sk_free(fScanlineScratch); 1315} 1316 1317void SkAAClipBlitter::ensureRunsAndAA() { 1318 if (NULL == fScanlineScratch) { 1319 // add 1 so we can store the terminating run count of 0 1320 int count = fAAClipBounds.width() + 1; 1321 // we use this either for fRuns + fAA, or a scaline of a mask 1322 // which may be as deep as 32bits 1323 fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1324 fRuns = (int16_t*)fScanlineScratch; 1325 fAA = (SkAlpha*)(fRuns + count); 1326 } 1327} 1328 1329void SkAAClipBlitter::blitH(int x, int y, int width) { 1330 SkASSERT(width > 0); 1331 SkASSERT(fAAClipBounds.contains(x, y)); 1332 SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1333 1334 int lastY; 1335 const uint8_t* row = fAAClip->findRow(y, &lastY); 1336 int initialCount; 1337 row = fAAClip->findX(row, x, &initialCount); 1338 1339 if (initialCount >= width) { 1340 SkAlpha alpha = row[1]; 1341 if (0 == alpha) { 1342 return; 1343 } 1344 if (0xFF == alpha) { 1345 fBlitter->blitH(x, y, width); 1346 return; 1347 } 1348 } 1349 1350 this->ensureRunsAndAA(); 1351 expandToRuns(row, initialCount, width, fRuns, fAA); 1352 1353 fBlitter->blitAntiH(x, y, fAA, fRuns); 1354} 1355 1356static void merge(const uint8_t* SK_RESTRICT row, int rowN, 1357 const SkAlpha* SK_RESTRICT srcAA, 1358 const int16_t* SK_RESTRICT srcRuns, 1359 SkAlpha* SK_RESTRICT dstAA, 1360 int16_t* SK_RESTRICT dstRuns, 1361 int width) { 1362 SkDEBUGCODE(int accumulated = 0;) 1363 int srcN = srcRuns[0]; 1364 // do we need this check? 1365 if (0 == srcN) { 1366 return; 1367 } 1368 1369 for (;;) { 1370 SkASSERT(rowN > 0); 1371 SkASSERT(srcN > 0); 1372 1373 unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1374 int minN = SkMin32(srcN, rowN); 1375 dstRuns[0] = minN; 1376 dstRuns += minN; 1377 dstAA[0] = newAlpha; 1378 dstAA += minN; 1379 1380 if (0 == (srcN -= minN)) { 1381 srcN = srcRuns[0]; // refresh 1382 srcRuns += srcN; 1383 srcAA += srcN; 1384 srcN = srcRuns[0]; // reload 1385 if (0 == srcN) { 1386 break; 1387 } 1388 } 1389 if (0 == (rowN -= minN)) { 1390 row += 2; 1391 rowN = row[0]; // reload 1392 } 1393 1394 SkDEBUGCODE(accumulated += minN;) 1395 SkASSERT(accumulated <= width); 1396 } 1397 dstRuns[0] = 0; 1398} 1399 1400void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 1401 const int16_t runs[]) { 1402 int lastY; 1403 const uint8_t* row = fAAClip->findRow(y, &lastY); 1404 int initialCount; 1405 row = fAAClip->findX(row, x, &initialCount); 1406 1407 this->ensureRunsAndAA(); 1408 1409 merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 1410 fBlitter->blitAntiH(x, y, fAA, fRuns); 1411} 1412 1413void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 1414 if (fAAClip->quickContains(x, y, x + 1, y + height)) { 1415 fBlitter->blitV(x, y, height, alpha); 1416 return; 1417 } 1418 1419 for (;;) { 1420 int lastY; 1421 const uint8_t* row = fAAClip->findRow(y, &lastY); 1422 int dy = lastY - y + 1; 1423 if (dy > height) { 1424 dy = height; 1425 } 1426 height -= dy; 1427 1428 int initialCount; 1429 row = fAAClip->findX(row, x, &initialCount); 1430 SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 1431 if (newAlpha) { 1432 fBlitter->blitV(x, y, dy, newAlpha); 1433 } 1434 SkASSERT(height >= 0); 1435 if (height <= 0) { 1436 break; 1437 } 1438 y = lastY + 1; 1439 } 1440} 1441 1442void SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 1443 if (fAAClip->quickContains(x, y, x + width, y + height)) { 1444 fBlitter->blitRect(x, y, width, height); 1445 return; 1446 } 1447 1448 while (--height >= 0) { 1449 this->blitH(x, y, width); 1450 y += 1; 1451 } 1452} 1453 1454typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 1455 int initialRowCount, void* dst); 1456 1457static void small_memcpy(void* dst, const void* src, size_t n) { 1458 memcpy(dst, src, n); 1459} 1460 1461static void small_bzero(void* dst, size_t n) { 1462 sk_bzero(dst, n); 1463} 1464 1465static inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 1466 return SkMulDiv255Round(value, alpha); 1467} 1468static inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 1469 unsigned r = SkGetPackedR16(value); 1470 unsigned g = SkGetPackedG16(value); 1471 unsigned b = SkGetPackedB16(value); 1472 return SkPackRGB16(SkMulDiv255Round(r, alpha), 1473 SkMulDiv255Round(r, alpha), 1474 SkMulDiv255Round(r, alpha)); 1475} 1476static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) { 1477 unsigned a = SkGetPackedA32(value); 1478 unsigned r = SkGetPackedR32(value); 1479 unsigned g = SkGetPackedG32(value); 1480 unsigned b = SkGetPackedB32(value); 1481 return SkPackARGB32(SkMulDiv255Round(a, alpha), 1482 SkMulDiv255Round(r, alpha), 1483 SkMulDiv255Round(g, alpha), 1484 SkMulDiv255Round(b, alpha)); 1485} 1486 1487template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN, 1488 const uint8_t* SK_RESTRICT row, int rowN, 1489 T* SK_RESTRICT dst) { 1490 SkDEBUGCODE(int accumulated = 0;) 1491 for (;;) { 1492 SkASSERT(rowN > 0); 1493 SkASSERT(srcN > 0); 1494 1495 int n = SkMin32(rowN, srcN); 1496 unsigned rowA = row[1]; 1497 if (0xFF == rowA) { 1498 small_memcpy(dst, src, n * sizeof(T)); 1499 } else if (0 == rowA) { 1500 small_bzero(dst, n * sizeof(T)); 1501 } else { 1502 for (int i = 0; i < n; ++i) { 1503 dst[i] = mergeOne(src[i], rowA); 1504 } 1505 } 1506 1507 if (0 == (srcN -= n)) { 1508 break; 1509 } 1510 1511 src += n; 1512 dst += n; 1513 1514 SkASSERT(rowN == n); 1515 row += 2; 1516 rowN = row[0]; 1517 } 1518} 1519 1520static MergeAAProc find_merge_aa_proc(SkMask::Format format) { 1521 switch (format) { 1522 case SkMask::kBW_Format: 1523 SkASSERT(!"unsupported"); 1524 return NULL; 1525 case SkMask::kA8_Format: 1526 case SkMask::k3D_Format: { 1527 void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT; 1528 return (MergeAAProc)proc8; 1529 } 1530 case SkMask::kLCD16_Format: { 1531 void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT; 1532 return (MergeAAProc)proc16; 1533 } 1534 case SkMask::kLCD32_Format: { 1535 void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT; 1536 return (MergeAAProc)proc32; 1537 } 1538 default: 1539 SkASSERT(!"unsupported"); 1540 return NULL; 1541 } 1542} 1543 1544static U8CPU bit2byte(int bitInAByte) { 1545 SkASSERT(bitInAByte <= 0xFF); 1546 // negation turns any non-zero into 0xFFFFFF??, so we just shift down 1547 // some value >= 8 to get a full FF value 1548 return -bitInAByte >> 8; 1549} 1550 1551static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 1552 SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 1553 SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 1554 1555 const int width = srcMask.fBounds.width(); 1556 const int height = srcMask.fBounds.height(); 1557 1558 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 1559 const size_t srcRB = srcMask.fRowBytes; 1560 uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 1561 const size_t dstRB = dstMask->fRowBytes; 1562 1563 const int wholeBytes = width >> 3; 1564 const int leftOverBits = width & 7; 1565 1566 for (int y = 0; y < height; ++y) { 1567 uint8_t* SK_RESTRICT d = dst; 1568 for (int i = 0; i < wholeBytes; ++i) { 1569 int srcByte = src[i]; 1570 d[0] = bit2byte(srcByte & (1 << 7)); 1571 d[1] = bit2byte(srcByte & (1 << 6)); 1572 d[2] = bit2byte(srcByte & (1 << 5)); 1573 d[3] = bit2byte(srcByte & (1 << 4)); 1574 d[4] = bit2byte(srcByte & (1 << 3)); 1575 d[5] = bit2byte(srcByte & (1 << 2)); 1576 d[6] = bit2byte(srcByte & (1 << 1)); 1577 d[7] = bit2byte(srcByte & (1 << 0)); 1578 d += 8; 1579 } 1580 if (leftOverBits) { 1581 int srcByte = src[wholeBytes]; 1582 for (int x = 0; x < leftOverBits; ++x) { 1583 *d++ = bit2byte(srcByte & 0x80); 1584 srcByte <<= 1; 1585 } 1586 } 1587 src += srcRB; 1588 dst += dstRB; 1589 } 1590} 1591 1592void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 1593 SkASSERT(fAAClip->getBounds().contains(clip)); 1594 1595 if (fAAClip->quickContains(clip)) { 1596 fBlitter->blitMask(origMask, clip); 1597 return; 1598 } 1599 1600 const SkMask* mask = &origMask; 1601 1602 // if we're BW, we need to upscale to A8 (ugh) 1603 SkMask grayMask; 1604 grayMask.fImage = NULL; 1605 if (SkMask::kBW_Format == origMask.fFormat) { 1606 grayMask.fFormat = SkMask::kA8_Format; 1607 grayMask.fBounds = origMask.fBounds; 1608 grayMask.fRowBytes = origMask.fBounds.width(); 1609 size_t size = grayMask.computeImageSize(); 1610 grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 1611 SkAutoMalloc::kReuse_OnShrink); 1612 1613 upscaleBW2A8(&grayMask, origMask); 1614 mask = &grayMask; 1615 } 1616 1617 this->ensureRunsAndAA(); 1618 1619 // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 1620 // data into a temp block to support it better (ugh) 1621 1622 const void* src = mask->getAddr(clip.fLeft, clip.fTop); 1623 const size_t srcRB = mask->fRowBytes; 1624 const int width = clip.width(); 1625 MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 1626 1627 SkMask rowMask; 1628 rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 1629 rowMask.fBounds.fLeft = clip.fLeft; 1630 rowMask.fBounds.fRight = clip.fRight; 1631 rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 1632 rowMask.fImage = (uint8_t*)fScanlineScratch; 1633 1634 int y = clip.fTop; 1635 const int stopY = y + clip.height(); 1636 1637 do { 1638 int localStopY; 1639 const uint8_t* row = fAAClip->findRow(y, &localStopY); 1640 // findRow returns last Y, not stop, so we add 1 1641 localStopY = SkMin32(localStopY + 1, stopY); 1642 1643 int initialCount; 1644 row = fAAClip->findX(row, clip.fLeft, &initialCount); 1645 do { 1646 mergeProc(src, width, row, initialCount, rowMask.fImage); 1647 rowMask.fBounds.fTop = y; 1648 rowMask.fBounds.fBottom = y + 1; 1649 fBlitter->blitMask(rowMask, rowMask.fBounds); 1650 src = (const void*)((const char*)src + srcRB); 1651 } while (++y < localStopY); 1652 } while (y < stopY); 1653} 1654 1655const SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 1656 return NULL; 1657} 1658 1659