Make a separate path renderer object. Move enum types to GrTypes.h

Review URL http://codereview.appspot.com/4167067/



git-svn-id: http://skia.googlecode.com/svn/trunk@829 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 93c012c..9df7105 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -27,6 +27,7 @@
 class GrVertexBufferAllocPool;

 class GrIndexBufferAllocPool;

 class GrInOrderDrawBuffer;

+class GrPathRenderer;

 

 class GrContext : public GrRefCnt {

 public:

@@ -277,19 +278,6 @@
                         const GrMatrix* srcMatrix = NULL);

 

     /**

-     * Path filling rules

-     */

-    enum PathFills {

-        kWinding_PathFill,

-        kEvenOdd_PathFill,

-        kInverseWinding_PathFill,

-        kInverseEvenOdd_PathFill,

-        kHairLine_PathFill,

-

-        kPathFillCount

-    };

-

-    /**

      * Tessellates and draws a path.

      *

      * @param paint         describes how to color pixels.

@@ -300,7 +288,7 @@
      */

     void drawPath(const GrPaint& paint,

                   GrPathIter* path,

-                  PathFills fill,

+                  GrPathFill fill,

                   const GrPoint* translate = NULL);

     /**

      * Draws vertices with a paint.

@@ -319,7 +307,7 @@
      *                          number of indices.

      */

     void drawVertices(const GrPaint& paint,

-                      GrDrawTarget::PrimitiveType primitiveType,

+                      GrPrimitiveType primitiveType,

                       int vertexCount,

                       const GrPoint positions[],

                       const GrPoint texs[],

@@ -358,7 +346,7 @@
               typename COL_SRC,

               typename IDX_SRC>

     void drawCustomVertices(const GrPaint& paint,

-                            GrDrawTarget::PrimitiveType primitiveType,

+                            GrPrimitiveType primitiveType,

                             const POS_SRC& posSrc,

                             const TEX_SRC* texCoordSrc,

                             const COL_SRC* colorSrc,

@@ -369,16 +357,16 @@
      */

     template <typename POS_SRC>

     void drawCustomVertices(const GrPaint& paint,

-                            GrDrawTarget::PrimitiveType primitiveType,

+                            GrPrimitiveType primitiveType,

                             const POS_SRC& posSrc);

     template <typename POS_SRC, typename TEX_SRC>

     void drawCustomVertices(const GrPaint& paint,

-                            GrDrawTarget::PrimitiveType primitiveType,

+                            GrPrimitiveType primitiveType,

                             const POS_SRC& posSrc,

                             const TEX_SRC* texCoordSrc);

     template <typename POS_SRC, typename TEX_SRC, typename COL_SRC>

     void drawCustomVertices(const GrPaint& paint,

-                            GrDrawTarget::PrimitiveType primitiveType,

+                            GrPrimitiveType primitiveType,

                             const POS_SRC& posSrc,

                             const TEX_SRC* texCoordSrc,

                             const COL_SRC* colorSrc);

@@ -466,6 +454,7 @@
     GrGpu*          fGpu;

     GrTextureCache* fTextureCache;

     GrFontCache*    fFontCache;

+    GrPathRenderer* fPathRenderer;

 

     GrVertexBufferAllocPool*    fDrawBufferVBAllocPool;

     GrIndexBufferAllocPool*     fDrawBufferIBAllocPool;

diff --git a/gpu/include/GrContext_impl.h b/gpu/include/GrContext_impl.h
index 8af38e6..c0a2107 100644
--- a/gpu/include/GrContext_impl.h
+++ b/gpu/include/GrContext_impl.h
@@ -20,7 +20,7 @@
 template <typename POS_SRC, typename TEX_SRC,

           typename COL_SRC, typename IDX_SRC>

 inline void GrContext::drawCustomVertices(const GrPaint& paint,

-                                          GrDrawTarget::PrimitiveType primitiveType,

+                                          GrPrimitiveType primitiveType,

                                           const POS_SRC& posSrc,

                                           const TEX_SRC* texCoordSrc,

                                           const COL_SRC* colorSrc,

@@ -101,7 +101,7 @@
 

 template <typename POS_SRC>

 inline void GrContext::drawCustomVertices(const GrPaint& paint,

-                                          GrDrawTarget::PrimitiveType primitiveType,

+                                          GrPrimitiveType primitiveType,

                                           const POS_SRC& posSrc) {

     this->drawCustomVertices<POS_SRC,

                              GrNullTexCoordSource,

@@ -112,7 +112,7 @@
 

 template <typename POS_SRC, typename TEX_SRC>

 inline void GrContext::drawCustomVertices(const GrPaint& paint,

-                                          GrDrawTarget::PrimitiveType primitiveType,

+                                          GrPrimitiveType primitiveType,

                                           const POS_SRC& posSrc,

                                           const TEX_SRC* texCoordSrc) {

     this->drawCustomVertices<POS_SRC, TEX_SRC,

@@ -123,7 +123,7 @@
 

 template <typename POS_SRC, typename TEX_SRC, typename COL_SRC>

 inline void GrContext::drawCustomVertices(const GrPaint& paint,

-                                          GrDrawTarget::PrimitiveType primitiveType,

+                                          GrPrimitiveType primitiveType,

                                           const POS_SRC& posSrc,

                                           const TEX_SRC* texCoordSrc,

                                           const COL_SRC* colorSrc) {

diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 9c78902..929b9ff 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -52,16 +52,10 @@
     };
 
     /**
-     * Geometric primitives used for drawing.
+     *  Bitfield used to indicate which stages are in use.
      */
-    enum PrimitiveType {
-        kTriangles_PrimitiveType,
-        kTriangleStrip_PrimitiveType,
-        kTriangleFan_PrimitiveType,
-        kPoints_PrimitiveType,
-        kLines_PrimitiveType,
-        kLineStrip_PrimitiveType
-    };
+    typedef int StageBitfield;
+    GR_STATIC_ASSERT(sizeof(StageBitfield)*8 >= kNumStages);
 
     /**
      *  Flags that affect rendering. Controlled using enable/disableState(). All
@@ -81,22 +75,6 @@
     };
 
     /**
-     * Coeffecients for alpha-blending.
-     */
-    enum BlendCoeff {
-        kZero_BlendCoeff,    //<! 0
-        kOne_BlendCoeff,     //<! 1
-        kSC_BlendCoeff,      //<! src color
-        kISC_BlendCoeff,     //<! one minus src color
-        kDC_BlendCoeff,      //<! dst color
-        kIDC_BlendCoeff,     //<! one minus dst color
-        kSA_BlendCoeff,      //<! src alpha
-        kISA_BlendCoeff,     //<! one minus src alpha
-        kDA_BlendCoeff,      //<! dst alpha
-        kIDA_BlendCoeff,     //<! one minus dst alpha
-    };
-
-    /**
      * StencilPass
      *
      * Sets the stencil state for subsequent draw calls. Used to fill paths.
@@ -145,8 +123,8 @@
 
     struct DrState {
         uint32_t                fFlagBits;
-        BlendCoeff              fSrcBlend;
-        BlendCoeff              fDstBlend;
+        GrBlendCoeff            fSrcBlend;
+        GrBlendCoeff            fDstBlend;
         GrTexture*              fTextures[kNumStages];
         GrSamplerState          fSamplerStates[kNumStages];
         GrRenderTarget*         fRenderTarget;
@@ -362,7 +340,7 @@
      * @param srcCoef coeffecient applied to the src color.
      * @param dstCoef coeffecient applied to the dst color.
      */
-    void setBlendFunc(BlendCoeff srcCoef, BlendCoeff dstCoef);
+    void setBlendFunc(GrBlendCoeff srcCoef, GrBlendCoeff dstCoef);
 
     /**
      * Used to save and restore the GrGpu's drawing state
@@ -645,7 +623,7 @@
      *                     is effectively trimmed to the last completely
      *                     specified primitive.
      */
-    virtual void drawIndexed(PrimitiveType type,
+    virtual void drawIndexed(GrPrimitiveType type,
                              int startVertex,
                              int startIndex,
                              int vertexCount,
@@ -660,7 +638,7 @@
      *                     to index 0
      * @param vertexCount  one greater than the max index.
      */
-    virtual void drawNonIndexed(PrimitiveType type,
+    virtual void drawNonIndexed(GrPrimitiveType type,
                                 int startVertex,
                                 int vertexCount)  = 0;
 
@@ -674,8 +652,8 @@
      * drawNonIndexed.
      * @param rect      the rect to draw
      * @param matrix    optional matrix applied to rect (before viewMatrix)
-     * @param stageEnableMask   bitmask indicating which stages are enabled.
-     *                          Bit i indicates whether stage i is enabled.
+     * @param stageEnableBitfield bitmask indicating which stages are enabled.
+     *                            Bit i indicates whether stage i is enabled.
      * @param srcRects  specifies rects for stages enabled by stageEnableMask.
      *                  if stageEnableMask bit i is 1, srcRects is not NULL,
      *                  and srcRects[i] is not NULL, then srcRects[i] will be
@@ -689,7 +667,7 @@
      */
     virtual void drawRect(const GrRect& rect, 
                           const GrMatrix* matrix,
-                          int stageEnableMask,
+                          StageBitfield stageEnableBitfield,
                           const GrRect* srcRects[],
                           const GrMatrix* srcMatrices[]);
 
@@ -699,8 +677,8 @@
      */
     void drawSimpleRect(const GrRect& rect, 
                         const GrMatrix* matrix, 
-                        int stageEnableMask) {
-         drawRect(rect, matrix, stageEnableMask, NULL, NULL);
+                        StageBitfield stageEnableBitfield) {
+         drawRect(rect, matrix, stageEnableBitfield, NULL, NULL);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -1003,7 +981,7 @@
 
     // Helpers for drawRect, protected so subclasses that override drawRect
     // can use them.
-    static GrVertexLayout GetRectVertexLayout(int stageEnableMask, 
+    static GrVertexLayout GetRectVertexLayout(StageBitfield stageEnableBitfield,
                                               const GrRect* srcRects[]);
 
     static void SetRectVertices(const GrRect& rect,
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index cfa1509..661708b 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -284,13 +284,13 @@
     int maxTextureDimension() const { return fMaxTextureDimension; }
 
     // GrDrawTarget overrides
-    virtual void drawIndexed(PrimitiveType type,
+    virtual void drawIndexed(GrPrimitiveType type,
                              int startVertex,
                              int startIndex,
                              int vertexCount,
                              int indexCount);
 
-    virtual void drawNonIndexed(PrimitiveType type,
+    virtual void drawNonIndexed(GrPrimitiveType type,
                                 int startVertex,
                                 int vertexCount);
 
@@ -351,7 +351,7 @@
     virtual void clipWillBeSet(const GrClip& newClip);
 
     // prepares clip flushes gpu state before a draw
-    bool setupClipAndFlushState(PrimitiveType type);
+    bool setupClipAndFlushState(GrPrimitiveType type);
 
     // defaults to false, subclass can set true to support palleted textures
     bool f8bitPaletteSupport;
@@ -398,13 +398,13 @@
     void finalizeReservedIndices();
 
     // overridden by API specific GrGpu-derived class to perform the draw call.
-    virtual void drawIndexedHelper(PrimitiveType type,
+    virtual void drawIndexedHelper(GrPrimitiveType type,
                                    uint32_t startVertex,
                                    uint32_t startIndex,
                                    uint32_t vertexCount,
                                    uint32_t indexCount) = 0;
 
-    virtual void drawNonIndexedHelper(PrimitiveType type,
+    virtual void drawNonIndexedHelper(GrPrimitiveType type,
                                       uint32_t vertexCount,
                                       uint32_t numVertices) = 0;
 
@@ -421,7 +421,7 @@
     // deltas from previous state at draw time. This function does the
     // API-specific flush of the state
     // returns false if current state is unsupported.
-    virtual bool flushGraphicsState(PrimitiveType type) = 0;
+    virtual bool flushGraphicsState(GrPrimitiveType type) = 0;
 
     // Sets the scissor rect, or disables if rect is NULL.
     virtual void flushScissor(const GrIRect* rect) = 0;
diff --git a/gpu/include/GrInOrderDrawBuffer.h b/gpu/include/GrInOrderDrawBuffer.h
index 0dba8e3..d59eb96 100644
--- a/gpu/include/GrInOrderDrawBuffer.h
+++ b/gpu/include/GrInOrderDrawBuffer.h
@@ -81,12 +81,12 @@
     void playback(GrDrawTarget* target);
     
     // overrides from GrDrawTarget
-    virtual void drawIndexed(PrimitiveType primitiveType,
+    virtual void drawIndexed(GrPrimitiveType primitiveType,
                              int startVertex,
                              int startIndex,
                              int vertexCount,
                              int indexCount);
-    virtual void drawNonIndexed(PrimitiveType primitiveType,
+    virtual void drawNonIndexed(GrPrimitiveType primitiveType,
                                 int startVertex,
                                 int vertexCount);
 
@@ -103,7 +103,7 @@
 private:
 
     struct Draw {
-        PrimitiveType           fPrimitiveType;
+        GrPrimitiveType         fPrimitiveType;
         int                     fStartVertex;
         int                     fStartIndex;
         int                     fVertexCount;
diff --git a/gpu/include/GrPaint.h b/gpu/include/GrPaint.h
index 770647a..a34cbaf 100644
--- a/gpu/include/GrPaint.h
+++ b/gpu/include/GrPaint.h
@@ -18,8 +18,8 @@
 #define GrPaint_DEFINED

 

 #include "GrTexture.h"

+#include "GrColor.h"

 #include "GrSamplerState.h"

-#include "GrDrawTarget.h"

 

 /**

  * The paint describes how pixels are colored when the context draws to

@@ -29,8 +29,8 @@
 public:

 

     // All the paint fields are public except texture (it's ref-counted)

-    GrDrawTarget::BlendCoeff    fSrcBlendCoeff;

-    GrDrawTarget::BlendCoeff    fDstBlendCoeff;

+    GrBlendCoeff                fSrcBlendCoeff;

+    GrBlendCoeff                fDstBlendCoeff;

     bool                        fAntiAlias;

     bool                        fDither;

 

@@ -80,8 +80,8 @@
     GrTexture*      fTexture;

 

     void resetBlend() {

-        fSrcBlendCoeff = GrDrawTarget::kOne_BlendCoeff;

-        fDstBlendCoeff = GrDrawTarget::kZero_BlendCoeff;

+        fSrcBlendCoeff = kOne_BlendCoeff;

+        fDstBlendCoeff = kZero_BlendCoeff;

     }

 

     void resetOptions() {

diff --git a/gpu/include/GrTextContext.h b/gpu/include/GrTextContext.h
index 3dc9c7a..a598251 100644
--- a/gpu/include/GrTextContext.h
+++ b/gpu/include/GrTextContext.h
@@ -26,6 +26,7 @@
 class GrContext;
 class GrTextStrike;
 class GrFontScaler;
+class GrDrawTarget;
 
 class GrTextContext {
 public:
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index 8311239..02a652a 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -160,6 +160,47 @@
  */
 typedef uint16_t GrVertexLayout;
 
+/**
+ * Path filling rules
+ */
+enum GrPathFill {
+    kWinding_PathFill,
+    kEvenOdd_PathFill,
+    kInverseWinding_PathFill,
+    kInverseEvenOdd_PathFill,
+    kHairLine_PathFill,
+
+    kPathFillCount
+};
+
+/**
+* Geometric primitives used for drawing.
+*/
+enum GrPrimitiveType {
+    kTriangles_PrimitiveType,
+    kTriangleStrip_PrimitiveType,
+    kTriangleFan_PrimitiveType,
+    kPoints_PrimitiveType,
+    kLines_PrimitiveType,
+    kLineStrip_PrimitiveType
+};
+
+/**
+ * Coeffecients for alpha-blending.
+ */
+enum GrBlendCoeff {
+    kZero_BlendCoeff,    //<! 0
+    kOne_BlendCoeff,     //<! 1
+    kSC_BlendCoeff,      //<! src color
+    kISC_BlendCoeff,     //<! one minus src color
+    kDC_BlendCoeff,      //<! dst color
+    kIDC_BlendCoeff,     //<! one minus dst color
+    kSA_BlendCoeff,      //<! src alpha
+    kISA_BlendCoeff,     //<! one minus src alpha
+    kDA_BlendCoeff,      //<! dst alpha
+    kIDA_BlendCoeff,     //<! one minus dst alpha
+};
+
 ///////////////////////////////////////////////////////////////////////////////
 
 // this is included only to make it easy to use this debugging facility
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 7ce8f35..dbc7f6c 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -24,6 +24,7 @@
 #include "GrIndexBuffer.h"

 #include "GrInOrderDrawBuffer.h"

 #include "GrBufferAllocPool.h"

+#include "GrPathRenderer.h"

 

 #define DEFER_TEXT_RENDERING 1

 

@@ -62,6 +63,7 @@
     delete fDrawBuffer;

     delete fDrawBufferVBAllocPool;

     delete fDrawBufferVBAllocPool;

+    delete fPathRenderer;

 }

 

 void GrContext::abandonAllTextures() {

@@ -146,7 +148,7 @@
             fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);

             fGpu->setViewMatrix(GrMatrix::I());

             fGpu->setAlpha(0xff);

-            fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff, GrDrawTarget::kZero_BlendCoeff);

+            fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);

             fGpu->disableState(GrDrawTarget::kDither_StateBit |

                                GrDrawTarget::kClip_StateBit   |

                                GrDrawTarget::kAntialias_StateBit);

@@ -166,7 +168,7 @@
                                      texture->height(),

                                      2*sizeof(GrPoint));

                 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));

-                fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,

+                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,

                                      0, 4);

                 entry = fTextureCache->createAndLock(*key, texture);

             }

@@ -349,18 +351,18 @@
             return;

         }

 

-        GrDrawTarget::PrimitiveType primType;

+        GrPrimitiveType primType;

         int vertCount;

         GrPoint* vertex = geo.positions();

 

         if (width > 0) {

             vertCount = 10;

-            primType = GrDrawTarget::kTriangleStrip_PrimitiveType;

+            primType = kTriangleStrip_PrimitiveType;

             setStrokeRectStrip(vertex, rect, width);

         } else {

             // hairline

             vertCount = 5;

-            primType = GrDrawTarget::kLineStrip_PrimitiveType;

+            primType = kLineStrip_PrimitiveType;

             vertex[0].set(rect.fLeft, rect.fTop);

             vertex[1].set(rect.fRight, rect.fTop);

             vertex[2].set(rect.fRight, rect.fBottom);

@@ -398,7 +400,7 @@
             if (textured) {

                 target->preConcatSamplerMatrix(0, m);

             }

-            target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);

+            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);

         #else

             target->drawSimpleRect(rect, matrix, textured ? 1 : 0);

         #endif

@@ -443,7 +445,7 @@
     target->preConcatSamplerMatrix(0, m);

 

     target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());

-    target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);

+    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);

 #else

 

     GrDrawTarget* target;

@@ -463,7 +465,7 @@
 }

 

 void GrContext::drawVertices(const GrPaint& paint,

-                             GrDrawTarget::PrimitiveType primitiveType,

+                             GrPrimitiveType primitiveType,

                              int vertexCount,

                              const GrPoint positions[],

                              const GrPoint texCoords[],

@@ -529,339 +531,19 @@
 

 ////////////////////////////////////////////////////////////////////////////////

 

-#define STENCIL_OFF     0   // Always disable stencil (even when needed)

-#define EVAL_TOL GR_Scalar1

-

-static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10;

-

-static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) {

-    GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);

-    // TODO: fixed points sqrt

-    if (d < tol) {

-        return 1;

-    } else {

-        // Each time we subdivide, d should be cut in 4. So we need to

-        // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)

-        // points.

-        // 2^(log4(x)) = sqrt(x);

-        d = ceilf(sqrtf(d/tol));

-        return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);

-    }

-}

-

-static uint32_t generate_quadratic_points(const GrPoint& p0,

-                                          const GrPoint& p1,

-                                          const GrPoint& p2,

-                                          GrScalar tolSqd,

-                                          GrPoint** points,

-                                          uint32_t pointsLeft) {

-    if (pointsLeft < 2 ||

-        (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {

-        (*points)[0] = p2;

-        *points += 1;

-        return 1;

-    }

-

-    GrPoint q[] = {

-        GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),

-        GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),

-    };

-    GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));

-

-    pointsLeft >>= 1;

-    uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft);

