use SkPath for GrPath, removing GrPathIter entirely

http://codereview.appspot.com/4515071/



git-svn-id: http://skia.googlecode.com/svn/trunk@1335 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrClip.cpp b/gpu/src/GrClip.cpp
index 2d1680c..c2613bb 100644
--- a/gpu/src/GrClip.cpp
+++ b/gpu/src/GrClip.cpp
@@ -132,7 +132,7 @@
                     }
                     break;
                 case kPath_ClipType:
-                    e.fPath.resetFromIter(iter->getPathIter());
+                    e.fPath = *iter->getPath();
                     if (tx || ty) {
                         e.fPath.offset(tx, ty);
                     }
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 8cb932b..3a4233a 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -19,7 +19,6 @@
 #include "GrTextureCache.h"
 #include "GrTextStrike.h"
 #include "GrMemory.h"
-#include "GrPathIter.h"
 #include "GrClipIterator.h"
 #include "GrIndexBuffer.h"
 #include "GrInOrderDrawBuffer.h"
@@ -1155,10 +1154,8 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrContext::drawPath(const GrPaint& paint,
-                         GrPathIter* path,
-                         GrPathFill fill,
-                         const GrPoint* translate) {
+void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
+                         GrPathFill fill, const GrPoint* translate) {
 
     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
     GrPathRenderer* pr = this->getPathRenderer(target, path, fill);
@@ -1180,8 +1177,8 @@
                 return;
             }
         }
