| 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 |