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/Makefile b/Makefile
index d03c12f..7a53951 100644
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@
 GPP := g++
 C_INCLUDES := -Iinclude/config -Iinclude/core -Iinclude/effects -Iinclude/images -Iinclude/ports
 C_INCLUDES +=  -Iinclude/gpu -Iinclude/utils -Igpu/include
+C_INCLUDES +=  -Ithird_party/glu
 
 CFLAGS := -Wall -fstrict-aliasing
 #CFLAGS += -W -Wextra -Wcast-align -Wchar-subscripts -Wformat -Wformat-security -Wno-format-y2k -Wno-parentheses -Wno-unused-parameter -Wpointer-arith  -Wreturn-type -Wundef -Wwrite-strings
diff --git a/gpu/include/GrClipIterator.h b/gpu/include/GrClipIterator.h
index 1fcbdd1..f7f74a7 100644
--- a/gpu/include/GrClipIterator.h
+++ b/gpu/include/GrClipIterator.h
@@ -47,7 +47,7 @@
      * Return the current path. It is an error to call this when isDone() is
      * true or when getType() is kRect_Type.
      */
-    virtual GrPathIter* getPathIter() = 0;
+    virtual const GrPath* getPath() = 0;
 
     /**
      * Return the fill rule for the path. It is an error to call this when
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 951c0e6..c29526a 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -25,7 +25,6 @@
 class GrFontCache;
 class GrGpu;
 struct GrGpuStats;
-class GrPathIter;
 class GrVertexBufferAllocPool;
 class GrIndexBufferAllocPool;
 class GrInOrderDrawBuffer;
@@ -323,22 +322,14 @@
      * Draws a path.
      *
      * @param paint         describes how to color pixels.
-     * @param pathIter      the path to draw
+     * @param path          the path to draw
      * @param fill          the path filling rule to use.
      * @param translate     optional additional translation applied to the
      *                      path.
      */
