blob: 17ecd5d158a2d3e3df88f8807f491b8c14500edc [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001#include "GrPath.h"
2
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00003GrPath::GrPath() {
4 fConvexHint = kNone_ConvexHint;
bsalomon@google.com06e17952011-04-27 21:13:04 +00005 fConservativeBounds.setLargestInverted();
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +00006}
reed@google.comac10a2d2010-12-22 21:39:39 +00007
reed@google.comc9218432011-01-25 19:05:12 +00008GrPath::GrPath(const GrPath& src) : INHERITED() {
bsalomon@google.comd302f142011-03-03 13:54:13 +00009 GrPath::Iter iter(src);
10 this->resetFromIter(&iter);
reed@google.comac10a2d2010-12-22 21:39:39 +000011}
12
13GrPath::GrPath(GrPathIter& iter) {
14 this->resetFromIter(&iter);
15}
16
17GrPath::~GrPath() {
18}
19
bsalomon@google.comd302f142011-03-03 13:54:13 +000020bool GrPath::operator ==(const GrPath& path) const {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000021 if (fCmds.count() != path.fCmds.count() ||
bsalomon@google.comd302f142011-03-03 13:54:13 +000022 fPts.count() != path.fPts.count()) {
23 return false;
24 }
25
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000026 for (int v = 0; v < fCmds.count(); ++v) {
27 if (fCmds[v] != path.fCmds[v]) {
bsalomon@google.comd302f142011-03-03 13:54:13 +000028 return false;
29 }
30 }
31
32 for (int p = 0; p < fPts.count(); ++p) {
33 if (fPts[p] != path.fPts[p]) {
34 return false;
35 }
36 }
37 return true;
38}
39
reed@google.comac10a2d2010-12-22 21:39:39 +000040void GrPath::ensureMoveTo() {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000041 if (fCmds.isEmpty() || this->wasLastVerb(kClose_PathCmd)) {
42 *fCmds.append() = kMove_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +000043 fPts.append()->set(0, 0);
bsalomon@google.com06e17952011-04-27 21:13:04 +000044 fConservativeBounds.growToInclude(0,0);
reed@google.comac10a2d2010-12-22 21:39:39 +000045 }
46}
47
48void GrPath::moveTo(GrScalar x, GrScalar y) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000049 if (this->wasLastVerb(kMove_PathCmd)) {
reed@google.comac10a2d2010-12-22 21:39:39 +000050 // overwrite prev kMove value
51 fPts[fPts.count() - 1].set(x, y);
52 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000053 *fCmds.append() = kMove_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +000054 fPts.append()->set(x, y);
55 }
bsalomon@google.com06e17952011-04-27 21:13:04 +000056 fConservativeBounds.growToInclude(x,y);
reed@google.comac10a2d2010-12-22 21:39:39 +000057}
58
59void GrPath::lineTo(GrScalar x, GrScalar y) {
60 this->ensureMoveTo();
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000061 *fCmds.append() = kLine_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +000062 fPts.append()->set(x, y);
bsalomon@google.com06e17952011-04-27 21:13:04 +000063 fConservativeBounds.growToInclude(x,y);
reed@google.comac10a2d2010-12-22 21:39:39 +000064}
65
66void GrPath::quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1) {
67 this->ensureMoveTo();
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000068 *fCmds.append() = kQuadratic_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +000069 fPts.append()->set(x0, y0);
70 fPts.append()->set(x1, y1);
bsalomon@google.com06e17952011-04-27 21:13:04 +000071 fConservativeBounds.growToInclude(x0,y0);
72 fConservativeBounds.growToInclude(x1,y1);
reed@google.comac10a2d2010-12-22 21:39:39 +000073}
74
75void GrPath::cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
76 GrScalar x2, GrScalar y2) {
77 this->ensureMoveTo();
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000078 *fCmds.append() = kCubic_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +000079 fPts.append()->set(x0, y0);
80 fPts.append()->set(x1, y1);
81 fPts.append()->set(x2, y2);
bsalomon@google.com06e17952011-04-27 21:13:04 +000082 fConservativeBounds.growToInclude(x0,y0);
83 fConservativeBounds.growToInclude(x1,y1);
84 fConservativeBounds.growToInclude(x2,y2);
reed@google.comac10a2d2010-12-22 21:39:39 +000085}
86
87void GrPath::close() {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000088 if (!fCmds.isEmpty() && !this->wasLastVerb(kClose_PathCmd)) {
reed@google.comac10a2d2010-12-22 21:39:39 +000089 // should we allow kMove followed by kClose?
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000090 *fCmds.append() = kClose_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +000091 }
92}
93
94///////////////////////////////////////////////////////////////////////////////
95
reed@google.com6f8f2922011-03-04 22:27:10 +000096void GrPath::offset(GrScalar tx, GrScalar ty) {
97 if (!tx && !ty) {
98 return; // nothing to do
99 }
100
101 GrPoint* iter = fPts.begin();
102 GrPoint* stop = fPts.end();
103 while (iter < stop) {
104 iter->offset(tx, ty);
105 ++iter;
106 }
bsalomon@google.com06e17952011-04-27 21:13:04 +0000107 fConservativeBounds.translate(tx, ty);
reed@google.com6f8f2922011-03-04 22:27:10 +0000108}
109
110///////////////////////////////////////////////////////////////////////////////
111
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000112static bool check_two_vecs(const GrVec& prevVec,
113 const GrVec& currVec,
114 GrScalar turnDir,
115 int* xDir,
116 int* yDir,
reed@google.com6f8f2922011-03-04 22:27:10 +0000117 int* flipX,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000118 int* flipY) {
119 if (currVec.fX * *xDir < 0) {
120 ++*flipX;
121 if (*flipX > 2) {
122 return false;
123 }
124 *xDir = -*xDir;
125 }
126 if (currVec.fY * *yDir < 0) {
127 ++*flipY;
128 if (*flipY > 2) {
129 return false;
130 }
131 *yDir = -*yDir;
132 }
133 GrScalar d = prevVec.cross(currVec);
134 return (d * turnDir) >= 0;
135}
136
137static void init_from_two_vecs(const GrVec& firstVec,
138 const GrVec& secondVec,
139 GrScalar* turnDir,
140 int* xDir, int* yDir) {
141 *turnDir = firstVec.cross(secondVec);
142 if (firstVec.fX > 0) {
143 *xDir = 1;
144 } else if (firstVec.fX < 0) {
145 *xDir = -1;
146 } else {
147 *xDir = 0;
148 }
149 if (firstVec.fY > 0) {
150 *yDir = 1;
151 } else if (firstVec.fY < 0) {
152 *yDir = -1;
153 } else {
154 *yDir = 0;
155 }
156}
157
reed@google.comac10a2d2010-12-22 21:39:39 +0000158void GrPath::resetFromIter(GrPathIter* iter) {
159 fPts.reset();
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000160 fCmds.reset();
bsalomon@google.com06e17952011-04-27 21:13:04 +0000161 fConservativeBounds.setLargestInverted();
reed@google.comac10a2d2010-12-22 21:39:39 +0000162
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000163 fConvexHint = iter->convexHint();
164
165 // first point of the subpath
bsalomon@google.combf4338c2011-03-04 22:48:25 +0000166 GrPoint firstPt(0,0);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000167 // first edge of the subpath
bsalomon@google.combf4338c2011-03-04 22:48:25 +0000168 GrVec firstVec(0,0);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000169 // vec of most recently processed edge, that wasn't degenerate
bsalomon@google.combf4338c2011-03-04 22:48:25 +0000170 GrVec previousVec(0,0);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000171 // most recently processed point
bsalomon@google.combf4338c2011-03-04 22:48:25 +0000172 GrPoint previousPt(0,0);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000173
174 // sign indicates whether we're bending left or right
bsalomon@google.combf4338c2011-03-04 22:48:25 +0000175 GrScalar turnDir = 0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000176 // number of times the direction has flipped in x or y
177
178 // we track which direction we are moving in x/y and the
179 // number of times it changes.
bsalomon@google.combf4338c2011-03-04 22:48:25 +0000180 int xDir = 0;
181 int yDir = 0;
182 int flipX = 0;
183 int flipY = 0;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000184
185 // counts number of sub path pts that didn't add a degenerate edge.
186 int subPathPts = 0;
bsalomon@google.comed856102011-03-07 14:07:01 +0000187 bool subPathClosed = false;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000188
189 int numSubPaths = 0;
190 iter->rewind();
191 GrPathCmd cmd;
reed@google.comac10a2d2010-12-22 21:39:39 +0000192 GrPoint pts[4];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000193 do {
194 cmd = iter->next(pts);
195 // If the convexity test is ever updated to handle multiple subpaths
196 // the loop has to be adjusted to handle moving to a new subpath without
197 // closing the previous one. Currently the implicit closing vectors for a
198 // filled path would never be examined.
reed@google.comac10a2d2010-12-22 21:39:39 +0000199 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000200 case kMove_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000201 this->moveTo(pts[0].fX, pts[0].fY);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000202 subPathPts = 0;
203 subPathClosed = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000204 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000205 case kLine_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 this->lineTo(pts[1].fX, pts[1].fY);
207 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000208 case kQuadratic_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000209 this->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
210 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000211 case kCubic_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000212 this->cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
213 pts[3].fX, pts[3].fY);
214 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000215 case kClose_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 this->close();
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000217 subPathClosed = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000218 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000219 case kEnd_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000220 break;
221 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000222 int n = NumPathCmdPoints(cmd);
bsalomon@google.com06e17952011-04-27 21:13:04 +0000223 for (int i = 0; i < n; ++i) {
224 fConservativeBounds.growToInclude(pts[i]);
225 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000226 if (0 == subPathPts && n > 0) {
227 previousPt = pts[0];
228 firstPt = previousPt;
229 flipX = 0;
230 flipY = 0;
231 turnDir = 0;
232 subPathPts = 1;
233 ++numSubPaths;
234 }
235 // either we skip the first pt because it is redundant with
236 // last point of the previous subpath cmd or we just ate it
237 // in the above if.
238 int consumed = 1;
239 if (numSubPaths < 2 && kNone_ConvexHint == fConvexHint) {
240 while (consumed < n) {
241 GrAssert(pts[consumed-1] == previousPt);
242 GrVec vec;
243 vec.setBetween(previousPt, pts[consumed]);
244 if (vec.fX || vec.fY) {
245 if (subPathPts >= 2) {
reed@google.com6f8f2922011-03-04 22:27:10 +0000246 if (0 == turnDir) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000247 firstVec = previousVec;
reed@google.com6f8f2922011-03-04 22:27:10 +0000248 init_from_two_vecs(firstVec, vec,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000249 &turnDir, &xDir, &yDir);
250 // here we aren't checking whether the x/y dirs
251 // change between the first and second edge. It
252 // gets covered when the path is closed.
253 } else {
254 if (!check_two_vecs(previousVec, vec, turnDir,
255 &xDir, &yDir,
256 &flipX, &flipY)) {
257 fConvexHint = kConcave_ConvexHint;
258 break;
259 }
260 }
261 }
262 previousVec = vec;
263 previousPt = pts[consumed];
264 ++subPathPts;
265 }
266 ++consumed;
267 }
reed@google.com6f8f2922011-03-04 22:27:10 +0000268 if (subPathPts > 2 && (kClose_PathCmd == cmd ||
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000269 (!subPathClosed && kEnd_PathCmd == cmd ))) {
270 // if an additional vector is needed to close the loop check
271 // that it validates against the previous vector.
272 GrVec vec;
273 vec.setBetween(previousPt, firstPt);
274 if (vec.fX || vec.fY) {
reed@google.com6f8f2922011-03-04 22:27:10 +0000275 if (!check_two_vecs(previousVec, vec, turnDir,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000276 &xDir, &yDir, &flipX, &flipY)) {
277 fConvexHint = kConcave_ConvexHint;
278 break;
279 }
280 previousVec = vec;
281 }
282 // check that closing vector validates against the first vector.
reed@google.com6f8f2922011-03-04 22:27:10 +0000283 if (!check_two_vecs(previousVec, firstVec, turnDir,
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000284 &xDir, &yDir, &flipX, &flipY)) {
285 fConvexHint = kConcave_ConvexHint;
286 break;
287 }
288 }
289 }
290 } while (cmd != kEnd_PathCmd);
291 if (kNone_ConvexHint == fConvexHint && numSubPaths < 2) {
292 fConvexHint = kConvex_ConvexHint;
293 } else {
294 bool recurse = false;
295 if (recurse) {
296 this->resetFromIter(iter);
297 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000298 }
299}
300
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000301void GrPath::ConvexUnitTest() {
302 GrPath testPath;
303 GrPath::Iter testIter;
304
305 GrPath pt;
306 pt.moveTo(0, 0);
307 pt.close();
308
309 testIter.reset(pt);
310 testPath.resetFromIter(&testIter);
311 GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
312
313 GrPath line;
314 line.moveTo(GrIntToScalar(12), GrIntToScalar(20));
315 line.lineTo(GrIntToScalar(-12), GrIntToScalar(-20));
316 line.close();
317
318 testIter.reset(line);
319 testPath.resetFromIter(&testIter);
320 GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
321
322 GrPath triLeft;
323 triLeft.moveTo(0, 0);
324 triLeft.lineTo(1, 0);
325 triLeft.lineTo(1, 1);
326 triLeft.close();
327
328 testIter.reset(triLeft);
329 testPath.resetFromIter(&testIter);
330 GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
331
332 GrPath triRight;
333 triRight.moveTo(0, 0);
334 triRight.lineTo(-1, 0);
335 triRight.lineTo(1, 1);
336 triRight.close();
337
338 testIter.reset(triRight);
339 testPath.resetFromIter(&testIter);
340 GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
reed@google.com6f8f2922011-03-04 22:27:10 +0000341
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000342 GrPath square;
343 square.moveTo(0, 0);
344 square.lineTo(1, 0);
345 square.lineTo(1, 1);
346 square.lineTo(0, 1);
347 square.close();
348
349 testIter.reset(square);
350 testPath.resetFromIter(&testIter);
351 GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
352
353 GrPath redundantSquare;
354 square.moveTo(0, 0);
355 square.lineTo(0, 0);
356 square.lineTo(0, 0);
357 square.lineTo(1, 0);
358 square.lineTo(1, 0);
359 square.lineTo(1, 0);
360 square.lineTo(1, 1);
361 square.lineTo(1, 1);
362 square.lineTo(1, 1);
363 square.lineTo(0, 1);
364 square.lineTo(0, 1);
365 square.lineTo(0, 1);
366 square.close();
reed@google.com6f8f2922011-03-04 22:27:10 +0000367
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000368 testIter.reset(redundantSquare);
369 testPath.resetFromIter(&testIter);
370 GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
371
372 GrPath bowTie;
373 bowTie.moveTo(0, 0);
374 bowTie.lineTo(0, 0);
375 bowTie.lineTo(0, 0);
376 bowTie.lineTo(1, 1);
377 bowTie.lineTo(1, 1);
378 bowTie.lineTo(1, 1);
379 bowTie.lineTo(1, 0);
380 bowTie.lineTo(1, 0);
381 bowTie.lineTo(1, 0);
382 bowTie.lineTo(0, 1);
383 bowTie.lineTo(0, 1);
384 bowTie.lineTo(0, 1);
385 bowTie.close();
reed@google.com6f8f2922011-03-04 22:27:10 +0000386
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000387 testIter.reset(bowTie);
388 testPath.resetFromIter(&testIter);
389 GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
390
391 GrPath spiral;
392 spiral.moveTo(0, 0);
393 spiral.lineTo(1, 0);
394 spiral.lineTo(1, 1);
395 spiral.lineTo(0, 1);
396 spiral.lineTo(0,.5);
397 spiral.lineTo(.5,.5);
398 spiral.lineTo(.5,.75);
399 spiral.close();
400
401 testIter.reset(spiral);
402 testPath.resetFromIter(&testIter);
403 GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
404
405 GrPath dent;
406 dent.moveTo(0, 0);
407 dent.lineTo(1, 1);
408 dent.lineTo(0, 1);
409 dent.lineTo(-.5,2);
410 dent.lineTo(-2, 1);
411 dent.close();
412
413 testIter.reset(dent);
414 testPath.resetFromIter(&testIter);
415 GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
416}
reed@google.comac10a2d2010-12-22 21:39:39 +0000417///////////////////////////////////////////////////////////////////////////////
418
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000419GrPath::Iter::Iter() : fPath(NULL) {
420}
421
422GrPath::Iter::Iter(const GrPath& path) : fPath(&path) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000423 this->rewind();
424}
425
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000426GrPathCmd GrPath::Iter::next(GrPoint points[]) {
427 if (fCmdIndex == fPath->fCmds.count()) {
428 GrAssert(fPtIndex == fPath->fPts.count());
429 return kEnd_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +0000430 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000431 GrAssert(fCmdIndex < fPath->fCmds.count());
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 }
433
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000434 GrPathCmd cmd = fPath->fCmds[fCmdIndex++];
435 const GrPoint* srcPts = fPath->fPts.begin() + fPtIndex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000436
437 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000438 case kMove_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000439 if (points) {
440 points[0] = srcPts[0];
441 }
442 fLastPt = srcPts[0];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000443 GrAssert(fPtIndex <= fPath->fPts.count() + 1);
bsalomon@google.com06e17952011-04-27 21:13:04 +0000444 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[0]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000445 fPtIndex += 1;
446 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000447 case kLine_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000448 if (points) {
449 points[0] = fLastPt;
450 points[1] = srcPts[0];
451 }
452 fLastPt = srcPts[0];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000453 GrAssert(fPtIndex <= fPath->fPts.count() + 1);
bsalomon@google.com06e17952011-04-27 21:13:04 +0000454 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[0]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000455 fPtIndex += 1;
456 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000457 case kQuadratic_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000458 if (points) {
459 points[0] = fLastPt;
460 points[1] = srcPts[0];
461 points[2] = srcPts[1];
462 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000463 fLastPt = srcPts[1];
464 GrAssert(fPtIndex <= fPath->fPts.count() + 2);
bsalomon@google.com06e17952011-04-27 21:13:04 +0000465 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[0]));
466 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[1]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000467 fPtIndex += 2;
468 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000469 case kCubic_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000470 if (points) {
471 points[0] = fLastPt;
472 points[1] = srcPts[0];
473 points[2] = srcPts[1];
474 points[3] = srcPts[2];
475 }
476 fLastPt = srcPts[2];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000477 GrAssert(fPtIndex <= fPath->fPts.count() + 3);
bsalomon@google.com06e17952011-04-27 21:13:04 +0000478 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[0]));
479 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[1]));
480 GrAssert(fPath->getConservativeBounds().containsInclusive(srcPts[2]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000481 fPtIndex += 3;
482 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000483 case kClose_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000484 break;
485 default:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000486 GrAssert(!"unknown grpath cmd");
reed@google.comac10a2d2010-12-22 21:39:39 +0000487 break;
488 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000489 return cmd;
reed@google.comac10a2d2010-12-22 21:39:39 +0000490}
491
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000492GrConvexHint GrPath::Iter::convexHint() const {
493 return fPath->getConvexHint();
reed@google.comac10a2d2010-12-22 21:39:39 +0000494}
495
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000496GrPathCmd GrPath::Iter::next() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000497 return this->next(NULL);
498}
499
500void GrPath::Iter::rewind() {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000501 this->reset(*fPath);
reed@google.comac10a2d2010-12-22 21:39:39 +0000502}
503
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000504void GrPath::Iter::reset(const GrPath& path) {
505 fPath = &path;
506 fCmdIndex = fPtIndex = 0;
507}
reed@google.comac10a2d2010-12-22 21:39:39 +0000508
bsalomon@google.com06e17952011-04-27 21:13:04 +0000509bool GrPath::Iter::getConservativeBounds(GrRect* rect) const {
510 if (!fPath->getConservativeBounds().isEmpty()) {
511 *rect = fPath->getConservativeBounds();
512 return true;
513 }
514 return false;
515}
reed@google.comac10a2d2010-12-22 21:39:39 +0000516