blob: ace765f6cb663d581f3ced80f7891fe7534a651d [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#include "GrClip.h"
12
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000013GrClip::GrClip()
14 : fRequiresAA(false) {
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +000015 fConservativeBounds.setEmpty();
16 fConservativeBoundsValid = true;
reed@google.comac10a2d2010-12-22 21:39:39 +000017}
18
bsalomon@google.com92669012011-09-27 19:10:05 +000019GrClip::GrClip(const GrClip& src) {
reed@google.comac10a2d2010-12-22 21:39:39 +000020 *this = src;
21}
22
bsalomon@google.com92669012011-09-27 19:10:05 +000023GrClip::GrClip(const GrIRect& rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000024 this->setFromIRect(rect);
25}
26
bsalomon@google.com92669012011-09-27 19:10:05 +000027GrClip::GrClip(const GrRect& rect) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000028 this->setFromRect(rect);
29}
30
reed@google.com6f8f2922011-03-04 22:27:10 +000031GrClip::GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000032 const GrRect& bounds) {
reed@google.com6f8f2922011-03-04 22:27:10 +000033 this->setFromIterator(iter, tx, ty, bounds);
reed@google.comac10a2d2010-12-22 21:39:39 +000034}
35
36GrClip::~GrClip() {}
37
38GrClip& GrClip::operator=(const GrClip& src) {
39 fList = src.fList;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +000040 fConservativeBounds = src.fConservativeBounds;
41 fConservativeBoundsValid = src.fConservativeBoundsValid;
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000042 fRequiresAA = src.fRequiresAA;
reed@google.comac10a2d2010-12-22 21:39:39 +000043 return *this;
44}
45
46void GrClip::setEmpty() {
47 fList.reset();
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +000048 fConservativeBounds.setEmpty();
49 fConservativeBoundsValid = true;
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000050 fRequiresAA = false;
reed@google.comac10a2d2010-12-22 21:39:39 +000051}
52
bsalomon@google.comd302f142011-03-03 13:54:13 +000053void GrClip::setFromRect(const GrRect& r) {
54 fList.reset();
55 if (r.isEmpty()) {
56 // use a canonical empty rect for == testing.
57 setEmpty();
58 } else {
59 fList.push_back();
60 fList.back().fRect = r;
61 fList.back().fType = kRect_ClipType;
robertphillips@google.com0f191f32012-04-25 15:23:36 +000062 fList.back().fOp = SkRegion::kReplace_Op;
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000063 fList.back().fDoAA = false;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +000064 fConservativeBounds = r;
65 fConservativeBoundsValid = true;
robertphillips@google.comb99225c2012-07-24 18:20:10 +000066 fRequiresAA = false;
bsalomon@google.comd302f142011-03-03 13:54:13 +000067 }
68}
69
70void GrClip::setFromIRect(const GrIRect& r) {
71 fList.reset();
72 if (r.isEmpty()) {
73 // use a canonical empty rect for == testing.
74 setEmpty();
75 } else {
76 fList.push_back();
77 fList.back().fRect.set(r);
78 fList.back().fType = kRect_ClipType;
robertphillips@google.com0f191f32012-04-25 15:23:36 +000079 fList.back().fOp = SkRegion::kReplace_Op;
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000080 fList.back().fDoAA = false;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +000081 fConservativeBounds.set(r);
82 fConservativeBoundsValid = true;
robertphillips@google.comb99225c2012-07-24 18:20:10 +000083 fRequiresAA = false;
bsalomon@google.comd302f142011-03-03 13:54:13 +000084 }
85}
86
reed@google.com20efde72011-05-09 17:00:02 +000087static void intersectWith(SkRect* dst, const SkRect& src) {
88 if (!dst->intersect(src)) {
89 dst->setEmpty();
90 }
91}
92
reed@google.com6f8f2922011-03-04 22:27:10 +000093void GrClip::setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty,
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +000094 const GrRect& conservativeBounds) {
reed@google.comac10a2d2010-12-22 21:39:39 +000095 fList.reset();
robertphillips@google.comfa1d2912012-04-16 14:49:14 +000096 fRequiresAA = false;
reed@google.comac10a2d2010-12-22 21:39:39 +000097
bsalomon@google.comd302f142011-03-03 13:54:13 +000098 int rectCount = 0;
reed@google.comac10a2d2010-12-22 21:39:39 +000099
bsalomon@google.comd302f142011-03-03 13:54:13 +0000100 // compute bounds for common case of series of intersecting rects.
101 bool isectRectValid = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000102
reed@google.comac10a2d2010-12-22 21:39:39 +0000103 if (iter) {
104 for (iter->rewind(); !iter->isDone(); iter->next()) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000105 Element& e = fList.push_back();
106 e.fType = iter->getType();
107 e.fOp = iter->getOp();
robertphillips@google.comfa1d2912012-04-16 14:49:14 +0000108 e.fDoAA = iter->getDoAA();
109 if (e.fDoAA) {
110 fRequiresAA = true;
111 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000112 // iterators should not emit replace
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000113 GrAssert(SkRegion::kReplace_Op != e.fOp);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000114 switch (e.fType) {
115 case kRect_ClipType:
116 iter->getRect(&e.fRect);
reed@google.com6f8f2922011-03-04 22:27:10 +0000117 if (tx || ty) {
118 e.fRect.offset(tx, ty);
119 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000120 ++rectCount;
121 if (isectRectValid) {
robertphillips@google.com0f191f32012-04-25 15:23:36 +0000122 if (SkRegion::kIntersect_Op == e.fOp) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000123 GrAssert(fList.count() <= 2);
124 if (fList.count() > 1) {
125 GrAssert(2 == rectCount);
126 rectCount = 1;
127 fList.pop_back();
128 GrAssert(kRect_ClipType == fList.back().fType);
reed@google.com20efde72011-05-09 17:00:02 +0000129 intersectWith(&fList.back().fRect, e.fRect);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000130 }
131 } else {
132 isectRectValid = false;
133 }
134 }
135 break;
136 case kPath_ClipType:
reed@google.com07f3ee12011-05-16 17:21:57 +0000137 e.fPath = *iter->getPath();
reed@google.com6f8f2922011-03-04 22:27:10 +0000138 if (tx || ty) {
139 e.fPath.offset(tx, ty);
140 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000141 e.fPathFill = iter->getPathFill();
142 isectRectValid = false;
143 break;
144 default:
145 GrCrash("Unknown clip element type.");
reed@google.comac10a2d2010-12-22 21:39:39 +0000146 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000147 }
148 }
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000149 fConservativeBoundsValid = false;
epoger@google.com17b78942011-08-26 14:40:38 +0000150 if (isectRectValid && rectCount) {
151 fConservativeBounds = fList[0].fRect;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000152 fConservativeBoundsValid = true;
robertphillips@google.com3e11c0b2012-07-11 18:20:35 +0000153 } else {
154 fConservativeBounds = conservativeBounds;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000155 fConservativeBoundsValid = true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000156 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000157}
robertphillips@google.coma6f11c42012-07-23 17:39:44 +0000158
159///////////////////////////////////////////////////////////////////////////////
160
161GrClip::Iter::Iter()
162 : fStack(NULL)
163 , fCurIndex(0) {
164}
165
166GrClip::Iter::Iter(const GrClip& stack, IterStart startLoc)
167 : fStack(&stack) {
168 this->reset(stack, startLoc);
169}
170
171const GrClip::Iter::Clip* GrClip::Iter::updateClip(int index) {
172
173 if (NULL == fStack) {
174 return NULL;
175 }
176
177 GrAssert(0 <= index && index < fStack->getElementCount());
178
179
180
181 switch (fStack->getElementType(index)) {
182 case kRect_ClipType:
183 fClip.fRect = &fStack->getRect(index);
184 fClip.fPath = NULL;
185 break;
186 case kPath_ClipType:
187 fClip.fRect = NULL;
188 fClip.fPath = &fStack->getPath(index);
189 break;
190 }
191 fClip.fOp = fStack->getOp(index);
192 fClip.fDoAA = fStack->getDoAA(index);
193 return &fClip;
194}
195
196const GrClip::Iter::Clip* GrClip::Iter::next() {
197
198 if (NULL == fStack) {
199 return NULL;
200 }
201
202 if (0 > fCurIndex || fCurIndex >= fStack->getElementCount()) {
203 return NULL;
204 }
205
206 int oldIndex = fCurIndex;
207 ++fCurIndex;
208
209 return this->updateClip(oldIndex);
210}
211
212const GrClip::Iter::Clip* GrClip::Iter::prev() {
213
214 if (NULL == fStack) {
215 return NULL;
216 }
217
218 if (0 > fCurIndex || fCurIndex >= fStack->getElementCount()) {
219 return NULL;
220 }
221
222 int oldIndex = fCurIndex;
223 --fCurIndex;
224
225 return this->updateClip(oldIndex);
226}
227
228const GrClip::Iter::Clip* GrClip::Iter::skipToTopmost(SkRegion::Op op) {
229
230 GrAssert(SkRegion::kReplace_Op == op);
231
232 if (NULL == fStack) {
233 return NULL;
234 }
235
236 // GrClip removes all clips below the topmost replace
237 this->reset(*fStack, kBottom_IterStart);
238
239 return this->next();
240}
241
242void GrClip::Iter::reset(const GrClip& stack, IterStart startLoc) {
243 fStack = &stack;
244 if (kBottom_IterStart == startLoc) {
245 fCurIndex = 0;
246 } else {
247 fCurIndex = fStack->getElementCount()-1;
248 }
249}