-    void drawPath(const GrPaint& paint,
-                  GrPathIter* pathIter,
-                  GrPathFill fill,
+    void drawPath(const GrPaint& paint, const GrPath& path, GrPathFill fill,
                   const GrPoint* translate = NULL);
-    /**
-     * Helper version of drawPath that takes a GrPath
-     */
-    void drawPath(const GrPaint& paint,
-                  const GrPath& path,
-                  GrPathFill fill,
-                  const GrPoint* translate = NULL);
+
     /**
      * Draws vertices with a paint.
      *
@@ -585,9 +576,7 @@
 
     void drawClipIntoStencil();
 
-    GrPathRenderer* getPathRenderer(const GrDrawTarget* target,
-                                    GrPathIter* path,
-                                    GrPathFill fill);
+    GrPathRenderer* getPathRenderer(const GrDrawTarget*, const GrPath&, GrPathFill);
 
     struct OffscreenRecord;
     // we currently only expose stage 0 through the paint so use stage 1. We
diff --git a/gpu/include/GrFontScaler.h b/gpu/include/GrFontScaler.h
index 77730d7..ab73ea4 100644
--- a/gpu/include/GrFontScaler.h
+++ b/gpu/include/GrFontScaler.h
@@ -21,7 +21,7 @@
 #include "GrGlyph.h"
 #include "GrKey.h"
 
-class GrPath;
+class SkPath;
 
 /**
  *  This is a virtual base class which Gr's interface to the host platform's
@@ -37,7 +37,7 @@
     virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds) = 0;
     virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
                                      int rowBytes, void* image) = 0;
-    virtual bool getGlyphPath(uint16_t glyphID, GrPath*) = 0;
+    virtual bool getGlyphPath(uint16_t glyphID, SkPath*) = 0;
 };
 
 #endif
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index e44956f..1bb5c54 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -513,8 +513,7 @@
     void prepareIndexPool();
 
     // determines the path renderer used to draw a clip path element.
-    GrPathRenderer* getClipPathRenderer(GrPathIter* path,
-                                        GrPathFill fill);
+    GrPathRenderer* getClipPathRenderer(const SkPath& path, GrPathFill fill);
 
     void handleDirtyContext() {
         if (fContextIsDirty) {
diff --git a/gpu/include/GrPath.h b/gpu/include/GrPath.h
index f958329..c23cfc4 100644
--- a/gpu/include/GrPath.h
+++ b/gpu/include/GrPath.h
@@ -18,91 +18,10 @@
 #ifndef GrPath_DEFINED
 #define GrPath_DEFINED
 
-#include "GrPathSink.h"
-#include "GrPathIter.h"
-#include "GrTDArray.h"
-#include "GrPoint.h"
-#include "GrRect.h"
+#include "GrTypes.h"
+#include "SkPath.h"
 
-class GrPath : public GrPathSink {
-public:
-    GrPath();
-    GrPath(const GrPath&);
-    explicit GrPath(GrPathIter&);
-    virtual ~GrPath();
-
-    GrConvexHint getConvexHint() const { return fConvexHint; }
-    void setConvexHint(GrConvexHint hint) { fConvexHint = hint; }
-
-    const GrRect& getConservativeBounds() const { return fConservativeBounds; }
-
-    void resetFromIter(GrPathIter*);
-
-    bool operator ==(const GrPath& path) const;
-    bool operator !=(const GrPath& path) const { return !(*this == path); }
-    // overrides from GrPathSink
-
-    virtual void moveTo(GrScalar x, GrScalar y);
-    virtual void lineTo(GrScalar x, GrScalar y);
-    virtual void quadTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1);
-    virtual void cubicTo(GrScalar x0, GrScalar y0, GrScalar x1, GrScalar y1,
-                         GrScalar x2, GrScalar y2);
-    virtual void close();
-
-    /**
-     *  Offset the path by (tx, ty), adding tx to the horizontal position
-     *  and adds ty to the vertical position of every point.
-     */
-    void offset(GrScalar tx, GrScalar ty);
-
-    class Iter : public GrPathIter {
-    public:
-        /**
-         * Creates an uninitialized iterator
-         */
-        Iter();
-
-        Iter(const GrPath& path);
-
-        // overrides from GrPathIter
-        virtual GrPathCmd next(GrPoint points[]);
-        virtual GrConvexHint convexHint() const;
-        virtual GrPathCmd next();
-        virtual void rewind();
-        virtual bool getConservativeBounds(GrRect* rect) const;
-
-        /**
-         * Sets iterator to begining of path
-         */
-        void reset(const GrPath& path);
-    private:
-        const GrPath* fPath;
-        GrPoint       fLastPt;
-        int           fCmdIndex;
-        int           fPtIndex;
-    };
-
-    static void ConvexUnitTest();
-
-private:
-
-    GrTDArray<GrPathCmd>    fCmds;
-    GrTDArray<GrPoint>      fPts;
-    GrConvexHint            fConvexHint;
-    GrRect                  fConservativeBounds;
-
-    // this ensures we have a moveTo at the start of each contour
-    inline void ensureMoveTo();
-
-    bool wasLastVerb(GrPathCmd cmd) const {
-        int count = fCmds.count();
-        return count > 0 && cmd == fCmds[count - 1];
-    }
-
-    friend class Iter;
-
-    typedef GrPathSink INHERITED;
-};
+typedef SkPath GrPath;
 
 #endif
 
diff --git a/gpu/include/GrPathIter.h b/gpu/include/GrPathIter.h
deleted file mode 100644
index e67ff69..0000000
--- a/gpu/include/GrPathIter.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-    Copyright 2010 Google Inc.
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- */
-
-
-#ifndef GrPathIter_DEFINED
-#define GrPathIter_DEFINED
-
-#include "GrRect.h"
-
-/**
- 2D Path iterator. Porting layer creates a subclass of this. It allows Ganesh to
- parse the top-level API's 2D paths. Supports lines, quadratics, and cubic
- pieces and moves (multi-part paths).
- */
-class GrPathIter {
-public:
-
-    virtual ~GrPathIter() {};
-
-    /**
-     * Iterates through the path. Should not be called after
-     * kEnd_Command has been returned once. This version retrieves the
-     * points for the command.
-     * @param points  The points relevant to returned commend. See Command
-     *               enum for number of points valid for each command.
-     * @return The next command of the path.
-     */
-    virtual GrPathCmd next(GrPoint points[4]) = 0;
-
-    /**
-     * If the host API has knowledge of the convexity of the path
-     * it can be communicated by this hint. Gr can analyze the path
-     * as it is iterated. So it is not necessary to do additional work to
-     * compute convexity status if it isn't already determined.
-     *
-     * @return a hint about the convexity of the path.
-     */
-    virtual GrConvexHint convexHint() const = 0;
-
-     /**
-      * Iterates through the path. Should not be called after
-      * kEnd_Command has been returned once. This version does not retrieve the
-      * points for the command.
-      * @return The next command of the path.
-      */
-     virtual GrPathCmd next() = 0;
-
-     /**
-      * Returns conservative bounds on the path points. If returns false then
-      * no bounds are available.
-      */
-     virtual bool getConservativeBounds(GrRect* rect) const = 0;
-
-    /**
-     Restarts iteration from the beginning.
-     */
-    virtual void rewind() = 0;
-
-};
-
-#endif
diff --git a/gpu/include/GrPathRenderer.h b/gpu/include/GrPathRenderer.h
index 21cab6b..1ebad4f 100644
--- a/gpu/include/GrPathRenderer.h
+++ b/gpu/include/GrPathRenderer.h
@@ -19,7 +19,7 @@
 
 #include "GrDrawTarget.h"
 
