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 |