1 #include "SkClipStack.h"
2 #include "SkPath.h"
3 #include <new>
4
5 struct SkClipStack::Rec {
6 enum State {
7 kEmpty_State,
8 kRect_State,
9 kPath_State
10 };
11
12 SkPath fPath;
13 SkRect fRect;
14 int fSaveCount;
15 SkRegion::Op fOp;
16 State fState;
17
RecSkClipStack::Rec18 Rec(int saveCount, const SkRect& rect, SkRegion::Op op) : fRect(rect) {
19 fSaveCount = saveCount;
20 fOp = op;
21 fState = kRect_State;
22 }
23
RecSkClipStack::Rec24 Rec(int saveCount, const SkPath& path, SkRegion::Op op) : fPath(path) {
25 fSaveCount = saveCount;
26 fOp = op;
27 fState = kPath_State;
28 }
29
operator ==SkClipStack::Rec30 bool operator==(const Rec& b) const {
31 if (fSaveCount != b.fSaveCount || fOp != b.fOp || fState != b.fState) {
32 return false;
33 }
34 switch (fState) {
35 case kEmpty_State:
36 return true;
37 case kRect_State:
38 return fRect == b.fRect;
39 case kPath_State:
40 return fPath == b.fPath;
41 }
42 return false; // Silence the compiler.
43 }
44
operator !=SkClipStack::Rec45 bool operator!=(const Rec& b) const {
46 return !(*this == b);
47 }
48
49
50 /**
51 * Returns true if this Rec can be intersected in place with a new clip
52 */
canBeIntersectedSkClipStack::Rec53 bool canBeIntersected(int saveCount, SkRegion::Op op) const {
54 if (kEmpty_State == fState && (
55 SkRegion::kDifference_Op == op ||
56 SkRegion::kIntersect_Op == op)) {
57 return true;
58 }
59 return fSaveCount == saveCount &&
60 SkRegion::kIntersect_Op == fOp &&
61 SkRegion::kIntersect_Op == op;
62 }
63 };
64
SkClipStack()65 SkClipStack::SkClipStack() : fDeque(sizeof(Rec)) {
66 fSaveCount = 0;
67 }
68
SkClipStack(const SkClipStack & b)69 SkClipStack::SkClipStack(const SkClipStack& b) : fDeque(sizeof(Rec)) {
70 *this = b;
71 }
72
operator =(const SkClipStack & b)73 SkClipStack& SkClipStack::operator=(const SkClipStack& b) {
74 if (this == &b) {
75 return *this;
76 }
77 reset();
78
79 fSaveCount = b.fSaveCount;
80 SkDeque::F2BIter recIter(b.fDeque);
81 for (const Rec* rec = (const Rec*)recIter.next();
82 rec != NULL;
83 rec = (const Rec*)recIter.next()) {
84 new (fDeque.push_back()) Rec(*rec);
85 }
86
87 return *this;
88 }
89
operator ==(const SkClipStack & b) const90 bool SkClipStack::operator==(const SkClipStack& b) const {
91 if (fSaveCount != b.fSaveCount || fDeque.count() != b.fDeque.count()) {
92 return false;
93 }
94 SkDeque::F2BIter myIter(fDeque);
95 SkDeque::F2BIter bIter(b.fDeque);
96 const Rec* myRec = (const Rec*)myIter.next();
97 const Rec* bRec = (const Rec*)bIter.next();
98
99 while (myRec != NULL && bRec != NULL) {
100 if (*myRec != *bRec) {
101 return false;
102 }
103 myRec = (const Rec*)myIter.next();
104 bRec = (const Rec*)bIter.next();
105 }
106 return myRec == NULL && bRec == NULL;
107 }
108
reset()109 void SkClipStack::reset() {
110 // don't have a reset() on SkDeque, so fake it here
111 fDeque.~SkDeque();
112 new (&fDeque) SkDeque(sizeof(Rec));
113
114 fSaveCount = 0;
115 }
116
save()117 void SkClipStack::save() {
118 fSaveCount += 1;
119 }
120
restore()121 void SkClipStack::restore() {
122 fSaveCount -= 1;
123 while (!fDeque.empty()) {
124 Rec* rec = (Rec*)fDeque.back();
125 if (rec->fSaveCount <= fSaveCount) {
126 break;
127 }
128 rec->~Rec();
129 fDeque.pop_back();
130 }
131 }
132
clipDevRect(const SkRect & rect,SkRegion::Op op)133 void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op) {
134 Rec* rec = (Rec*)fDeque.back();
135 if (rec && rec->canBeIntersected(fSaveCount, op)) {
136 switch (rec->fState) {
137 case Rec::kEmpty_State:
138 return;
139 case Rec::kRect_State:
140 if (!rec->fRect.intersect(rect)) {
141 rec->fState = Rec::kEmpty_State;
142 }
143 return;
144 case Rec::kPath_State:
145 if (!SkRect::Intersects(rec->fPath.getBounds(), rect)) {
146 rec->fState = Rec::kEmpty_State;
147 return;
148 }
149 break;
150 }
151 }
152 new (fDeque.push_back()) Rec(fSaveCount, rect, op);
153 }
154
clipDevPath(const SkPath & path,SkRegion::Op op)155 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op) {
156 Rec* rec = (Rec*)fDeque.back();
157 if (rec && rec->canBeIntersected(fSaveCount, op)) {
158 const SkRect& pathBounds = path.getBounds();
159 switch (rec->fState) {
160 case Rec::kEmpty_State:
161 return;
162 case Rec::kRect_State:
163 if (!SkRect::Intersects(rec->fRect, pathBounds)) {
164 rec->fState = Rec::kEmpty_State;
165 return;
166 }
167 break;
168 case Rec::kPath_State:
169 if (!SkRect::Intersects(rec->fPath.getBounds(), pathBounds)) {
170 rec->fState = Rec::kEmpty_State;
171 return;
172 }
173 break;
174 }
175 }
176 new (fDeque.push_back()) Rec(fSaveCount, path, op);
177 }
178
179 ///////////////////////////////////////////////////////////////////////////////
180
B2FIter()181 SkClipStack::B2FIter::B2FIter() {
182 }
183
operator ==(const SkClipStack::B2FIter::Clip & a,const SkClipStack::B2FIter::Clip & b)184 bool operator==(const SkClipStack::B2FIter::Clip& a,
185 const SkClipStack::B2FIter::Clip& b) {
186 return a.fOp == b.fOp &&
187 ((a.fRect == NULL && b.fRect == NULL) || *a.fRect == *b.fRect) &&
188 ((a.fPath == NULL && b.fPath == NULL) || *a.fPath == *b.fPath);
189 }
190
operator !=(const SkClipStack::B2FIter::Clip & a,const SkClipStack::B2FIter::Clip & b)191 bool operator!=(const SkClipStack::B2FIter::Clip& a,
192 const SkClipStack::B2FIter::Clip& b) {
193 return !(a == b);
194 }
195
B2FIter(const SkClipStack & stack)196 SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) {
197 this->reset(stack);
198 }
199
next()200 const SkClipStack::B2FIter::Clip* SkClipStack::B2FIter::next() {
201 const SkClipStack::Rec* rec = (const SkClipStack::Rec*)fIter.next();
202 if (NULL == rec) {
203 return NULL;
204 }
205
206 switch (rec->fState) {
207 case SkClipStack::Rec::kEmpty_State:
208 fClip.fRect = NULL;
209 fClip.fPath = NULL;
210 break;
211 case SkClipStack::Rec::kRect_State:
212 fClip.fRect = &rec->fRect;
213 fClip.fPath = NULL;
214 break;
215 case SkClipStack::Rec::kPath_State:
216 fClip.fRect = NULL;
217 fClip.fPath = &rec->fPath;
218 break;
219 }
220 fClip.fOp = rec->fOp;
221 return &fClip;
222 }
223
reset(const SkClipStack & stack)224 void SkClipStack::B2FIter::reset(const SkClipStack& stack) {
225 fIter.reset(stack.fDeque);
226 }
227