-class GrPathIter;
+class SkPath;
 struct GrPoint;
 
 /**
@@ -37,8 +37,7 @@
      *
      * @return  true if the path can be drawn by this object, false otherwise.
      */
-    virtual bool canDrawPath(const GrDrawTarget* target,
-                             GrPathIter* path,
+    virtual bool canDrawPath(const GrDrawTarget* target, const SkPath& path,
                              GrPathFill fill) const = 0;
 
     /**
@@ -57,7 +56,7 @@
      */
     virtual void drawPath(GrDrawTarget* target,
                           GrDrawTarget::StageBitfield stages,
-                          GrPathIter* path,
+                          const SkPath& path,
                           GrPathFill fill,
                           const GrPoint* translate) = 0;
 
@@ -80,7 +79,7 @@
      *         clips.
      */
     virtual bool requiresStencilPass(const GrDrawTarget* target,
-                                     GrPathIter* path,
+                                     const SkPath& path,
                                      GrPathFill fill) const { return false; }
 
     /**
@@ -102,7 +101,7 @@
      *                              the path. NULL means (0,0).
      */
     virtual void drawPathToStencil(GrDrawTarget* target,
-                                   GrPathIter* path,
+                                   const SkPath& path,
                                    GrPathFill fill,
                                    const GrPoint* translate) {
         GrCrash("Unexpected call to drawPathToStencil.");
@@ -113,7 +112,7 @@
      * having FSAA enabled for a render target)
      */
     virtual bool supportsAA(GrDrawTarget* target,
-                            GrPathIter* path,
+                            const SkPath& path,
                             GrPathFill fill) { return false; }
 
     /**
@@ -138,26 +137,26 @@
                           bool stencilWrapOpsSupport);
 
     virtual bool canDrawPath(const GrDrawTarget* target,
-                             GrPathIter* path,
+                             const SkPath& path,
                              GrPathFill fill) const { return true; }
 
     virtual void drawPath(GrDrawTarget* target,
                           GrDrawTarget::StageBitfield stages,
-                          GrPathIter* path,
+                          const SkPath& path,
                           GrPathFill fill,
                           const GrPoint* translate);
     virtual bool requiresStencilPass(const GrDrawTarget* target,
-                                     GrPathIter* path,
+                                     const SkPath& path,
                                      GrPathFill fill) const;
     virtual void drawPathToStencil(GrDrawTarget* target,
-                                   GrPathIter* path,
+                                   const SkPath& path,
                                    GrPathFill fill,
                                    const GrPoint* translate);
 private:
 
     void onDrawPath(GrDrawTarget* target,
                     GrDrawTarget::StageBitfield stages,
-                    GrPathIter* path,
+                    const SkPath& path,
                     GrPathFill fill,
                     const GrPoint* translate,
                     bool stencilOnly);
diff --git a/gpu/include/GrTesselatedPathRenderer.h b/gpu/include/GrTesselatedPathRenderer.h
index accd114..e37e66b 100644
--- a/gpu/include/GrTesselatedPathRenderer.h
+++ b/gpu/include/GrTesselatedPathRenderer.h
@@ -25,22 +25,22 @@
 
     virtual void drawPath(GrDrawTarget* target,
                           GrDrawTarget::StageBitfield stages,
-                          GrPathIter* path,
+                          const GrPath& path,
                           GrPathFill fill,
                           const GrPoint* translate);
     virtual bool canDrawPath(const GrDrawTarget* target,
-                             GrPathIter* path,
+                             const GrPath& path,
                              GrPathFill fill) const;
 
     virtual bool requiresStencilPass(const GrDrawTarget* target,
-                                     GrPathIter* path,
+                                     const GrPath& path,
                                      GrPathFill fill) const { return false; }
     virtual void drawPathToStencil(GrDrawTarget* target,
-                                   GrPathIter* path,
+                                   const GrPath& path,
                                    GrPathFill fill,
                                    const GrPoint* translate);
     virtual bool supportsAA(GrDrawTarget* target,
-                            GrPathIter* path,
+                            const GrPath& path,
                             GrPathFill fill);
 };
 
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();
 }
 
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 75099b2..65565c9 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -24,8 +24,8 @@
 #include "GrConfig.h"
 #include "GrContext.h"
 #include "GrFontScaler.h"
-#include "GrPathIter.h"
 #include "GrClipIterator.h"
+#include "GrPath.h"
 
 // skia headers
 #include "SkBitmap.h"
@@ -130,29 +130,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Classes
 
-class SkGrPathIter : public GrPathIter {
-public:
-    SkGrPathIter() { fPath = NULL; }
-    SkGrPathIter(const SkPath& path) { reset(path); }
-    virtual GrPathCmd next(GrPoint pts[]);
-    virtual GrPathCmd next();
-    virtual void rewind();
-    virtual GrConvexHint convexHint() const;
-    virtual bool getConservativeBounds(GrRect* rect) const;
-
-    void reset(const SkPath& path) {
-        fPath = &path;
-        fIter.setPath(path, false);
-    }
-private:
-
-#if !SK_SCALAR_IS_GR_SCALAR
-    SkPoint             fPoints[4];
-#endif
-    SkPath::Iter        fIter;
-    const SkPath*       fPath;
-};
-
 class SkGrClipIterator : public GrClipIterator {
 public:
     SkGrClipIterator() { fClipStack = NULL;  fCurr = NULL; }
@@ -176,9 +153,8 @@
         }
     }
 
-    virtual GrPathIter* getPathIter() {
-        fPathIter.reset(*fCurr->fPath);
-        return &fPathIter;
+    virtual const GrPath* getPath() {
+        return fCurr->fPath;
     }
 
     virtual GrPathFill getPathFill() const;
@@ -186,7 +162,6 @@
 private:
     const SkClipStack*                  fClipStack;
     SkClipStack::B2FIter                fIter;
-    SkGrPathIter                        fPathIter;
     // SkClipStack's auto advances on each get
     // so we store the current pos here.
     const SkClipStack::B2FIter::Clip*   fCurr;
@@ -218,7 +193,7 @@
         rect->fBottom = GrIntToScalar(r.fBottom);
     }
 
-    virtual GrPathIter* getPathIter() {
+    virtual const GrPath* getPath() {
         SkASSERT(0);
         return NULL;
     }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index afea47a..a015347 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -860,8 +860,7 @@
         }
     }
 
-    SkGrPathIter iter(*pathPtr);
-    fContext->drawPath(grPaint, &iter, fill);
+    fContext->drawPath(grPaint, *pathPtr, fill);
 }
 
 void SkGpuDevice::drawBitmap(const SkDraw& draw,
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index f65cf1e..600c336 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -112,42 +112,6 @@
                                      bitmap->rowBytes());
 }
 
-////////////////////////////////////////////////////////////////////////////////
-
-
-GrPathCmd SkGrPathIter::next(GrPoint pts[]) {
-    GrAssert(NULL != pts);
-#if SK_SCALAR_IS_GR_SCALAR
-    return sk_path_verb_to_gr_path_command(fIter.next((SkPoint*)pts));
-#else
-    Command cmd = sk_path_verb_to_gr_path_command(fIter.next(fPoints));
-    int n = NumCommandPoints(cmd);
-    for (int i = 0; i < n; ++i) {
-        pts[i].fX = SkScalarToGrScalar(fPoints[i].fX);
-        pts[i].fY = SkScalarToGrScalar(fPoints[i].fY);
-    }
-    return cmd;
-#endif
-}
-
-GrPathCmd SkGrPathIter::next() {
-    return sk_path_verb_to_gr_path_command(fIter.next(NULL));
-}
-
-void SkGrPathIter::rewind() {
-    fIter.setPath(*fPath, false);
-}
-
-GrConvexHint SkGrPathIter::convexHint() const {
-    return fPath->isConvex() ? kConvex_ConvexHint :
-                               kNone_ConvexHint;
-}
-
-bool SkGrPathIter::getConservativeBounds(GrRect* rect) const {
-    *rect = fPath->getBounds();
-    return true;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkGrClipIterator::reset(const SkClipStack& clipStack) {
diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp
index e58f035..eb260fb 100644
--- a/src/gpu/SkGrFontScaler.cpp
+++ b/src/gpu/SkGrFontScaler.cpp
@@ -163,13 +163,13 @@
     return true;
 }
 
+// we should just return const SkPath* (NULL means false)
 bool SkGrFontScaler::getGlyphPath(uint16_t glyphID, GrPath* path) {
 
     const SkGlyph& glyph = fStrike->getGlyphIDMetrics(glyphID);
     const SkPath* skPath = fStrike->findPath(glyph);
     if (skPath) {
-        SkGrPathIter iter(*skPath);
-        path->resetFromIter(&iter);
+        *path = *skPath;
         return true;
     }
     return false;
diff --git a/xcode/gpu/gpu.xcodeproj/project.pbxproj b/xcode/gpu/gpu.xcodeproj/project.pbxproj
index ec49dbf..024fd2f 100644
--- a/xcode/gpu/gpu.xcodeproj/project.pbxproj
+++ b/xcode/gpu/gpu.xcodeproj/project.pbxproj
@@ -25,7 +25,6 @@
 		00115E1D12C1167A008296FE /* GrInOrderDrawBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DED12C1167A008296FE /* GrInOrderDrawBuffer.cpp */; };
 		00115E1E12C1167A008296FE /* GrMatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DEE12C1167A008296FE /* GrMatrix.cpp */; };
 		00115E1F12C1167A008296FE /* GrMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DEF12C1167A008296FE /* GrMemory.cpp */; };
