| epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 1 | |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 2 | /* |
| epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 3 | * Copyright 2010 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. |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 7 | */ |
| 8 | |
| 9 | |
| epoger@google.com | ec3ed6a | 2011-07-28 14:26:00 +0000 | [diff] [blame] | 10 | |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 11 | #ifndef GrClip_DEFINED |
| 12 | #define GrClip_DEFINED |
| 13 | |
| 14 | #include "GrClipIterator.h" |
| 15 | #include "GrRect.h" |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 16 | |
| bsalomon@google.com | 8d033a1 | 2012-04-27 15:52:53 +0000 | [diff] [blame] | 17 | #include "SkPath.h" |
| bsalomon@google.com | 49313f6 | 2011-09-14 13:54:05 +0000 | [diff] [blame] | 18 | #include "SkTArray.h" |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 19 | |
| robertphillips@google.com | e4d69c0 | 2012-07-26 21:37:40 +0000 | [diff] [blame] | 20 | class GrSurface; |
| 21 | |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 22 | class GrClip { |
| 23 | public: |
| 24 | GrClip(); |
| 25 | GrClip(const GrClip& src); |
| reed@google.com | 6f8f292 | 2011-03-04 22:27:10 +0000 | [diff] [blame] | 26 | /** |
| robertphillips@google.com | 3e11c0b | 2012-07-11 18:20:35 +0000 | [diff] [blame] | 27 | * The conservativeBounds parameter already takes (tx,ty) into account. |
| reed@google.com | 6f8f292 | 2011-03-04 22:27:10 +0000 | [diff] [blame] | 28 | */ |
| 29 | GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty, |
| robertphillips@google.com | 3e11c0b | 2012-07-11 18:20:35 +0000 | [diff] [blame] | 30 | const GrRect& conservativeBounds); |
| 31 | explicit GrClip(const GrIRect& rect); |
| 32 | explicit GrClip(const GrRect& rect); |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 33 | |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 34 | ~GrClip(); |
| 35 | |
| 36 | GrClip& operator=(const GrClip& src); |
| 37 | |
| robertphillips@google.com | 3e11c0b | 2012-07-11 18:20:35 +0000 | [diff] [blame] | 38 | const GrRect& getConservativeBounds() const { |
| 39 | GrAssert(fConservativeBoundsValid); |
| 40 | return fConservativeBounds; |
| 41 | } |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 42 | |
| robertphillips@google.com | fa1d291 | 2012-04-16 14:49:14 +0000 | [diff] [blame] | 43 | bool requiresAA() const { return fRequiresAA; } |
| 44 | |
| robertphillips@google.com | a6f11c4 | 2012-07-23 17:39:44 +0000 | [diff] [blame] | 45 | class Iter { |
| 46 | public: |
| 47 | enum IterStart { |
| 48 | kBottom_IterStart, |
| 49 | kTop_IterStart |
| 50 | }; |
| 51 | |
| 52 | /** |
| 53 | * Creates an uninitialized iterator. Must be reset() |
| 54 | */ |
| 55 | Iter(); |
| 56 | |
| 57 | Iter(const GrClip& stack, IterStart startLoc); |
| 58 | |
| 59 | struct Clip { |
| 60 | Clip() : fRect(NULL), fPath(NULL), fOp(SkRegion::kIntersect_Op), |
| 61 | fDoAA(false) {} |
| 62 | |
| 63 | const SkRect* fRect; // if non-null, this is a rect clip |
| 64 | const SkPath* fPath; // if non-null, this is a path clip |
| 65 | SkRegion::Op fOp; |
| 66 | bool fDoAA; |
| 67 | }; |
| 68 | |
| 69 | /** |
| 70 | * Return the clip for this element in the iterator. If next() returns |
| 71 | * NULL, then the iterator is done. The type of clip is determined by |
| 72 | * the pointers fRect and fPath: |
| 73 | * |
| 74 | * fRect==NULL fPath!=NULL path clip |
| 75 | * fRect!=NULL fPath==NULL rect clip |
| 76 | * fRect==NULL fPath==NULL empty clip |
| 77 | */ |
| 78 | const Clip* next(); |
| 79 | const Clip* prev(); |
| 80 | |
| 81 | /** |
| 82 | * Moves the iterator to the topmost clip with the specified RegionOp |
| 83 | * and returns that clip. If no clip with that op is found, |
| 84 | * returns NULL. |
| 85 | */ |
| 86 | const Clip* skipToTopmost(SkRegion::Op op); |
| 87 | |
| 88 | /** |
| 89 | * Restarts the iterator on a clip stack. |
| 90 | */ |
| 91 | void reset(const GrClip& stack, IterStart startLoc); |
| 92 | |
| 93 | private: |
| 94 | const GrClip* fStack; |
| 95 | Clip fClip; |
| 96 | int fCurIndex; |
| 97 | |
| 98 | /** |
| 99 | * updateClip updates fClip to represent the clip in the index slot of |
| 100 | * GrClip's list. * It unifies functionality needed by both next() and |
| 101 | * prev(). |
| 102 | */ |
| 103 | const Clip* updateClip(int index); |
| 104 | }; |
| 105 | |
| 106 | private: |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 107 | int getElementCount() const { return fList.count(); } |
| 108 | |
| 109 | GrClipType getElementType(int i) const { return fList[i].fType; } |
| 110 | |
| bsalomon@google.com | 8d033a1 | 2012-04-27 15:52:53 +0000 | [diff] [blame] | 111 | const SkPath& getPath(int i) const { |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 112 | GrAssert(kPath_ClipType == fList[i].fType); |
| 113 | return fList[i].fPath; |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 114 | } |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 115 | |
| 116 | GrPathFill getPathFill(int i) const { |
| 117 | GrAssert(kPath_ClipType == fList[i].fType); |
| 118 | return fList[i].fPathFill; |
| 119 | } |
| 120 | |
| 121 | const GrRect& getRect(int i) const { |
| 122 | GrAssert(kRect_ClipType == fList[i].fType); |
| 123 | return fList[i].fRect; |
| 124 | } |
| 125 | |
| robertphillips@google.com | 0f191f3 | 2012-04-25 15:23:36 +0000 | [diff] [blame] | 126 | SkRegion::Op getOp(int i) const { return fList[i].fOp; } |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 127 | |
| robertphillips@google.com | fa1d291 | 2012-04-16 14:49:14 +0000 | [diff] [blame] | 128 | bool getDoAA(int i) const { return fList[i].fDoAA; } |
| 129 | |
| robertphillips@google.com | a6f11c4 | 2012-07-23 17:39:44 +0000 | [diff] [blame] | 130 | public: |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 131 | bool isRect() const { |
| bsalomon@google.com | ab3dee5 | 2011-08-29 15:18:41 +0000 | [diff] [blame] | 132 | if (1 == fList.count() && kRect_ClipType == fList[0].fType && |
| robertphillips@google.com | 0f191f3 | 2012-04-25 15:23:36 +0000 | [diff] [blame] | 133 | (SkRegion::kIntersect_Op == fList[0].fOp || |
| 134 | SkRegion::kReplace_Op == fList[0].fOp)) { |
| bsalomon@google.com | 0b50b2e | 2011-03-08 21:07:21 +0000 | [diff] [blame] | 135 | // if we determined that the clip is a single rect |
| 136 | // we ought to have also used that rect as the bounds. |
| 137 | GrAssert(fConservativeBoundsValid); |
| 138 | GrAssert(fConservativeBounds == fList[0].fRect); |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 139 | return true; |
| 140 | } else { |
| 141 | return false; |
| 142 | } |
| 143 | } |
| 144 | |
| bsalomon@google.com | a320194 | 2012-06-21 19:58:20 +0000 | [diff] [blame] | 145 | // FIXME: This word "empty" is confusing. It means that the clip has no |
| 146 | // elements (it is the infinite plane) not that it has no area. |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 147 | bool isEmpty() const { return 0 == fList.count(); } |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 148 | |
| 149 | /** |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 150 | * Resets this clip to be empty |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 151 | */ |
| 152 | void setEmpty(); |
| reed@google.com | 6f8f292 | 2011-03-04 22:27:10 +0000 | [diff] [blame] | 153 | |
| 154 | /** |
| 155 | * If specified, the bounds parameter already takes (tx,ty) into account. |
| 156 | */ |
| 157 | void setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty, |
| robertphillips@google.com | 3e11c0b | 2012-07-11 18:20:35 +0000 | [diff] [blame] | 158 | const GrRect& conservativeBounds); |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 159 | void setFromRect(const GrRect& rect); |
| 160 | void setFromIRect(const GrIRect& rect); |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 161 | |
| 162 | friend bool operator==(const GrClip& a, const GrClip& b) { |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 163 | if (a.fList.count() != b.fList.count()) { |
| 164 | return false; |
| 165 | } |
| 166 | int count = a.fList.count(); |
| 167 | for (int i = 0; i < count; ++i) { |
| 168 | if (a.fList[i] != b.fList[i]) { |
| 169 | return false; |
| 170 | } |
| 171 | } |
| 172 | return true; |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 173 | } |
| 174 | friend bool operator!=(const GrClip& a, const GrClip& b) { |
| 175 | return !(a == b); |
| 176 | } |
| 177 | |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 178 | private: |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 179 | struct Element { |
| robertphillips@google.com | 0f191f3 | 2012-04-25 15:23:36 +0000 | [diff] [blame] | 180 | GrClipType fType; |
| 181 | GrRect fRect; |
| bsalomon@google.com | 8d033a1 | 2012-04-27 15:52:53 +0000 | [diff] [blame] | 182 | SkPath fPath; |
| robertphillips@google.com | 0f191f3 | 2012-04-25 15:23:36 +0000 | [diff] [blame] | 183 | GrPathFill fPathFill; |
| 184 | SkRegion::Op fOp; |
| 185 | bool fDoAA; |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 186 | bool operator ==(const Element& e) const { |
| robertphillips@google.com | fa1d291 | 2012-04-16 14:49:14 +0000 | [diff] [blame] | 187 | if (e.fType != fType || e.fOp != fOp || e.fDoAA != fDoAA) { |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 188 | return false; |
| 189 | } |
| 190 | switch (fType) { |
| 191 | case kRect_ClipType: |
| 192 | return fRect == e.fRect; |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 193 | case kPath_ClipType: |
| 194 | return fPath == e.fPath; |
| 195 | default: |
| 196 | GrCrash("Unknown clip element type."); |
| 197 | return false; // suppress warning |
| 198 | } |
| 199 | } |
| 200 | bool operator !=(const Element& e) const { return !(*this == e); } |
| 201 | }; |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 202 | |
| bsalomon@google.com | 0b50b2e | 2011-03-08 21:07:21 +0000 | [diff] [blame] | 203 | GrRect fConservativeBounds; |
| 204 | bool fConservativeBoundsValid; |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 205 | |
| robertphillips@google.com | fa1d291 | 2012-04-16 14:49:14 +0000 | [diff] [blame] | 206 | bool fRequiresAA; |
| 207 | |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 208 | enum { |
| 209 | kPreAllocElements = 4, |
| 210 | }; |
| bsalomon@google.com | 9266901 | 2011-09-27 19:10:05 +0000 | [diff] [blame] | 211 | SkSTArray<kPreAllocElements, Element> fList; |
| bsalomon@google.com | d302f14 | 2011-03-03 13:54:13 +0000 | [diff] [blame] | 212 | }; |
| robertphillips@google.com | beb1af7 | 2012-07-26 18:52:16 +0000 | [diff] [blame] | 213 | |
| 214 | /** |
| 215 | * GrClipData encapsulates the information required to construct the clip |
| 216 | * masks. 'fOrigin' is only non-zero when saveLayer has been called |
| 217 | * with an offset bounding box. The clips in 'fClipStack' are in |
| 218 | * device coordinates (i.e., they have been translated by -fOrigin w.r.t. |
| 219 | * the canvas' device coordinates). |
| 220 | */ |
| 221 | class GrClipData : public SkNoncopyable { |
| 222 | public: |
| 223 | const GrClip* fClipStack; |
| 224 | SkIPoint fOrigin; |
| 225 | |
| 226 | GrClipData() |
| 227 | : fClipStack(NULL) { |
| 228 | fOrigin.setZero(); |
| 229 | } |
| 230 | |
| 231 | bool operator==(const GrClipData& other) const { |
| 232 | if (fOrigin != other.fOrigin) { |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | if (NULL != fClipStack && NULL != other.fClipStack) { |
| 237 | return *fClipStack == *other.fClipStack; |
| 238 | } |
| 239 | |
| 240 | return fClipStack == other.fClipStack; |
| 241 | } |
| 242 | |
| 243 | bool operator!=(const GrClipData& other) const { |
| 244 | return !(*this == other); |
| 245 | } |
| robertphillips@google.com | e4d69c0 | 2012-07-26 21:37:40 +0000 | [diff] [blame] | 246 | |
| 247 | void getConservativeBounds(const GrSurface* surface, |
| 248 | GrIRect* result, |
| 249 | bool* isIntersectionOfRects = NULL) const; |
| robertphillips@google.com | beb1af7 | 2012-07-26 18:52:16 +0000 | [diff] [blame] | 250 | }; |
| 251 | |
| reed@google.com | ac10a2d | 2010-12-22 21:39:39 +0000 | [diff] [blame] | 252 | #endif |
| 253 | |