-    uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft);

-    return a + b;

-}

-

-static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) {

-    GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),

-                       points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));

-    d = sqrtf(d);

-    if (d < tol) {

-        return 1;

-    } else {

-        d = ceilf(sqrtf(d/tol));

-        return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);

-    }

-}

-

-static uint32_t generate_cubic_points(const GrPoint& p0,

-                                      const GrPoint& p1,

-                                      const GrPoint& p2,

-                                      const GrPoint& p3,

-                                      GrScalar tolSqd,

-                                      GrPoint** points,

-                                      uint32_t pointsLeft) {

-    if (pointsLeft < 2 ||

-        (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&

-         p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {

-            (*points)[0] = p3;

-            *points += 1;

-            return 1;

-        }

-    GrPoint q[] = {

-        GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),

-        GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),

-        GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))

-    };

-    GrPoint r[] = {

-        GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),

-        GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))

-    };

-    GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));

-    pointsLeft >>= 1;

-    uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft);

-    uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft);

-    return a + b;

-}

-

-static int worst_case_point_count(GrPathIter* path,

-                                  int* subpaths,

-                                  GrScalar tol) {

-    int pointCount = 0;

-    *subpaths = 1;

-

-    bool first = true;

-

-    GrPathIter::Command cmd;

-

-    GrPoint pts[4];

-    while ((cmd = path->next(pts)) != GrPathIter::kEnd_Command) {

-

-        switch (cmd) {

-            case GrPathIter::kLine_Command:

-                pointCount += 1;

-                break;

-            case GrPathIter::kQuadratic_Command:

-                pointCount += quadratic_point_count(pts, tol);

-                break;

-            case GrPathIter::kCubic_Command:

-                pointCount += cubic_point_count(pts, tol);

-                break;

-            case GrPathIter::kMove_Command:

-                pointCount += 1;

-                if (!first) {

-                    ++(*subpaths);

-                }

-                break;

-            default:

-                break;

-        }

-        first = false;

-    }

-    return pointCount;

-}