-		00115E2012C1167A008296FE /* GrPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DF012C1167A008296FE /* GrPath.cpp */; };
 		00115E2412C1167A008296FE /* GrRectanizer_fifo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DF412C1167A008296FE /* GrRectanizer_fifo.cpp */; };
 		00115E2512C1167A008296FE /* GrRectanizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DF512C1167A008296FE /* GrRectanizer.cpp */; };
 		00115E2612C1167A008296FE /* GrTextContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00115DF612C1167A008296FE /* GrTextContext.cpp */; };
@@ -87,6 +86,7 @@
 		00216E5E130F0B03009A2160 /* GrGLIRect.h in Headers */ = {isa = PBXBuildFile; fileRef = 00216E5D130F0B03009A2160 /* GrGLIRect.h */; };
 		005CE9221372E6D200F36FD0 /* GrGpuGLShaders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 005CE9211372E6D200F36FD0 /* GrGpuGLShaders.cpp */; };
 		005CE93C1372E70900F36FD0 /* GrGLProgram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 005CE93B1372E70900F36FD0 /* GrGLProgram.cpp */; };
+		00ACCE171381719E009214F3 /* GrTesselatedPathRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00ACCE161381719E009214F3 /* GrTesselatedPathRenderer.cpp */; };
 		7D669346132ABD5D003AC2F5 /* GrGLInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7D669345132ABD5D003AC2F5 /* GrGLInterface.cpp */; };
 		7D66934C132ABD8F003AC2F5 /* GrGLInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D66934B132ABD8F003AC2F5 /* GrGLInterface.h */; };
 		7D6EBF5A13330E8400AEAADD /* GrGLDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D6EBF5913330E8400AEAADD /* GrGLDefines.h */; };
