OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkAtomics.h" | 8 #include "SkAtomics.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkClipStack.h" | 10 #include "SkClipStack.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 case kPath_Type: | 76 case kPath_Type: |
77 visitor->clipPath(this->getPath(), this->getOp(), this->isAA()); | 77 visitor->clipPath(this->getPath(), this->getOp(), this->isAA()); |
78 break; | 78 break; |
79 case kRRect_Type: | 79 case kRRect_Type: |
80 visitor->clipRRect(this->getRRect(), this->getOp(), this->isAA()); | 80 visitor->clipRRect(this->getRRect(), this->getOp(), this->isAA()); |
81 break; | 81 break; |
82 case kRect_Type: | 82 case kRect_Type: |
83 visitor->clipRect(this->getRect(), this->getOp(), this->isAA()); | 83 visitor->clipRect(this->getRect(), this->getOp(), this->isAA()); |
84 break; | 84 break; |
85 case kEmpty_Type: | 85 case kEmpty_Type: |
86 visitor->clipRect(kEmptyRect, SkRegion::kIntersect_Op, false); | 86 visitor->clipRect(kEmptyRect, SkCanvas::kIntersect_Op, false); |
87 break; | 87 break; |
88 } | 88 } |
89 } | 89 } |
90 | 90 |
91 void SkClipStack::Element::invertShapeFillType() { | 91 void SkClipStack::Element::invertShapeFillType() { |
92 switch (fType) { | 92 switch (fType) { |
93 case kRect_Type: | 93 case kRect_Type: |
94 fPath.init(); | 94 fPath.init(); |
95 fPath.get()->addRect(this->getRect()); | 95 fPath.get()->addRect(this->getRect()); |
96 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); | 96 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); |
97 fType = kPath_Type; | 97 fType = kPath_Type; |
98 break; | 98 break; |
99 case kRRect_Type: | 99 case kRRect_Type: |
100 fPath.init(); | 100 fPath.init(); |
101 fPath.get()->addRRect(fRRect); | 101 fPath.get()->addRRect(fRRect); |
102 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); | 102 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); |
103 fType = kPath_Type; | 103 fType = kPath_Type; |
104 break; | 104 break; |
105 case kPath_Type: | 105 case kPath_Type: |
106 fPath.get()->toggleInverseFillType(); | 106 fPath.get()->toggleInverseFillType(); |
107 break; | 107 break; |
108 case kEmpty_Type: | 108 case kEmpty_Type: |
109 // Should this set to an empty, inverse filled path? | 109 // Should this set to an empty, inverse filled path? |
110 break; | 110 break; |
111 } | 111 } |
112 } | 112 } |
113 | 113 |
114 void SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion:
:Op op, | 114 void SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkCanvas:
:ClipOp op, |
115 bool doAA) { | 115 bool doAA) { |
116 if (!path.isInverseFillType()) { | 116 if (!path.isInverseFillType()) { |
117 SkRect r; | 117 SkRect r; |
118 if (path.isRect(&r)) { | 118 if (path.isRect(&r)) { |
119 this->initRect(saveCount, r, op, doAA); | 119 this->initRect(saveCount, r, op, doAA); |
120 return; | 120 return; |
121 } | 121 } |
122 SkRect ovalRect; | 122 SkRect ovalRect; |
123 if (path.isOval(&ovalRect)) { | 123 if (path.isOval(&ovalRect)) { |
124 SkRRect rrect; | 124 SkRRect rrect; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 | 169 |
170 void SkClipStack::Element::checkEmpty() const { | 170 void SkClipStack::Element::checkEmpty() const { |
171 SkASSERT(fFiniteBound.isEmpty()); | 171 SkASSERT(fFiniteBound.isEmpty()); |
172 SkASSERT(kNormal_BoundsType == fFiniteBoundType); | 172 SkASSERT(kNormal_BoundsType == fFiniteBoundType); |
173 SkASSERT(!fIsIntersectionOfRects); | 173 SkASSERT(!fIsIntersectionOfRects); |
174 SkASSERT(kEmptyGenID == fGenID); | 174 SkASSERT(kEmptyGenID == fGenID); |
175 SkASSERT(fRRect.isEmpty()); | 175 SkASSERT(fRRect.isEmpty()); |
176 SkASSERT(!fPath.isValid()); | 176 SkASSERT(!fPath.isValid()); |
177 } | 177 } |
178 | 178 |
179 bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op o
p) const { | 179 bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkCanvas::Clip
Op op) const { |
180 if (kEmpty_Type == fType && | 180 if (kEmpty_Type == fType && |
181 (SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) { | 181 (SkCanvas::kDifference_Op == op || SkCanvas::kIntersect_Op == op)) { |
182 return true; | 182 return true; |
183 } | 183 } |
184 // Only clips within the same save/restore frame (as captured by | 184 // Only clips within the same save/restore frame (as captured by |
185 // the save count) can be merged | 185 // the save count) can be merged |
186 return fSaveCount == saveCount && | 186 return fSaveCount == saveCount && |
187 SkRegion::kIntersect_Op == op && | 187 SkCanvas::kIntersect_Op == op && |
188 (SkRegion::kIntersect_Op == fOp || SkRegion::kReplace_Op == fOp); | 188 (SkCanvas::kIntersect_Op == fOp || SkCanvas::kReplace_Op == fOp); |
189 } | 189 } |
190 | 190 |
191 bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool new
AA) const { | 191 bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool new
AA) const { |
192 SkASSERT(kRect_Type == fType); | 192 SkASSERT(kRect_Type == fType); |
193 | 193 |
194 if (fDoAA == newAA) { | 194 if (fDoAA == newAA) { |
195 // if the AA setting is the same there is no issue | 195 // if the AA setting is the same there is no issue |
196 return true; | 196 return true; |
197 } | 197 } |
198 | 198 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 fGenID = GetNextGenID(); | 392 fGenID = GetNextGenID(); |
393 | 393 |
394 // First, optimistically update the current Element's bound information | 394 // First, optimistically update the current Element's bound information |
395 // with the current clip's bound | 395 // with the current clip's bound |
396 fIsIntersectionOfRects = false; | 396 fIsIntersectionOfRects = false; |
397 switch (fType) { | 397 switch (fType) { |
398 case kRect_Type: | 398 case kRect_Type: |
399 fFiniteBound = this->getRect(); | 399 fFiniteBound = this->getRect(); |
400 fFiniteBoundType = kNormal_BoundsType; | 400 fFiniteBoundType = kNormal_BoundsType; |
401 | 401 |
402 if (SkRegion::kReplace_Op == fOp || | 402 if (SkCanvas::kReplace_Op == fOp || |
403 (SkRegion::kIntersect_Op == fOp && nullptr == prior) || | 403 (SkCanvas::kIntersect_Op == fOp && nullptr == prior) || |
404 (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects
&& | 404 (SkCanvas::kIntersect_Op == fOp && prior->fIsIntersectionOfRects
&& |
405 prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) { | 405 prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) { |
406 fIsIntersectionOfRects = true; | 406 fIsIntersectionOfRects = true; |
407 } | 407 } |
408 break; | 408 break; |
409 case kRRect_Type: | 409 case kRRect_Type: |
410 fFiniteBound = fRRect.getBounds(); | 410 fFiniteBound = fRRect.getBounds(); |
411 fFiniteBoundType = kNormal_BoundsType; | 411 fFiniteBoundType = kNormal_BoundsType; |
412 break; | 412 break; |
413 case kPath_Type: | 413 case kPath_Type: |
414 fFiniteBound = fPath.get()->getBounds(); | 414 fFiniteBound = fPath.get()->getBounds(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 combination = (FillCombo) (combination | 0x02); | 453 combination = (FillCombo) (combination | 0x02); |
454 } | 454 } |
455 | 455 |
456 SkASSERT(kInvPrev_InvCur_FillCombo == combination || | 456 SkASSERT(kInvPrev_InvCur_FillCombo == combination || |
457 kInvPrev_Cur_FillCombo == combination || | 457 kInvPrev_Cur_FillCombo == combination || |
458 kPrev_InvCur_FillCombo == combination || | 458 kPrev_InvCur_FillCombo == combination || |
459 kPrev_Cur_FillCombo == combination); | 459 kPrev_Cur_FillCombo == combination); |
460 | 460 |
461 // Now integrate with clip with the prior clips | 461 // Now integrate with clip with the prior clips |
462 switch (fOp) { | 462 switch (fOp) { |
463 case SkRegion::kDifference_Op: | 463 case SkCanvas::kDifference_Op: |
464 this->combineBoundsDiff(combination, prevFinite); | 464 this->combineBoundsDiff(combination, prevFinite); |
465 break; | 465 break; |
466 case SkRegion::kXOR_Op: | 466 case SkCanvas::kXOR_Op: |
467 this->combineBoundsXOR(combination, prevFinite); | 467 this->combineBoundsXOR(combination, prevFinite); |
468 break; | 468 break; |
469 case SkRegion::kUnion_Op: | 469 case SkCanvas::kUnion_Op: |
470 this->combineBoundsUnion(combination, prevFinite); | 470 this->combineBoundsUnion(combination, prevFinite); |
471 break; | 471 break; |
472 case SkRegion::kIntersect_Op: | 472 case SkCanvas::kIntersect_Op: |
473 this->combineBoundsIntersection(combination, prevFinite); | 473 this->combineBoundsIntersection(combination, prevFinite); |
474 break; | 474 break; |
475 case SkRegion::kReverseDifference_Op: | 475 case SkCanvas::kReverseDifference_Op: |
476 this->combineBoundsRevDiff(combination, prevFinite); | 476 this->combineBoundsRevDiff(combination, prevFinite); |
477 break; | 477 break; |
478 case SkRegion::kReplace_Op: | 478 case SkCanvas::kReplace_Op: |
479 // Replace just ignores everything prior | 479 // Replace just ignores everything prior |
480 // The current clip's bound information is already filled in | 480 // The current clip's bound information is already filled in |
481 // so nothing to do | 481 // so nothing to do |
482 break; | 482 break; |
483 default: | 483 default: |
484 SkDebugf("SkRegion::Op error\n"); | 484 SkDebugf("SkCanvas::ClipOp error\n"); |
485 SkASSERT(0); | 485 SkASSERT(0); |
486 break; | 486 break; |
487 } | 487 } |
488 } | 488 } |
489 | 489 |
490 // This constant determines how many Element's are allocated together as a block
in | 490 // This constant determines how many Element's are allocated together as a block
in |
491 // the deque. As such it needs to balance allocating too much memory vs. | 491 // the deque. As such it needs to balance allocating too much memory vs. |
492 // incurring allocation/deallocation thrashing. It should roughly correspond to | 492 // incurring allocation/deallocation thrashing. It should roughly correspond to |
493 // the deepest save/restore stack we expect to see. | 493 // the deepest save/restore stack we expect to see. |
494 static const int kDefaultElementAllocCnt = 8; | 494 static const int kDefaultElementAllocCnt = 8; |
495 | 495 |
496 SkClipStack::SkClipStack() | 496 SkClipStack::SkClipStack() |
497 : fDeque(sizeof(Element), kDefaultElementAllocCnt) | 497 : fDeque(sizeof(Element), kDefaultElementAllocCnt) |
498 , fSaveCount(0) { | 498 , fSaveCount(0) { |
499 } | 499 } |
500 | 500 |
501 SkClipStack::SkClipStack(const SkClipStack& b) | 501 SkClipStack::SkClipStack(const SkClipStack& b) |
502 : fDeque(sizeof(Element), kDefaultElementAllocCnt) { | 502 : fDeque(sizeof(Element), kDefaultElementAllocCnt) { |
503 *this = b; | 503 *this = b; |
504 } | 504 } |
505 | 505 |
506 SkClipStack::SkClipStack(const SkRect& r) | 506 SkClipStack::SkClipStack(const SkRect& r) |
507 : fDeque(sizeof(Element), kDefaultElementAllocCnt) | 507 : fDeque(sizeof(Element), kDefaultElementAllocCnt) |
508 , fSaveCount(0) { | 508 , fSaveCount(0) { |
509 if (!r.isEmpty()) { | 509 if (!r.isEmpty()) { |
510 this->clipDevRect(r, SkRegion::kReplace_Op, false); | 510 this->clipDevRect(r, SkCanvas::kReplace_Op, false); |
511 } | 511 } |
512 } | 512 } |
513 | 513 |
514 SkClipStack::SkClipStack(const SkIRect& r) | 514 SkClipStack::SkClipStack(const SkIRect& r) |
515 : fDeque(sizeof(Element), kDefaultElementAllocCnt) | 515 : fDeque(sizeof(Element), kDefaultElementAllocCnt) |
516 , fSaveCount(0) { | 516 , fSaveCount(0) { |
517 if (!r.isEmpty()) { | 517 if (!r.isEmpty()) { |
518 SkRect temp; | 518 SkRect temp; |
519 temp.set(r); | 519 temp.set(r); |
520 this->clipDevRect(temp, SkRegion::kReplace_Op, false); | 520 this->clipDevRect(temp, SkCanvas::kReplace_Op, false); |
521 } | 521 } |
522 } | 522 } |
523 | 523 |
524 SkClipStack::~SkClipStack() { | 524 SkClipStack::~SkClipStack() { |
525 reset(); | 525 reset(); |
526 } | 526 } |
527 | 527 |
528 SkClipStack& SkClipStack::operator=(const SkClipStack& b) { | 528 SkClipStack& SkClipStack::operator=(const SkClipStack& b) { |
529 if (this == &b) { | 529 if (this == &b) { |
530 return *this; | 530 return *this; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 if (isIntersectionOfRects) { | 619 if (isIntersectionOfRects) { |
620 *isIntersectionOfRects = element->fIsIntersectionOfRects; | 620 *isIntersectionOfRects = element->fIsIntersectionOfRects; |
621 } | 621 } |
622 } | 622 } |
623 | 623 |
624 bool SkClipStack::internalQuickContains(const SkRect& rect) const { | 624 bool SkClipStack::internalQuickContains(const SkRect& rect) const { |
625 | 625 |
626 Iter iter(*this, Iter::kTop_IterStart); | 626 Iter iter(*this, Iter::kTop_IterStart); |
627 const Element* element = iter.prev(); | 627 const Element* element = iter.prev(); |
628 while (element != nullptr) { | 628 while (element != nullptr) { |
629 if (SkRegion::kIntersect_Op != element->getOp() && SkRegion::kReplace_Op
!= element->getOp()) | 629 if (SkCanvas::kIntersect_Op != element->getOp() && SkCanvas::kReplace_Op
!= element->getOp()) |
630 return false; | 630 return false; |
631 if (element->isInverseFilled()) { | 631 if (element->isInverseFilled()) { |
632 // Part of 'rect' could be trimmed off by the inverse-filled clip el
ement | 632 // Part of 'rect' could be trimmed off by the inverse-filled clip el
ement |
633 if (SkRect::Intersects(element->getBounds(), rect)) { | 633 if (SkRect::Intersects(element->getBounds(), rect)) { |
634 return false; | 634 return false; |
635 } | 635 } |
636 } else { | 636 } else { |
637 if (!element->contains(rect)) { | 637 if (!element->contains(rect)) { |
638 return false; | 638 return false; |
639 } | 639 } |
640 } | 640 } |
641 if (SkRegion::kReplace_Op == element->getOp()) { | 641 if (SkCanvas::kReplace_Op == element->getOp()) { |
642 break; | 642 break; |
643 } | 643 } |
644 element = iter.prev(); | 644 element = iter.prev(); |
645 } | 645 } |
646 return true; | 646 return true; |
647 } | 647 } |
648 | 648 |
649 bool SkClipStack::internalQuickContains(const SkRRect& rrect) const { | 649 bool SkClipStack::internalQuickContains(const SkRRect& rrect) const { |
650 | 650 |
651 Iter iter(*this, Iter::kTop_IterStart); | 651 Iter iter(*this, Iter::kTop_IterStart); |
652 const Element* element = iter.prev(); | 652 const Element* element = iter.prev(); |
653 while (element != nullptr) { | 653 while (element != nullptr) { |
654 if (SkRegion::kIntersect_Op != element->getOp() && SkRegion::kReplace_Op
!= element->getOp()) | 654 if (SkCanvas::kIntersect_Op != element->getOp() && SkCanvas::kReplace_Op
!= element->getOp()) |
655 return false; | 655 return false; |
656 if (element->isInverseFilled()) { | 656 if (element->isInverseFilled()) { |
657 // Part of 'rrect' could be trimmed off by the inverse-filled clip e
lement | 657 // Part of 'rrect' could be trimmed off by the inverse-filled clip e
lement |
658 if (SkRect::Intersects(element->getBounds(), rrect.getBounds())) { | 658 if (SkRect::Intersects(element->getBounds(), rrect.getBounds())) { |
659 return false; | 659 return false; |
660 } | 660 } |
661 } else { | 661 } else { |
662 if (!element->contains(rrect)) { | 662 if (!element->contains(rrect)) { |
663 return false; | 663 return false; |
664 } | 664 } |
665 } | 665 } |
666 if (SkRegion::kReplace_Op == element->getOp()) { | 666 if (SkCanvas::kReplace_Op == element->getOp()) { |
667 break; | 667 break; |
668 } | 668 } |
669 element = iter.prev(); | 669 element = iter.prev(); |
670 } | 670 } |
671 return true; | 671 return true; |
672 } | 672 } |
673 | 673 |
674 bool SkClipStack::asPath(SkPath *path) const { | 674 bool SkClipStack::asPath(SkPath *path) const { |
675 bool isAA = false; | 675 bool isAA = false; |
676 | 676 |
677 path->reset(); | 677 path->reset(); |
678 path->setFillType(SkPath::kInverseEvenOdd_FillType); | 678 path->setFillType(SkPath::kInverseEvenOdd_FillType); |
679 | 679 |
680 SkClipStack::Iter iter(*this, SkClipStack::Iter::kBottom_IterStart); | 680 SkClipStack::Iter iter(*this, SkClipStack::Iter::kBottom_IterStart); |
681 while (const SkClipStack::Element* element = iter.next()) { | 681 while (const SkClipStack::Element* element = iter.next()) { |
682 SkPath operand; | 682 SkPath operand; |
683 if (element->getType() != SkClipStack::Element::kEmpty_Type) { | 683 if (element->getType() != SkClipStack::Element::kEmpty_Type) { |
684 element->asPath(&operand); | 684 element->asPath(&operand); |
685 } | 685 } |
686 | 686 |
687 SkRegion::Op elementOp = element->getOp(); | 687 SkCanvas::ClipOp elementOp = element->getOp(); |
688 if (elementOp == SkRegion::kReplace_Op) { | 688 if (elementOp == SkCanvas::kReplace_Op) { |
689 *path = operand; | 689 *path = operand; |
690 } else { | 690 } else { |
691 Op(*path, operand, (SkPathOp)elementOp, path); | 691 Op(*path, operand, (SkPathOp)elementOp, path); |
692 } | 692 } |
693 | 693 |
694 // if the prev and curr clips disagree about aa -vs- not, favor the aa r
equest. | 694 // if the prev and curr clips disagree about aa -vs- not, favor the aa r
equest. |
695 // perhaps we need an API change to avoid this sort of mixed-signals abo
ut | 695 // perhaps we need an API change to avoid this sort of mixed-signals abo
ut |
696 // clipping. | 696 // clipping. |
697 isAA = (isAA || element->isAA()); | 697 isAA = (isAA || element->isAA()); |
698 } | 698 } |
(...skipping 30 matching lines...) Expand all Loading... |
729 break; | 729 break; |
730 } | 730 } |
731 // fallthrough | 731 // fallthrough |
732 default: | 732 default: |
733 if (!SkRect::Intersects(prior->getBounds(), element.getBound
s())) { | 733 if (!SkRect::Intersects(prior->getBounds(), element.getBound
s())) { |
734 prior->setEmpty(); | 734 prior->setEmpty(); |
735 return; | 735 return; |
736 } | 736 } |
737 break; | 737 break; |
738 } | 738 } |
739 } else if (SkRegion::kReplace_Op == element.getOp()) { | 739 } else if (SkCanvas::kReplace_Op == element.getOp()) { |
740 this->restoreTo(fSaveCount - 1); | 740 this->restoreTo(fSaveCount - 1); |
741 prior = (Element*) fDeque.back(); | 741 prior = (Element*) fDeque.back(); |
742 } | 742 } |
743 } | 743 } |
744 Element* newElement = new (fDeque.push_back()) Element(element); | 744 Element* newElement = new (fDeque.push_back()) Element(element); |
745 newElement->updateBoundAndGenID(prior); | 745 newElement->updateBoundAndGenID(prior); |
746 } | 746 } |
747 | 747 |
748 void SkClipStack::clipDevRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA)
{ | 748 void SkClipStack::clipDevRRect(const SkRRect& rrect, SkCanvas::ClipOp op, bool d
oAA) { |
749 Element element(fSaveCount, rrect, op, doAA); | 749 Element element(fSaveCount, rrect, op, doAA); |
750 this->pushElement(element); | 750 this->pushElement(element); |
751 } | 751 } |
752 | 752 |
753 void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | 753 void SkClipStack::clipDevRect(const SkRect& rect, SkCanvas::ClipOp op, bool doAA
) { |
754 Element element(fSaveCount, rect, op, doAA); | 754 Element element(fSaveCount, rect, op, doAA); |
755 this->pushElement(element); | 755 this->pushElement(element); |
756 } | 756 } |
757 | 757 |
758 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 758 void SkClipStack::clipDevPath(const SkPath& path, SkCanvas::ClipOp op, bool doAA
) { |
759 Element element(fSaveCount, path, op, doAA); | 759 Element element(fSaveCount, path, op, doAA); |
760 this->pushElement(element); | 760 this->pushElement(element); |
761 } | 761 } |
762 | 762 |
763 void SkClipStack::clipEmpty() { | 763 void SkClipStack::clipEmpty() { |
764 Element* element = (Element*) fDeque.back(); | 764 Element* element = (Element*) fDeque.back(); |
765 | 765 |
766 if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kInter
sect_Op)) { | 766 if (element && element->canBeIntersectedInPlace(fSaveCount, SkCanvas::kInter
sect_Op)) { |
767 element->setEmpty(); | 767 element->setEmpty(); |
768 } | 768 } |
769 new (fDeque.push_back()) Element(fSaveCount); | 769 new (fDeque.push_back()) Element(fSaveCount); |
770 | 770 |
771 ((Element*)fDeque.back())->fGenID = kEmptyGenID; | 771 ((Element*)fDeque.back())->fGenID = kEmptyGenID; |
772 } | 772 } |
773 | 773 |
774 /////////////////////////////////////////////////////////////////////////////// | 774 /////////////////////////////////////////////////////////////////////////////// |
775 | 775 |
776 SkClipStack::Iter::Iter() : fStack(nullptr) { | 776 SkClipStack::Iter::Iter() : fStack(nullptr) { |
777 } | 777 } |
778 | 778 |
779 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) | 779 SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc) |
780 : fStack(&stack) { | 780 : fStack(&stack) { |
781 this->reset(stack, startLoc); | 781 this->reset(stack, startLoc); |
782 } | 782 } |
783 | 783 |
784 const SkClipStack::Element* SkClipStack::Iter::next() { | 784 const SkClipStack::Element* SkClipStack::Iter::next() { |
785 return (const SkClipStack::Element*)fIter.next(); | 785 return (const SkClipStack::Element*)fIter.next(); |
786 } | 786 } |
787 | 787 |
788 const SkClipStack::Element* SkClipStack::Iter::prev() { | 788 const SkClipStack::Element* SkClipStack::Iter::prev() { |
789 return (const SkClipStack::Element*)fIter.prev(); | 789 return (const SkClipStack::Element*)fIter.prev(); |
790 } | 790 } |
791 | 791 |
792 const SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) { | 792 const SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkCanvas::ClipOp op
) { |
793 | 793 |
794 if (nullptr == fStack) { | 794 if (nullptr == fStack) { |
795 return nullptr; | 795 return nullptr; |
796 } | 796 } |
797 | 797 |
798 fIter.reset(fStack->fDeque, SkDeque::Iter::kBack_IterStart); | 798 fIter.reset(fStack->fDeque, SkDeque::Iter::kBack_IterStart); |
799 | 799 |
800 const SkClipStack::Element* element = nullptr; | 800 const SkClipStack::Element* element = nullptr; |
801 | 801 |
802 for (element = (const SkClipStack::Element*) fIter.prev(); | 802 for (element = (const SkClipStack::Element*) fIter.prev(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 // it is an rrect. | 867 // it is an rrect. |
868 int cnt = fDeque.count(); | 868 int cnt = fDeque.count(); |
869 if (!cnt || cnt > 5) { | 869 if (!cnt || cnt > 5) { |
870 return false; | 870 return false; |
871 } | 871 } |
872 const Element* back = static_cast<const Element*>(fDeque.back()); | 872 const Element* back = static_cast<const Element*>(fDeque.back()); |
873 if (back->getType() != SkClipStack::Element::kRect_Type && | 873 if (back->getType() != SkClipStack::Element::kRect_Type && |
874 back->getType() != SkClipStack::Element::kRRect_Type) { | 874 back->getType() != SkClipStack::Element::kRRect_Type) { |
875 return false; | 875 return false; |
876 } | 876 } |
877 if (back->getOp() == SkRegion::kReplace_Op) { | 877 if (back->getOp() == SkCanvas::kReplace_Op) { |
878 *rrect = back->asRRect(); | 878 *rrect = back->asRRect(); |
879 *aa = back->isAA(); | 879 *aa = back->isAA(); |
880 return true; | 880 return true; |
881 } | 881 } |
882 | 882 |
883 if (back->getOp() == SkRegion::kIntersect_Op) { | 883 if (back->getOp() == SkCanvas::kIntersect_Op) { |
884 SkRect backBounds; | 884 SkRect backBounds; |
885 if (!backBounds.intersect(bounds, back->asRRect().rect())) { | 885 if (!backBounds.intersect(bounds, back->asRRect().rect())) { |
886 return false; | 886 return false; |
887 } | 887 } |
888 if (cnt > 1) { | 888 if (cnt > 1) { |
889 SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart); | 889 SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart); |
890 SkAssertResult(static_cast<const Element*>(iter.prev()) == back); | 890 SkAssertResult(static_cast<const Element*>(iter.prev()) == back); |
891 while (const Element* prior = (const Element*)iter.prev()) { | 891 while (const Element* prior = (const Element*)iter.prev()) { |
892 if ((prior->getOp() != SkRegion::kIntersect_Op && | 892 if ((prior->getOp() != SkCanvas::kIntersect_Op && |
893 prior->getOp() != SkRegion::kReplace_Op) || | 893 prior->getOp() != SkCanvas::kReplace_Op) || |
894 !prior->contains(backBounds)) { | 894 !prior->contains(backBounds)) { |
895 return false; | 895 return false; |
896 } | 896 } |
897 if (prior->getOp() == SkRegion::kReplace_Op) { | 897 if (prior->getOp() == SkCanvas::kReplace_Op) { |
898 break; | 898 break; |
899 } | 899 } |
900 } | 900 } |
901 } | 901 } |
902 *rrect = back->asRRect(); | 902 *rrect = back->asRRect(); |
903 *aa = back->isAA(); | 903 *aa = back->isAA(); |
904 return true; | 904 return true; |
905 } | 905 } |
906 return false; | 906 return false; |
907 } | 907 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 static_assert(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, "type_str"); | 939 static_assert(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, "type_str"); |
940 | 940 |
941 static const char* kOpStrings[] = { | 941 static const char* kOpStrings[] = { |
942 "difference", | 942 "difference", |
943 "intersect", | 943 "intersect", |
944 "union", | 944 "union", |
945 "xor", | 945 "xor", |
946 "reverse-difference", | 946 "reverse-difference", |
947 "replace", | 947 "replace", |
948 }; | 948 }; |
949 static_assert(0 == SkRegion::kDifference_Op, "op_str"); | 949 static_assert(0 == SkCanvas::kDifference_Op, "op_str"); |
950 static_assert(1 == SkRegion::kIntersect_Op, "op_str"); | 950 static_assert(1 == SkCanvas::kIntersect_Op, "op_str"); |
951 static_assert(2 == SkRegion::kUnion_Op, "op_str"); | 951 static_assert(2 == SkCanvas::kUnion_Op, "op_str"); |
952 static_assert(3 == SkRegion::kXOR_Op, "op_str"); | 952 static_assert(3 == SkCanvas::kXOR_Op, "op_str"); |
953 static_assert(4 == SkRegion::kReverseDifference_Op, "op_str"); | 953 static_assert(4 == SkCanvas::kReverseDifference_Op, "op_str"); |
954 static_assert(5 == SkRegion::kReplace_Op, "op_str"); | 954 static_assert(5 == SkCanvas::kReplace_Op, "op_str"); |
955 static_assert(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, "op_str"); | 955 static_assert(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, "op_str"); |
956 | 956 |
957 SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[fType], | 957 SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[fType], |
958 kOpStrings[fOp], (fDoAA ? "yes" : "no"), fSaveCount); | 958 kOpStrings[fOp], (fDoAA ? "yes" : "no"), fSaveCount); |
959 switch (fType) { | 959 switch (fType) { |
960 case kEmpty_Type: | 960 case kEmpty_Type: |
961 SkDebugf("\n"); | 961 SkDebugf("\n"); |
962 break; | 962 break; |
963 case kRect_Type: | 963 case kRect_Type: |
964 this->getRect().dump(); | 964 this->getRect().dump(); |
(...skipping 11 matching lines...) Expand all Loading... |
976 | 976 |
977 void SkClipStack::dump() const { | 977 void SkClipStack::dump() const { |
978 B2TIter iter(*this); | 978 B2TIter iter(*this); |
979 const Element* e; | 979 const Element* e; |
980 while ((e = iter.next())) { | 980 while ((e = iter.next())) { |
981 e->dump(); | 981 e->dump(); |
982 SkDebugf("\n"); | 982 SkDebugf("\n"); |
983 } | 983 } |
984 } | 984 } |
985 #endif | 985 #endif |
OLD | NEW |