blob: 4243cee7b06fd84d2d89dade74992c70f9db8f3e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@google.com5c3d1472011-02-22 19:12:23 +00008#ifndef SkClipStack_DEFINED
9#define SkClipStack_DEFINED
10
11#include "SkDeque.h"
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000012#include "SkPath.h"
13#include "SkRect.h"
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +000014#include "SkRRect.h"
reed@google.com5c3d1472011-02-22 19:12:23 +000015#include "SkRegion.h"
robertphillips@google.com46f93502012-08-07 15:38:08 +000016#include "SkTDArray.h"
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +000017#include "SkTLazy.h"
reed@google.com5c3d1472011-02-22 19:12:23 +000018
fmalitac3b589a2014-06-05 12:40:07 -070019class SkCanvasClipVisitor;
reed@google.com5c3d1472011-02-22 19:12:23 +000020
robertphillips@google.com4c2a2f72012-07-24 22:07:50 +000021// Because a single save/restore state can have multiple clips, this class
22// stores the stack depth (fSaveCount) and clips (fDeque) separately.
23// Each clip in fDeque stores the stack state to which it belongs
24// (i.e., the fSaveCount in force when it was added). Restores are thus
25// implemented by removing clips from fDeque that have an fSaveCount larger
26// then the freshly decremented count.
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000027class SK_API SkClipStack {
reed@google.com5c3d1472011-02-22 19:12:23 +000028public:
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000029 enum BoundsType {
30 // The bounding box contains all the pixels that can be written to
31 kNormal_BoundsType,
32 // The bounding box contains all the pixels that cannot be written to.
33 // The real bound extends out to infinity and all the pixels outside
34 // of the bound can be written to. Note that some of the pixels inside
35 // the bound may also be writeable but all pixels that cannot be
36 // written to are guaranteed to be inside.
37 kInsideOut_BoundsType
38 };
39
40 class Element {
41 public:
42 enum Type {
43 //!< This element makes the clip empty (regardless of previous elements).
44 kEmpty_Type,
45 //!< This element combines a rect with the current clip using a set operation
46 kRect_Type,
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +000047 //!< This element combines a round-rect with the current clip using a set operation
48 kRRect_Type,
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000049 //!< This element combines a path with the current clip using a set operation
50 kPath_Type,
51 };
52
53 Element() {
54 this->initCommon(0, SkRegion::kReplace_Op, false);
55 this->setEmpty();
56 }
57
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +000058 Element(const Element&);
59
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000060 Element(const SkRect& rect, SkRegion::Op op, bool doAA) {
61 this->initRect(0, rect, op, doAA);
62 }
63
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +000064 Element(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
65 this->initRRect(0, rrect, op, doAA);
66 }
67
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000068 Element(const SkPath& path, SkRegion::Op op, bool doAA) {
69 this->initPath(0, path, op, doAA);
70 }
71
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +000072 bool operator== (const Element& element) const;
bsalomon@google.com8182fa02012-12-04 14:06:06 +000073 bool operator!= (const Element& element) const { return !(*this == element); }
74
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000075 //!< Call to get the type of the clip element.
76 Type getType() const { return fType; }
77
fmalitac3b589a2014-06-05 12:40:07 -070078 //!< Call to get the save count associated with this clip element.
79 int getSaveCount() const { return fSaveCount; }
80
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000081 //!< Call if getType() is kPath to get the path.
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +000082 const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return *fPath.get(); }
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +000083
84 //!< Call if getType() is kRRect to get the round-rect.
85 const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return fRRect; }
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000086
87 //!< Call if getType() is kRect to get the rect.
commit-bot@chromium.org032a52f2014-02-21 20:09:13 +000088 const SkRect& getRect() const {
89 SkASSERT(kRect_Type == fType && (fRRect.isRect() || fRRect.isEmpty()));
90 return fRRect.getBounds();
91 }
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000092
93 //!< Call if getType() is not kEmpty to get the set operation used to combine this element.
94 SkRegion::Op getOp() const { return fOp; }
95
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +000096 //!< Call to get the element as a path, regardless of its type.
97 void asPath(SkPath* path) const;
98
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +000099 /** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased
100 when it is rasterized. */
101 bool isAA() const { return fDoAA; }
102
bsalomon@google.comc6b3e482012-12-07 20:43:52 +0000103 //!< Inverts the fill of the clip shape. Note that a kEmpty element remains kEmpty.
104 void invertShapeFillType();
105
106 //!< Sets the set operation represented by the element.
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000107 void setOp(SkRegion::Op op) { fOp = op; }
108
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000109 /** The GenID can be used by clip stack clients to cache representations of the clip. The
110 ID corresponds to the set of clip elements up to and including this element within the
111 stack not to the element itself. That is the same clip path in different stacks will
112 have a different ID since the elements produce different clip result in the context of
113 their stacks. */
commit-bot@chromium.orgd3e58422013-11-05 15:03:08 +0000114 int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGenID; }
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000115
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000116 /**
117 * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape
118 * is inverse filled is not considered.)
119 */
120 const SkRect& getBounds() const {
121 static const SkRect kEmpty = { 0, 0, 0, 0 };
122 switch (fType) {
commit-bot@chromium.org032a52f2014-02-21 20:09:13 +0000123 case kRect_Type: // fallthrough
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000124 case kRRect_Type:
125 return fRRect.getBounds();
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000126 case kPath_Type:
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +0000127 return fPath.get()->getBounds();
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000128 case kEmpty_Type:
129 return kEmpty;
130 default:
131 SkDEBUGFAIL("Unexpected type.");
132 return kEmpty;
133 }
134 }
135
136 /**
137 * Conservatively checks whether the clip shape contains the rect param. (Whether the shape
138 * is inverse filled is not considered.)
139 */
140 bool contains(const SkRect& rect) const {
141 switch (fType) {
142 case kRect_Type:
commit-bot@chromium.org032a52f2014-02-21 20:09:13 +0000143 return this->getRect().contains(rect);
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000144 case kRRect_Type:
145 return fRRect.contains(rect);
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000146 case kPath_Type:
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +0000147 return fPath.get()->conservativelyContainsRect(rect);
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000148 case kEmpty_Type:
149 return false;
150 default:
151 SkDEBUGFAIL("Unexpected type.");
152 return false;
153 }
154 }
155
156 /**
157 * Is the clip shape inverse filled.
158 */
159 bool isInverseFilled() const {
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +0000160 return kPath_Type == fType && fPath.get()->isInverseFillType();
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000161 }
162
fmalitac3b589a2014-06-05 12:40:07 -0700163 /**
164 * Replay this clip into the visitor.
165 */
166 void replay(SkCanvasClipVisitor*) const;
167
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000168 private:
169 friend class SkClipStack;
170
commit-bot@chromium.org6f954b92014-02-27 17:39:46 +0000171 SkTLazy<SkPath> fPath;
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000172 SkRRect fRRect;
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000173 int fSaveCount; // save count of stack when this element was added.
174 SkRegion::Op fOp;
175 Type fType;
176 bool fDoAA;
177
178 /* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
179 bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the
180 conservative bounding box of the pixels that aren't clipped (i.e., any pixels that can be
181 drawn to are inside the bound). When fFiniteBoundType is kInsideOut_BoundsType (which
182 occurs when a clip is inverse filled), fFiniteBound represents the conservative bounding
183 box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside
184 the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the
185 infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we
186 can capture the cancelling out of the extensions to infinity when two inverse filled
187 clips are Booleaned together. */
188 SkClipStack::BoundsType fFiniteBoundType;
189 SkRect fFiniteBound;
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +0000190
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000191 // When element is applied to the previous elements in the stack is the result known to be
192 // equivalent to a single rect intersection? IIOW, is the clip effectively a rectangle.
193 bool fIsIntersectionOfRects;
194
195 int fGenID;
196
197 Element(int saveCount) {
198 this->initCommon(saveCount, SkRegion::kReplace_Op, false);
199 this->setEmpty();
200 }
201
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000202 Element(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
203 this->initRRect(saveCount, rrect, op, doAA);
204 }
205
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000206 Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
207 this->initRect(saveCount, rect, op, doAA);
208 }
209
210 Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
211 this->initPath(saveCount, path, op, doAA);
212 }
213
214 void initCommon(int saveCount, SkRegion::Op op, bool doAA) {
215 fSaveCount = saveCount;
216 fOp = op;
217 fDoAA = doAA;
218 // A default of inside-out and empty bounds means the bounds are effectively void as it
219 // indicates that nothing is known to be outside the clip.
220 fFiniteBoundType = kInsideOut_BoundsType;
221 fFiniteBound.setEmpty();
222 fIsIntersectionOfRects = false;
223 fGenID = kInvalidGenID;
224 }
225
226 void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
commit-bot@chromium.org032a52f2014-02-21 20:09:13 +0000227 fRRect.setRect(rect);
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000228 fType = kRect_Type;
229 this->initCommon(saveCount, op, doAA);
230 }
231
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000232 void initRRect(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA) {
commit-bot@chromium.org032a52f2014-02-21 20:09:13 +0000233 SkRRect::Type type = rrect.getType();
234 fRRect = rrect;
235 if (SkRRect::kRect_Type == type || SkRRect::kEmpty_Type == type) {
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000236 fType = kRect_Type;
237 } else {
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000238 fType = kRRect_Type;
239 }
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000240 this->initCommon(saveCount, op, doAA);
241 }
242
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000243 void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA);
244
commit-bot@chromium.org9cb671a2014-02-16 14:45:45 +0000245 void setEmpty();
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000246
247 // All Element methods below are only used within SkClipStack.cpp
248 inline void checkEmpty() const;
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000249 inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const;
250 /* This method checks to see if two rect clips can be safely merged into one. The issue here
skia.committer@gmail.comc3d7d902012-11-30 02:01:24 +0000251 is that to be strictly correct all the edges of the resulting rect must have the same
bsalomon@google.com8a98e3b2012-11-29 21:05:13 +0000252 anti-aliasing. */
253 bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const;
254 /** Determines possible finite bounds for the Element given the previous element of the
255 stack */
256 void updateBoundAndGenID(const Element* prior);
257 // The different combination of fill & inverse fill when combining bounding boxes
258 enum FillCombo {
259 kPrev_Cur_FillCombo,
260 kPrev_InvCur_FillCombo,
261 kInvPrev_Cur_FillCombo,
262 kInvPrev_InvCur_FillCombo
263 };
264 // per-set operation functions used by updateBoundAndGenID().
265 inline void combineBoundsDiff(FillCombo combination, const SkRect& prevFinite);
266 inline void combineBoundsXOR(int combination, const SkRect& prevFinite);
267 inline void combineBoundsUnion(int combination, const SkRect& prevFinite);
268 inline void combineBoundsIntersection(int combination, const SkRect& prevFinite);
269 inline void combineBoundsRevDiff(int combination, const SkRect& prevFinite);
270 };
271
reed@google.com5c3d1472011-02-22 19:12:23 +0000272 SkClipStack();
vandebo@chromium.org1e1c36f2011-05-03 16:26:09 +0000273 SkClipStack(const SkClipStack& b);
robertphillips@google.comcc6493b2012-07-26 18:39:13 +0000274 explicit SkClipStack(const SkRect& r);
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000275 explicit SkClipStack(const SkIRect& r);
vandebo@chromium.org610f7162012-03-14 18:34:15 +0000276 ~SkClipStack();
reed@google.com5c3d1472011-02-22 19:12:23 +0000277
vandebo@chromium.org1e1c36f2011-05-03 16:26:09 +0000278 SkClipStack& operator=(const SkClipStack& b);
279 bool operator==(const SkClipStack& b) const;
280 bool operator!=(const SkClipStack& b) const { return !(*this == b); }
281
reed@google.com5c3d1472011-02-22 19:12:23 +0000282 void reset();
283
284 int getSaveCount() const { return fSaveCount; }
285 void save();
286 void restore();
287
robertphillips@google.com607fe072012-07-24 13:54:00 +0000288 /**
289 * getBounds places the current finite bound in its first parameter. In its
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000290 * second, it indicates which kind of bound is being returned. If
robertphillips@google.com7b112892012-07-31 15:18:21 +0000291 * 'canvFiniteBound' is a normal bounding box then it encloses all writeable
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000292 * pixels. If 'canvFiniteBound' is an inside out bounding box then it
robertphillips@google.com607fe072012-07-24 13:54:00 +0000293 * encloses all the un-writeable pixels and the true/normal bound is the
robertphillips@google.com4c2a2f72012-07-24 22:07:50 +0000294 * infinite plane. isIntersectionOfRects is an optional parameter
robertphillips@google.com7b112892012-07-31 15:18:21 +0000295 * that is true if 'canvFiniteBound' resulted from an intersection of rects.
robertphillips@google.com607fe072012-07-24 13:54:00 +0000296 */
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000297 void getBounds(SkRect* canvFiniteBound,
robertphillips@google.com4c2a2f72012-07-24 22:07:50 +0000298 BoundsType* boundType,
299 bool* isIntersectionOfRects = NULL) const;
robertphillips@google.com607fe072012-07-24 13:54:00 +0000300
bsalomon@google.com3ab43d52012-10-11 19:39:09 +0000301 /**
302 * Takes an input rect in device space and conservatively clips it to the
303 * clip-stack. If false is returned then the rect does not intersect the
304 * clip and is unmodified.
305 */
306 bool intersectRectWithClip(SkRect* devRect) const;
307
junov@chromium.org8cdf0f52012-12-12 17:58:15 +0000308 /**
309 * Returns true if the input rect in device space is entirely contained
310 * by the clip. A return value of false does not guarantee that the rect
311 * is not contained by the clip.
312 */
313 bool quickContains(const SkRect& devRect) const;
314
reed@google.com115d9312012-05-16 18:50:40 +0000315 void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
reed@google.com5c3d1472011-02-22 19:12:23 +0000316 SkRect r;
317 r.set(ir);
reed@google.com00177082011-10-12 14:34:30 +0000318 this->clipDevRect(r, op, false);
reed@google.com5c3d1472011-02-22 19:12:23 +0000319 }
reed@google.com00177082011-10-12 14:34:30 +0000320 void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000321 void clipDevRRect(const SkRRect&, SkRegion::Op, bool doAA);
reed@google.com00177082011-10-12 14:34:30 +0000322 void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
reed@google.com0557d9e2012-08-16 15:59:59 +0000323 // An optimized version of clipDevRect(emptyRect, kIntersect, ...)
324 void clipEmpty();
reed@google.com5c3d1472011-02-22 19:12:23 +0000325
robertphillips@google.comcc6493b2012-07-26 18:39:13 +0000326 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000327 * isWideOpen returns true if the clip state corresponds to the infinite
robertphillips@google.comcc6493b2012-07-26 18:39:13 +0000328 * plane (i.e., draws are not limited at all)
329 */
330 bool isWideOpen() const;
331
robertphillips@google.com46f93502012-08-07 15:38:08 +0000332 /**
robertphillips@google.com46f93502012-08-07 15:38:08 +0000333 * The generation ID has three reserved values to indicate special
bsalomon@google.come8ca6c62012-11-07 21:19:10 +0000334 * (potentially ignorable) cases
robertphillips@google.com46f93502012-08-07 15:38:08 +0000335 */
commit-bot@chromium.orgd3e58422013-11-05 15:03:08 +0000336 static const int32_t kInvalidGenID = 0; //!< Invalid id that is never returned by
337 //!< SkClipStack. Useful when caching clips
338 //!< based on GenID.
robertphillips@google.com46f93502012-08-07 15:38:08 +0000339 static const int32_t kEmptyGenID = 1; // no pixels writeable
340 static const int32_t kWideOpenGenID = 2; // all pixels writeable
341
robertphillips@google.com73e71022012-08-09 18:10:49 +0000342 int32_t getTopmostGenID() const;
343
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000344public:
345 class Iter {
reed@google.com5c3d1472011-02-22 19:12:23 +0000346 public:
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000347 enum IterStart {
robertphillips@google.com80214e22012-07-20 15:33:18 +0000348 kBottom_IterStart = SkDeque::Iter::kFront_IterStart,
349 kTop_IterStart = SkDeque::Iter::kBack_IterStart
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000350 };
351
bsalomon@google.comd302f142011-03-03 13:54:13 +0000352 /**
353 * Creates an uninitialized iterator. Must be reset()
354 */
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000355 Iter();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000356
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000357 Iter(const SkClipStack& stack, IterStart startLoc);
reed@google.com5c3d1472011-02-22 19:12:23 +0000358
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000359 /**
360 * Return the clip element for this iterator. If next()/prev() returns NULL, then the
361 * iterator is done.
362 */
363 const Element* next();
364 const Element* prev();
reed@google.com5c3d1472011-02-22 19:12:23 +0000365
366 /**
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000367 * Moves the iterator to the topmost element with the specified RegionOp and returns that
368 * element. If no clip element with that op is found, the first element is returned.
reed@google.com5c3d1472011-02-22 19:12:23 +0000369 */
bsalomon@google.com8182fa02012-12-04 14:06:06 +0000370 const Element* skipToTopmost(SkRegion::Op op);
robertphillips@google.com5836b6d2012-07-18 12:06:15 +0000371
372 /**
bsalomon@google.comd302f142011-03-03 13:54:13 +0000373 * Restarts the iterator on a clip stack.
374 */
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000375 void reset(const SkClipStack& stack, IterStart startLoc);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000376
reed@google.com5c3d1472011-02-22 19:12:23 +0000377 private:
robertphillips@google.com5836b6d2012-07-18 12:06:15 +0000378 const SkClipStack* fStack;
robertphillips@google.com5836b6d2012-07-18 12:06:15 +0000379 SkDeque::Iter fIter;
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000380 };
381
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000382 /**
robertphillips@google.com80214e22012-07-20 15:33:18 +0000383 * The B2TIter iterates from the bottom of the stack to the top.
384 * It inherits privately from Iter to prevent access to reverse iteration.
385 */
386 class B2TIter : private Iter {
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000387 public:
robertphillips@google.com80214e22012-07-20 15:33:18 +0000388 B2TIter() {}
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000389
390 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000391 * Wrap Iter's 2 parameter ctor to force initialization to the
robertphillips@google.com80214e22012-07-20 15:33:18 +0000392 * beginning of the deque/bottom of the stack
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000393 */
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000394 B2TIter(const SkClipStack& stack)
robertphillips@google.com80214e22012-07-20 15:33:18 +0000395 : INHERITED(stack, kBottom_IterStart) {
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000396 }
397
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000398 using Iter::next;
399
400 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000401 * Wrap Iter::reset to force initialization to the
robertphillips@google.com80214e22012-07-20 15:33:18 +0000402 * beginning of the deque/bottom of the stack
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000403 */
404 void reset(const SkClipStack& stack) {
robertphillips@google.com80214e22012-07-20 15:33:18 +0000405 this->INHERITED::reset(stack, kBottom_IterStart);
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000406 }
407
408 private:
409
410 typedef Iter INHERITED;
reed@google.com5c3d1472011-02-22 19:12:23 +0000411 };
412
robertphillips@google.com607fe072012-07-24 13:54:00 +0000413 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000414 * GetConservativeBounds returns a conservative bound of the current clip.
415 * Since this could be the infinite plane (if inverse fills were involved) the
416 * maxWidth and maxHeight parameters can be used to limit the returned bound
robertphillips@google.com607fe072012-07-24 13:54:00 +0000417 * to the expected drawing area. Similarly, the offsetX and offsetY parameters
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000418 * allow the caller to offset the returned bound to account for translated
robertphillips@google.com607fe072012-07-24 13:54:00 +0000419 * drawing areas (i.e., those resulting from a saveLayer). For finite bounds,
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000420 * the translation (+offsetX, +offsetY) is applied before the clamp to the
robertphillips@google.com607fe072012-07-24 13:54:00 +0000421 * maximum rectangle: [0,maxWidth) x [0,maxHeight).
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000422 * isIntersectionOfRects is an optional parameter that is true when
robertphillips@google.com641f8b12012-07-31 19:15:58 +0000423 * 'devBounds' is the result of an intersection of rects. In this case
424 * 'devBounds' is the exact answer/clip.
robertphillips@google.com607fe072012-07-24 13:54:00 +0000425 */
426 void getConservativeBounds(int offsetX,
427 int offsetY,
428 int maxWidth,
429 int maxHeight,
robertphillips@google.com7b112892012-07-31 15:18:21 +0000430 SkRect* devBounds,
robertphillips@google.com4c2a2f72012-07-24 22:07:50 +0000431 bool* isIntersectionOfRects = NULL) const;
robertphillips@google.com607fe072012-07-24 13:54:00 +0000432
reed@google.com5c3d1472011-02-22 19:12:23 +0000433private:
robertphillips@google.com52cb2c72012-07-16 18:52:29 +0000434 friend class Iter;
reed@google.com5c3d1472011-02-22 19:12:23 +0000435
436 SkDeque fDeque;
437 int fSaveCount;
robertphillips@google.com46f93502012-08-07 15:38:08 +0000438
439 // Generation ID for the clip stack. This is incremented for each
440 // clipDevRect and clipDevPath call. 0 is reserved to indicate an
441 // invalid ID.
442 static int32_t gGenID;
443
robertphillips@google.com46f93502012-08-07 15:38:08 +0000444 /**
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +0000445 * Helper for clipDevPath, etc.
446 */
447 void pushElement(const Element& element);
448
449 /**
commit-bot@chromium.org6fbe54c2013-06-11 11:01:48 +0000450 * Restore the stack back to the specified save count.
451 */
452 void restoreTo(int saveCount);
453
454 /**
robertphillips@google.com46f93502012-08-07 15:38:08 +0000455 * Return the next unique generation ID.
456 */
457 static int32_t GetNextGenID();
reed@google.com5c3d1472011-02-22 19:12:23 +0000458};
459
460#endif