@@ -129,7 +129,6 @@
 		00115DED12C1167A008296FE /* GrInOrderDrawBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrInOrderDrawBuffer.cpp; path = ../../gpu/src/GrInOrderDrawBuffer.cpp; sourceTree = SOURCE_ROOT; };
 		00115DEE12C1167A008296FE /* GrMatrix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrMatrix.cpp; path = ../../gpu/src/GrMatrix.cpp; sourceTree = SOURCE_ROOT; };
 		00115DEF12C1167A008296FE /* GrMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrMemory.cpp; path = ../../gpu/src/GrMemory.cpp; sourceTree = SOURCE_ROOT; };
-		00115DF012C1167A008296FE /* GrPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrPath.cpp; path = ../../gpu/src/GrPath.cpp; sourceTree = SOURCE_ROOT; };
 		00115DF412C1167A008296FE /* GrRectanizer_fifo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrRectanizer_fifo.cpp; path = ../../gpu/src/GrRectanizer_fifo.cpp; sourceTree = SOURCE_ROOT; };
 		00115DF512C1167A008296FE /* GrRectanizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrRectanizer.cpp; path = ../../gpu/src/GrRectanizer.cpp; sourceTree = SOURCE_ROOT; };
 		00115DF612C1167A008296FE /* GrTextContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrTextContext.cpp; path = ../../gpu/src/GrTextContext.cpp; sourceTree = SOURCE_ROOT; };
@@ -191,6 +190,7 @@
 		00216E5D130F0B03009A2160 /* GrGLIRect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrGLIRect.h; path = ../../gpu/include/GrGLIRect.h; sourceTree = SOURCE_ROOT; };
 		005CE9211372E6D200F36FD0 /* GrGpuGLShaders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrGpuGLShaders.cpp; path = ../../gpu/src/GrGpuGLShaders.cpp; sourceTree = SOURCE_ROOT; };
 		005CE93B1372E70900F36FD0 /* GrGLProgram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrGLProgram.cpp; path = ../../gpu/src/GrGLProgram.cpp; sourceTree = SOURCE_ROOT; };
+		00ACCE161381719E009214F3 /* GrTesselatedPathRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrTesselatedPathRenderer.cpp; path = ../../gpu/src/GrTesselatedPathRenderer.cpp; sourceTree = SOURCE_ROOT; };
 		7D669345132ABD5D003AC2F5 /* GrGLInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GrGLInterface.cpp; path = ../../gpu/src/GrGLInterface.cpp; sourceTree = SOURCE_ROOT; };
 		7D66934B132ABD8F003AC2F5 /* GrGLInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrGLInterface.h; path = ../../gpu/include/GrGLInterface.h; sourceTree = SOURCE_ROOT; };
 		7D6EBF5913330E8400AEAADD /* GrGLDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GrGLDefines.h; path = ../../gpu/include/GrGLDefines.h; sourceTree = SOURCE_ROOT; };
@@ -307,6 +307,7 @@
 		08FB7795FE84155DC02AAC07 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				00ACCE161381719E009214F3 /* GrTesselatedPathRenderer.cpp */,
 				005CE93B1372E70900F36FD0 /* GrGLProgram.cpp */,
 				005CE9211372E6D200F36FD0 /* GrGpuGLShaders.cpp */,
 				D595ACF7134B70A80069756C /* GrTexture.cpp */,
