| 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); |
| 455 element->~Element(); | 456 element->~Element(); |
| 456 fDeque.pop_back(); | 457 fDeque.pop_back(); |
| 457 } | 458 } |
| 458 } | 459 } |
| 459 | 460 |
| 460 void SkClipStack::getBounds(SkRect* canvFiniteBound, | 461 void SkClipStack::getBounds(SkRect* canvFiniteBound, |
| 461 BoundsType* boundType, | 462 BoundsType* boundType, |
| 462 bool* isIntersectionOfRects) const { | 463 bool* isIntersectionOfRects) const { |
| 463 SkASSERT(NULL != canvFiniteBound && NULL != boundType); | 464 SkASSERT(NULL != canvFiniteBound && NULL != boundType); |
| 464 | 465 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 Element* element = (Element*) iter.prev(); | 533 Element* element = (Element*) iter.prev(); |
| 533 | 534 |
| 534 if (NULL != element) { | 535 if (NULL != element) { |
| 535 if (element->canBeIntersectedInPlace(fSaveCount, op)) { | 536 if (element->canBeIntersectedInPlace(fSaveCount, op)) { |
| 536 switch (element->fType) { | 537 switch (element->fType) { |
| 537 case Element::kEmpty_Type: | 538 case Element::kEmpty_Type: |
| 538 element->checkEmpty(); | 539 element->checkEmpty(); |
| 539 return; | 540 return; |
| 540 case Element::kRect_Type: | 541 case Element::kRect_Type: |
| 541 if (element->rectRectIntersectAllowed(rect, doAA)) { | 542 if (element->rectRectIntersectAllowed(rect, doAA)) { |
| 543 this->purgeClip(element); |
| 542 if (!element->fRect.intersect(rect)) { | 544 if (!element->fRect.intersect(rect)) { |
| 543 element->setEmpty(); | 545 element->setEmpty(); |
| 544 return; | 546 return; |
| 545 } | 547 } |
| 546 | 548 |
| 547 element->fDoAA = doAA; | 549 element->fDoAA = doAA; |
| 548 Element* prev = (Element*) iter.prev(); | 550 Element* prev = (Element*) iter.prev(); |
| 549 element->updateBoundAndGenID(prev); | 551 element->updateBoundAndGenID(prev); |
| 550 return; | 552 return; |
| 551 } | 553 } |
| 552 break; | 554 break; |
| 553 case Element::kPath_Type: | 555 case Element::kPath_Type: |
| 554 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { | 556 if (!SkRect::Intersects(element->fPath.getBounds(), rect)) { |
| 557 this->purgeClip(element); |
| 555 element->setEmpty(); | 558 element->setEmpty(); |
| 556 return; | 559 return; |
| 557 } | 560 } |
| 558 break; | 561 break; |
| 559 } | 562 } |
| 560 } else if (SkRegion::kReplace_Op == op) { | 563 } else if (SkRegion::kReplace_Op == op) { |
| 561 this->restoreTo(fSaveCount - 1); | 564 this->restoreTo(fSaveCount - 1); |
| 562 element = (Element*) fDeque.back(); | 565 element = (Element*) fDeque.back(); |
| 563 } | 566 } |
| 564 } | 567 } |
| 565 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); | 568 new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA); |
| 566 ((Element*) fDeque.back())->updateBoundAndGenID(element); | 569 ((Element*) fDeque.back())->updateBoundAndGenID(element); |
| 570 |
| 571 if (element && element->fSaveCount == fSaveCount) { |
| 572 this->purgeClip(element); |
| 573 } |
| 567 } | 574 } |
| 568 | 575 |
| 569 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 576 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { |
| 570 SkRect alt; | 577 SkRect alt; |
| 571 if (path.isRect(&alt) && !path.isInverseFillType()) { | 578 if (path.isRect(&alt) && !path.isInverseFillType()) { |
| 572 return this->clipDevRect(alt, op, doAA); | 579 return this->clipDevRect(alt, op, doAA); |
| 573 } | 580 } |
| 574 | 581 |
| 575 Element* element = (Element*)fDeque.back(); | 582 Element* element = (Element*)fDeque.back(); |
| 576 if (NULL != element) { | 583 if (NULL != element) { |
| 577 if (element->canBeIntersectedInPlace(fSaveCount, op)) { | 584 if (element->canBeIntersectedInPlace(fSaveCount, op)) { |
| 578 const SkRect& pathBounds = path.getBounds(); | 585 const SkRect& pathBounds = path.getBounds(); |
| 579 switch (element->fType) { | 586 switch (element->fType) { |
| 580 case Element::kEmpty_Type: | 587 case Element::kEmpty_Type: |
| 581 element->checkEmpty(); | 588 element->checkEmpty(); |
| 582 return; | 589 return; |
| 583 case Element::kRect_Type: | 590 case Element::kRect_Type: |
| 584 if (!SkRect::Intersects(element->fRect, pathBounds)) { | 591 if (!SkRect::Intersects(element->fRect, pathBounds)) { |
| 592 this->purgeClip(element); |
| 585 element->setEmpty(); | 593 element->setEmpty(); |
| 586 return; | 594 return; |
| 587 } | 595 } |
| 588 break; | 596 break; |
| 589 case Element::kPath_Type: | 597 case Element::kPath_Type: |
| 590 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun
ds)) { | 598 if (!SkRect::Intersects(element->fPath.getBounds(), pathBoun
ds)) { |
| 599 this->purgeClip(element); |
| 591 element->setEmpty(); | 600 element->setEmpty(); |
| 592 return; | 601 return; |
| 593 } | 602 } |
| 594 break; | 603 break; |
| 595 } | 604 } |
| 596 } else if (SkRegion::kReplace_Op == op) { | 605 } else if (SkRegion::kReplace_Op == op) { |
| 597 this->restoreTo(fSaveCount - 1); | 606 this->restoreTo(fSaveCount - 1); |
| 598 element = (Element*) fDeque.back(); | 607 element = (Element*) fDeque.back(); |
| 599 } | 608 } |
| 600 } | 609 } |
| 601 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA); | 610 new (fDeque.push_back()) Element(fSaveCount, path, op, doAA); |
| 602 ((Element*) fDeque.back())->updateBoundAndGenID(element); | 611 ((Element*) fDeque.back())->updateBoundAndGenID(element); |
| 612 |
| 613 if (element && element->fSaveCount == fSaveCount) { |
| 614 this->purgeClip(element); |
| 615 } |
| 603 } | 616 } |
| 604 | 617 |
| 605 void SkClipStack::clipEmpty() { | 618 void SkClipStack::clipEmpty() { |
| 606 | 619 |
| 607 Element* element = (Element*) fDeque.back(); | 620 Element* element = (Element*) fDeque.back(); |
| 608 | 621 |
| 609 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter
sect_Op)) { | 622 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter
sect_Op)) { |
| 610 switch (element->fType) { | 623 switch (element->fType) { |
| 611 case Element::kEmpty_Type: | 624 case Element::kEmpty_Type: |
| 612 element->checkEmpty(); | 625 element->checkEmpty(); |
| 613 return; | 626 return; |
| 614 case Element::kRect_Type: | 627 case Element::kRect_Type: |
| 615 case Element::kPath_Type: | 628 case Element::kPath_Type: |
| 629 this->purgeClip(element); |
| 616 element->setEmpty(); | 630 element->setEmpty(); |
| 617 return; | 631 return; |
| 618 } | 632 } |
| 619 } | 633 } |
| 620 new (fDeque.push_back()) Element(fSaveCount); | 634 new (fDeque.push_back()) Element(fSaveCount); |
| 621 | 635 |
| 636 if (element && element->fSaveCount == fSaveCount) { |
| 637 this->purgeClip(element); |
| 638 } |
| 622 ((Element*)fDeque.back())->fGenID = kEmptyGenID; | 639 ((Element*)fDeque.back())->fGenID = kEmptyGenID; |
| 623 } | 640 } |
| 624 | 641 |
| 625 bool SkClipStack::isWideOpen() const { | 642 bool SkClipStack::isWideOpen() const { |
| 626 return this->getTopmostGenID() == kWideOpenGenID; | 643 if (0 == fDeque.count()) { |
| 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()); |
| 627 } | 650 } |
| 628 | 651 |
| 629 /////////////////////////////////////////////////////////////////////////////// | 652 /////////////////////////////////////////////////////////////////////////////// |
| 630 | 653 |
| 631 SkClipStack::Iter::Iter() : fStack(NULL) { | 654 SkClipStack::Iter::Iter() : fStack(NULL) { |
| 632 } | 655 } |
| 633 | 656 |
| 634 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) | 657 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) |
| 635 : fStack(&stack) { | 658 : fStack(&stack) { |
| 636 this->reset(stack, startLoc); | 659 this->reset(stack, startLoc); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 } | 733 } |
| 711 | 734 |
| 712 // but is converted to device space here | 735 // but is converted to device space here |
| 713 temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY)); | 736 temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY)); |
| 714 | 737 |
| 715 if (!devBounds->intersect(temp)) { | 738 if (!devBounds->intersect(temp)) { |
| 716 devBounds->setEmpty(); | 739 devBounds->setEmpty(); |
| 717 } | 740 } |
| 718 } | 741 } |
| 719 | 742 |
| 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 |
| 720 int32_t SkClipStack::GetNextGenID() { | 771 int32_t SkClipStack::GetNextGenID() { |
| 721 // TODO: handle overflow. | 772 // TODO: handle overflow. |
| 722 return sk_atomic_inc(&gGenID); | 773 return sk_atomic_inc(&gGenID); |
| 723 } | 774 } |
| 724 | 775 |
| 725 int32_t SkClipStack::getTopmostGenID() const { | 776 int32_t SkClipStack::getTopmostGenID() const { |
| 777 |
| 726 if (fDeque.empty()) { | 778 if (fDeque.empty()) { |
| 727 return kWideOpenGenID; | 779 return kInvalidGenID; |
| 728 } | 780 } |
| 729 | 781 |
| 730 const Element* back = static_cast<const Element*>(fDeque.back()); | 782 Element* element = (Element*)fDeque.back(); |
| 731 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is
Empty()) { | 783 return element->fGenID; |
| 732 return kWideOpenGenID; | |
| 733 } | |
| 734 | |
| 735 return back->getGenID(); | |
| 736 } | 784 } |
| OLD | NEW |