• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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