SkAAClip.cpp revision 045e62d715f5ee9b03deb5af3c750f8318096179
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 482public: 483 Builder(const SkIRect& bounds) : fBounds(bounds) { 484 fPrevY = -1; 485 fWidth = bounds.width(); 486 fCurrRow = NULL; 487 } 488 489 ~Builder() { 490 Row* row = fRows.begin(); 491 Row* stop = fRows.end(); 492 while (row < stop) { 493 delete row->fData; 494 row += 1; 495 } 496 } 497 498 const SkIRect& getBounds() const { return fBounds; } 499 500 void addRun(int x, int y, U8CPU alpha, int count) { 501 SkASSERT(count > 0); 502 SkASSERT(fBounds.contains(x, y)); 503 SkASSERT(fBounds.contains(x + count - 1, y)); 504 505 x -= fBounds.left(); 506 y -= fBounds.top(); 507 508 Row* row = fCurrRow; 509 if (y != fPrevY) { 510 SkASSERT(y > fPrevY); 511 fPrevY = y; 512 row = this->flushRow(true); 513 row->fY = y; 514 row->fWidth = 0; 515 SkASSERT(row->fData); 516 SkASSERT(0 == row->fData->count()); 517 fCurrRow = row; 518 } 519 520 SkASSERT(row->fWidth <= x); 521 SkASSERT(row->fWidth < fBounds.width()); 522 523 SkTDArray<uint8_t>& data = *row->fData; 524 525 int gap = x - row->fWidth; 526 if (gap) { 527 AppendRun(data, 0, gap); 528 row->fWidth += gap; 529 SkASSERT(row->fWidth < fBounds.width()); 530 } 531 532 AppendRun(data, alpha, count); 533 row->fWidth += count; 534 SkASSERT(row->fWidth <= fBounds.width()); 535 } 536 537 bool finish(SkAAClip* target) { 538 this->flushRow(false); 539 540 const Row* row = fRows.begin(); 541 const Row* stop = fRows.end(); 542 543 size_t dataSize = 0; 544 while (row < stop) { 545 dataSize += row->fData->count(); 546 row += 1; 547 } 548 549 if (0 == dataSize) { 550 return target->setEmpty(); 551 } 552 553 RunHead* head = RunHead::Alloc(fRows.count(), dataSize); 554 YOffset* yoffset = head->yoffsets(); 555 uint8_t* data = head->data(); 556 uint8_t* baseData = data; 557 558 row = fRows.begin(); 559 while (row < stop) { 560 yoffset->fY = row->fY; 561 yoffset->fOffset = data - baseData; 562 yoffset += 1; 563 564 size_t n = row->fData->count(); 565 memcpy(data, row->fData->begin(), n); 566 data += n; 567 568 row += 1; 569 } 570 571 target->freeRuns(); 572 target->fBounds = fBounds; 573 target->fRunHead = head; 574 return target->trimBounds(); 575 } 576 577 void dump() { 578 this->validate(); 579 int y; 580 for (y = 0; y < fRows.count(); ++y) { 581 const Row& row = fRows[y]; 582 SkDebugf("Y:%3d W:%3d", row.fY, row.fWidth); 583 const SkTDArray<uint8_t>& data = *row.fData; 584 int count = data.count(); 585 SkASSERT(!(count & 1)); 586 const uint8_t* ptr = data.begin(); 587 for (int x = 0; x < count; x += 2) { 588 SkDebugf(" [%3d:%02X]", ptr[0], ptr[1]); 589 ptr += 2; 590 } 591 SkDebugf("\n"); 592 } 593 } 594 595 void validate() { 596#ifdef SK_DEBUG 597 int prevY = -1; 598 for (int i = 0; i < fRows.count(); ++i) { 599 const Row& row = fRows[i]; 600 SkASSERT(prevY < row.fY); 601 SkASSERT(fWidth == row.fWidth); 602 int count = row.fData->count(); 603 const uint8_t* ptr = row.fData->begin(); 604 SkASSERT(!(count & 1)); 605 int w = 0; 606 for (int x = 0; x < count; x += 2) { 607 w += ptr[0]; 608 SkASSERT(w <= fWidth); 609 ptr += 2; 610 } 611 SkASSERT(w == fWidth); 612 prevY = row.fY; 613 } 614#endif 615 } 616 617private: 618 Row* flushRow(bool readyForAnother) { 619 Row* next = NULL; 620 int count = fRows.count(); 621 if (count > 0) { 622 // flush current row if needed 623 Row* curr = &fRows[count - 1]; 624 if (curr->fWidth < fWidth) { 625 AppendRun(*curr->fData, 0, fWidth - curr->fWidth); 626 curr->fWidth = fWidth; 627 } 628 } 629 if (count > 1) { 630 // are our last two runs the same? 631 Row* prev = &fRows[count - 2]; 632 Row* curr = &fRows[count - 1]; 633 SkASSERT(prev->fWidth == fWidth); 634 SkASSERT(curr->fWidth == fWidth); 635 if (*prev->fData == *curr->fData) { 636 prev->fY = curr->fY; 637 if (readyForAnother) { 638 curr->fData->rewind(); 639 next = curr; 640 } else { 641 delete curr->fData; 642 fRows.removeShuffle(count - 1); 643 } 644 } else { 645 if (readyForAnother) { 646 next = fRows.append(); 647 next->fData = new SkTDArray<uint8_t>; 648 } 649 } 650 } else { 651 if (readyForAnother) { 652 next = fRows.append(); 653 next->fData = new SkTDArray<uint8_t>; 654 } 655 } 656 return next; 657 } 658 659 static void AppendRun(SkTDArray<uint8_t>& data, U8CPU alpha, int count) { 660 do { 661 int n = count; 662 if (n > 255) { 663 n = 255; 664 } 665 uint8_t* ptr = data.append(2); 666 ptr[0] = n; 667 ptr[1] = alpha; 668 count -= n; 669 } while (count > 0); 670 } 671}; 672 673class SkAAClip::BuilderBlitter : public SkBlitter { 674public: 675 BuilderBlitter(Builder* builder) { 676 fBuilder = builder; 677 fLeft = builder->getBounds().fLeft; 678 fRight = builder->getBounds().fRight; 679 } 680 681 virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE 682 { unexpected(); } 683 684 // let the default impl call blitH 685// virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE 686 687 virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE 688 { unexpected(); } 689 690 virtual const SkBitmap* justAnOpaqueColor(uint32_t*) SK_OVERRIDE { 691 return NULL; 692 } 693 694 virtual void blitH(int x, int y, int width) SK_OVERRIDE { 695 fBuilder->addRun(x, y, 0xFF, width); 696 } 697 698 virtual void blitAntiH(int x, int y, const SkAlpha alpha[], 699 const int16_t runs[]) SK_OVERRIDE { 700 for (;;) { 701 int count = *runs; 702 if (count <= 0) { 703 return; 704 } 705 706 // The supersampler's buffer can be the width of the device, so 707 // we may have to trim the run to our bounds. If so, we assert that 708 // the extra spans are always alpha==0 709 int localX = x; 710 int localCount = count; 711 if (x < fLeft) { 712 SkASSERT(0 == *alpha); 713 int gap = fLeft - x; 714 SkASSERT(gap <= count); 715 localX += gap; 716 localCount -= gap; 717 } 718 int right = x + count; 719 if (right > fRight) { 720 SkASSERT(0 == *alpha); 721 localCount -= right - fRight; 722 SkASSERT(localCount >= 0); 723 } 724 725 if (localCount) { 726 fBuilder->addRun(localX, y, *alpha, localCount); 727 } 728 NEXT_RUN: 729 runs += count; 730 alpha += count; 731 x += count; 732 } 733 } 734 735private: 736 Builder* fBuilder; 737 int fLeft; // cache of builder's bounds' left edge 738 int fRight; 739 740 void unexpected() { 741 SkDebugf("---- did not expect to get called here"); 742 sk_throw(); 743 } 744}; 745 746bool SkAAClip::setPath(const SkPath& path, const SkRegion* clip, bool doAA) { 747 AUTO_AACLIP_VALIDATE(*this); 748 749 if (clip && clip->isEmpty()) { 750 return this->setEmpty(); 751 } 752 753 SkIRect ibounds; 754 path.getBounds().roundOut(&ibounds); 755 756 SkRegion tmpClip; 757 if (NULL == clip) { 758 tmpClip.setRect(ibounds); 759 clip = &tmpClip; 760 } 761 762 if (path.isInverseFillType()) { 763 ibounds = clip->getBounds(); 764 } else { 765 if (ibounds.isEmpty() || !ibounds.intersect(clip->getBounds())) { 766 return this->setEmpty(); 767 } 768 } 769 770 Builder builder(ibounds); 771 BuilderBlitter blitter(&builder); 772 773 if (doAA) { 774 SkScan::AntiFillPath(path, *clip, &blitter, true); 775 } else { 776 SkScan::FillPath(path, *clip, &blitter); 777 } 778 779 return builder.finish(this); 780} 781 782/////////////////////////////////////////////////////////////////////////////// 783 784typedef void (*RowProc)(SkAAClip::Builder&, int bottom, 785 const uint8_t* rowA, const SkIRect& rectA, 786 const uint8_t* rowB, const SkIRect& rectB); 787 788static void sectRowProc(SkAAClip::Builder& builder, int bottom, 789 const uint8_t* rowA, const SkIRect& rectA, 790 const uint8_t* rowB, const SkIRect& rectB) { 791 792} 793 794typedef U8CPU (*AlphaProc)(U8CPU alphaA, U8CPU alphaB); 795 796static U8CPU sectAlphaProc(U8CPU alphaA, U8CPU alphaB) { 797 // Multiply 798 return SkMulDiv255Round(alphaA, alphaB); 799} 800 801static U8CPU unionAlphaProc(U8CPU alphaA, U8CPU alphaB) { 802 // SrcOver 803 return alphaA + alphaB - SkMulDiv255Round(alphaA, alphaB); 804} 805 806static U8CPU diffAlphaProc(U8CPU alphaA, U8CPU alphaB) { 807 // SrcOut 808 return SkMulDiv255Round(alphaA, 0xFF - alphaB); 809} 810 811static U8CPU xorAlphaProc(U8CPU alphaA, U8CPU alphaB) { 812 // XOR 813 return alphaA + alphaB - 2 * SkMulDiv255Round(alphaA, alphaB); 814} 815 816static AlphaProc find_alpha_proc(SkRegion::Op op) { 817 switch (op) { 818 case SkRegion::kIntersect_Op: 819 return sectAlphaProc; 820 case SkRegion::kDifference_Op: 821 return diffAlphaProc; 822 case SkRegion::kUnion_Op: 823 return unionAlphaProc; 824 case SkRegion::kXOR_Op: 825 return xorAlphaProc; 826 default: 827 SkASSERT(!"unexpected region op"); 828 return sectAlphaProc; 829 } 830} 831 832static const uint8_t gEmptyRow[] = { 833 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 834 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 835 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 836 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 837 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 838 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 839 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 840 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 0xFF, 0, 841}; 842 843class RowIter { 844public: 845 RowIter(const uint8_t* row, const SkIRect& bounds) { 846 fRow = row; 847 fLeft = bounds.fLeft; 848 fBoundsRight = bounds.fRight; 849 if (row) { 850 fRight = bounds.fLeft + row[0]; 851 SkASSERT(fRight <= fBoundsRight); 852 fAlpha = row[1]; 853 fDone = false; 854 } else { 855 fDone = true; 856 fRight = kMaxInt32; 857 fAlpha = 0; 858 } 859 } 860 861 bool done() const { return fDone; } 862 int left() const { return fLeft; } 863 int right() const { return fRight; } 864 U8CPU alpha() const { return fAlpha; } 865 void next() { 866 if (!fDone) { 867 fLeft = fRight; 868 if (fRight == fBoundsRight) { 869 fDone = true; 870 fRight = kMaxInt32; 871 fAlpha = 0; 872 } else { 873 fRow += 2; 874 fRight += fRow[0]; 875 fAlpha = fRow[1]; 876 SkASSERT(fRight <= fBoundsRight); 877 } 878 } 879 } 880 881private: 882 const uint8_t* fRow; 883 int fLeft; 884 int fRight; 885 int fBoundsRight; 886 bool fDone; 887 uint8_t fAlpha; 888}; 889 890static void adjust_row(RowIter& iter, int& leftA, int& riteA, int rite) { 891 if (rite == riteA) { 892 iter.next(); 893 leftA = iter.left(); 894 riteA = iter.right(); 895 } 896} 897 898static bool intersect(int& min, int& max, int boundsMin, int boundsMax) { 899 SkASSERT(min < max); 900 SkASSERT(boundsMin < boundsMax); 901 if (min >= boundsMax || max <= boundsMin) { 902 return false; 903 } 904 if (min < boundsMin) { 905 min = boundsMin; 906 } 907 if (max > boundsMax) { 908 max = boundsMax; 909 } 910 return true; 911} 912 913static void operatorX(SkAAClip::Builder& builder, int lastY, 914 RowIter& iterA, RowIter& iterB, 915 AlphaProc proc, const SkIRect& bounds) { 916 int leftA = iterA.left(); 917 int riteA = iterA.right(); 918 int leftB = iterB.left(); 919 int riteB = iterB.right(); 920 921 int prevRite = bounds.fLeft; 922 923 do { 924 U8CPU alphaA = 0; 925 U8CPU alphaB = 0; 926 int left, rite; 927 928 if (leftA < leftB) { 929 left = leftA; 930 alphaA = iterA.alpha(); 931 if (riteA <= leftB) { 932 rite = riteA; 933 } else { 934 rite = leftA = leftB; 935 } 936 } else if (leftB < leftA) { 937 left = leftB; 938 alphaB = iterB.alpha(); 939 if (riteB <= leftA) { 940 rite = riteB; 941 } else { 942 rite = leftB = leftA; 943 } 944 } else { 945 left = leftA; // or leftB, since leftA == leftB 946 rite = leftA = leftB = SkMin32(riteA, riteB); 947 alphaA = iterA.alpha(); 948 alphaB = iterB.alpha(); 949 } 950 951 if (left >= bounds.fRight) { 952 break; 953 } 954 if (rite > bounds.fRight) { 955 rite = bounds.fRight; 956 } 957 958 if (left >= bounds.fLeft) { 959 SkASSERT(rite > left); 960 builder.addRun(left, lastY, proc(alphaA, alphaB), rite - left); 961 prevRite = rite; 962 } 963 964 adjust_row(iterA, leftA, riteA, rite); 965 adjust_row(iterB, leftB, riteB, rite); 966 } while (!iterA.done() || !iterB.done()); 967 968 if (prevRite < bounds.fRight) { 969 builder.addRun(prevRite, lastY, 0, bounds.fRight - prevRite); 970 } 971} 972 973static void adjust_iter(SkAAClip::Iter& iter, int& topA, int& botA, int bot) { 974 if (bot == botA) { 975 iter.next(); 976 topA = botA; 977 SkASSERT(botA == iter.top()); 978 botA = iter.bottom(); 979 } 980} 981 982static void operateY(SkAAClip::Builder& builder, const SkAAClip& A, 983 const SkAAClip& B, SkRegion::Op op) { 984 AlphaProc proc = find_alpha_proc(op); 985 const SkIRect& bounds = builder.getBounds(); 986 987 SkAAClip::Iter iterA(A); 988 SkAAClip::Iter iterB(B); 989 990 SkASSERT(!iterA.done()); 991 int topA = iterA.top(); 992 int botA = iterA.bottom(); 993 SkASSERT(!iterB.done()); 994 int topB = iterB.top(); 995 int botB = iterB.bottom(); 996 997 do { 998 const uint8_t* rowA = NULL; 999 const uint8_t* rowB = NULL; 1000 int top, bot; 1001 1002 if (topA < topB) { 1003 top = topA; 1004 rowA = iterA.data(); 1005 if (botA <= topB) { 1006 bot = botA; 1007 } else { 1008 bot = topA = topB; 1009 } 1010 1011 } else if (topB < topA) { 1012 top = topB; 1013 rowB = iterB.data(); 1014 if (botB <= topA) { 1015 bot = botB; 1016 } else { 1017 bot = topB = topA; 1018 } 1019 } else { 1020 top = topA; // or topB, since topA == topB 1021 bot = topA = topB = SkMin32(botA, botB); 1022 rowA = iterA.data(); 1023 rowB = iterB.data(); 1024 } 1025 1026 if (top >= bounds.fBottom) { 1027 break; 1028 } 1029 1030 if (bot > bounds.fBottom) { 1031 bot = bounds.fBottom; 1032 } 1033 SkASSERT(top < bot); 1034 1035 if (!rowA && !rowB) { 1036 builder.addRun(bounds.fLeft, bot - 1, 0, bounds.width()); 1037 } else if (top >= bounds.fTop) { 1038 SkASSERT(bot <= bounds.fBottom); 1039 RowIter rowIterA(rowA, rowA ? A.getBounds() : bounds); 1040 RowIter rowIterB(rowB, rowB ? B.getBounds() : bounds); 1041 operatorX(builder, bot - 1, rowIterA, rowIterB, proc, bounds); 1042 } 1043 1044 adjust_iter(iterA, topA, botA, bot); 1045 adjust_iter(iterB, topB, botB, bot); 1046 } while (!iterA.done() || !iterB.done()); 1047} 1048 1049bool SkAAClip::op(const SkAAClip& clipAOrig, const SkAAClip& clipBOrig, 1050 SkRegion::Op op) { 1051 AUTO_AACLIP_VALIDATE(*this); 1052 1053 if (SkRegion::kReplace_Op == op) { 1054 return this->set(clipBOrig); 1055 } 1056 1057 const SkAAClip* clipA = &clipAOrig; 1058 const SkAAClip* clipB = &clipBOrig; 1059 1060 if (SkRegion::kReverseDifference_Op == op) { 1061 SkTSwap(clipA, clipB); 1062 op = SkRegion::kDifference_Op; 1063 } 1064 1065 bool a_empty = clipA->isEmpty(); 1066 bool b_empty = clipB->isEmpty(); 1067 1068 SkIRect bounds; 1069 switch (op) { 1070 case SkRegion::kDifference_Op: 1071 if (a_empty) { 1072 return this->setEmpty(); 1073 } 1074 if (b_empty || !SkIRect::Intersects(clipA->fBounds, clipB->fBounds)) { 1075 return this->set(*clipA); 1076 } 1077 bounds = clipA->fBounds; 1078 break; 1079 1080 case SkRegion::kIntersect_Op: 1081 if ((a_empty | b_empty) || !bounds.intersect(clipA->fBounds, 1082 clipB->fBounds)) { 1083 return this->setEmpty(); 1084 } 1085 break; 1086 1087 case SkRegion::kUnion_Op: 1088 case SkRegion::kXOR_Op: 1089 if (a_empty) { 1090 return this->set(*clipB); 1091 } 1092 if (b_empty) { 1093 return this->set(*clipA); 1094 } 1095 bounds = clipA->fBounds; 1096 bounds.join(clipB->fBounds); 1097 break; 1098 1099 default: 1100 SkASSERT(!"unknown region op"); 1101 return !this->isEmpty(); 1102 } 1103 1104 SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1105 SkASSERT(SkIRect::Intersects(bounds, clipB->fBounds)); 1106 1107 Builder builder(bounds); 1108 operateY(builder, *clipA, *clipB, op); 1109 1110 return builder.finish(this); 1111} 1112 1113/* 1114 * It can be expensive to build a local aaclip before applying the op, so 1115 * we first see if we can restrict the bounds of new rect to our current 1116 * bounds, or note that the new rect subsumes our current clip. 1117 */ 1118 1119bool SkAAClip::op(const SkIRect& rOrig, SkRegion::Op op) { 1120 SkIRect rStorage; 1121 const SkIRect* r = &rOrig; 1122 1123 switch (op) { 1124 case SkRegion::kIntersect_Op: 1125 if (!rStorage.intersect(rOrig, fBounds)) { 1126 // no overlap, so we're empty 1127 return this->setEmpty(); 1128 } 1129 if (rStorage == fBounds) { 1130 // we were wholly inside the rect, no change 1131 return !this->isEmpty(); 1132 } 1133 if (this->quickContains(rStorage)) { 1134 // the intersection is wholly inside us, we're a rect 1135 return this->setRect(rStorage); 1136 } 1137 r = &rStorage; // use the intersected bounds 1138 break; 1139 case SkRegion::kDifference_Op: 1140 break; 1141 case SkRegion::kUnion_Op: 1142 if (rOrig.contains(fBounds)) { 1143 return this->setRect(rOrig); 1144 } 1145 break; 1146 default: 1147 break; 1148 } 1149 1150 SkAAClip clip; 1151 clip.setRect(*r); 1152 return this->op(*this, clip, op); 1153} 1154 1155bool SkAAClip::op(const SkRect& rOrig, SkRegion::Op op, bool doAA) { 1156 SkRect rStorage, boundsStorage; 1157 const SkRect* r = &rOrig; 1158 1159 boundsStorage.set(fBounds); 1160 switch (op) { 1161 case SkRegion::kIntersect_Op: 1162 case SkRegion::kDifference_Op: 1163 if (!rStorage.intersect(rOrig, boundsStorage)) { 1164 return this->setEmpty(); 1165 } 1166 r = &rStorage; // use the intersected bounds 1167 break; 1168 case SkRegion::kUnion_Op: 1169 if (rOrig.contains(boundsStorage)) { 1170 return this->setRect(rOrig); 1171 } 1172 break; 1173 default: 1174 break; 1175 } 1176 1177 SkAAClip clip; 1178 clip.setRect(*r, doAA); 1179 return this->op(*this, clip, op); 1180} 1181 1182bool SkAAClip::op(const SkAAClip& clip, SkRegion::Op op) { 1183 return this->op(*this, clip, op); 1184} 1185 1186/////////////////////////////////////////////////////////////////////////////// 1187 1188bool SkAAClip::translate(int dx, int dy, SkAAClip* dst) const { 1189 if (NULL == dst) { 1190 return !this->isEmpty(); 1191 } 1192 1193 if (this->isEmpty()) { 1194 return dst->setEmpty(); 1195 } 1196 1197 if (this != dst) { 1198 sk_atomic_inc(&fRunHead->fRefCnt); 1199 dst->fRunHead = fRunHead; 1200 dst->fBounds = fBounds; 1201 } 1202 dst->fBounds.offset(dx, dy); 1203 return true; 1204} 1205 1206static void expand_row_to_mask(uint8_t* SK_RESTRICT mask, 1207 const uint8_t* SK_RESTRICT row, 1208 int width) { 1209 while (width > 0) { 1210 int n = row[0]; 1211 SkASSERT(width >= n); 1212 memset(mask, row[1], n); 1213 mask += n; 1214 row += 2; 1215 width -= n; 1216 } 1217} 1218 1219void SkAAClip::copyToMask(SkMask* mask) const { 1220 mask->fFormat = SkMask::kA8_Format; 1221 if (this->isEmpty()) { 1222 mask->fBounds.setEmpty(); 1223 mask->fImage = NULL; 1224 mask->fRowBytes = 0; 1225 return; 1226 } 1227 1228 mask->fBounds = fBounds; 1229 mask->fRowBytes = fBounds.width(); 1230 size_t size = mask->computeImageSize(); 1231 mask->fImage = SkMask::AllocImage(size); 1232 1233 Iter iter(*this); 1234 uint8_t* dst = mask->fImage; 1235 const int width = fBounds.width(); 1236 1237 int y = fBounds.fTop; 1238 while (!iter.done()) { 1239 do { 1240 expand_row_to_mask(dst, iter.data(), width); 1241 dst += mask->fRowBytes; 1242 } while (++y < iter.bottom()); 1243 iter.next(); 1244 } 1245} 1246 1247/////////////////////////////////////////////////////////////////////////////// 1248/////////////////////////////////////////////////////////////////////////////// 1249 1250static void expandToRuns(const uint8_t* SK_RESTRICT data, int initialCount, int width, 1251 int16_t* SK_RESTRICT runs, SkAlpha* SK_RESTRICT aa) { 1252 // we don't read our initial n from data, since the caller may have had to 1253 // clip it, hence the initialCount parameter. 1254 int n = initialCount; 1255 for (;;) { 1256 if (n > width) { 1257 n = width; 1258 } 1259 SkASSERT(n > 0); 1260 runs[0] = n; 1261 runs += n; 1262 1263 aa[0] = data[1]; 1264 aa += n; 1265 1266 data += 2; 1267 width -= n; 1268 if (0 == width) { 1269 break; 1270 } 1271 // load the next count 1272 n = data[0]; 1273 } 1274 runs[0] = 0; // sentinel 1275} 1276 1277SkAAClipBlitter::~SkAAClipBlitter() { 1278 sk_free(fScanlineScratch); 1279} 1280 1281void SkAAClipBlitter::ensureRunsAndAA() { 1282 if (NULL == fScanlineScratch) { 1283 // add 1 so we can store the terminating run count of 0 1284 int count = fAAClipBounds.width() + 1; 1285 // we use this either for fRuns + fAA, or a scaline of a mask 1286 // which may be as deep as 32bits 1287 fScanlineScratch = sk_malloc_throw(count * sizeof(SkPMColor)); 1288 fRuns = (int16_t*)fScanlineScratch; 1289 fAA = (SkAlpha*)(fRuns + count); 1290 } 1291} 1292 1293void SkAAClipBlitter::blitH(int x, int y, int width) { 1294 SkASSERT(width > 0); 1295 SkASSERT(fAAClipBounds.contains(x, y)); 1296 SkASSERT(fAAClipBounds.contains(x + width - 1, y)); 1297 1298 int lastY; 1299 const uint8_t* row = fAAClip->findRow(y, &lastY); 1300 int initialCount; 1301 row = fAAClip->findX(row, x, &initialCount); 1302 1303 if (initialCount >= width) { 1304 SkAlpha alpha = row[1]; 1305 if (0 == alpha) { 1306 return; 1307 } 1308 if (0xFF == alpha) { 1309 fBlitter->blitH(x, y, width); 1310 return; 1311 } 1312 } 1313 1314 this->ensureRunsAndAA(); 1315 expandToRuns(row, initialCount, width, fRuns, fAA); 1316 1317 fBlitter->blitAntiH(x, y, fAA, fRuns); 1318} 1319 1320static void merge(const uint8_t* SK_RESTRICT row, int rowN, 1321 const SkAlpha* SK_RESTRICT srcAA, 1322 const int16_t* SK_RESTRICT srcRuns, 1323 SkAlpha* SK_RESTRICT dstAA, 1324 int16_t* SK_RESTRICT dstRuns, 1325 int width) { 1326 SkDEBUGCODE(int accumulated = 0;) 1327 int srcN = srcRuns[0]; 1328 // do we need this check? 1329 if (0 == srcN) { 1330 return; 1331 } 1332 1333 for (;;) { 1334 SkASSERT(rowN > 0); 1335 SkASSERT(srcN > 0); 1336 1337 unsigned newAlpha = SkMulDiv255Round(srcAA[0], row[1]); 1338 int minN = SkMin32(srcN, rowN); 1339 dstRuns[0] = minN; 1340 dstRuns += minN; 1341 dstAA[0] = newAlpha; 1342 dstAA += minN; 1343 1344 if (0 == (srcN -= minN)) { 1345 srcN = srcRuns[0]; // refresh 1346 srcRuns += srcN; 1347 srcAA += srcN; 1348 srcN = srcRuns[0]; // reload 1349 if (0 == srcN) { 1350 break; 1351 } 1352 } 1353 if (0 == (rowN -= minN)) { 1354 row += 2; 1355 rowN = row[0]; // reload 1356 } 1357 1358 SkDEBUGCODE(accumulated += minN;) 1359 SkASSERT(accumulated <= width); 1360 } 1361 dstRuns[0] = 0; 1362} 1363 1364void SkAAClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 1365 const int16_t runs[]) { 1366 int lastY; 1367 const uint8_t* row = fAAClip->findRow(y, &lastY); 1368 int initialCount; 1369 row = fAAClip->findX(row, x, &initialCount); 1370 1371 this->ensureRunsAndAA(); 1372 1373 merge(row, initialCount, aa, runs, fAA, fRuns, fAAClipBounds.width()); 1374 fBlitter->blitAntiH(x, y, fAA, fRuns); 1375} 1376 1377void SkAAClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 1378 if (fAAClip->quickContains(x, y, x + 1, y + height)) { 1379 fBlitter->blitV(x, y, height, alpha); 1380 return; 1381 } 1382 1383 for (;;) { 1384 int lastY; 1385 const uint8_t* row = fAAClip->findRow(y, &lastY); 1386 int dy = lastY - y + 1; 1387 if (dy > height) { 1388 dy = height; 1389 } 1390 height -= dy; 1391 1392 int initialCount; 1393 row = fAAClip->findX(row, x, &initialCount); 1394 SkAlpha newAlpha = SkMulDiv255Round(alpha, row[1]); 1395 if (newAlpha) { 1396 fBlitter->blitV(x, y, dy, newAlpha); 1397 } 1398 SkASSERT(height >= 0); 1399 if (height <= 0) { 1400 break; 1401 } 1402 y = lastY + 1; 1403 } 1404} 1405 1406void SkAAClipBlitter::blitRect(int x, int y, int width, int height) { 1407 if (fAAClip->quickContains(x, y, x + width, y + height)) { 1408 fBlitter->blitRect(x, y, width, height); 1409 return; 1410 } 1411 1412 while (--height >= 0) { 1413 this->blitH(x, y, width); 1414 y += 1; 1415 } 1416} 1417 1418typedef void (*MergeAAProc)(const void* src, int width, const uint8_t* row, 1419 int initialRowCount, void* dst); 1420 1421static void small_memcpy(void* dst, const void* src, size_t n) { 1422 memcpy(dst, src, n); 1423} 1424 1425static void small_bzero(void* dst, size_t n) { 1426 sk_bzero(dst, n); 1427} 1428 1429static inline uint8_t mergeOne(uint8_t value, unsigned alpha) { 1430 return SkMulDiv255Round(value, alpha); 1431} 1432static inline uint16_t mergeOne(uint16_t value, unsigned alpha) { 1433 unsigned r = SkGetPackedR16(value); 1434 unsigned g = SkGetPackedG16(value); 1435 unsigned b = SkGetPackedB16(value); 1436 return SkPackRGB16(SkMulDiv255Round(r, alpha), 1437 SkMulDiv255Round(r, alpha), 1438 SkMulDiv255Round(r, alpha)); 1439} 1440static inline SkPMColor mergeOne(SkPMColor value, unsigned alpha) { 1441 unsigned a = SkGetPackedA32(value); 1442 unsigned r = SkGetPackedR32(value); 1443 unsigned g = SkGetPackedG32(value); 1444 unsigned b = SkGetPackedB32(value); 1445 return SkPackARGB32(SkMulDiv255Round(a, alpha), 1446 SkMulDiv255Round(r, alpha), 1447 SkMulDiv255Round(g, alpha), 1448 SkMulDiv255Round(b, alpha)); 1449} 1450 1451template <typename T> void mergeT(const T* SK_RESTRICT src, int srcN, 1452 const uint8_t* SK_RESTRICT row, int rowN, 1453 T* SK_RESTRICT dst) { 1454 SkDEBUGCODE(int accumulated = 0;) 1455 for (;;) { 1456 SkASSERT(rowN > 0); 1457 SkASSERT(srcN > 0); 1458 1459 int n = SkMin32(rowN, srcN); 1460 unsigned rowA = row[1]; 1461 if (0xFF == rowA) { 1462 small_memcpy(dst, src, n * sizeof(T)); 1463 } else if (0 == rowA) { 1464 small_bzero(dst, n * sizeof(T)); 1465 } else { 1466 for (int i = 0; i < n; ++i) { 1467 dst[i] = mergeOne(src[i], rowA); 1468 } 1469 } 1470 1471 if (0 == (srcN -= n)) { 1472 break; 1473 } 1474 1475 src += n; 1476 dst += n; 1477 1478 SkASSERT(rowN == n); 1479 row += 2; 1480 rowN = row[0]; 1481 } 1482} 1483 1484static MergeAAProc find_merge_aa_proc(SkMask::Format format) { 1485 switch (format) { 1486 case SkMask::kBW_Format: 1487 SkASSERT(!"unsupported"); 1488 return NULL; 1489 case SkMask::kA8_Format: 1490 case SkMask::k3D_Format: { 1491 void (*proc8)(const uint8_t*, int, const uint8_t*, int, uint8_t*) = mergeT; 1492 return (MergeAAProc)proc8; 1493 } 1494 case SkMask::kLCD16_Format: { 1495 void (*proc16)(const uint16_t*, int, const uint8_t*, int, uint16_t*) = mergeT; 1496 return (MergeAAProc)proc16; 1497 } 1498 case SkMask::kLCD32_Format: { 1499 void (*proc32)(const SkPMColor*, int, const uint8_t*, int, SkPMColor*) = mergeT; 1500 return (MergeAAProc)proc32; 1501 } 1502 default: 1503 SkASSERT(!"unsupported"); 1504 return NULL; 1505 } 1506} 1507 1508static U8CPU bit2byte(int bitInAByte) { 1509 SkASSERT(bitInAByte <= 0xFF); 1510 // negation turns any non-zero into 0xFFFFFF??, so we just shift down 1511 // some value >= 8 to get a full FF value 1512 return -bitInAByte >> 8; 1513} 1514 1515static void upscaleBW2A8(SkMask* dstMask, const SkMask& srcMask) { 1516 SkASSERT(SkMask::kBW_Format == srcMask.fFormat); 1517 SkASSERT(SkMask::kA8_Format == dstMask->fFormat); 1518 1519 const int width = srcMask.fBounds.width(); 1520 const int height = srcMask.fBounds.height(); 1521 1522 const uint8_t* SK_RESTRICT src = (const uint8_t*)srcMask.fImage; 1523 const size_t srcRB = srcMask.fRowBytes; 1524 uint8_t* SK_RESTRICT dst = (uint8_t*)dstMask->fImage; 1525 const size_t dstRB = dstMask->fRowBytes; 1526 1527 const int wholeBytes = width >> 3; 1528 const int leftOverBits = width & 7; 1529 1530 for (int y = 0; y < height; ++y) { 1531 uint8_t* SK_RESTRICT d = dst; 1532 for (int i = 0; i < wholeBytes; ++i) { 1533 int srcByte = src[i]; 1534 d[0] = bit2byte(srcByte & (1 << 7)); 1535 d[1] = bit2byte(srcByte & (1 << 6)); 1536 d[2] = bit2byte(srcByte & (1 << 5)); 1537 d[3] = bit2byte(srcByte & (1 << 4)); 1538 d[4] = bit2byte(srcByte & (1 << 3)); 1539 d[5] = bit2byte(srcByte & (1 << 2)); 1540 d[6] = bit2byte(srcByte & (1 << 1)); 1541 d[7] = bit2byte(srcByte & (1 << 0)); 1542 d += 8; 1543 } 1544 if (leftOverBits) { 1545 int srcByte = src[wholeBytes]; 1546 for (int x = 0; x < leftOverBits; ++x) { 1547 *d++ = bit2byte(srcByte & 0x80); 1548 srcByte <<= 1; 1549 } 1550 } 1551 src += srcRB; 1552 dst += dstRB; 1553 } 1554} 1555 1556void SkAAClipBlitter::blitMask(const SkMask& origMask, const SkIRect& clip) { 1557 SkASSERT(fAAClip->getBounds().contains(clip)); 1558 1559 if (fAAClip->quickContains(clip)) { 1560 fBlitter->blitMask(origMask, clip); 1561 return; 1562 } 1563 1564 const SkMask* mask = &origMask; 1565 1566 // if we're BW, we need to upscale to A8 (ugh) 1567 SkMask grayMask; 1568 grayMask.fImage = NULL; 1569 if (SkMask::kBW_Format == origMask.fFormat) { 1570 grayMask.fFormat = SkMask::kA8_Format; 1571 grayMask.fBounds = origMask.fBounds; 1572 grayMask.fRowBytes = origMask.fBounds.width(); 1573 size_t size = grayMask.computeImageSize(); 1574 grayMask.fImage = (uint8_t*)fGrayMaskScratch.reset(size, 1575 SkAutoMalloc::kReuse_OnShrink); 1576 1577 upscaleBW2A8(&grayMask, origMask); 1578 mask = &grayMask; 1579 } 1580 1581 this->ensureRunsAndAA(); 1582 1583 // HACK -- we are devolving 3D into A8, need to copy the rest of the 3D 1584 // data into a temp block to support it better (ugh) 1585 1586 const void* src = mask->getAddr(clip.fLeft, clip.fTop); 1587 const size_t srcRB = mask->fRowBytes; 1588 const int width = clip.width(); 1589 MergeAAProc mergeProc = find_merge_aa_proc(mask->fFormat); 1590 1591 SkMask rowMask; 1592 rowMask.fFormat = SkMask::k3D_Format == mask->fFormat ? SkMask::kA8_Format : mask->fFormat; 1593 rowMask.fBounds.fLeft = clip.fLeft; 1594 rowMask.fBounds.fRight = clip.fRight; 1595 rowMask.fRowBytes = mask->fRowBytes; // doesn't matter, since our height==1 1596 rowMask.fImage = (uint8_t*)fScanlineScratch; 1597 1598 int y = clip.fTop; 1599 const int stopY = y + clip.height(); 1600 1601 do { 1602 int localStopY; 1603 const uint8_t* row = fAAClip->findRow(y, &localStopY); 1604 // findRow returns last Y, not stop, so we add 1 1605 localStopY = SkMin32(localStopY + 1, stopY); 1606 1607 int initialCount; 1608 row = fAAClip->findX(row, clip.fLeft, &initialCount); 1609 do { 1610 mergeProc(src, width, row, initialCount, rowMask.fImage); 1611 rowMask.fBounds.fTop = y; 1612 rowMask.fBounds.fBottom = y + 1; 1613 fBlitter->blitMask(rowMask, rowMask.fBounds); 1614 src = (const void*)((const char*)src + srcRB); 1615 } while (++y < localStopY); 1616 } while (y < stopY); 1617} 1618 1619const SkBitmap* SkAAClipBlitter::justAnOpaqueColor(uint32_t* value) { 1620 return NULL; 1621} 1622 1623