-        GrRect pathBounds;
-        if (path->getConservativeBounds(&pathBounds)) {
+        GrRect pathBounds = path.getBounds();
+        if (!pathBounds.isEmpty()) {
             GrIRect pathIBounds;
             target->getViewMatrix().mapRect(&pathBounds, pathBounds);
             pathBounds.roundOut(&pathIBounds);
@@ -1204,15 +1201,6 @@
     pr->drawPath(target, enabledStages, path, fill, translate);
 }
 
-void GrContext::drawPath(const GrPaint& paint,
-                         const GrPath& path,
-                         GrPathFill fill,
-                         const GrPoint* translate) {
-    GrPath::Iter iter(path);
-    this->drawPath(paint, &iter, fill, translate);
-}
-
-
 ////////////////////////////////////////////////////////////////////////////////
 
 void GrContext::flush(int flagsBitfield) {
@@ -1483,7 +1471,7 @@
 }
 
 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
-                                           GrPathIter* path,
+                                           const GrPath& path,
                                            GrPathFill fill) {
     if (NULL != fCustomPathRenderer &&
         fCustomPathRenderer->canDrawPath(target, path, fill)) {
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 9950afd..a64a8db 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -467,17 +467,16 @@
                                                // resolve in/out status.
 
                 GrPathRenderer* pr = NULL;
-                GrPath::Iter pathIter;
+                const GrPath* clipPath = NULL;
                 if (kRect_ClipType == clip.getElementType(c)) {
                     canRenderDirectToStencil = true;
                     fill = kEvenOdd_PathFill;
                 } else {
                     fill = clip.getPathFill(c);
-                    const GrPath& path = clip.getPath(c);
-                    pathIter.reset(path);
-                    pr = this->getClipPathRenderer(&pathIter, NonInvertedFill(fill));
+                    clipPath = &clip.getPath(c);
+                    pr = this->getClipPathRenderer(*clipPath, NonInvertedFill(fill));
                     canRenderDirectToStencil =
-                        !pr->requiresStencilPass(this, &pathIter,
+                        !pr->requiresStencilPass(this, *clipPath,
                                                  NonInvertedFill(fill));
                 }
 
@@ -513,12 +512,10 @@
                     } else {
                         if (canRenderDirectToStencil) {
                             this->setStencil(gDrawToStencil);
-                            pr->drawPath(this, 0,
-                                         &pathIter,
-                                         NonInvertedFill(fill),
+                            pr->drawPath(this, 0, *clipPath, NonInvertedFill(fill),
                                          NULL);
                         } else {
-                            pr->drawPathToStencil(this, &pathIter,
+                            pr->drawPathToStencil(this, *clipPath,
                                                   NonInvertedFill(fill),
                                                   NULL);
                         }
@@ -537,7 +534,7 @@
                         } else {
                             SET_RANDOM_COLOR
                             GrAssert(!IsFillInverted(fill));
-                            pr->drawPath(this, 0, &pathIter, fill, NULL);
+                            pr->drawPath(this, 0, *clipPath, fill, NULL);
                         }
                     } else {
                         SET_RANDOM_COLOR
@@ -561,7 +558,7 @@
     return true;
 }
 
-GrPathRenderer* GrGpu::getClipPathRenderer(GrPathIter* path,
+GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path,
                                            GrPathFill fill) {
     if (NULL != fClientPathRenderer &&
         fClientPathRenderer->canDrawPath(this, path, fill)) {
diff --git a/gpu/src/GrPath.cpp b/gpu/src/GrPath.cpp
deleted file mode 100644
index aa89d37..0000000
--- a/gpu/src/GrPath.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-#include "GrPath.h"
-
-GrPath::GrPath() {
-    fConvexHint = kNone_ConvexHint;
-    fConservativeBounds.setLargestInverted();
-}
-
-GrPath::GrPath(const GrPath& src) : INHERITED() {
-    GrPath::Iter iter(src);
-    this->resetFromIter(&iter);
-}
-
-GrPath::GrPath(GrPathIter& iter) {
-    this->resetFromIter(&iter);
-}
-
-GrPath::~GrPath() {
-}
-
-bool GrPath::operator ==(const GrPath& path) const {
-    if (fCmds.count() != path.fCmds.count() ||
-        fPts.count() != path.fPts.count()) {
-        return false;
-    }
-
-    for (int v = 0; v < fCmds.count(); ++v) {
-        if (fCmds[v] != path.fCmds[v]) {
-            return false;
-        }
-    }
-
-    for (int p = 0; p < fPts.count(); ++p) {
-        if (fPts[p] != path.fPts[p]) {
-            return false;
-        }
-    }
-    return true;
-}
-
-void GrPath::ensureMoveTo() {
-    if (fCmds.isEmpty() || this->wasLastVerb(kClose_PathCmd)) {
-        *fCmds.append() = kMove_PathCmd;
-        fPts.append()->set(0, 0);
-        fConservativeBounds.growToInclude(0,0);
-    }
-}
-
-void GrPath::moveTo(GrScalar x, GrScalar y) {
-    if (this->wasLastVerb(kMove_PathCmd)) {
-        // overwrite prev kMove value
-        fPts[fPts.count() - 1].set(x, y);
-    } else {
-        *fCmds.append() = kMove_PathCmd;
-        fPts.append()->set(x, y);
-    }
-    fConservativeBounds.growToInclude(x,y);
-}
-
-void GrPath::lineTo(GrScalar x, GrScalar y) {
-    this->ensureMoveTo();
-    *fCmds.append() = kLine_PathCmd;
-    fPts.append()->set(x, y);
-    fConservativeBounds.growToInclude(x,y);
-}
-
-void GrPath::quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1) {
-    this->ensureMoveTo();
-    *fCmds.append() = kQuadratic_PathCmd;
-    fPts.append()->set(x0, y0);
-    fPts.append()->set(x1, y1);
-    fConservativeBounds.growToInclude(x0,y0);
-    fConservativeBounds.growToInclude(x1,y1);
-}
-
-void GrPath::cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
-                     GrScalar x2, GrScalar y2) {
-    this->ensureMoveTo();
-    *fCmds.append() = kCubic_PathCmd;
-    fPts.append()->set(x0, y0);
-    fPts.append()->set(x1, y1);
-    fPts.append()->set(x2, y2);
-    fConservativeBounds.growToInclude(x0,y0);
-    fConservativeBounds.growToInclude(x1,y1);
-    fConservativeBounds.growToInclude(x2,y2);
-}
-
-void GrPath::close() {
-    if (!fCmds.isEmpty() && !this->wasLastVerb(kClose_PathCmd)) {
-        // should we allow kMove followed by kClose?
-        *fCmds.append() = kClose_PathCmd;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GrPath::offset(GrScalar tx, GrScalar ty) {
-    if (!tx && !ty) {
-        return; // nothing to do
-    }
-
-    GrPoint* iter = fPts.begin();
-    GrPoint* stop = fPts.end();
-    while (iter < stop) {
-        iter->offset(tx, ty);
-        ++iter;
-    }
-    fConservativeBounds.offset(tx, ty);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static bool check_two_vecs(const GrVec& prevVec,
-                           const GrVec& currVec,
-                           GrScalar turnDir,
-                           int* xDir,
-                           int* yDir,
-                           int* flipX,
-                           int* flipY) {
-    if (currVec.fX * *xDir < 0) {
-        ++*flipX;
-        if (*flipX > 2) {
-            return false;
-        }
-        *xDir = -*xDir;
-    }
-    if (currVec.fY * *yDir < 0) {
-        ++*flipY;
-        if (*flipY > 2) {
-            return false;
-        }
-        *yDir = -*yDir;
-    }
-    GrScalar d = prevVec.cross(currVec);
-    return (d * turnDir) >= 0;
-}
-
-static void init_from_two_vecs(const GrVec& firstVec,
-                               const GrVec& secondVec,
-                               GrScalar* turnDir,
-                               int* xDir, int* yDir) {
-    *turnDir = firstVec.cross(secondVec);
-    if (firstVec.fX > 0) {
-        *xDir = 1;
-    } else if (firstVec.fX < 0) {
-        *xDir = -1;
-    } else {
-        *xDir = 0;
-    }
-    if (firstVec.fY > 0) {
-        *yDir = 1;
-    } else if (firstVec.fY < 0) {
-        *yDir = -1;
-    } else {
-        *yDir = 0;
-    }
-}
-
-void GrPath::resetFromIter(GrPathIter* iter) {
-    fPts.reset();
-    fCmds.reset();
-    fConservativeBounds.setLargestInverted();
-
-    fConvexHint = iter->convexHint();
-
-    // first point of the subpath
-    GrPoint firstPt = { 0, 0 };
-    // first edge of the subpath
-    GrVec firstVec = { 0, 0 };
-    // vec of most recently processed edge, that wasn't degenerate
-    GrVec previousVec = { 0, 0 };
-    // most recently processed point
-    GrPoint previousPt = { 0, 0 };
-
-    // sign indicates whether we're bending left or right
-    GrScalar turnDir = 0;
-    // number of times the direction has flipped in x or y
-
-    // we track which direction we are moving in x/y and the
-    // number of times it changes.
-    int xDir = 0;
-    int yDir = 0;
-    int flipX = 0;
-    int flipY = 0;
-
-    // counts number of sub path pts that didn't add a degenerate edge.
-    int subPathPts = 0;
-    bool subPathClosed = false;
-
-    int numSubPaths = 0;
-    iter->rewind();
-    GrPathCmd cmd;
-    GrPoint pts[4];
-    do {
-        cmd = iter->next(pts);
-        // If the convexity test is ever updated to handle multiple subpaths
-        // the loop has to be adjusted to handle moving to a new subpath without
-        // closing the previous one. Currently the implicit closing vectors for a
-        // filled path would never be examined.
-        switch (cmd) {
-            case kMove_PathCmd:
-                this->moveTo(pts[0].fX, pts[0].fY);
-                subPathPts = 0;
-                subPathClosed = false;
-                break;
-            case kLine_PathCmd:
-                this->lineTo(pts[1].fX, pts[1].fY);
-                break;
-            case kQuadratic_PathCmd:
-                this->quadTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
-                break;
-            case kCubic_PathCmd:
-                this->cubicTo(pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
-                              pts[3].fX, pts[3].fY);
-                break;
-            case kClose_PathCmd:
-                this->close();
-                subPathClosed = true;
-                break;
-            case kEnd_PathCmd:
-                break;
-        }
-        int n = NumPathCmdPoints(cmd);
-        for (int i = 0; i < n; ++i) {
-            fConservativeBounds.growToInclude(pts[i].fX, pts[i].fY);
-        }
-        if (0 == subPathPts && n > 0) {
-            previousPt = pts[0];
-            firstPt = previousPt;
-            flipX = 0;
-            flipY = 0;
-            turnDir = 0;
-            subPathPts = 1;
-            ++numSubPaths;
-        }
-        // either we skip the first pt because it is redundant with
-        // last point of the previous subpath cmd or we just ate it
-        // in the above if.
-        int consumed = 1;
-        if (numSubPaths < 2 && kNone_ConvexHint == fConvexHint) {
-            while (consumed < n) {
-                GrAssert(pts[consumed-1] == previousPt);
-                GrVec vec = pts[consumed] - previousPt;
-//                vec.setBetween(previousPt, pts[consumed]);
-                if (vec.fX || vec.fY) {
-                    if (subPathPts >= 2) {
-                        if (0 == turnDir) {
-                            firstVec = previousVec;
-                            init_from_two_vecs(firstVec, vec,
-                                               &turnDir, &xDir, &yDir);
-                            // here we aren't checking whether the x/y dirs
-                            // change between the first and second edge. It
-                            // gets covered when the path is closed.
-                        } else {
-                            if (!check_two_vecs(previousVec, vec, turnDir,
-                                                &xDir, &yDir,
-                                                &flipX, &flipY)) {
-                                fConvexHint = kConcave_ConvexHint;
-                                break;
-                            }
-                        }
-                    }
-                    previousVec = vec;
-                    previousPt = pts[consumed];
-                    ++subPathPts;
-                }
-                ++consumed;
-            }
-            if (subPathPts > 2 && (kClose_PathCmd == cmd ||
-                        (!subPathClosed && kEnd_PathCmd == cmd ))) {
-                // if an additional vector is needed to close the loop check
-                // that it validates against the previous vector.
-                GrVec vec = firstPt - previousPt;
-//                vec.setBetween(previousPt, firstPt);
-                if (vec.fX || vec.fY) {
-                    if (!check_two_vecs(previousVec, vec, turnDir,
-                                        &xDir, &yDir, &flipX, &flipY)) {
-                        fConvexHint = kConcave_ConvexHint;
-                        break;
-                    }
-                    previousVec = vec;
-                }
-                // check that closing vector validates against the first vector.
-                if (!check_two_vecs(previousVec, firstVec, turnDir,
-                                    &xDir, &yDir, &flipX, &flipY)) {
-                    fConvexHint = kConcave_ConvexHint;
-                    break;
-                }
-            }
-        }
-    } while (cmd != kEnd_PathCmd);
-    if (kNone_ConvexHint == fConvexHint && numSubPaths < 2) {
-        fConvexHint = kConvex_ConvexHint;
-    } else {
-        bool recurse = false;
-        if (recurse) {
-            this->resetFromIter(iter);
-        }
-    }
-}
-
-void GrPath::ConvexUnitTest() {
-    GrPath testPath;
-    GrPath::Iter testIter;
-
-    GrPath pt;
-    pt.moveTo(0, 0);
-    pt.close();
-
-    testIter.reset(pt);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
-    GrPath line;
-    line.moveTo(GrIntToScalar(12), GrIntToScalar(20));
-    line.lineTo(GrIntToScalar(-12), GrIntToScalar(-20));
-    line.close();
-
-    testIter.reset(line);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
-    GrPath triLeft;
-    triLeft.moveTo(0, 0);
-    triLeft.lineTo(1, 0);
-    triLeft.lineTo(1, 1);
-    triLeft.close();
-
-    testIter.reset(triLeft);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
-    GrPath triRight;
-    triRight.moveTo(0, 0);
-    triRight.lineTo(-1, 0);
-    triRight.lineTo(1, 1);
-    triRight.close();
-
-    testIter.reset(triRight);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
-    GrPath square;
-    square.moveTo(0, 0);
-    square.lineTo(1, 0);
-    square.lineTo(1, 1);
-    square.lineTo(0, 1);
-    square.close();
-
-    testIter.reset(square);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
-    GrPath redundantSquare;
-    square.moveTo(0, 0);
-    square.lineTo(0, 0);
-    square.lineTo(0, 0);
-    square.lineTo(1, 0);
-    square.lineTo(1, 0);
-    square.lineTo(1, 0);
-    square.lineTo(1, 1);
-    square.lineTo(1, 1);
-    square.lineTo(1, 1);
-    square.lineTo(0, 1);
-    square.lineTo(0, 1);
-    square.lineTo(0, 1);
-    square.close();
-
-    testIter.reset(redundantSquare);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
-
-    GrPath bowTie;
-    bowTie.moveTo(0, 0);
-    bowTie.lineTo(0, 0);
-    bowTie.lineTo(0, 0);
-    bowTie.lineTo(1, 1);
-    bowTie.lineTo(1, 1);
-    bowTie.lineTo(1, 1);
-    bowTie.lineTo(1, 0);
-    bowTie.lineTo(1, 0);
-    bowTie.lineTo(1, 0);
-    bowTie.lineTo(0, 1);
-    bowTie.lineTo(0, 1);
-    bowTie.lineTo(0, 1);
-    bowTie.close();
-
-    testIter.reset(bowTie);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
-
-    GrPath spiral;
-    spiral.moveTo(0, 0);
-    spiral.lineTo(1, 0);
-    spiral.lineTo(1, 1);
-    spiral.lineTo(0, 1);
-    spiral.lineTo(0,.5);
-    spiral.lineTo(.5,.5);
-    spiral.lineTo(.5,.75);
-    spiral.close();
-
-    testIter.reset(spiral);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
-
-    GrPath dent;
-    dent.moveTo(0, 0);
-    dent.lineTo(1, 1);
-    dent.lineTo(0, 1);
-    dent.lineTo(-.5,2);
-    dent.lineTo(-2, 1);
-    dent.close();
-
-    testIter.reset(dent);
-    testPath.resetFromIter(&testIter);
-    GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
-}
-///////////////////////////////////////////////////////////////////////////////
-
-GrPath::Iter::Iter() : fPath(NULL) {
-}
-
-GrPath::Iter::Iter(const GrPath& path) : fPath(&path) {
-    this->rewind();
-}
-
-#ifdef SK_DEBUG
-static bool containsInclusive(const GrRect& rect, const GrPoint& point) {
-    return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
-            point.fY >= rect.fTop && point.fY <= rect.fBottom;
-}
-#endif
-
-GrPathCmd GrPath::Iter::next(GrPoint points[]) {
-    if (fCmdIndex == fPath->fCmds.count()) {
-        GrAssert(fPtIndex == fPath->fPts.count());
-        return kEnd_PathCmd;
-    } else {
-        GrAssert(fCmdIndex < fPath->fCmds.count());
-    }
-
-    GrPathCmd cmd = fPath->fCmds[fCmdIndex++];
-    const GrPoint* srcPts = fPath->fPts.begin() + fPtIndex;
-
-    switch (cmd) {
-        case kMove_PathCmd:
-            if (points) {
-                points[0] = srcPts[0];
-            }
-            fLastPt = srcPts[0];
-            GrAssert(fPtIndex <= fPath->fPts.count() + 1);
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
-            fPtIndex += 1;
-            break;
-        case kLine_PathCmd:
-            if (points) {
-                points[0] = fLastPt;
-                points[1] = srcPts[0];
-            }
-            fLastPt = srcPts[0];
-            GrAssert(fPtIndex <= fPath->fPts.count() + 1);
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
-            fPtIndex += 1;
-            break;
-        case kQuadratic_PathCmd:
-            if (points) {
-                points[0] = fLastPt;
-                points[1] = srcPts[0];
-                points[2] = srcPts[1];
-            }
-            fLastPt = srcPts[1];
-            GrAssert(fPtIndex <= fPath->fPts.count() + 2);
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
-            fPtIndex += 2;
-            break;
-        case kCubic_PathCmd:
-            if (points) {
-                points[0] = fLastPt;
-                points[1] = srcPts[0];
-                points[2] = srcPts[1];
-                points[3] = srcPts[2];
-            }
-            fLastPt = srcPts[2];
-            GrAssert(fPtIndex <= fPath->fPts.count() + 3);
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[0]));
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[1]));
-            GrAssert(containsInclusive(fPath->getConservativeBounds(), srcPts[2]));
-            fPtIndex += 3;
-            break;
-        case kClose_PathCmd:
-            break;
-        default:
-            GrAssert(!"unknown grpath cmd");
-            break;
-    }
-    return cmd;
-}
-
-GrConvexHint GrPath::Iter::convexHint() const {
-    return fPath->getConvexHint();
-}
-
-GrPathCmd GrPath::Iter::next() {
-    return this->next(NULL);
-}
-
-void GrPath::Iter::rewind() {
-    this->reset(*fPath);
-}
-
-void GrPath::Iter::reset(const GrPath& path) {
-    fPath = &path;
-    fCmdIndex = fPtIndex = 0;
-}
-
-bool GrPath::Iter::getConservativeBounds(GrRect* rect) const {
-    if (!fPath->getConservativeBounds().isEmpty()) {
-        *rect = fPath->getConservativeBounds();
-        return true;
-    }
-    return false;
-}
-
diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp
index 317b7d3..5bea5e6 100644
--- a/gpu/src/GrPathRenderer.cpp
+++ b/gpu/src/GrPathRenderer.cpp
@@ -2,7 +2,6 @@
 
 #include "GrPoint.h"
 #include "GrDrawTarget.h"
-#include "GrPathIter.h"
 #include "GrPathUtils.h"
 #include "GrMemory.h"
 #include "GrTexture.h"
@@ -147,20 +146,24 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Helpers for drawPath
 
+static GrConvexHint getConvexHint(const SkPath& path) {
+    return path.isConvex() ? kConvex_ConvexHint : kConcave_ConvexHint;
+}
+
 #define STENCIL_OFF     0   // Always disable stencil (even when needed)
 
 static inline bool single_pass_path(const GrDrawTarget& target,
-                                    const GrPathIter& path,
+                                    const GrPath& path,
                                     GrPathFill fill) {
 #if STENCIL_OFF
     return true;
 #else
     if (kEvenOdd_PathFill == fill) {
-        GrConvexHint hint = path.convexHint();
+        GrConvexHint hint = getConvexHint(path);
         return hint == kConvex_ConvexHint ||
                hint == kNonOverlappingConvexPieces_ConvexHint;
     } else if (kWinding_PathFill == fill) {
-        GrConvexHint hint = path.convexHint();
+        GrConvexHint hint = getConvexHint(path);
         return hint == kConvex_ConvexHint ||
                hint == kNonOverlappingConvexPieces_ConvexHint ||
                (hint == kSameWindingConvexPieces_ConvexHint &&
@@ -172,14 +175,14 @@
 }
 
 bool GrDefaultPathRenderer::requiresStencilPass(const GrDrawTarget* target,
-                                                GrPathIter* path, 
+                                                const GrPath& path, 
                                                 GrPathFill fill) const {
-    return !single_pass_path(*target, *path, fill);
+    return !single_pass_path(*target, path, fill);
 }
 
 void GrDefaultPathRenderer::onDrawPath(GrDrawTarget* target,
                                        GrDrawTarget::StageBitfield stages,
-                                       GrPathIter* path,
+                                       const GrPath& path,
                                        GrPathFill fill,
                                        const GrPoint* translate,
                                        bool stencilOnly) {
@@ -205,8 +208,6 @@
     }
     GrScalar tolSqd = GrMul(tol, tol);
 
-    path->rewind();
-
     int subpathCnt;
     int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
 
@@ -226,8 +227,6 @@
 
     GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
 
-    path->rewind();
-
     // TODO: use primitve restart if available rather than multiple draws
     GrPrimitiveType             type;
     int                         passCount = 0;
@@ -248,7 +247,7 @@
         drawFace[0] = GrDrawTarget::kBoth_DrawFace;
     } else {
         type = kTriangleFan_PrimitiveType;
-        if (single_pass_path(*target, *path, fill)) {
+        if (single_pass_path(*target, path, fill)) {
             passCount = 1;
             if (stencilOnly) {
                 passes[0] = &gDirectToStencil;
@@ -329,8 +328,10 @@
     bool first = true;
     int subpath = 0;
 
+    SkPath::Iter iter(path, false);
+
     for (;;) {
-        GrPathCmd cmd = path->next(pts);
+        GrPathCmd cmd = (GrPathCmd)iter.next(pts);
         switch (cmd) {
             case kMove_PathCmd:
                 if (!first) {
@@ -431,14 +432,14 @@
 
 void GrDefaultPathRenderer::drawPath(GrDrawTarget* target,
                                      GrDrawTarget::StageBitfield stages,
-                                     GrPathIter* path,
+                                     const GrPath& path,
                                      GrPathFill fill,
                                      const GrPoint* translate) {
     this->onDrawPath(target, stages, path, fill, translate, false);
 }
 
 void GrDefaultPathRenderer::drawPathToStencil(GrDrawTarget* target,
-                                              GrPathIter* path,
+                                              const GrPath& path,
                                               GrPathFill fill,
                                               const GrPoint* translate) {
     GrAssert(kInverseEvenOdd_PathFill != fill);
diff --git a/gpu/src/GrPathUtils.cpp b/gpu/src/GrPathUtils.cpp
index 115b0f6..69dd0e6 100644
--- a/gpu/src/GrPathUtils.cpp
+++ b/gpu/src/GrPathUtils.cpp
@@ -15,8 +15,6 @@
  */
 
 #include "GrPathUtils.h"
-
-#include "GrPathIter.h"
 #include "GrPoint.h"
 
 const GrScalar GrPathUtils::gTolerance = GR_Scalar1;
@@ -106,18 +104,18 @@
     return a + b;
 }
 
-int GrPathUtils::worstCasePointCount(GrPathIter* path,
-                                        int* subpaths,
-                                        GrScalar tol) {
+int GrPathUtils::worstCasePointCount(const GrPath& path, int* subpaths,
+                                     GrScalar tol) {
     int pointCount = 0;
     *subpaths = 1;
 
     bool first = true;
 
+    SkPath::Iter iter(path, false);
     GrPathCmd cmd;
 
     GrPoint pts[4];
-    while ((cmd = path->next(pts)) != kEnd_PathCmd) {
+    while ((cmd = (GrPathCmd)iter.next(pts)) != kEnd_PathCmd) {
 
         switch (cmd) {
             case kLine_PathCmd:
diff --git a/gpu/src/GrPathUtils.h b/gpu/src/GrPathUtils.h
index af05682..2cd00cb 100644
--- a/gpu/src/GrPathUtils.h
+++ b/gpu/src/GrPathUtils.h
@@ -19,15 +19,14 @@
 
 #include "GrNoncopyable.h"
 #include "GrPoint.h"
-
-class GrPathIter;
+#include "GrPath.h"
 
 /**
  *  Utilities for evaluating paths.
  */
 class GrPathUtils : public GrNoncopyable {
 public:
-    static int worstCasePointCount(GrPathIter* path,
+    static int worstCasePointCount(const GrPath&,
                                    int* subpaths,
                                    GrScalar tol);
     static uint32_t quadraticPointCount(const GrPoint points[], GrScalar tol);
diff --git a/gpu/src/GrTesselatedPathRenderer.cpp b/gpu/src/GrTesselatedPathRenderer.cpp
index 19ee46d..da6da5c 100644
--- a/gpu/src/GrTesselatedPathRenderer.cpp
+++ b/gpu/src/GrTesselatedPathRenderer.cpp
@@ -18,6 +18,8 @@
 
 #include "GrMemory.h"
 #include "GrPathUtils.h"
+#include "GrPoint.h"
+#include "GrTDArray.h"
 
 #include <internal_glu.h>
 
@@ -137,7 +139,7 @@
 
 void GrTesselatedPathRenderer::drawPath(GrDrawTarget* target,
                                         GrDrawTarget::StageBitfield stages,
-                                        GrPathIter* path,
+                                        const GrPath& path,
                                         GrPathFill fill,
                                         const GrPoint* translate) {
     GrDrawTarget::AutoStateRestore asr(target);
@@ -161,8 +163,6 @@
     }
     GrScalar tolSqd = GrMul(tol, tol);
 
-    path->rewind();
-
     int subpathCnt;
     int maxPts = GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
 
@@ -184,16 +184,14 @@
 
     GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
 
-    path->rewind();
-
     GrPoint pts[4];
+    SkPath::Iter iter(path, true);
 
     bool first = true;
     int subpath = 0;
 
     for (;;) {
-        GrPathCmd cmd = path->next(pts);
-        switch (cmd) {
+        switch (iter.next(pts)) {
             case kMove_PathCmd:
                 if (!first) {
                     subpathVertCount[subpath] = vert-subpathBase;
@@ -262,7 +260,7 @@
       return;
     }
 
-    if (subpathCnt == 1 && !inverted && path->convexHint() == kConvex_ConvexHint) {
+    if (subpathCnt == 1 && !inverted && path.isConvex()) {
         if (target->isAntialiasState()) {
             target->enableState(GrDrawTarget::kEdgeAA_StateBit);
             EdgeArray edges;
@@ -347,25 +345,25 @@
 }
 
 bool GrTesselatedPathRenderer::canDrawPath(const GrDrawTarget* target,
-                                           GrPathIter* path,
+                                           const SkPath& path,
                                            GrPathFill fill) const {
     return kHairLine_PathFill != fill;
 }
 
 void GrTesselatedPathRenderer::drawPathToStencil(GrDrawTarget* target,
-                                                 GrPathIter* path,
+                                                 const SkPath& path,
                                                  GrPathFill fill,
                                                  const GrPoint* translate) {
     GrAlwaysAssert(!"multipass stencil should not be needed");
 }
 
 bool GrTesselatedPathRenderer::supportsAA(GrDrawTarget* target,
-                                                  GrPathIter* path,
+                                                  const SkPath& path,
                                                   GrPathFill fill) {
     int subpathCnt = 0;
     int tol = GrPathUtils::gTolerance;
     GrPathUtils::worstCasePointCount(path, &subpathCnt, tol);
     return (subpathCnt == 1 &&
             !IsFillInverted(fill) &&
-            path->convexHint() == kConvex_ConvexHint);
+            path.isConvex());
 }
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 0222042..9e8e40a 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -201,11 +201,11 @@
             }
             glyph->fPath = path;
         }
-        GrPath::Iter iter(*glyph->fPath);
+
         GrPoint translate;
         translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)),
                       GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop)));
-        fContext->drawPath(fPaint, &iter, kWinding_PathFill,
+        fContext->drawPath(fPaint, *glyph->fPath, kWinding_PathFill,
                            &translate);
         return;
     }
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index fef9784..bd6f061 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -19,10 +19,10 @@
     GrInOrderDrawBuffer.cpp \
     GrMatrix.cpp \
     GrMemory.cpp \
-    GrPath.cpp \
     GrPathUtils.cpp \
     GrRectanizer_fifo.cpp \
     GrResource.cpp \
+    GrTesselatedPathRenderer.cpp \
     GrTexture.cpp \
     GrTextureCache.cpp \
     GrTextContext.cpp \
diff --git a/gpu/src/gr_unittests.cpp b/gpu/src/gr_unittests.cpp
index 320dd15..7981bb1 100644
--- a/gpu/src/gr_unittests.cpp
+++ b/gpu/src/gr_unittests.cpp
@@ -148,12 +148,131 @@
     GrAssert(keyBust3.compare(keyBust2) == 0);
 }
 
+static void test_convex() {
+#if 0
+    GrPath testPath;
+    GrPath::Iter testIter;
+    
+    GrPath pt;
+    pt.moveTo(0, 0);
+    pt.close();
+    
+    testIter.reset(pt);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+    
+    GrPath line;
+    line.moveTo(GrIntToScalar(12), GrIntToScalar(20));
+    line.lineTo(GrIntToScalar(-12), GrIntToScalar(-20));
+    line.close();
+    
+    testIter.reset(line);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+    
+    GrPath triLeft;
+    triLeft.moveTo(0, 0);
+    triLeft.lineTo(1, 0);
+    triLeft.lineTo(1, 1);
+    triLeft.close();
+    
+    testIter.reset(triLeft);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+    
+    GrPath triRight;
+    triRight.moveTo(0, 0);
+    triRight.lineTo(-1, 0);
+    triRight.lineTo(1, 1);
+    triRight.close();
+    
+    testIter.reset(triRight);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+    
+    GrPath square;
+    square.moveTo(0, 0);
+    square.lineTo(1, 0);
+    square.lineTo(1, 1);
+    square.lineTo(0, 1);
+    square.close();
+    
+    testIter.reset(square);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+    
+    GrPath redundantSquare;
+    square.moveTo(0, 0);
+    square.lineTo(0, 0);
+    square.lineTo(0, 0);
+    square.lineTo(1, 0);
+    square.lineTo(1, 0);
+    square.lineTo(1, 0);
+    square.lineTo(1, 1);
+    square.lineTo(1, 1);
+    square.lineTo(1, 1);
+    square.lineTo(0, 1);
+    square.lineTo(0, 1);
+    square.lineTo(0, 1);
+    square.close();
+    
+    testIter.reset(redundantSquare);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
+    
+    GrPath bowTie;
+    bowTie.moveTo(0, 0);
+    bowTie.lineTo(0, 0);
+    bowTie.lineTo(0, 0);
+    bowTie.lineTo(1, 1);
+    bowTie.lineTo(1, 1);
+    bowTie.lineTo(1, 1);
+    bowTie.lineTo(1, 0);
+    bowTie.lineTo(1, 0);
+    bowTie.lineTo(1, 0);
+    bowTie.lineTo(0, 1);
+    bowTie.lineTo(0, 1);
+    bowTie.lineTo(0, 1);
+    bowTie.close();
+    
+    testIter.reset(bowTie);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
+    
+    GrPath spiral;
+    spiral.moveTo(0, 0);
+    spiral.lineTo(1, 0);
+    spiral.lineTo(1, 1);
+    spiral.lineTo(0, 1);
+    spiral.lineTo(0,.5);
+    spiral.lineTo(.5,.5);
+    spiral.lineTo(.5,.75);
+    spiral.close();
+    
+    testIter.reset(spiral);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
+    
+    GrPath dent;
+    dent.moveTo(0, 0);
+    dent.lineTo(1, 1);
+    dent.lineTo(0, 1);
+    dent.lineTo(-.5,2);
+    dent.lineTo(-2, 1);
+    dent.close();
+    
+    testIter.reset(dent);
+    testPath.resetFromIter(&testIter);
+    GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
+#endif
+}
+
 void gr_run_unittests() {
     test_tdarray();
     test_bsearch();
     test_binHashKey();
+    test_convex();
     GrRedBlackTree<int>::UnitTest();
-    GrPath::ConvexUnitTest();
     GrDrawTarget::VertexLayoutUnitTest();
 }