-

-static inline bool single_pass_path(const GrPathIter& path,

-                                    GrContext::PathFills fill,

-                                    const GrDrawTarget& target) {

-#if STENCIL_OFF

-    return true;

-#else

-    if (GrContext::kEvenOdd_PathFill == fill) {

-        GrPathIter::ConvexHint hint = path.hint();

-        return hint == GrPathIter::kConvex_ConvexHint ||

-               hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint;

-    } else if (GrContext::kWinding_PathFill == fill) {

-        GrPathIter::ConvexHint hint = path.hint();

-        return hint == GrPathIter::kConvex_ConvexHint ||

-               hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint ||

-               (hint == GrPathIter::kSameWindingConvexPieces_ConvexHint &&

-                target.canDisableBlend() && !target.isDitherState());

-

-    }

-    return false;

-#endif

-}

-

 void GrContext::drawPath(const GrPaint& paint,

                          GrPathIter* path,

-                         PathFills fill,

+                         GrPathFill fill,

                          const GrPoint* translate) {

 

 

     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);

 

-    GrDrawTarget::AutoStateRestore asr(target);

-

-    GrMatrix viewM = target->getViewMatrix();

-    // In order to tesselate the path we get a bound on how much the matrix can

-    // stretch when mapping to screen coordinates.

