blob: aa89d37382c77f89684f1a15f8647168cec83f51 [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 }
reed@google.com20efde72011-05-09 17:00:02 +0000107 fConservativeBounds.offset(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
reed@google.com7744c202011-05-06 19:26:26 +0000166 GrPoint firstPt = { 0, 0 };
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000167 // first edge of the subpath
reed@google.com7744c202011-05-06 19:26:26 +0000168 GrVec firstVec = { 0, 0 };
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000169 // vec of most recently processed edge, that wasn't degenerate
reed@google.com7744c202011-05-06 19:26:26 +0000170 GrVec previousVec = { 0, 0 };
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000171 // most recently processed point
reed@google.com7744c202011-05-06 19:26:26 +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) {
reed@google.com20efde72011-05-09 17:00:02 +0000224 fConservativeBounds.growToInclude(pts[i].fX, pts[i].fY);
bsalomon@google.com06e17952011-04-27 21:13:04 +0000225 }
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);
reed@google.com7744c202011-05-06 19:26:26 +0000242 GrVec vec = pts[consumed] - previousPt;
243// vec.setBetween(previousPt, pts[consumed]);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000244 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.
reed@google.com7744c202011-05-06 19:26:26 +0000272 GrVec vec = firstPt - previousPt;
273// vec.setBetween(previousPt, firstPt);
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000274 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
reed@google.com20efde72011-05-09 17:00:02 +0000426#ifdef SK_DEBUG
427static bool containsInclusive(const GrRect& rect, const GrPoint& point) {
428 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
429 point.fY >= rect.fTop && point.fY <= rect.fBottom;
430}
431#endif
432
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000433GrPathCmd GrPath::Iter::next(GrPoint points[]) {
434 if (fCmdIndex == fPath->fCmds.count()) {
435 GrAssert(fPtIndex == fPath->fPts.count());
436 return kEnd_PathCmd;
reed@google.comac10a2d2010-12-22 21:39:39 +0000437 } else {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000438 GrAssert(fCmdIndex < fPath->fCmds.count());
reed@google.comac10a2d2010-12-22 21:39:39 +0000439 }
440
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000441 GrPathCmd cmd = fPath->fCmds[fCmdIndex++];
442 const GrPoint* srcPts = fPath->fPts.begin() + fPtIndex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000443
444 switch (cmd) {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000445 case kMove_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000446 if (points) {
447 points[0] = srcPts[0];
448 }
449 fLastPt = srcPts[0];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000450 GrAssert(fPtIndex <= fPath->fPts.count() + 1);
reed@google.com20efde72011-05-09 17:00:02 +0000451 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000452 fPtIndex += 1;
453 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000454 case kLine_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000455 if (points) {
456 points[0] = fLastPt;
457 points[1] = srcPts[0];
458 }
459 fLastPt = srcPts[0];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000460 GrAssert(fPtIndex <= fPath->fPts.count() + 1);
reed@google.com20efde72011-05-09 17:00:02 +0000461 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000462 fPtIndex += 1;
463 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000464 case kQuadratic_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000465 if (points) {
466 points[0] = fLastPt;
467 points[1] = srcPts[0];
468 points[2] = srcPts[1];
469 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000470 fLastPt = srcPts[1];
471 GrAssert(fPtIndex <= fPath->fPts.count() + 2);
reed@google.com20efde72011-05-09 17:00:02 +0000472 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
473 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000474 fPtIndex += 2;
475 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000476 case kCubic_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000477 if (points) {
478 points[0] = fLastPt;
479 points[1] = srcPts[0];
480 points[2] = srcPts[1];
481 points[3] = srcPts[2];
482 }
483 fLastPt = srcPts[2];
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000484 GrAssert(fPtIndex <= fPath->fPts.count() + 3);
reed@google.com20efde72011-05-09 17:00:02 +0000485 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
486 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
487 GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[2]));
reed@google.comac10a2d2010-12-22 21:39:39 +0000488 fPtIndex += 3;
489 break;
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000490 case kClose_PathCmd:
reed@google.comac10a2d2010-12-22 21:39:39 +0000491 break;
492 default:
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000493 GrAssert(!"unknown grpath cmd");
reed@google.comac10a2d2010-12-22 21:39:39 +0000494 break;
495 }
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000496 return cmd;
reed@google.comac10a2d2010-12-22 21:39:39 +0000497}
498
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000499GrConvexHint GrPath::Iter::convexHint() const {
500 return fPath->getConvexHint();
reed@google.comac10a2d2010-12-22 21:39:39 +0000501}
502
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000503GrPathCmd GrPath::Iter::next() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000504 return this->next(NULL);
505}
506
507void GrPath::Iter::rewind() {
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000508 this->reset(*fPath);
reed@google.comac10a2d2010-12-22 21:39:39 +0000509}
510
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000511void GrPath::Iter::reset(const GrPath& path) {
512 fPath = &path;
513 fCmdIndex = fPtIndex = 0;
514}
reed@google.comac10a2d2010-12-22 21:39:39 +0000515
bsalomon@google.com06e17952011-04-27 21:13:04 +0000516bool GrPath::Iter::getConservativeBounds(GrRect* rect) const {
517 if (!fPath->getConservativeBounds().isEmpty()) {
518 *rect = fPath->getConservativeBounds();
519 return true;
520 }
521 return false;
522}
reed@google.comac10a2d2010-12-22 21:39:39 +0000523