| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "SkClipStack.h" | 8 #include "SkClipStack.h" |
| 9 #include "SkPath.h" | 9 #include "SkPath.h" |
| 10 #include "SkThread.h" | 10 #include "SkThread.h" |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 fSaveCount -= 1; | 445 fSaveCount -= 1; |
| 446 restoreTo(fSaveCount); | 446 restoreTo(fSaveCount); |
| 447 } | 447 } |
| 448 | 448 |
| 449 void SkClipStack::restoreTo(int saveCount) { | 449 void SkClipStack::restoreTo(int saveCount) { |
| 450 while (!fDeque.empty()) { | 450 while (!fDeque.empty()) { |
| 451 Element* element = (Element*)fDeque.back(); | 451 Element* element = (Element*)fDeque.back(); |
| 452 if (element->fSaveCount <= saveCount) { | 452 if (element->fSaveCount <= saveCount) { |
| 453 break; | 453 break; |
| 454 } | 454 } |
| 455 this->purgeClip(element); | |
| 456 element->~Element(); | 455 element->~Element(); |
| 457 fDeque.pop_back(); | 456 fDeque.pop_back(); |
| 458 } | 457 } |
| 459 } | 458 } |
| 460 | 459 |
| 461 void SkClipStack::getBounds(SkRect* canvFiniteBound, | 460 void SkClipStack::getBounds(SkRect* canvFiniteBound, |
| 462 BoundsType* boundType, | 461 BoundsType* boundType, |
| 463 bool* isIntersectionOfRects) const { | 462 bool* isIntersectionOfRects) const { |
| 464 SkASSERT(NULL != canvFiniteBound && NULL != boundType); | 463 SkASSERT(NULL != canvFiniteBound && NULL != boundType); |
| 465 | 464 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 Element* element = (Element*) iter.prev(); | 532 Element* element = (Element*) iter.prev(); |
| 534 | 533 |
| 535 if (NULL != element) { | 534 if (NULL != element) { |
| 536 if (element->canBeIntersectedInPlace(fSaveCount, op)) { | 535 if (element->canBeIntersectedInPlace(fSaveCount, op)) { |
| 537 switch (element->fType) { | 536 switch (element->fType) { |
| 538 case Element::kEmpty_Type: | 537 case Element::kEmpty_Type: |
| 539 element->checkEmpty(); | 538 element->checkEmpty(); |
| 540 return; | 539 return; |
| 541 case Element::kRect_Type: | 540 case Element::kRect_Type: |
| 542 if (element->rectRectIntersectAllowed(rect, doAA)) { | 541 if (element->rectRectIntersectAllowed(rect, doAA)) { |
| 543 this->purgeClip(element); | |
| 544 if (!element->fRect.intersect(rect)) { | 542 if (!element->fRect.intersect(rect)) { |
| 545 element->setEmpty(); | 543 element->setEmpty(); |
| 546 return; | 544 return; |
| 547 } | 545 } |
| 548 | 546 |
| 549 element->fDoAA = doAA; | 547 element->fDoAA = doAA; |
| 550 Element* prev = (Element*) iter.prev(); | 548 Element* prev = (Element*) iter.prev(); |
| 551 element->updateBoundAndGenID(prev); | 549 element->updateBoundAndGenID(prev); |
| 552 return; | 550 return; |
| 553 } | 551 } |
| 554 break; | 552 break; |
| 555 case Element::kPath_Type: | 553 case Element::kPath_Type: |
| 556 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { | 554 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { |
| 557 this->purgeClip(element); | |
| 558 element->setEmpty(); | 555 element->setEmpty(); |
| 559 return; | 556 return; |
| 560 } | 557 } |
| 561 break; | 558 break; |
| 562 } | 559 } |
| 563 } else if (SkRegion::kReplace_Op == op) { | 560 } else if (SkRegion::kReplace_Op == op) { |
| 564 this->restoreTo(fSaveCount - 1); | 561 this->restoreTo(fSaveCount - 1); |
| 565 element = (Element*) fDeque.back(); | 562 element = (Element*) fDeque.back(); |
| 566 } | 563 } |
| 567 } | 564 } |
| 568 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); | 565 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); |
| 569 ((Element*) fDeque.back())->updateBoundAndGenID(element); | 566 ((Element*) fDeque.back())->updateBoundAndGenID(element); |
| 570 | |
| 571 if (element && element->fSaveCount == fSaveCount) { | |
| 572 this->purgeClip(element); | |
| 573 } | |
| 574 } | 567 } |
| 575 | 568 |
| 576 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 569 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
| 577 SkRect alt; | 570 SkRect alt; |
| 578 if (path.isRect(&alt) && !path.isInverseFillType()) { | 571 if (path.isRect(&alt) && !path.isInverseFillType()) { |
| 579 return this->clipDevRect(alt, op, doAA); | 572 return this->clipDevRect(alt, op, doAA); |
| 580 } | 573 } |
| 581 | 574 |
| 582 Element* element = (Element*)fDeque.back(); | 575 Element* element = (Element*)fDeque.back(); |
| 583 if (NULL != element) { | 576 if (NULL != element) { |
| 584 if (element->canBeIntersectedInPlace(fSaveCount, op)) { | 577 if (element->canBeIntersectedInPlace(fSaveCount, op)) { |
| 585 const SkRect& pathBounds = path.getBounds(); | 578 const SkRect& pathBounds = path.getBounds(); |
| 586 switch (element->fType) { | 579 switch (element->fType) { |
| 587 case Element::kEmpty_Type: | 580 case Element::kEmpty_Type: |
| 588 element->checkEmpty(); | 581 element->checkEmpty(); |
| 589 return; | 582 return; |
| 590 case Element::kRect_Type: | 583 case Element::kRect_Type: |
| 591 if (!SkRect::Intersects(element->fRect, pathBounds)) { | 584 if (!SkRect::Intersects(element->fRect, pathBounds)) { |
| 592 this->purgeClip(element); | |
| 593 element->setEmpty(); | 585 element->setEmpty(); |
| 594 return; | 586 return; |
| 595 } | 587 } |
| 596 break; | 588 break; |
| 597 case Element::kPath_Type: | 589 case Element::kPath_Type: |
| 598 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun
ds)) { | 590 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun
ds)) { |
| 599 this->purgeClip(element); | |
| 600 element->setEmpty(); | 591 element->setEmpty(); |
| 601 return; | 592 return; |
| 602 } | 593 } |
| 603 break; | 594 break; |
| 604 } | 595 } |
| 605 } else if (SkRegion::kReplace_Op == op) { | 596 } else if (SkRegion::kReplace_Op == op) { |
| 606 this->restoreTo(fSaveCount - 1); | 597 this->restoreTo(fSaveCount - 1); |
| 607 element = (Element*) fDeque.back(); | 598 element = (Element*) fDeque.back(); |
| 608 } | 599 } |
| 609 } | 600 } |
| 610 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA); | 601 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA); |
| 611 ((Element*) fDeque.back())->updateBoundAndGenID(element); | 602 ((Element*) fDeque.back())->updateBoundAndGenID(element); |
| 612 | |
| 613 if (element && element->fSaveCount == fSaveCount) { | |
| 614 this->purgeClip(element); | |
| 615 } | |
| 616 } | 603 } |
| 617 | 604 |
| 618 void SkClipStack::clipEmpty() { | 605 void SkClipStack::clipEmpty() { |
| 619 | 606 |
| 620 Element* element = (Element*) fDeque.back(); | 607 Element* element = (Element*) fDeque.back(); |
| 621 | 608 |
| 622 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter
sect_Op)) { | 609 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter
sect_Op)) { |
| 623 switch (element->fType) { | 610 switch (element->fType) { |
| 624 case Element::kEmpty_Type: | 611 case Element::kEmpty_Type: |
| 625 element->checkEmpty(); | 612 element->checkEmpty(); |
| 626 return; | 613 return; |
| 627 case Element::kRect_Type: | 614 case Element::kRect_Type: |
| 628 case Element::kPath_Type: | 615 case Element::kPath_Type: |
| 629 this->purgeClip(element); | |
| 630 element->setEmpty(); | 616 element->setEmpty(); |
| 631 return; | 617 return; |
| 632 } | 618 } |
| 633 } | 619 } |
| 634 new (fDeque.push_back()) Element(fSaveCount); | 620 new (fDeque.push_back()) Element(fSaveCount); |
| 635 | 621 |
| 636 if (element && element->fSaveCount == fSaveCount) { | |
| 637 this->purgeClip(element); | |
| 638 } | |
| 639 ((Element*)fDeque.back())->fGenID = kEmptyGenID; | 622 ((Element*)fDeque.back())->fGenID = kEmptyGenID; |
| 640 } | 623 } |
| 641 | 624 |
| 642 bool SkClipStack::isWideOpen() const { | 625 bool SkClipStack::isWideOpen() const { |
| 643 if (0 == fDeque.count()) { | 626 return this->getTopmostGenID() == kWideOpenGenID; |
| 644 return true; | |
| 645 } | |
| 646 | |
| 647 const Element* back = (const Element*) fDeque.back(); | |
| 648 return kWideOpenGenID == back->fGenID || | |
| 649 (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBoun
d.isEmpty()); | |
| 650 } | 627 } |
| 651 | 628 |
| 652 /////////////////////////////////////////////////////////////////////////////// | 629 /////////////////////////////////////////////////////////////////////////////// |
| 653 | 630 |
| 654 SkClipStack::Iter::Iter() : fStack(NULL) { | 631 SkClipStack::Iter::Iter() : fStack(NULL) { |
| 655 } | 632 } |
| 656 | 633 |
| 657 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) | 634 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) |
| 658 : fStack(&stack) { | 635 : fStack(&stack) { |
| 659 this->reset(stack, startLoc); | 636 this->reset(stack, startLoc); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 } | 710 } |
| 734 | 711 |
| 735 // but is converted to device space here | 712 // but is converted to device space here |
| 736 temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY)); | 713 temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY)); |
| 737 | 714 |
| 738 if (!devBounds->intersect(temp)) { | 715 if (!devBounds->intersect(temp)) { |
| 739 devBounds->setEmpty(); | 716 devBounds->setEmpty(); |
| 740 } | 717 } |
| 741 } | 718 } |
| 742 | 719 |
| 743 void SkClipStack::addPurgeClipCallback(PFPurgeClipCB callback, void* data) const
{ | |
| 744 ClipCallbackData temp = { callback, data }; | |
| 745 fCallbackData.append(1, &temp); | |
| 746 } | |
| 747 | |
| 748 void SkClipStack::removePurgeClipCallback(PFPurgeClipCB callback, void* data) co
nst { | |
| 749 ClipCallbackData temp = { callback, data }; | |
| 750 int index = fCallbackData.find(temp); | |
| 751 if (index >= 0) { | |
| 752 fCallbackData.removeShuffle(index); | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 // The clip state represented by 'element' will never be used again. Purge it. | |
| 757 void SkClipStack::purgeClip(Element* element) { | |
| 758 SkASSERT(NULL != element); | |
| 759 if (element->fGenID >= 0 && element->fGenID < kFirstUnreservedGenID) { | |
| 760 return; | |
| 761 } | |
| 762 | |
| 763 for (int i = 0; i < fCallbackData.count(); ++i) { | |
| 764 (*fCallbackData[i].fCallback)(element->fGenID, fCallbackData[i].fData); | |
| 765 } | |
| 766 | |
| 767 // Invalidate element's gen ID so handlers can detect already handled record
s | |
| 768 element->fGenID = kInvalidGenID; | |
| 769 } | |
| 770 | |
| 771 int32_t SkClipStack::GetNextGenID() { | 720 int32_t SkClipStack::GetNextGenID() { |
| 772 // TODO: handle overflow. | 721 // TODO: handle overflow. |
| 773 return sk_atomic_inc(&gGenID); | 722 return sk_atomic_inc(&gGenID); |
| 774 } | 723 } |
| 775 | 724 |
| 776 int32_t SkClipStack::getTopmostGenID() const { | 725 int32_t SkClipStack::getTopmostGenID() const { |
| 777 | |
| 778 if (fDeque.empty()) { | 726 if (fDeque.empty()) { |
| 779 return kInvalidGenID; | 727 return kWideOpenGenID; |
| 780 } | 728 } |
| 781 | 729 |
| 782 Element* element = (Element*)fDeque.back(); | 730 const Element* back = static_cast<const Element*>(fDeque.back()); |
| 783 return element->fGenID; | 731 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is
Empty()) { |
| 732 return kWideOpenGenID; |
| 733 } |
| 734 |
| 735 return back->getGenID(); |
| 784 } | 736 } |
| OLD | NEW |