@@ -338,7 +339,6 @@
 				00115DED12C1167A008296FE /* GrInOrderDrawBuffer.cpp */,
 				00115DEE12C1167A008296FE /* GrMatrix.cpp */,
 				00115DEF12C1167A008296FE /* GrMemory.cpp */,
-				00115DF012C1167A008296FE /* GrPath.cpp */,
 				D5ED88E913144FD600B98D64 /* GrPathRenderer.cpp */,
 				00115DF412C1167A008296FE /* GrRectanizer_fifo.cpp */,
 				00115DF512C1167A008296FE /* GrRectanizer.cpp */,
@@ -509,7 +509,6 @@
 				00115E1D12C1167A008296FE /* GrInOrderDrawBuffer.cpp in Sources */,
 				00115E1E12C1167A008296FE /* GrMatrix.cpp in Sources */,
 				00115E1F12C1167A008296FE /* GrMemory.cpp in Sources */,
-				00115E2012C1167A008296FE /* GrPath.cpp in Sources */,
 				00115E2412C1167A008296FE /* GrRectanizer_fifo.cpp in Sources */,
 				00115E2512C1167A008296FE /* GrRectanizer.cpp in Sources */,
 				00115E2612C1167A008296FE /* GrTextContext.cpp in Sources */,
@@ -527,6 +526,7 @@
 				D595ACF8134B70A80069756C /* GrTexture.cpp in Sources */,
 				005CE9221372E6D200F36FD0 /* GrGpuGLShaders.cpp in Sources */,
 				005CE93C1372E70900F36FD0 /* GrGLProgram.cpp in Sources */,
+				00ACCE171381719E009214F3 /* GrTesselatedPathRenderer.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -571,6 +571,8 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
+					../../third_party/glu,
+					../../gpu/include,
 					../../include/core,
 					../../include/config,
 				);
@@ -593,6 +595,8 @@
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				HEADER_SEARCH_PATHS = (
+					../../third_party/glu,
+					../../gpu/include,
 					../../include/core,
 					../../include/config,
 				);