Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1926)

Side by Side Diff: include/core/SkClipStack.h

Issue 163683002: Store SkRRects in SkClipStack (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: fix unhandled enum value warning in unit test Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/core/SkCanvas.h ('k') | src/core/SkCanvas.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #ifndef SkClipStack_DEFINED 8 #ifndef SkClipStack_DEFINED
9 #define SkClipStack_DEFINED 9 #define SkClipStack_DEFINED
10 10
11 #include "SkDeque.h" 11 #include "SkDeque.h"
12 #include "SkPath.h" 12 #include "SkPath.h"
13 #include "SkRect.h" 13 #include "SkRect.h"
14 #include "SkRRect.h"
14 #include "SkRegion.h" 15 #include "SkRegion.h"
15 #include "SkTDArray.h" 16 #include "SkTDArray.h"
16 17
17 18
18 // Because a single save/restore state can have multiple clips, this class 19 // Because a single save/restore state can have multiple clips, this class
19 // stores the stack depth (fSaveCount) and clips (fDeque) separately. 20 // stores the stack depth (fSaveCount) and clips (fDeque) separately.
20 // Each clip in fDeque stores the stack state to which it belongs 21 // Each clip in fDeque stores the stack state to which it belongs
21 // (i.e., the fSaveCount in force when it was added). Restores are thus 22 // (i.e., the fSaveCount in force when it was added). Restores are thus
22 // implemented by removing clips from fDeque that have an fSaveCount larger 23 // implemented by removing clips from fDeque that have an fSaveCount larger
23 // then the freshly decremented count. 24 // then the freshly decremented count.
(...skipping 10 matching lines...) Expand all
34 kInsideOut_BoundsType 35 kInsideOut_BoundsType
35 }; 36 };
36 37
37 class Element { 38 class Element {
38 public: 39 public:
39 enum Type { 40 enum Type {
40 //!< This element makes the clip empty (regardless of previous eleme nts). 41 //!< This element makes the clip empty (regardless of previous eleme nts).
41 kEmpty_Type, 42 kEmpty_Type,
42 //!< This element combines a rect with the current clip using a set operation 43 //!< This element combines a rect with the current clip using a set operation
43 kRect_Type, 44 kRect_Type,
45 //!< This element combines a round-rect with the current clip using a set operation
46 kRRect_Type,
44 //!< This element combines a path with the current clip using a set operation 47 //!< This element combines a path with the current clip using a set operation
45 kPath_Type, 48 kPath_Type,
46 }; 49 };
47 50
48 Element() { 51 Element() {
49 this->initCommon(0, SkRegion::kReplace_Op, false); 52 this->initCommon(0, SkRegion::kReplace_Op, false);
50 this->setEmpty(); 53 this->setEmpty();
51 } 54 }
52 55
53 Element(const SkRect& rect, SkRegion::Op op, bool doAA) { 56 Element(const SkRect& rect, SkRegion::Op op, bool doAA) {
54 this->initRect(0, rect, op, doAA); 57 this->initRect(0, rect, op, doAA);
55 } 58 }
56 59
60 Element(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
61 this->initRRect(0, rrect, op, doAA);
62 }
63
57 Element(const SkPath& path, SkRegion::Op op, bool doAA) { 64 Element(const SkPath& path, SkRegion::Op op, bool doAA) {
58 this->initPath(0, path, op, doAA); 65 this->initPath(0, path, op, doAA);
59 } 66 }
60 67
61 bool operator== (const Element& element) const { 68 bool operator== (const Element& element) const;
62 if (this == &element) {
63 return true;
64 }
65 if (fOp != element.fOp ||
66 fType != element.fType ||
67 fDoAA != element.fDoAA ||
68 fSaveCount != element.fSaveCount) {
69 return false;
70 }
71 switch (fType) {
72 case kPath_Type:
73 return fPath == element.fPath;
74 case kRect_Type:
75 return fRect == element.fRect;
76 case kEmpty_Type:
77 return true;
78 default:
79 SkDEBUGFAIL("Unexpected type.");
80 return false;
81 }
82 }
83 bool operator!= (const Element& element) const { return !(*this == eleme nt); } 69 bool operator!= (const Element& element) const { return !(*this == eleme nt); }
84 70
85 //!< Call to get the type of the clip element. 71 //!< Call to get the type of the clip element.
86 Type getType() const { return fType; } 72 Type getType() const { return fType; }
87 73
88 //!< Call if getType() is kPath to get the path. 74 //!< Call if getType() is kPath to get the path.
89 const SkPath& getPath() const { return fPath; } 75 const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return fP ath; }
76
77 //!< Call if getType() is kRRect to get the round-rect.
78 const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return fRRect; }
90 79
91 //!< Call if getType() is kRect to get the rect. 80 //!< Call if getType() is kRect to get the rect.
92 const SkRect& getRect() const { return fRect; } 81 const SkRect& getRect() const { SkASSERT(kRect_Type == fType); return fR ect; }
93 82
94 //!< Call if getType() is not kEmpty to get the set operation used to co mbine this element. 83 //!< Call if getType() is not kEmpty to get the set operation used to co mbine this element.
95 SkRegion::Op getOp() const { return fOp; } 84 SkRegion::Op getOp() const { return fOp; }
96 85
86 //!< Call to get the element as a path, regardless of its type.
87 void asPath(SkPath* path) const;
88
97 /** If getType() is not kEmpty this indicates whether the clip shape sho uld be anti-aliased 89 /** If getType() is not kEmpty this indicates whether the clip shape sho uld be anti-aliased
98 when it is rasterized. */ 90 when it is rasterized. */
99 bool isAA() const { return fDoAA; } 91 bool isAA() const { return fDoAA; }
100 92
101 //!< Inverts the fill of the clip shape. Note that a kEmpty element rema ins kEmpty. 93 //!< Inverts the fill of the clip shape. Note that a kEmpty element rema ins kEmpty.
102 void invertShapeFillType(); 94 void invertShapeFillType();
103 95
104 //!< Sets the set operation represented by the element. 96 //!< Sets the set operation represented by the element.
105 void setOp(SkRegion::Op op) { fOp = op; } 97 void setOp(SkRegion::Op op) { fOp = op; }
106 98
107 /** The GenID can be used by clip stack clients to cache representations of the clip. The 99 /** The GenID can be used by clip stack clients to cache representations of the clip. The
108 ID corresponds to the set of clip elements up to and including this element within the 100 ID corresponds to the set of clip elements up to and including this element within the
109 stack not to the element itself. That is the same clip path in diffe rent stacks will 101 stack not to the element itself. That is the same clip path in diffe rent stacks will
110 have a different ID since the elements produce different clip result in the context of 102 have a different ID since the elements produce different clip result in the context of
111 their stacks. */ 103 their stacks. */
112 int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGe nID; } 104 int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGe nID; }
113 105
114 /** 106 /**
115 * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape 107 * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape
116 * is inverse filled is not considered.) 108 * is inverse filled is not considered.)
117 */ 109 */
118 const SkRect& getBounds() const { 110 const SkRect& getBounds() const {
119 static const SkRect kEmpty = { 0, 0, 0, 0 }; 111 static const SkRect kEmpty = { 0, 0, 0, 0 };
120 switch (fType) { 112 switch (fType) {
121 case kRect_Type: 113 case kRect_Type:
122 return fRect; 114 return fRect;
115 case kRRect_Type:
116 return fRRect.getBounds();
123 case kPath_Type: 117 case kPath_Type:
124 return fPath.getBounds(); 118 return fPath.getBounds();
125 case kEmpty_Type: 119 case kEmpty_Type:
126 return kEmpty; 120 return kEmpty;
127 default: 121 default:
128 SkDEBUGFAIL("Unexpected type."); 122 SkDEBUGFAIL("Unexpected type.");
129 return kEmpty; 123 return kEmpty;
130 } 124 }
131 } 125 }
132 126
133 /** 127 /**
134 * Conservatively checks whether the clip shape contains the rect param. (Whether the shape 128 * Conservatively checks whether the clip shape contains the rect param. (Whether the shape
135 * is inverse filled is not considered.) 129 * is inverse filled is not considered.)
136 */ 130 */
137 bool contains(const SkRect& rect) const { 131 bool contains(const SkRect& rect) const {
138 switch (fType) { 132 switch (fType) {
139 case kRect_Type: 133 case kRect_Type:
140 return fRect.contains(rect); 134 return fRect.contains(rect);
135 case kRRect_Type:
136 return fRRect.contains(rect);
141 case kPath_Type: 137 case kPath_Type:
142 return fPath.conservativelyContainsRect(rect); 138 return fPath.conservativelyContainsRect(rect);
143 case kEmpty_Type: 139 case kEmpty_Type:
144 return false; 140 return false;
145 default: 141 default:
146 SkDEBUGFAIL("Unexpected type."); 142 SkDEBUGFAIL("Unexpected type.");
147 return false; 143 return false;
148 } 144 }
149 } 145 }
150 146
151 /** 147 /**
152 * Is the clip shape inverse filled. 148 * Is the clip shape inverse filled.
153 */ 149 */
154 bool isInverseFilled() const { 150 bool isInverseFilled() const {
155 return kPath_Type == fType && fPath.isInverseFillType(); 151 return kPath_Type == fType && fPath.isInverseFillType();
156 } 152 }
157 153
158 private: 154 private:
159 friend class SkClipStack; 155 friend class SkClipStack;
160 156
161 SkPath fPath; 157 SkPath fPath;
162 SkRect fRect; 158 SkRect fRect;
159 SkRRect fRRect;
163 int fSaveCount; // save count of stack when this element was added. 160 int fSaveCount; // save count of stack when this element was added.
164 SkRegion::Op fOp; 161 SkRegion::Op fOp;
165 Type fType; 162 Type fType;
166 bool fDoAA; 163 bool fDoAA;
167 164
168 /* fFiniteBoundType and fFiniteBound are used to incrementally update th e clip stack's 165 /* fFiniteBoundType and fFiniteBound are used to incrementally update th e clip stack's
169 bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound repr esents the 166 bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound repr esents the
170 conservative bounding box of the pixels that aren't clipped (i.e., an y pixels that can be 167 conservative bounding box of the pixels that aren't clipped (i.e., an y pixels that can be
171 drawn to are inside the bound). When fFiniteBoundType is kInsideOut_B oundsType (which 168 drawn to are inside the bound). When fFiniteBoundType is kInsideOut_B oundsType (which
172 occurs when a clip is inverse filled), fFiniteBound represents the co nservative bounding 169 occurs when a clip is inverse filled), fFiniteBound represents the co nservative bounding
173 box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside 170 box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside
174 the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the 171 the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the
175 infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we 172 infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we
176 can capture the cancelling out of the extensions to infinity when two inverse filled 173 can capture the cancelling out of the extensions to infinity when two inverse filled
177 clips are Booleaned together. */ 174 clips are Booleaned together. */
178 SkClipStack::BoundsType fFiniteBoundType; 175 SkClipStack::BoundsType fFiniteBoundType;
179 SkRect fFiniteBound; 176 SkRect fFiniteBound;
180 177
181 // When element is applied to the previous elements in the stack is the result known to be 178 // When element is applied to the previous elements in the stack is the result known to be
182 // equivalent to a single rect intersection? IIOW, is the clip effective ly a rectangle. 179 // equivalent to a single rect intersection? IIOW, is the clip effective ly a rectangle.
183 bool fIsIntersectionOfRects; 180 bool fIsIntersectionOfRects;
184 181
185 int fGenID; 182 int fGenID;
186 183
187 Element(int saveCount) { 184 Element(int saveCount) {
188 this->initCommon(saveCount, SkRegion::kReplace_Op, false); 185 this->initCommon(saveCount, SkRegion::kReplace_Op, false);
189 this->setEmpty(); 186 this->setEmpty();
190 } 187 }
191 188
189 Element(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
190 this->initRRect(saveCount, rrect, op, doAA);
191 }
192
192 Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) { 193 Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
193 this->initRect(saveCount, rect, op, doAA); 194 this->initRect(saveCount, rect, op, doAA);
194 } 195 }
195 196
196 Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) { 197 Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
197 this->initPath(saveCount, path, op, doAA); 198 this->initPath(saveCount, path, op, doAA);
198 } 199 }
199 200
200 void initCommon(int saveCount, SkRegion::Op op, bool doAA) { 201 void initCommon(int saveCount, SkRegion::Op op, bool doAA) {
201 fSaveCount = saveCount; 202 fSaveCount = saveCount;
202 fOp = op; 203 fOp = op;
203 fDoAA = doAA; 204 fDoAA = doAA;
204 // A default of inside-out and empty bounds means the bounds are eff ectively void as it 205 // A default of inside-out and empty bounds means the bounds are eff ectively void as it
205 // indicates that nothing is known to be outside the clip. 206 // indicates that nothing is known to be outside the clip.
206 fFiniteBoundType = kInsideOut_BoundsType; 207 fFiniteBoundType = kInsideOut_BoundsType;
207 fFiniteBound.setEmpty(); 208 fFiniteBound.setEmpty();
208 fIsIntersectionOfRects = false; 209 fIsIntersectionOfRects = false;
209 fGenID = kInvalidGenID; 210 fGenID = kInvalidGenID;
210 } 211 }
211 212
212 void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool d oAA) { 213 void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool d oAA) {
213 fRect = rect; 214 fRect = rect;
214 fType = kRect_Type; 215 fType = kRect_Type;
215 this->initCommon(saveCount, op, doAA); 216 this->initCommon(saveCount, op, doAA);
216 } 217 }
217 218
218 void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool d oAA) { 219 void initRRect(int saveCount, const SkRRect& rrect, SkRegion::Op op, boo l doAA) {
219 fPath = path; 220 if (rrect.isRect()) {
220 fType = kPath_Type; 221 fRect = rrect.getBounds();
222 fType = kRect_Type;
223 } else {
224 fRRect = rrect;
225 fType = kRRect_Type;
226 }
221 this->initCommon(saveCount, op, doAA); 227 this->initCommon(saveCount, op, doAA);
222 } 228 }
223 229
230 void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool d oAA);
231
224 void setEmpty() { 232 void setEmpty() {
225 fType = kEmpty_Type; 233 fType = kEmpty_Type;
226 fFiniteBound.setEmpty(); 234 fFiniteBound.setEmpty();
227 fFiniteBoundType = kNormal_BoundsType; 235 fFiniteBoundType = kNormal_BoundsType;
228 fIsIntersectionOfRects = false; 236 fIsIntersectionOfRects = false;
229 fRect.setEmpty(); 237 fRect.setEmpty();
238 fRRect.setEmpty();
230 fPath.reset(); 239 fPath.reset();
231 fGenID = kEmptyGenID; 240 fGenID = kEmptyGenID;
241 SkDEBUGCODE(this->checkEmpty();)
232 } 242 }
233 243
234 // All Element methods below are only used within SkClipStack.cpp 244 // All Element methods below are only used within SkClipStack.cpp
235 inline void checkEmpty() const; 245 inline void checkEmpty() const;
236 inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) cons t; 246 inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) cons t;
237 /* This method checks to see if two rect clips can be safely merged into one. The issue here 247 /* This method checks to see if two rect clips can be safely merged into one. The issue here
238 is that to be strictly correct all the edges of the resulting rect mus t have the same 248 is that to be strictly correct all the edges of the resulting rect mus t have the same
239 anti-aliasing. */ 249 anti-aliasing. */
240 bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const; 250 bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const;
241 /** Determines possible finite bounds for the Element given the previous element of the 251 /** Determines possible finite bounds for the Element given the previous element of the
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 * is not contained by the clip. 308 * is not contained by the clip.
299 */ 309 */
300 bool quickContains(const SkRect& devRect) const; 310 bool quickContains(const SkRect& devRect) const;
301 311
302 void clipDevRect(const SkIRect& ir, SkRegion::Op op) { 312 void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
303 SkRect r; 313 SkRect r;
304 r.set(ir); 314 r.set(ir);
305 this->clipDevRect(r, op, false); 315 this->clipDevRect(r, op, false);
306 } 316 }
307 void clipDevRect(const SkRect&, SkRegion::Op, bool doAA); 317 void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
318 void clipDevRRect(const SkRRect&, SkRegion::Op, bool doAA);
308 void clipDevPath(const SkPath&, SkRegion::Op, bool doAA); 319 void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
309 // An optimized version of clipDevRect(emptyRect, kIntersect, ...) 320 // An optimized version of clipDevRect(emptyRect, kIntersect, ...)
310 void clipEmpty(); 321 void clipEmpty();
311 322
312 /** 323 /**
313 * isWideOpen returns true if the clip state corresponds to the infinite 324 * isWideOpen returns true if the clip state corresponds to the infinite
314 * plane (i.e., draws are not limited at all) 325 * plane (i.e., draws are not limited at all)
315 */ 326 */
316 bool isWideOpen() const; 327 bool isWideOpen() const;
317 328
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 432
422 SkDeque fDeque; 433 SkDeque fDeque;
423 int fSaveCount; 434 int fSaveCount;
424 435
425 // Generation ID for the clip stack. This is incremented for each 436 // Generation ID for the clip stack. This is incremented for each
426 // clipDevRect and clipDevPath call. 0 is reserved to indicate an 437 // clipDevRect and clipDevPath call. 0 is reserved to indicate an
427 // invalid ID. 438 // invalid ID.
428 static int32_t gGenID; 439 static int32_t gGenID;
429 440
430 /** 441 /**
442 * Helper for clipDevPath, etc.
443 */
444 void pushElement(const Element& element);
445
446 /**
431 * Restore the stack back to the specified save count. 447 * Restore the stack back to the specified save count.
432 */ 448 */
433 void restoreTo(int saveCount); 449 void restoreTo(int saveCount);
434 450
435 /** 451 /**
436 * Return the next unique generation ID. 452 * Return the next unique generation ID.
437 */ 453 */
438 static int32_t GetNextGenID(); 454 static int32_t GetNextGenID();
439 }; 455 };
440 456
441 #endif 457 #endif
OLDNEW
« no previous file with comments | « include/core/SkCanvas.h ('k') | src/core/SkCanvas.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698