-    GrScalar stretch = viewM.getMaxStretch();

-    bool useStretch = stretch > 0;

-    GrScalar tol = EVAL_TOL;

-    if (!useStretch) {

-        // TODO: deal with perspective in some better way.

-        tol /= 10;

-    } else {

-        // TODO: fixed point divide

-        GrScalar sinv = 1 / stretch;

-        tol = GrMul(tol, sinv);

-    }

-    GrScalar tolSqd = GrMul(tol, tol);

-

-    int subpathCnt;

-    int maxPts = worst_case_point_count(path,

-                                        &subpathCnt,

-                                        tol);

-    GrVertexLayout layout = 0;

-

+    GrDrawTarget::StageBitfield enabledStages = 0;

     if (NULL != paint.getTexture()) {

-        layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);

+        enabledStages |= 1;

     }

-    // add 4 to hold the bounding rect

-    GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);

-

-    GrPoint* base = (GrPoint*) arg.vertices();

-    GrPoint* vert = base;

-    GrPoint* subpathBase = base;

-

-    GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);

-

-    path->rewind();

-

-    // TODO: use primitve restart if available rather than multiple draws

-    GrDrawTarget::PrimitiveType type;

-    int                         passCount = 0;

-    GrDrawTarget::StencilPass   passes[3];

-    bool                        reverse = false;

-

-    if (kHairLine_PathFill == fill) {

-        type = GrDrawTarget::kLineStrip_PrimitiveType;

-        passCount = 1;

-        passes[0] = GrDrawTarget::kNone_StencilPass;

-    } else {

-        type = GrDrawTarget::kTriangleFan_PrimitiveType;

-        if (single_pass_path(*path, fill, *target)) {

-            passCount = 1;

-            passes[0] = GrDrawTarget::kNone_StencilPass;

-        } else {

-            switch (fill) {

-                case kInverseEvenOdd_PathFill:

-                    reverse = true;

-                    // fallthrough

-                case kEvenOdd_PathFill:

-                    passCount = 2;

-                    passes[0] = GrDrawTarget::kEvenOddStencil_StencilPass;

-                    passes[1] = GrDrawTarget::kEvenOddColor_StencilPass;

-                    break;

-

-                case kInverseWinding_PathFill:

-                    reverse = true;

-                    // fallthrough

-                case kWinding_PathFill:

-                    passes[0] = GrDrawTarget::kWindingStencil1_StencilPass;

-                    if (fGpu->supportsSingleStencilPassWinding()) {

-                        passes[1] = GrDrawTarget::kWindingColor_StencilPass;

-                        passCount = 2;

-                    } else {

-                        passes[1] = GrDrawTarget::kWindingStencil2_StencilPass;

-                        passes[2] = GrDrawTarget::kWindingColor_StencilPass;

-                        passCount = 3;

-                    }

-                    break;

-                default:

-                    GrAssert(!"Unknown path fill!");

-                    return;

-            }

-        }

-    }

-    target->setReverseFill(reverse);

-

-    GrPoint pts[4];

-

-    bool first = true;

-    int subpath = 0;

-

-    for (;;) {

-        GrPathIter::Command cmd = path->next(pts);

-        switch (cmd) {

-            case GrPathIter::kMove_Command:

-                if (!first) {

-                    subpathVertCount[subpath] = vert-subpathBase;

-                    subpathBase = vert;

-                    ++subpath;

-                }

-                *vert = pts[0];

-                vert++;

-                break;

-            case GrPathIter::kLine_Command:

-                *vert = pts[1];

-                vert++;

-                break;

-            case GrPathIter::kQuadratic_Command: {

-                generate_quadratic_points(pts[0], pts[1], pts[2],

-                                          tolSqd, &vert,

-                                          quadratic_point_count(pts, tol));

-                break;

-            }

-            case GrPathIter::kCubic_Command: {

-                generate_cubic_points(pts[0], pts[1], pts[2], pts[3],

-                                      tolSqd, &vert,

-                                      cubic_point_count(pts, tol));

-                break;

-            }

-            case GrPathIter::kClose_Command:

-                break;

-            case GrPathIter::kEnd_Command:

-                subpathVertCount[subpath] = vert-subpathBase;

-                ++subpath; // this could be only in debug

-                goto FINISHED;

-        }

-        first = false;

-    }

