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" |
11 | 11 |
12 #include <new> | 12 #include <new> |
13 | 13 |
14 | 14 |
15 // 0-2 are reserved for invalid, empty & wide-open | 15 // 0-2 are reserved for invalid, empty & wide-open |
16 static const int32_t kFirstUnreservedGenID = 3; | 16 static const int32_t kFirstUnreservedGenID = 3; |
17 int32_t SkClipStack::gGenID = kFirstUnreservedGenID; | 17 int32_t SkClipStack::gGenID = kFirstUnreservedGenID; |
18 | 18 |
| 19 SkClipStack::Element::Element(const Element& that) { |
| 20 switch (that.getType()) { |
| 21 case kEmpty_Type: |
| 22 fPath.reset(); |
| 23 break; |
| 24 case kRect_Type: // Rect uses rrect |
| 25 case kRRect_Type: |
| 26 fPath.reset(); |
| 27 fRRect = that.fRRect; |
| 28 break; |
| 29 case kPath_Type: |
| 30 fPath.set(that.getPath()); |
| 31 break; |
| 32 } |
| 33 |
| 34 fSaveCount = that.fSaveCount; |
| 35 fOp = that.fOp; |
| 36 fType = that.fType; |
| 37 fDoAA = that.fDoAA; |
| 38 fFiniteBoundType = that.fFiniteBoundType; |
| 39 fFiniteBound = that.fFiniteBound; |
| 40 fIsIntersectionOfRects = that.fIsIntersectionOfRects; |
| 41 fGenID = that.fGenID; |
| 42 } |
| 43 |
19 bool SkClipStack::Element::operator== (const Element& element) const { | 44 bool SkClipStack::Element::operator== (const Element& element) const { |
20 if (this == &element) { | 45 if (this == &element) { |
21 return true; | 46 return true; |
22 } | 47 } |
23 if (fOp != element.fOp || | 48 if (fOp != element.fOp || |
24 fType != element.fType || | 49 fType != element.fType || |
25 fDoAA != element.fDoAA || | 50 fDoAA != element.fDoAA || |
26 fSaveCount != element.fSaveCount) { | 51 fSaveCount != element.fSaveCount) { |
27 return false; | 52 return false; |
28 } | 53 } |
29 switch (fType) { | 54 switch (fType) { |
30 case kPath_Type: | 55 case kPath_Type: |
31 return fPath == element.fPath; | 56 return this->getPath() == element.getPath(); |
32 case kRRect_Type: | 57 case kRRect_Type: |
33 return fRRect == element.fRRect; | 58 return fRRect == element.fRRect; |
34 case kRect_Type: | 59 case kRect_Type: |
35 return this->getRect() == element.getRect(); | 60 return this->getRect() == element.getRect(); |
36 case kEmpty_Type: | 61 case kEmpty_Type: |
37 return true; | 62 return true; |
38 default: | 63 default: |
39 SkDEBUGFAIL("Unexpected type."); | 64 SkDEBUGFAIL("Unexpected type."); |
40 return false; | 65 return false; |
41 } | 66 } |
42 } | 67 } |
43 | 68 |
44 void SkClipStack::Element::invertShapeFillType() { | 69 void SkClipStack::Element::invertShapeFillType() { |
45 switch (fType) { | 70 switch (fType) { |
46 case kRect_Type: | 71 case kRect_Type: |
47 fPath.reset(); | 72 fPath.init(); |
48 fPath.addRect(this->getRect()); | 73 fPath.get()->addRect(this->getRect()); |
49 fPath.setFillType(SkPath::kInverseEvenOdd_FillType); | 74 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); |
50 fType = kPath_Type; | 75 fType = kPath_Type; |
51 break; | 76 break; |
52 case kRRect_Type: | 77 case kRRect_Type: |
53 fPath.reset(); | 78 fPath.init(); |
54 fPath.addRRect(fRRect); | 79 fPath.get()->addRRect(fRRect); |
55 fPath.setFillType(SkPath::kInverseEvenOdd_FillType); | 80 fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType); |
56 fType = kPath_Type; | 81 fType = kPath_Type; |
57 break; | 82 break; |
58 case kPath_Type: | 83 case kPath_Type: |
59 fPath.toggleInverseFillType(); | 84 fPath.get()->toggleInverseFillType(); |
60 break; | 85 break; |
61 case kEmpty_Type: | 86 case kEmpty_Type: |
62 // Should this set to an empty, inverse filled path? | 87 // Should this set to an empty, inverse filled path? |
63 break; | 88 break; |
64 } | 89 } |
65 } | 90 } |
66 | 91 |
67 void SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion:
:Op op, | 92 void SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion:
:Op op, |
68 bool doAA) { | 93 bool doAA) { |
69 if (!path.isInverseFillType()) { | 94 if (!path.isInverseFillType()) { |
70 if (SkPath::kNone_PathAsRect != path.asRect()) { | 95 if (SkPath::kNone_PathAsRect != path.asRect()) { |
71 this->initRect(saveCount, path.getBounds(), op, doAA); | 96 this->initRect(saveCount, path.getBounds(), op, doAA); |
72 return; | 97 return; |
73 } | 98 } |
74 SkRect ovalRect; | 99 SkRect ovalRect; |
75 if (path.isOval(&ovalRect)) { | 100 if (path.isOval(&ovalRect)) { |
76 SkRRect rrect; | 101 SkRRect rrect; |
77 rrect.setOval(ovalRect); | 102 rrect.setOval(ovalRect); |
78 this->initRRect(saveCount, rrect, op, doAA); | 103 this->initRRect(saveCount, rrect, op, doAA); |
79 return; | 104 return; |
80 } | 105 } |
81 } | 106 } |
82 fPath = path; | 107 fPath.set(path); |
83 fType = kPath_Type; | 108 fType = kPath_Type; |
84 this->initCommon(saveCount, op, doAA); | 109 this->initCommon(saveCount, op, doAA); |
85 } | 110 } |
86 | 111 |
87 void SkClipStack::Element::asPath(SkPath* path) const { | 112 void SkClipStack::Element::asPath(SkPath* path) const { |
88 switch (fType) { | 113 switch (fType) { |
89 case kEmpty_Type: | 114 case kEmpty_Type: |
90 path->reset(); | 115 path->reset(); |
91 break; | 116 break; |
92 case kRect_Type: | 117 case kRect_Type: |
93 path->reset(); | 118 path->reset(); |
94 path->addRect(this->getRect()); | 119 path->addRect(this->getRect()); |
95 break; | 120 break; |
96 case kRRect_Type: | 121 case kRRect_Type: |
97 path->reset(); | 122 path->reset(); |
98 path->addRRect(fRRect); | 123 path->addRRect(fRRect); |
99 break; | 124 break; |
100 case kPath_Type: | 125 case kPath_Type: |
101 *path = fPath; | 126 *path = *fPath.get(); |
102 break; | 127 break; |
103 } | 128 } |
104 } | 129 } |
105 | 130 |
106 void SkClipStack::Element::setEmpty() { | 131 void SkClipStack::Element::setEmpty() { |
107 fType = kEmpty_Type; | 132 fType = kEmpty_Type; |
108 fFiniteBound.setEmpty(); | 133 fFiniteBound.setEmpty(); |
109 fFiniteBoundType = kNormal_BoundsType; | 134 fFiniteBoundType = kNormal_BoundsType; |
110 fIsIntersectionOfRects = false; | 135 fIsIntersectionOfRects = false; |
111 fRRect.setEmpty(); | 136 fRRect.setEmpty(); |
112 fPath.reset(); | 137 fPath.reset(); |
113 fGenID = kEmptyGenID; | 138 fGenID = kEmptyGenID; |
114 SkDEBUGCODE(this->checkEmpty();) | 139 SkDEBUGCODE(this->checkEmpty();) |
115 } | 140 } |
116 | 141 |
117 void SkClipStack::Element::checkEmpty() const { | 142 void SkClipStack::Element::checkEmpty() const { |
118 SkASSERT(fFiniteBound.isEmpty()); | 143 SkASSERT(fFiniteBound.isEmpty()); |
119 SkASSERT(kNormal_BoundsType == fFiniteBoundType); | 144 SkASSERT(kNormal_BoundsType == fFiniteBoundType); |
120 SkASSERT(!fIsIntersectionOfRects); | 145 SkASSERT(!fIsIntersectionOfRects); |
121 SkASSERT(kEmptyGenID == fGenID); | 146 SkASSERT(kEmptyGenID == fGenID); |
122 SkASSERT(fPath.isEmpty()); | 147 SkASSERT(!fPath.isValid()); |
123 } | 148 } |
124 | 149 |
125 bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op o
p) const { | 150 bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op o
p) const { |
126 if (kEmpty_Type == fType && | 151 if (kEmpty_Type == fType && |
127 (SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) { | 152 (SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) { |
128 return true; | 153 return true; |
129 } | 154 } |
130 // Only clips within the same save/restore frame (as captured by | 155 // Only clips within the same save/restore frame (as captured by |
131 // the save count) can be merged | 156 // the save count) can be merged |
132 return fSaveCount == saveCount && | 157 return fSaveCount == saveCount && |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects
&& | 375 (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects
&& |
351 prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) { | 376 prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) { |
352 fIsIntersectionOfRects = true; | 377 fIsIntersectionOfRects = true; |
353 } | 378 } |
354 break; | 379 break; |
355 case kRRect_Type: | 380 case kRRect_Type: |
356 fFiniteBound = fRRect.getBounds(); | 381 fFiniteBound = fRRect.getBounds(); |
357 fFiniteBoundType = kNormal_BoundsType; | 382 fFiniteBoundType = kNormal_BoundsType; |
358 break; | 383 break; |
359 case kPath_Type: | 384 case kPath_Type: |
360 fFiniteBound = fPath.getBounds(); | 385 fFiniteBound = fPath.get()->getBounds(); |
361 | 386 |
362 if (fPath.isInverseFillType()) { | 387 if (fPath.get()->isInverseFillType()) { |
363 fFiniteBoundType = kInsideOut_BoundsType; | 388 fFiniteBoundType = kInsideOut_BoundsType; |
364 } else { | 389 } else { |
365 fFiniteBoundType = kNormal_BoundsType; | 390 fFiniteBoundType = kNormal_BoundsType; |
366 } | 391 } |
367 break; | 392 break; |
368 case kEmpty_Type: | 393 case kEmpty_Type: |
369 SkDEBUGFAIL("We shouldn't get here with an empty element."); | 394 SkDEBUGFAIL("We shouldn't get here with an empty element."); |
370 break; | 395 break; |
371 } | 396 } |
372 | 397 |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 return kWideOpenGenID; | 818 return kWideOpenGenID; |
794 } | 819 } |
795 | 820 |
796 const Element* back = static_cast<const Element*>(fDeque.back()); | 821 const Element* back = static_cast<const Element*>(fDeque.back()); |
797 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is
Empty()) { | 822 if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.is
Empty()) { |
798 return kWideOpenGenID; | 823 return kWideOpenGenID; |
799 } | 824 } |
800 | 825 |
801 return back->getGenID(); | 826 return back->getGenID(); |
802 } | 827 } |
OLD | NEW |