blob: d6655dd8e0349ac9a8cb0f218952912d33c09b6b [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#ifndef GrClip_DEFINED
12#define GrClip_DEFINED
13
14#include "GrClipIterator.h"
15#include "GrRect.h"
bsalomon@google.comd302f142011-03-03 13:54:13 +000016
bsalomon@google.com8d033a12012-04-27 15:52:53 +000017#include "SkPath.h"
bsalomon@google.com49313f62011-09-14 13:54:05 +000018#include "SkTArray.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000019
robertphillips@google.come4d69c02012-07-26 21:37:40 +000020class GrSurface;
21
reed@google.comac10a2d2010-12-22 21:39:39 +000022class GrClip {
23public:
24 GrClip();
25 GrClip(const GrClip& src);
reed@google.com6f8f2922011-03-04 22:27:10 +000026 /**
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000027 * The conservativeBounds parameter already takes (tx,ty) into account.
reed@google.com6f8f2922011-03-04 22:27:10 +000028 */
29 GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000030 const GrRect& conservativeBounds);
31 explicit GrClip(const GrIRect& rect);
32 explicit GrClip(const GrRect& rect);
bsalomon@google.comd302f142011-03-03 13:54:13 +000033
reed@google.comac10a2d2010-12-22 21:39:39 +000034 ~GrClip();
35
36 GrClip& operator=(const GrClip& src);
37
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000038 const GrRect& getConservativeBounds() const {
39 GrAssert(fConservativeBoundsValid);
40 return fConservativeBounds;
41 }
bsalomon@google.comd302f142011-03-03 13:54:13 +000042
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000043 bool requiresAA() const { return fRequiresAA; }
44
robertphillips@google.coma6f11c42012-07-23 17:39:44 +000045 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
106private:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000107 int getElementCount() const { return fList.count(); }
108
109 GrClipType getElementType(int i) const { return fList[i].fType; }
110
bsalomon@google.com8d033a12012-04-27 15:52:53 +0000111 const SkPath& getPath(int i) const {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000112 GrAssert(kPath_ClipType == fList[i].fType);
113 return fList[i].fPath;
reed@google.comac10a2d2010-12-22 21:39:39 +0000114 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000115
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.com0f191f32012-04-25 15:23:36 +0000126 SkRegion::Op getOp(int i) const { return fList[i].fOp; }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000127
robertphillips@google.comfa1d2912012-04-16 14:49:14 +0000128 bool getDoAA(int i) const { return fList[i].fDoAA; }
129
robertphillips@google.coma6f11c42012-07-23 17:39:44 +0000130public:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000131 bool isRect() const {
bsalomon@google.comab3dee52011-08-29 15:18:41 +0000132 if (1 == fList.count() && kRect_ClipType == fList[0].fType &&
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000133 (SkRegion::kIntersect_Op == fList[0].fOp ||
134 SkRegion::kReplace_Op == fList[0].fOp)) {
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000135 // 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.comd302f142011-03-03 13:54:13 +0000139 return true;
140 } else {
141 return false;
142 }
143 }
144
bsalomon@google.coma3201942012-06-21 19:58:20 +0000145 // 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.comd302f142011-03-03 13:54:13 +0000147 bool isEmpty() const { return 0 == fList.count(); }
reed@google.comac10a2d2010-12-22 21:39:39 +0000148
149 /**
bsalomon@google.comd302f142011-03-03 13:54:13 +0000150 * Resets this clip to be empty
reed@google.comac10a2d2010-12-22 21:39:39 +0000151 */
152 void setEmpty();
reed@google.com6f8f2922011-03-04 22:27:10 +0000153
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.com3e11c0b2012-07-11 18:20:35 +0000158 const GrRect& conservativeBounds);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000159 void setFromRect(const GrRect& rect);
160 void setFromIRect(const GrIRect& rect);
reed@google.comac10a2d2010-12-22 21:39:39 +0000161
162 friend bool operator==(const GrClip& a, const GrClip& b) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000163 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.comac10a2d2010-12-22 21:39:39 +0000173 }
174 friend bool operator!=(const GrClip& a, const GrClip& b) {
175 return !(a == b);
176 }
177
reed@google.comac10a2d2010-12-22 21:39:39 +0000178private:
bsalomon@google.comd302f142011-03-03 13:54:13 +0000179 struct Element {
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000180 GrClipType fType;
181 GrRect fRect;
bsalomon@google.com8d033a12012-04-27 15:52:53 +0000182 SkPath fPath;
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000183 GrPathFill fPathFill;
184 SkRegion::Op fOp;
185 bool fDoAA;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000186 bool operator ==(const Element& e) const {
robertphillips@google.comfa1d2912012-04-16 14:49:14 +0000187 if (e.fType != fType || e.fOp != fOp || e.fDoAA != fDoAA) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000188 return false;
189 }
190 switch (fType) {
191 case kRect_ClipType:
192 return fRect == e.fRect;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000193 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.comac10a2d2010-12-22 21:39:39 +0000202
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000203 GrRect fConservativeBounds;
204 bool fConservativeBoundsValid;
reed@google.comac10a2d2010-12-22 21:39:39 +0000205
robertphillips@google.comfa1d2912012-04-16 14:49:14 +0000206 bool fRequiresAA;
207
bsalomon@google.comd302f142011-03-03 13:54:13 +0000208 enum {
209 kPreAllocElements = 4,
210 };
bsalomon@google.com92669012011-09-27 19:10:05 +0000211 SkSTArray<kPreAllocElements, Element> fList;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000212};
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000213
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 */
221class GrClipData : public SkNoncopyable {
222public:
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.come4d69c02012-07-26 21:37:40 +0000246
247 void getConservativeBounds(const GrSurface* surface,
248 GrIRect* result,
249 bool* isIntersectionOfRects = NULL) const;
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000250};
251
reed@google.comac10a2d2010-12-22 21:39:39 +0000252#endif
253