-FINISHED:

-    GrAssert(subpath == subpathCnt);

-    GrAssert((vert - base) <= maxPts);

-

-    if (translate) {

-        int count = vert - base;

-        for (int i = 0; i < count; i++) {

-            base[i].offset(translate->fX, translate->fY);

-        }

-    }

-

-    // arbitrary path complexity cutoff

-    bool useBounds = fill != kHairLine_PathFill &&

-                    (reverse || (vert - base) > 8);

-    GrPoint* boundsVerts = base + maxPts;

-    if (useBounds) {

-        GrRect bounds;

-        if (reverse) {

-            GrAssert(NULL != target->getRenderTarget());

-            // draw over the whole world.

-            bounds.setLTRB(0, 0,

-                           GrIntToScalar(target->getRenderTarget()->width()),

-                           GrIntToScalar(target->getRenderTarget()->height()));

-            GrMatrix vmi;

-            if (target->getViewInverse(&vmi)) {

-                vmi.mapRect(&bounds);

-            }

-        } else {

-            bounds.setBounds((GrPoint*)base, vert - base);

-        }

-        boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,

-                                  bounds.fBottom);

-    }

-

-    for (int p = 0; p < passCount; ++p) {

-        target->setStencilPass(passes[p]);

-        if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||

-                          GrDrawTarget::kWindingColor_StencilPass == passes[p])) {

-            target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,

-                                 maxPts, 4);

-

-        } else {

-            int baseVertex = 0;

-            for (int sp = 0; sp < subpathCnt; ++sp) {

-                target->drawNonIndexed(type,

-                                     baseVertex,

-                                     subpathVertCount[sp]);

-                baseVertex += subpathVertCount[sp];

-            }

-        }

-    }

+    fPathRenderer->drawPath(target, enabledStages, path, fill, translate);

 }

 

 ////////////////////////////////////////////////////////////////////////////////

@@ -918,8 +600,8 @@
 

     fGpu->disableState(GrDrawTarget::kClip_StateBit);

     fGpu->setAlpha(0xFF);

-    fGpu->setBlendFunc(GrDrawTarget::kOne_BlendCoeff,

-                       GrDrawTarget::kZero_BlendCoeff);

+    fGpu->setBlendFunc(kOne_BlendCoeff,

+                       kZero_BlendCoeff);

     fGpu->setTexture(0, texture);

 

     GrSamplerState sampler;

@@ -936,7 +618,7 @@
         return;

     }

     ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);

-    fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);

+    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);

 }

 ////////////////////////////////////////////////////////////////////////////////

 

@@ -1069,7 +751,7 @@
 #if BATCH_RECT_TO_RECT

     fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());

 #endif

-

+    fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());

 }

 

 bool GrContext::finalizeTextureKey(GrTextureKey* key,

diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 63e59c4..ca525b3 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -374,8 +374,8 @@
     fCurrDrawState.fFlagBits &= ~(bits);
 }
 
-void GrDrawTarget::setBlendFunc(BlendCoeff srcCoef,
-                                BlendCoeff dstCoef) {
+void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoef,
+                                GrBlendCoeff dstCoef) {
     fCurrDrawState.fSrcBlend = srcCoef;
     fCurrDrawState.fDstBlend = dstCoef;
 }
@@ -515,12 +515,10 @@
 ///////////////////////////////////////////////////////////////////////////////
 void GrDrawTarget::drawRect(const GrRect& rect, 
                             const GrMatrix* matrix,
-                            int stageEnableMask,
+                            StageBitfield stageEnableBitfield,
                             const GrRect* srcRects[],
                             const GrMatrix* srcMatrices[]) {
-    GR_STATIC_ASSERT(8*sizeof(int) >= kNumStages);
-
-    GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects);
+    GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
 
     AutoReleaseGeometry geo(this, layout, 4, 0);
 
@@ -530,13 +528,13 @@
     drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
 }
 
