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