-GrVertexLayout GrDrawTarget::GetRectVertexLayout(int stageEnableMask, 
+GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield, 
                                                  const GrRect* srcRects[]) {
     GrVertexLayout layout = 0;
 
     for (int i = 0; i < kNumStages; ++i) {
         int numTC = 0;
-        if (stageEnableMask & (1 << i)) {
+        if (stageEnableBitfield & (1 << i)) {
             if (NULL != srcRects && NULL != srcRects[i]) {
                 layout |= StageTexCoordVertexLayoutBit(i, numTC);
                 ++numTC;
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 9e9c185..019c99f 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -167,7 +167,7 @@
     }
 }
 
-bool GrGpu::setupClipAndFlushState(PrimitiveType type) {
+bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
     const GrIRect* r = NULL;
 
     // we check this early because we need a valid
@@ -254,7 +254,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void GrGpu::drawIndexed(PrimitiveType type,
+void GrGpu::drawIndexed(GrPrimitiveType type,
                         int startVertex,
                         int startIndex,
                         int vertexCount,
@@ -282,7 +282,7 @@
                       vertexCount, indexCount);
 }
 
-void GrGpu::drawNonIndexed(PrimitiveType type,
+void GrGpu::drawNonIndexed(GrPrimitiveType type,
                            int startVertex,
                            int vertexCount) {
     GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index 8cfc4a0..edcadb4 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -443,8 +443,8 @@
     fHWDrawState.fFlagBits = 0;
 
     // illegal values
-    fHWDrawState.fSrcBlend = (BlendCoeff)-1;
-    fHWDrawState.fDstBlend = (BlendCoeff)-1;
+    fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
+    fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
     fHWDrawState.fColor = GrColor_ILLEGAL;
 
     fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
@@ -1183,7 +1183,7 @@
     GL_LINE_STRIP
 };
 
-void GrGpuGL::drawIndexedHelper(PrimitiveType type,
+void GrGpuGL::drawIndexedHelper(GrPrimitiveType type,
                                 uint32_t startVertex,
                                 uint32_t startIndex,
                                 uint32_t vertexCount,
@@ -1203,7 +1203,7 @@
                        GL_UNSIGNED_SHORT, indices));
 }
 
-void GrGpuGL::drawNonIndexedHelper(PrimitiveType type,
+void GrGpuGL::drawNonIndexedHelper(GrPrimitiveType type,
                                    uint32_t startVertex,
                                    uint32_t vertexCount) {
     GrAssert((size_t)type < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
@@ -1458,7 +1458,7 @@
     }
 }
 
-bool GrGpuGL::flushGLStateCommon(PrimitiveType type) {
+bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
 
     // GrGpu::setupClipAndFlushState should have already checked this
     // and bailed if not true.
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 017d9ea..f6216c5 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -98,12 +98,12 @@
     GrGLExts fExts;
 
     // GrGpu overrides
-    virtual void drawIndexedHelper(PrimitiveType type,
+    virtual void drawIndexedHelper(GrPrimitiveType type,
                                    uint32_t startVertex,
                                    uint32_t startIndex,
                                    uint32_t vertexCount,
                                    uint32_t indexCount);
-    virtual void drawNonIndexedHelper(PrimitiveType type,
+    virtual void drawNonIndexedHelper(GrPrimitiveType type,
                                       uint32_t vertexCount,
                                       uint32_t numVertices);
     virtual void flushScissor(const GrIRect* rect);
@@ -127,7 +127,7 @@
     // sampler state (filtering, tiling)
     // FBO binding
     // line width
-    bool flushGLStateCommon(PrimitiveType type);
+    bool flushGLStateCommon(GrPrimitiveType type);
 
     // adjusts texture matrix to account for orientation, size, and npotness
     static void AdjustTextureMatrix(const GrGLTexture* texture,
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index efb0990..516381e 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -128,7 +128,7 @@
     GR_GL(LoadMatrixf(mat));
 }
 
-bool GrGpuGLFixed::flushGraphicsState(PrimitiveType type) {
+bool GrGpuGLFixed::flushGraphicsState(GrPrimitiveType type) {
 
     bool usingTextures[kNumStages];
 
diff --git a/gpu/src/GrGpuGLFixed.h b/gpu/src/GrGpuGLFixed.h
index e5d472d..5b81ea6 100644
--- a/gpu/src/GrGpuGLFixed.h
+++ b/gpu/src/GrGpuGLFixed.h
@@ -30,7 +30,7 @@
 
 protected:
     // overrides from GrGpu
-    virtual bool flushGraphicsState(PrimitiveType type);
+    virtual bool flushGraphicsState(GrPrimitiveType type);
     virtual void setupGeometry(int* startVertex,
                                int* startIndex,
                                int vertexCount,
diff --git a/gpu/src/GrGpuGLShaders2.cpp b/gpu/src/GrGpuGLShaders2.cpp
index 34e7c87..14134e7 100644
--- a/gpu/src/GrGpuGLShaders2.cpp
+++ b/gpu/src/GrGpuGLShaders2.cpp
@@ -979,7 +979,7 @@
     program->fViewMatrix = GrMatrix::InvalidMatrix();
 }
 
-void GrGpuGLShaders2::getProgramDesc(PrimitiveType primType, ProgramDesc* desc) {
+void GrGpuGLShaders2::getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc) {
 
     // Must initialize all fields or cache will have false negatives!
     desc->fVertexLayout = fGeometrySrc.fVertexLayout;
@@ -1220,7 +1220,7 @@
                      unis));
 }
 
-void GrGpuGLShaders2::flushProgram(PrimitiveType type) {
+void GrGpuGLShaders2::flushProgram(GrPrimitiveType type) {
     ProgramDesc desc;
     getProgramDesc(type, &desc);
     fProgram = fProgramCache->getProgram(desc);
@@ -1234,7 +1234,7 @@
     }
 }
 
-bool GrGpuGLShaders2::flushGraphicsState(PrimitiveType type) {
+bool GrGpuGLShaders2::flushGraphicsState(GrPrimitiveType type) {
 
     if (!flushGLStateCommon(type)) {
         return false;
diff --git a/gpu/src/GrGpuGLShaders2.h b/gpu/src/GrGpuGLShaders2.h
index 2647e23..e8785c9 100644
--- a/gpu/src/GrGpuGLShaders2.h
+++ b/gpu/src/GrGpuGLShaders2.h
@@ -30,7 +30,7 @@
 
 protected:
     // overrides from GrGpu
-    virtual bool flushGraphicsState(PrimitiveType type);
+    virtual bool flushGraphicsState(GrPrimitiveType type);
     virtual void setupGeometry(int* startVertex,
                                int* startIndex,
                                int vertexCount,
@@ -54,7 +54,7 @@
     void flushRadial2(int stage);
 
     // called at flush time to setup the appropriate program
-    void flushProgram(PrimitiveType type);
+    void flushProgram(GrPrimitiveType type);
 
     struct Program;
 
@@ -69,7 +69,7 @@
     class ProgramCache;
 
     // gets a description of needed shader
-    void getProgramDesc(PrimitiveType primType, ProgramDesc* desc);
+    void getProgramDesc(GrPrimitiveType primType, ProgramDesc* desc);
 
     // generates and compiles a program from a description and vertex layout
     // will change GL's bound program
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 25e74e3..68590fc 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -74,7 +74,7 @@
 
 void GrInOrderDrawBuffer::drawRect(const GrRect& rect, 
                                    const GrMatrix* matrix,
-                                   int stageEnableMask,
+                                   StageBitfield stageEnableBitfield,
                                    const GrRect* srcRects[],
                                    const GrMatrix* srcMatrices[]) {
     
@@ -87,7 +87,7 @@
     if (fMaxQuads) {
         
         bool appendToPreviousDraw = false;
-        GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects);
+        GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
         AutoReleaseGeometry geo(this, layout, 4, 0);
         AutoViewMatrixRestore avmr(this);
         GrMatrix combinedMatrix = this->getViewMatrix();
@@ -167,13 +167,12 @@
         if (disabledClip) {
             this->enableState(kClip_StateBit);
         }
-this->enableState(kClip_StateBit);
     } else {
-        INHERITED::drawRect(rect, matrix, stageEnableMask, srcRects, srcMatrices);
+        INHERITED::drawRect(rect, matrix, stageEnableBitfield, srcRects, srcMatrices);
     }
 }
 
-void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType,
+void GrInOrderDrawBuffer::drawIndexed(GrPrimitiveType primitiveType,
                                       int startVertex,
                                       int startIndex,
                                       int vertexCount,
@@ -239,7 +238,7 @@
     draw.fIndexBuffer->ref();
 }
 
-void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType,
+void GrInOrderDrawBuffer::drawNonIndexed(GrPrimitiveType primitiveType,
                                          int startVertex,
                                          int vertexCount) {
     if (!vertexCount) {
diff --git a/gpu/src/GrPathRenderer.cpp b/gpu/src/GrPathRenderer.cpp
new file mode 100644
index 0000000..c47b6e5
--- /dev/null
+++ b/gpu/src/GrPathRenderer.cpp
@@ -0,0 +1,352 @@
+#include "GrPathRenderer.h"
+
+#include "GrPoint.h"
+#include "GrDrawTarget.h"
+#include "GrPathIter.h"
+#include "GrMemory.h"
+#include "GrTexture.h"
+
+
+
+GrDefaultPathRenderer::GrDefaultPathRenderer(bool singlePassWindingStencil)
+    : fSinglePassWindingStencil(singlePassWindingStencil) {
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helpers for draw Path
+
+#define STENCIL_OFF     0   // Always disable stencil (even when needed)
+static const GrScalar gTolerance = GR_Scalar1;
+
+static const uint32_t MAX_POINTS_PER_CURVE = 1 << 10;
+
+static uint32_t quadratic_point_count(const GrPoint points[], GrScalar tol) {
+    GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
+    if (d < tol) {
+        return 1;
+    } else {
+        // Each time we subdivide, d should be cut in 4. So we need to
+        // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
+        // points.
+        // 2^(log4(x)) = sqrt(x);
+        d = ceilf(sqrtf(d/tol));
+        return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
+    }
+}
+
+static uint32_t generate_quadratic_points(const GrPoint& p0,
+                                          const GrPoint& p1,
+                                          const GrPoint& p2,
+                                          GrScalar tolSqd,
+                                          GrPoint** points,
+                                          uint32_t pointsLeft) {
+    if (pointsLeft < 2 ||
+        (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
+        (*points)[0] = p2;
+        *points += 1;
+        return 1;
+    }
+
+    GrPoint q[] = {
+        GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
+        GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
+    };
+    GrPoint r(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY));
+
+    pointsLeft >>= 1;
+    uint32_t a = generate_quadratic_points(p0, q[0], r, tolSqd, points, pointsLeft);
+    uint32_t b = generate_quadratic_points(r, q[1], p2, tolSqd, points, pointsLeft);
+    return a + b;
+}
+
+static uint32_t cubic_point_count(const GrPoint points[], GrScalar tol) {
+    GrScalar d = GrMax(points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
+                       points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
+    d = sqrtf(d);
+    if (d < tol) {
+        return 1;
+    } else {
+        d = ceilf(sqrtf(d/tol));
+        return GrMin(GrNextPow2((uint32_t)d), MAX_POINTS_PER_CURVE);
+    }
+}
+
+static uint32_t generate_cubic_points(const GrPoint& p0,
+                                      const GrPoint& p1,
+                                      const GrPoint& p2,
+                                      const GrPoint& p3,
+                                      GrScalar tolSqd,
+                                      GrPoint** points,
+                                      uint32_t pointsLeft) {
+    if (pointsLeft < 2 ||
+        (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
+         p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
+            (*points)[0] = p3;
+            *points += 1;
+            return 1;
+        }
+    GrPoint q[] = {
+        GrPoint(GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY)),
+        GrPoint(GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY)),
+        GrPoint(GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY))
+    };
+    GrPoint r[] = {
+        GrPoint(GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY)),
+        GrPoint(GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY))
+    };
+    GrPoint s(GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY));
+    pointsLeft >>= 1;
+    uint32_t a = generate_cubic_points(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
+    uint32_t b = generate_cubic_points(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
+    return a + b;
+}
+
+static int worst_case_point_count(GrPathIter* path,
+                                  int* subpaths,
+                                  GrScalar tol) {
+    int pointCount = 0;
+    *subpaths = 1;
+
+    bool first = true;
+
+    GrPathIter::Command cmd;
+
+    GrPoint pts[4];
+    while ((cmd = path->next(pts)) != GrPathIter::kEnd_Command) {
+
+        switch (cmd) {
+            case GrPathIter::kLine_Command:
+                pointCount += 1;
+                break;
+            case GrPathIter::kQuadratic_Command:
+                pointCount += quadratic_point_count(pts, tol);
+                break;
+            case GrPathIter::kCubic_Command:
+                pointCount += cubic_point_count(pts, tol);
+                break;
+            case GrPathIter::kMove_Command:
+                pointCount += 1;
+                if (!first) {
+                    ++(*subpaths);
+                }
+                break;
+            default:
+                break;
+        }
+        first = false;
+    }
+    return pointCount;
+}
+
+static inline bool single_pass_path(const GrPathIter& path,
+                                    GrPathFill fill,
+                                    const GrDrawTarget& target) {
+#if STENCIL_OFF
+    return true;
+#else
+    if (kEvenOdd_PathFill == fill) {
+        GrPathIter::ConvexHint hint = path.hint();
+        return hint == GrPathIter::kConvex_ConvexHint ||
+               hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint;
+    } else if (kWinding_PathFill == fill) {
+        GrPathIter::ConvexHint hint = path.hint();
+        return hint == GrPathIter::kConvex_ConvexHint ||
+               hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint ||
+               (hint == GrPathIter::kSameWindingConvexPieces_ConvexHint &&
+                target.canDisableBlend() && !target.isDitherState());
+
+    }
+    return false;
+#endif
+}
+
+void GrDefaultPathRenderer::drawPath(GrDrawTarget* target,
+                                     GrDrawTarget::StageBitfield stages,
+                                     GrPathIter* path,
+                                     GrPathFill fill,
+                                     const GrPoint* translate) {
+
+    GrDrawTarget::AutoStateRestore asr(target);
+
+    GrMatrix viewM = target->getViewMatrix();
+    // In order to tesselate the path we get a bound on how much the matrix can
+    // stretch when mapping to screen coordinates.
+    GrScalar stretch = viewM.getMaxStretch();
+    bool useStretch = stretch > 0;
+    GrScalar tol = gTolerance;
+
+    if (!useStretch) {
+        // TODO: deal with perspective in some better way.
+        tol /= 10;
+    } else {
+        GrScalar sinv = GR_Scalar1 / stretch;
+        tol = GrMul(tol, sinv);
+    }
+    GrScalar tolSqd = GrMul(tol, tol);
+
+    int subpathCnt;
+    int maxPts = worst_case_point_count(path,
+                                        &subpathCnt,
+                                        tol);
+
+    GrVertexLayout layout = 0;
+    for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
+        if ((1 << s) & stages) {
+            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
+        }
+    }
+
+    // add 4 to hold the bounding rect
+    GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);
+
+    GrPoint* base = (GrPoint*) arg.vertices();
+    GrPoint* vert = base;
+    GrPoint* subpathBase = base;
+
+    GrAutoSTMalloc<8, uint16_t> subpathVertCount(subpathCnt);
+
+    path->rewind();
+
+    // TODO: use primitve restart if available rather than multiple draws
+    GrPrimitiveType             type;
+    int                         passCount = 0;
+    GrDrawTarget::StencilPass   passes[3];
+    bool                        reverse = false;
+
+    if (kHairLine_PathFill == fill) {
+        type = kLineStrip_PrimitiveType;
+        passCount = 1;
+        passes[0] = GrDrawTarget::kNone_StencilPass;
+    } else {
+        type = kTriangleFan_PrimitiveType;
+        if (single_pass_path(*path, fill, *target)) {
+            passCount = 1;
+            passes[0] = GrDrawTarget::kNone_StencilPass;
+        } else {
+            switch (fill) {
+                case kInverseEvenOdd_PathFill:
+                    reverse = true;
+                    // fallthrough
+                case kEvenOdd_PathFill:
+                    passCount = 2;
+                    passes[0] = GrDrawTarget::kEvenOddStencil_StencilPass;
+                    passes[1] = GrDrawTarget::kEvenOddColor_StencilPass;
+                    break;
+
+                case kInverseWinding_PathFill:
+                    reverse = true;
+                    // fallthrough
+                case kWinding_PathFill:
+                    passes[0] = GrDrawTarget::kWindingStencil1_StencilPass;
+                    if (fSinglePassWindingStencil) {
+                        passes[1] = GrDrawTarget::kWindingColor_StencilPass;
+                        passCount = 2;
+                    } else {
+                        passes[1] = GrDrawTarget::kWindingStencil2_StencilPass;
+                        passes[2] = GrDrawTarget::kWindingColor_StencilPass;
+                        passCount = 3;
+                    }
+                    break;
+                default:
+                    GrAssert(!"Unknown path fill!");
+                    return;
+            }
+        }
+    }
+    target->setReverseFill(reverse);
+
+    GrPoint pts[4];
+
+    bool first = true;
+    int subpath = 0;
+
+    for (;;) {
+        GrPathIter::Command cmd = path->next(pts);
+        switch (cmd) {
+            case GrPathIter::kMove_Command:
+                if (!first) {
+                    subpathVertCount[subpath] = vert-subpathBase;
+                    subpathBase = vert;
+                    ++subpath;
+                }
+                *vert = pts[0];
+                vert++;
+                break;
+            case GrPathIter::kLine_Command:
+                *vert = pts[1];
+                vert++;
+                break;
+            case GrPathIter::kQuadratic_Command: {
+                generate_quadratic_points(pts[0], pts[1], pts[2],
+                                          tolSqd, &vert,
+                                          quadratic_point_count(pts, tol));
+                break;
+            }
+            case GrPathIter::kCubic_Command: {
+                generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
+                                      tolSqd, &vert,
+                                      cubic_point_count(pts, tol));
+                break;
+            }
+            case GrPathIter::kClose_Command:
+                break;
+            case GrPathIter::kEnd_Command:
+                subpathVertCount[subpath] = vert-subpathBase;
+                ++subpath; // this could be only in debug
+                goto FINISHED;
+        }
+        first = false;
+    }
+FINISHED:
+    GrAssert(subpath == subpathCnt);
+    GrAssert((vert - base) <= maxPts);
+
+    if (translate) {
+        int count = vert - base;
+        for (int i = 0; i < count; i++) {
+            base[i].offset(translate->fX, translate->fY);
+        }
+    }
+
+    // arbitrary path complexity cutoff
+    bool useBounds = fill != kHairLine_PathFill &&
+                    (reverse || (vert - base) > 8);
+    GrPoint* boundsVerts = base + maxPts;
+    if (useBounds) {
+        GrRect bounds;
+        if (reverse) {
+            GrAssert(NULL != target->getRenderTarget());
+            // draw over the whole world.
+            bounds.setLTRB(0, 0,
+                           GrIntToScalar(target->getRenderTarget()->width()),
+                           GrIntToScalar(target->getRenderTarget()->height()));
+            GrMatrix vmi;
+            if (target->getViewInverse(&vmi)) {
+                vmi.mapRect(&bounds);
+            }
+        } else {
+            bounds.setBounds((GrPoint*)base, vert - base);
+        }
+        boundsVerts[0].setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight,
+                                  bounds.fBottom);
+    }
+
+    for (int p = 0; p < passCount; ++p) {
+        target->setStencilPass(passes[p]);
+        if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||
+                          GrDrawTarget::kWindingColor_StencilPass == passes[p])) {
+            target->drawNonIndexed(kTriangleFan_PrimitiveType,
+                                 maxPts, 4);
+
+        } else {
+            int baseVertex = 0;
+            for (int sp = 0; sp < subpathCnt; ++sp) {
+                target->drawNonIndexed(type,
+                                     baseVertex,
+                                     subpathVertCount[sp]);
+                baseVertex += subpathVertCount[sp];
+            }
+        }
+    }
+}
diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h
new file mode 100644
index 0000000..e3fd715
--- /dev/null
+++ b/gpu/src/GrPathRenderer.h
@@ -0,0 +1,64 @@
+/*
+    Copyright 2011 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 GrPathRenderer_DEFINED
+#define GrPathRenderer_DEFINED
+
+#include "GrDrawTarget.h"
+
+class GrPathIter;
+struct GrPoint;
+
+/**
+ * A path renderer.
+ */
+class GrPathRenderer {
+public:
+    /**
+     * Draws a path into the draw target. The target will already have its draw
+     * state configured for the draw.
+     * @param target                the target to draw into.
+     * @param stages                indicates which stages the are already
+     *                              in use. All enabled stages expect positions
+     *                              as texture coordinates. The path renderer
+     *                              use the remaining stages for its path 
+     *                              filling algorithm.
+     * @param path                  the path to draw.
+     * @param fill                  the fill rule to apply.
+     * @param translate             optional additional translation to apply to
+     *                              the path NULL means (0,0).
+     */
+    virtual void drawPath(GrDrawTarget* target,
+                          GrDrawTarget::StageBitfield stages,
+                          GrPathIter* path,
+                          GrPathFill fill,
+                          const GrPoint* translate) = 0;
+};
+
+class GrDefaultPathRenderer : public GrPathRenderer {
+public:
+    GrDefaultPathRenderer(bool singlePassWindingStencil);
+
+    virtual void drawPath(GrDrawTarget* target,
+                          GrDrawTarget::StageBitfield stages,
+                          GrPathIter* path,
+                          GrPathFill fill,
+                          const GrPoint* translate);
+private:
+    bool    fSinglePassWindingStencil;
+};
+
+#endif
\ No newline at end of file
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 0f244a2..8ce45e4 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -23,6 +23,7 @@
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
 #include "GrGpuVertex.h"
+#include "GrDrawTarget.h"
 
 static const int TEXT_STAGE = 1;
 
@@ -47,7 +48,7 @@
         fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture);
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
 
-        fDrawTarget->drawIndexed(GrDrawTarget::kTriangles_PrimitiveType,
+        fDrawTarget->drawIndexed(kTriangles_PrimitiveType,
                                  0, 0, fCurrVertex, nIndices);
         fDrawTarget->releaseReservedGeometry();
         fVertices = NULL;
@@ -178,7 +179,7 @@
         GrPoint translate;
         translate.set(GrFixedToScalar(vx - GrIntToFixed(glyph->fBounds.fLeft)),
                       GrFixedToScalar(vy - GrIntToFixed(glyph->fBounds.fTop)));
-        fContext->drawPath(fPaint, &iter, GrContext::kWinding_PathFill,
+        fContext->drawPath(fPaint, &iter, kWinding_PathFill,
                            &translate);
         return;
     }
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index e6d6997..88aa84b 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -21,4 +21,5 @@
     GrTextureCache.cpp \
     GrTextContext.cpp \
     GrTextStrike.cpp \
-    GrBufferAllocPool.cpp
+    GrBufferAllocPool.cpp\
+    GrPathRenderer.cpp