As part of preliminary groundwork for a chromium fix, this changelist is deprecating GrPathFill so that SkPath::FillType is used everywhere in order to remove some code duplication between Skia and Ganesh.

BUG=chromium:135111
TEST=Try path rendering tests from the gm
Review URL: https://codereview.appspot.com/6875058

git-svn-id: http://skia.googlecode.com/svn/trunk@6693 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index ebfcd7b..f8ded78 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -12,9 +12,9 @@
 #include "GrDrawState.h"
 #include "GrPathUtils.h"
 #include "SkString.h"
+#include "SkStroke.h"
 #include "SkTrace.h"
 
-
 GrAAConvexPathRenderer::GrAAConvexPathRenderer() {
 }
 
@@ -429,20 +429,15 @@
 }
 
 bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
-                                         GrPathFill fill,
+                                         const SkStroke& stroke,
                                          const GrDrawTarget* target,
                                          bool antiAlias) const {
-    if (!target->getCaps().shaderDerivativeSupport() || !antiAlias ||
-        kHairLine_GrPathFill == fill || GrIsFillInverted(fill) ||
-        !path.isConvex()) {
-        return false;
-    }  else {
-        return true;
-    }
+    return (target->getCaps().shaderDerivativeSupport() && antiAlias &&
+            stroke.getDoFill() && !path.isInverseFillType() && path.isConvex());
 }
 
 bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
-                                        GrPathFill fill,
+                                        const SkStroke&,
                                         GrDrawTarget* target,
                                         bool antiAlias) {
 
diff --git a/src/gpu/GrAAConvexPathRenderer.h b/src/gpu/GrAAConvexPathRenderer.h
index 7a2fd38..a64596c 100644
--- a/src/gpu/GrAAConvexPathRenderer.h
+++ b/src/gpu/GrAAConvexPathRenderer.h
@@ -14,13 +14,13 @@
     GrAAConvexPathRenderer();
 
     virtual bool canDrawPath(const SkPath& path,
-                             GrPathFill fill,
+                             const SkStroke& stroke,
                              const GrDrawTarget* target,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
     virtual bool onDrawPath(const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 };
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index cd3f774..6424ad5 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -14,6 +14,7 @@
 #include "GrIndexBuffer.h"
 #include "GrPathUtils.h"
 #include "SkGeometry.h"
+#include "SkStroke.h"
 #include "SkTemplates.h"
 
 namespace {
@@ -546,10 +547,10 @@
 }
 
 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
-                                           GrPathFill fill,
+                                           const SkStroke& stroke,
                                            const GrDrawTarget* target,
                                            bool antiAlias) const {
-    if (fill != kHairLine_GrPathFill || !antiAlias) {
+    if ((0 != stroke.getWidthIfStroked()) || !antiAlias) {
         return false;
     }
 
@@ -563,7 +564,7 @@
 }
 
 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
-                                          GrPathFill fill,
+                                          const SkStroke&,
                                           GrDrawTarget* target,
                                           bool antiAlias) {
 
diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h
index 9129a89..653fd01 100644
--- a/src/gpu/GrAAHairLinePathRenderer.h
+++ b/src/gpu/GrAAHairLinePathRenderer.h
@@ -18,13 +18,13 @@
     static GrPathRenderer* Create(GrContext* context);
 
     virtual bool canDrawPath(const SkPath& path,
-                            GrPathFill fill,
-                            const GrDrawTarget* target,
-                            bool antiAlias) const SK_OVERRIDE;
+                             const SkStroke& stroke,
+                             const GrDrawTarget* target,
+                             bool antiAlias) const SK_OVERRIDE;
 
 protected:
     virtual bool onDrawPath(const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index ff78bf9..5dfc6fa 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -14,6 +14,7 @@
 #include "GrPathRenderer.h"
 #include "GrPaint.h"
 #include "SkRasterClip.h"
+#include "SkStroke.h"
 #include "GrAAConvexPathRenderer.h"
 #include "GrAAHairLinePathRenderer.h"
 #include "GrSWMaskHelper.h"
@@ -57,26 +58,10 @@
 bool path_needs_SW_renderer(GrContext* context,
                             GrGpu* gpu,
                             const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             bool doAA) {
     // last (false) parameter disallows use of the SW path renderer
-    return NULL == context->getPathRenderer(path, fill, gpu, doAA, false);
-}
-
-GrPathFill get_path_fill(const SkPath& path) {
-    switch (path.getFillType()) {
-        case SkPath::kWinding_FillType:
-            return kWinding_GrPathFill;
-        case SkPath::kEvenOdd_FillType:
-            return  kEvenOdd_GrPathFill;
-        case SkPath::kInverseWinding_FillType:
-            return kInverseWinding_GrPathFill;
-        case SkPath::kInverseEvenOdd_FillType:
-            return kInverseEvenOdd_GrPathFill;
-        default:
-            GrCrash("Unsupported path fill in clip.");
-            return kWinding_GrPathFill; // suppress warning
-    }
+    return NULL == context->getPathRenderer(path, stroke, gpu, doAA, false);
 }
 
 /**
@@ -117,6 +102,9 @@
     SkClipStack::Iter iter(clipIn, SkClipStack::Iter::kBottom_IterStart);
     const Element* element = NULL;
 
+    SkStroke stroke;
+    stroke.setDoFill(true);
+
     for (element = iter.skipToTopmost(SkRegion::kReplace_Op);
          NULL != element;
          element = iter.next()) {
@@ -126,7 +114,7 @@
         if (Element::kPath_Type == element->getType() &&
             path_needs_SW_renderer(this->getContext(), fGpu,
                                    element->getPath(),
-                                   get_path_fill(element->getPath()),
+                                   stroke,
                                    element->isAA())) {
             useSW = true;
         }
@@ -407,13 +395,15 @@
 bool draw_path_in_software(GrContext* context,
                            GrGpu* gpu,
                            const SkPath& path,
-                           GrPathFill fill,
                            bool doAA,
                            const GrIRect& resultBounds) {
+    SkStroke stroke;
+    stroke.setDoFill(true);
 
     SkAutoTUnref<GrTexture> texture(
                 GrSWMaskHelper::DrawPathMaskToTexture(context, path,
-                                                      resultBounds, fill,
+                                                      stroke,
+                                                      resultBounds,
                                                       doAA, NULL));
     if (NULL == texture) {
         return false;
@@ -424,7 +414,7 @@
 
     GrSWMaskHelper::DrawToTargetWithPathMask(texture, gpu, rect);
 
-    GrAssert(!GrIsFillInverted(fill));
+    GrAssert(!path.isInverseFillType());
     return true;
 }
 
@@ -433,16 +423,17 @@
 bool draw_path(GrContext* context,
                GrGpu* gpu,
                const SkPath& path,
-               GrPathFill fill,
                bool doAA,
                const GrIRect& resultBounds) {
+    SkStroke stroke;
+    stroke.setDoFill(true);
 
-    GrPathRenderer* pr = context->getPathRenderer(path, fill, gpu, doAA, false);
+    GrPathRenderer* pr = context->getPathRenderer(path, stroke, gpu, doAA, false);
     if (NULL == pr) {
-        return draw_path_in_software(context, gpu, path, fill, doAA, resultBounds);
+        return draw_path_in_software(context, gpu, path, doAA, resultBounds);
     }
 
-    pr->drawPath(path, fill, gpu, doAA);
+    pr->drawPath(path, stroke, gpu, doAA);
     return true;
 }
 
@@ -478,7 +469,6 @@
         case Element::kPath_Type:
             return draw_path(this->getContext(), fGpu,
                              element->getPath(),
-                             get_path_fill(element->getPath()),
                              element->isAA(),
                              resultBounds);
         default:
@@ -786,7 +776,7 @@
         // walk through each clip element and perform its set op
         // with the existing clip.
         for ( ; NULL != element; element = iter.next()) {
-            GrPathFill fill;
+            SkPath::FillType fill;
             bool fillInverted = false;
             // enabled at bottom of loop
             drawState->disableState(GrGpu::kModifyStencilClip_StateBit);
@@ -800,6 +790,9 @@
             // resolve in/out status?
             bool canRenderDirectToStencil = false;
 
+            SkStroke stroke;
+            stroke.setDoFill(true);
+
             SkRegion::Op op = element->getOp();
             if (first) {
                 first = false;
@@ -807,10 +800,10 @@
             }
 
             GrPathRenderer* pr = NULL;
-            const SkPath* clipPath = NULL;
+            SkPath clipPath;
             if (Element::kRect_Type == element->getType()) {
                 canRenderDirectToStencil = true;
-                fill = kEvenOdd_GrPathFill;
+                fill = SkPath::kEvenOdd_FillType;
                 fillInverted = false;
                 // there is no point in intersecting a screen filling
                 // rectangle.
@@ -820,17 +813,18 @@
                 }
             } else {
                 GrAssert(Element::kPath_Type == element->getType());
-                clipPath = &element->getPath();
-                fill = get_path_fill(*clipPath);
-                fillInverted = GrIsFillInverted(fill);
-                fill = GrNonInvertedFill(fill);
-                pr = this->getContext()->getPathRenderer(*clipPath, fill, fGpu, false, true);
+                clipPath = element->getPath();
+                fill = clipPath.getFillType();
+                fillInverted = clipPath.isInverseFillType();
+                fill = SkPath::NonInverseFill(fill);
+                clipPath.setFillType(fill);
+                pr = this->getContext()->getPathRenderer(clipPath, stroke, fGpu, false, true);
                 if (NULL == pr) {
                     fGpu->setClip(oldClipData);
                     return false;
                 }
                 canRenderDirectToStencil =
-                    !pr->requiresStencilPass(*clipPath, fill, fGpu);
+                    !pr->requiresStencilPass(clipPath, stroke, fGpu);
             }
 
             int passes;
@@ -865,9 +859,9 @@
                     GrAssert(Element::kPath_Type == element->getType());
                     if (canRenderDirectToStencil) {
                         *drawState->stencil() = gDrawToStencil;
-                        pr->drawPath(*clipPath, fill, fGpu, false);
+                        pr->drawPath(clipPath, stroke, fGpu, false);
                     } else {
-                        pr->drawPathToStencil(*clipPath, fill, fGpu);
+                        pr->drawPathToStencil(clipPath, stroke, fGpu);
                     }
                 }
             }
@@ -884,7 +878,7 @@
                     } else {
                         GrAssert(Element::kPath_Type == element->getType());
                         SET_RANDOM_COLOR
-                        pr->drawPath(*clipPath, fill, fGpu, false);
+                        pr->drawPath(clipPath, stroke, fGpu, false);
                     }
                 } else {
                     SET_RANDOM_COLOR
@@ -1095,28 +1089,6 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-
-namespace {
-
-GrPathFill invert_fill(GrPathFill fill) {
-    static const GrPathFill gInvertedFillTable[] = {
-        kInverseWinding_GrPathFill, // kWinding_GrPathFill
-        kInverseEvenOdd_GrPathFill, // kEvenOdd_GrPathFill
-        kWinding_GrPathFill,        // kInverseWinding_GrPathFill
-        kEvenOdd_GrPathFill,        // kInverseEvenOdd_GrPathFill
-        kHairLine_GrPathFill,       // kHairLine_GrPathFill
-    };
-    GR_STATIC_ASSERT(0 == kWinding_GrPathFill);
-    GR_STATIC_ASSERT(1 == kEvenOdd_GrPathFill);
-    GR_STATIC_ASSERT(2 == kInverseWinding_GrPathFill);
-    GR_STATIC_ASSERT(3 == kInverseEvenOdd_GrPathFill);
-    GR_STATIC_ASSERT(4 == kHairLine_GrPathFill);
-    GR_STATIC_ASSERT(5 == kGrPathFillCount);
-    return gInvertedFillTable[fill];
-}
-
-}
-
 bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
                                                GrTexture** result,
                                                GrIRect* devResultBounds) {
@@ -1139,6 +1111,9 @@
                         SkIntToScalar(-clipDataIn.fOrigin.fY));
     helper.init(*devResultBounds, &matrix);
 
+    SkStroke stroke;
+    stroke.setDoFill(true);
+
     bool clearToInside;
     SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
 
@@ -1183,15 +1158,17 @@
                 // convert the rect to a path so we can invert the fill
                 SkPath temp;
                 temp.addRect(element->getRect());
+                temp.setFillType(SkPath::kInverseEvenOdd_FillType);
 
-                helper.draw(temp, SkRegion::kReplace_Op,
-                            kInverseEvenOdd_GrPathFill, element->isAA(),
+                helper.draw(temp, stroke, SkRegion::kReplace_Op,
+                            element->isAA(),
                             0x00);
             } else {
                 GrAssert(Element::kPath_Type == element->getType());
-                helper.draw(element->getPath(),
+                SkPath clipPath = element->getPath();
+                clipPath.toggleInverseFillType();
+                helper.draw(clipPath, stroke, 
                             SkRegion::kReplace_Op,
-                            invert_fill(get_path_fill(element->getPath())),
                             element->isAA(),
                             0x00);
             }
@@ -1205,10 +1182,7 @@
             helper.draw(element->getRect(), op, element->isAA(), 0xFF);
         } else {
             GrAssert(Element::kPath_Type == element->getType());
-            helper.draw(element->getPath(),
-                        op,
-                        get_path_fill(element->getPath()),
-                        element->isAA(), 0xFF);
+            helper.draw(element->getPath(), stroke, op, element->isAA(), 0xFF);
         }
     }
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 1292b51..9c209b3 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -26,6 +26,7 @@
 #include "SkTLazy.h"
 #include "SkTLS.h"
 #include "SkTrace.h"
+#include "SkStroke.h"
 
 SK_DEFINE_INST_COUNT(GrContext)
 SK_DEFINE_INST_COUNT(GrDrawState)
@@ -985,9 +986,14 @@
         rect.height() != rect.width()) {
         SkPath path;
         path.addOval(rect);
-        GrPathFill fill = (strokeWidth == 0) ?
-                           kHairLine_GrPathFill : kWinding_GrPathFill;
-        this->internalDrawPath(paint, path, fill);
+        path.setFillType(SkPath::kWinding_FillType);
+        SkStroke stroke;
+        if (strokeWidth < 0) {
+            stroke.setDoFill(true);
+        } else {
+            stroke.setWidth(strokeWidth);
+        }
+        this->internalDrawPath(paint, path, stroke);
         return;
     }
 
@@ -1057,26 +1063,33 @@
     target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
 }
 
-void GrContext::drawPath(const GrPaint& paint, const SkPath& path, GrPathFill fill) {
+void GrContext::drawPath(const GrPaint& paint, const SkPath& path, bool doHairLine) {
 
     if (path.isEmpty()) {
-       if (GrIsFillInverted(fill)) {
+       if (path.isInverseFillType()) {
            this->drawPaint(paint);
        }
        return;
     }
 
     SkRect ovalRect;
-    if (!GrIsFillInverted(fill) && path.isOval(&ovalRect)) {
-        SkScalar width = (fill == kHairLine_GrPathFill) ? 0 : -SK_Scalar1;
+    if (!path.isInverseFillType() && path.isOval(&ovalRect)) {
+        SkScalar width = doHairLine ? 0 : -SK_Scalar1;
         this->drawOval(paint, ovalRect, width);
         return;
     }
 
-    this->internalDrawPath(paint, path, fill);
+    SkStroke stroke;
+    if (doHairLine) {
+        stroke.setWidth(0);
+    } else {
+        stroke.setDoFill(true);
+    }
+
+    this->internalDrawPath(paint, path, stroke);
 }
 
-void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, GrPathFill fill) {
+void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStroke& stroke) {
 
     // Note that below we may sw-rasterize the path into a scratch texture.
     // Scratch textures can be recycled after they are returned to the texture
@@ -1099,7 +1112,7 @@
         prAA = false;
     }
 
-    GrPathRenderer* pr = this->getPathRenderer(path, fill, target, prAA, true);
+    GrPathRenderer* pr = this->getPathRenderer(path, stroke, target, prAA, true);
     if (NULL == pr) {
 #if GR_DEBUG
         GrPrintf("Unable to find path renderer compatible with path.\n");
@@ -1107,7 +1120,7 @@
         return;
     }
 
-    pr->drawPath(path, fill, target, prAA);
+    pr->drawPath(path, stroke, target, prAA);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -1598,7 +1611,7 @@
  * can be individually allowed/disallowed via the "allowSW" boolean.
  */
 GrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
-                                           GrPathFill fill,
+                                           const SkStroke& stroke,
                                            const GrDrawTarget* target,
                                            bool antiAlias,
                                            bool allowSW) {
@@ -1608,7 +1621,8 @@
                        (this, GrPathRendererChain::kNone_UsageFlag));
     }
 
-    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path, fill,
+    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
+                                                             stroke,
                                                              target,
                                                              antiAlias);
 
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index 521afd3..f80b4d7 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -12,6 +12,7 @@
 #include "GrDrawState.h"
 #include "GrPathUtils.h"
 #include "SkString.h"
+#include "SkStroke.h"
 #include "SkTrace.h"
 
 
@@ -150,11 +151,11 @@
 
 #define STENCIL_OFF     0   // Always disable stencil (even when needed)
 
-static inline bool single_pass_path(const SkPath& path, GrPathFill fill) {
+static inline bool single_pass_path(const SkPath& path, const SkStroke& stroke) {
 #if STENCIL_OFF
     return true;
 #else
-    if (kEvenOdd_GrPathFill == fill || kWinding_GrPathFill == fill) {
+    if ((0 != stroke.getWidthIfStroked()) && !path.isInverseFillType()) {
         return path.isConvex();
     }
     return false;
@@ -162,19 +163,19 @@
 }
 
 bool GrDefaultPathRenderer::requiresStencilPass(const SkPath& path,
-                                                GrPathFill fill,
+                                                const SkStroke& stroke,
                                                 const GrDrawTarget* target) const {
-    return !single_pass_path(path, fill);
+    return !single_pass_path(path, stroke);
 }
 
-static inline void append_countour_edge_indices(GrPathFill fillType,
+static inline void append_countour_edge_indices(bool hairLine,
                                                 uint16_t fanCenterIdx,
                                                 uint16_t edgeV0Idx,
                                                 uint16_t** indices) {
     // when drawing lines we're appending line segments along
     // the contour. When applying the other fill rules we're
     // drawing triangle fans around fanCenterIdx.
-    if (kHairLine_GrPathFill != fillType) {
+    if (!hairLine) {
         *((*indices)++) = fanCenterIdx;
     }
     *((*indices)++) = edgeV0Idx;
@@ -182,7 +183,7 @@
 }
 
 bool GrDefaultPathRenderer::createGeom(const SkPath& path,
-                                       GrPathFill fill,
+                                       const SkStroke& stroke,
                                        SkScalar srcSpaceTol,
                                        GrDrawTarget* target,
                                        GrPrimitiveType* primType,
@@ -208,8 +209,10 @@
     GrVertexLayout layout = 0;
     bool indexed = contourCnt > 1;
 
+    const bool isHairline = 0 == stroke.getWidthIfStroked();
+
     int maxIdxs = 0;
-    if (kHairLine_GrPathFill == fill) {
+    if (isHairline) {
         if (indexed) {
             maxIdxs = 2 * maxPts;
             *primType = kLines_GrPrimitiveType;
@@ -260,7 +263,7 @@
             case kLine_PathCmd:
                 if (indexed) {
                     uint16_t prevIdx = (uint16_t)(vert - base) - 1;
-                    append_countour_edge_indices(fill, subpathIdxStart,
+                    append_countour_edge_indices(isHairline, subpathIdxStart,
                                                  prevIdx, &idx);
                 }
                 *(vert++) = pts[1];
@@ -275,7 +278,7 @@
                             GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
                 if (indexed) {
                     for (uint16_t i = 0; i < numPts; ++i) {
-                        append_countour_edge_indices(fill, subpathIdxStart,
+                        append_countour_edge_indices(isHairline, subpathIdxStart,
                                                      firstQPtIdx + i, &idx);
                     }
                 }
@@ -290,7 +293,7 @@
                                 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
                 if (indexed) {
                     for (uint16_t i = 0; i < numPts; ++i) {
-                        append_countour_edge_indices(fill, subpathIdxStart,
+                        append_countour_edge_indices(isHairline, subpathIdxStart,
                                                      firstCPtIdx + i, &idx);
                     }
                 }
@@ -316,7 +319,7 @@
 }
 
 bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
-                                             GrPathFill fill,
+                                             const SkStroke& stroke,
                                              GrDrawTarget* target,
                                              bool stencilOnly) {
 
@@ -329,7 +332,7 @@
     GrPrimitiveType primType;
     GrDrawTarget::AutoReleaseGeometry arg;
     if (!this->createGeom(path,
-                          fill,
+                          stroke,
                           tol,
                           target,
                           &primType,
@@ -352,7 +355,7 @@
     bool                        reverse = false;
     bool                        lastPassIsBounds;
 
-    if (kHairLine_GrPathFill == fill) {
+    if (0 == stroke.getWidthIfStroked()) {
         passCount = 1;
         if (stencilOnly) {
             passes[0] = &gDirectToStencil;
@@ -362,7 +365,7 @@
         lastPassIsBounds = false;
         drawFace[0] = GrDrawState::kBoth_DrawFace;
     } else {
-        if (single_pass_path(path, fill)) {
+        if (single_pass_path(path, stroke)) {
             passCount = 1;
             if (stencilOnly) {
                 passes[0] = &gDirectToStencil;
@@ -372,11 +375,11 @@
             drawFace[0] = GrDrawState::kBoth_DrawFace;
             lastPassIsBounds = false;
         } else {
-            switch (fill) {
-                case kInverseEvenOdd_GrPathFill:
+            switch (path.getFillType()) {
+                case SkPath::kInverseEvenOdd_FillType:
                     reverse = true;
                     // fallthrough
-                case kEvenOdd_GrPathFill:
+                case SkPath::kEvenOdd_FillType:
                     passes[0] = &gEOStencilPass;
                     if (stencilOnly) {
                         passCount = 1;
@@ -393,10 +396,10 @@
                     drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
                     break;
 
-                case kInverseWinding_GrPathFill:
+                case SkPath::kInverseWinding_FillType:
                     reverse = true;
                     // fallthrough
-                case kWinding_GrPathFill:
+                case SkPath::kWinding_FillType:
                     if (fSeparateStencil) {
                         if (fStencilWrapOps) {
                             passes[0] = &gWindStencilSeparateWithWrap;
@@ -487,28 +490,28 @@
 }
 
 bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
-                                        GrPathFill fill,
+                                        const SkStroke& stroke,
                                         const GrDrawTarget* target,
                                         bool antiAlias) const {
     // this class can draw any path with any fill but doesn't do any
     // anti-aliasing.
-    return !antiAlias;
+    return (stroke.getWidthIfStroked() <= 0) && !antiAlias;
 }
 
 bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
-                                       GrPathFill fill,
+                                       const SkStroke& stroke,
                                        GrDrawTarget* target,
                                        bool antiAlias) {
     return this->internalDrawPath(path,
-                                  fill,
+                                  stroke,
                                   target,
                                   false);
 }
 
 void GrDefaultPathRenderer::drawPathToStencil(const SkPath& path,
-                                              GrPathFill fill,
+                                              const SkStroke& stroke,
                                               GrDrawTarget* target) {
-    GrAssert(kInverseEvenOdd_GrPathFill != fill);
-    GrAssert(kInverseWinding_GrPathFill != fill);
-    this->internalDrawPath(path, fill, target, true);
+    GrAssert(SkPath::kInverseEvenOdd_FillType != path.getFillType());
+    GrAssert(SkPath::kInverseWinding_FillType != path.getFillType());
+    this->internalDrawPath(path, stroke, target, true);
 }
diff --git a/src/gpu/GrDefaultPathRenderer.h b/src/gpu/GrDefaultPathRenderer.h
index c516552..e98f2d7 100644
--- a/src/gpu/GrDefaultPathRenderer.h
+++ b/src/gpu/GrDefaultPathRenderer.h
@@ -22,32 +22,32 @@
 
 
     virtual bool requiresStencilPass(const SkPath& path,
-                                     GrPathFill fill,
+                                     const SkStroke& stroke,
                                      const GrDrawTarget* target) const SK_OVERRIDE;
 
     virtual bool canDrawPath(const SkPath& path,
-                            GrPathFill fill,
-                            const GrDrawTarget* target,
-                            bool antiAlias) const SK_OVERRIDE;
+                             const SkStroke& stroke,
+                             const GrDrawTarget* target,
+                             bool antiAlias) const SK_OVERRIDE;
 
     virtual void drawPathToStencil(const SkPath& path,
-                                   GrPathFill fill,
+                                   const SkStroke& stroke,
                                    GrDrawTarget* target) SK_OVERRIDE;
 
 private:
 
     virtual bool onDrawPath(const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 
     bool internalDrawPath(const SkPath& path,
-                          GrPathFill fill,
+                          const SkStroke& stroke,
                           GrDrawTarget* target,
                           bool stencilOnly);
 
     bool createGeom(const SkPath& path,
-                    GrPathFill fill,
+                    const SkStroke& stroke,
                     SkScalar srcSpaceTol,
                     GrDrawTarget* target,
                     GrPrimitiveType* primType,
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 8fa39d2..6927895 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -15,6 +15,8 @@
 #include "GrTexture.h"
 #include "GrVertexBuffer.h"
 
+#include "SkStroke.h"
+
 SK_DEFINE_INST_COUNT(GrDrawTarget)
 
 namespace {
@@ -783,13 +785,13 @@
     }
 }
 
-void GrDrawTarget::stencilPath(const GrPath* path, GrPathFill fill) {
+void GrDrawTarget::stencilPath(const GrPath* path, const SkStroke& stroke, SkPath::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path stenciling.
     GrAssert(NULL != path);
     GrAssert(fCaps.pathStencilingSupport());
-    GrAssert(kHairLine_GrPathFill != fill);
-    GrAssert(!GrIsFillInverted(fill));
-    this->onStencilPath(path, fill);
+    GrAssert(0 != stroke.getWidthIfStroked());
+    GrAssert(!SkPath::IsInverseFill(fill));
+    this->onStencilPath(path, stroke, fill);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 4d652f6..6e0af43 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -17,6 +17,7 @@
 #include "GrRefCnt.h"
 #include "GrTemplates.h"
 
+#include "SkPath.h"
 #include "SkXfermode.h"
 #include "SkTLazy.h"
 #include "SkTArray.h"
@@ -25,6 +26,8 @@
 class GrPath;
 class GrVertexBuffer;
 
+class SkStroke;
+
 class GrDrawTarget : public GrRefCnt {
 protected:
     /** This helper class allows GrDrawTarget subclasses to set the caps values without having to be
@@ -452,7 +455,7 @@
      * winding (not inverse or hairline). It will respect the HW antialias flag
      * on the draw state (if possible in the 3D API).
      */
-    void stencilPath(const GrPath*, GrPathFill);
+    void stencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType fill);
 
     /**
      * Helper function for drawing rects. This does not use the current index
@@ -981,7 +984,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) = 0;
-    virtual void onStencilPath(const GrPath*, GrPathFill) = 0;
+    virtual void onStencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType fill) = 0;
 
     // subclass overrides to be notified when clip is set. Must call
     // INHERITED::clipwillBeSet
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 4602298..18013c1 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -410,7 +410,7 @@
     this->onGpuDrawNonIndexed(type, sVertex, vertexCount);
 }
 
-void GrGpu::onStencilPath(const GrPath* path, GrPathFill fill) {
+void GrGpu::onStencilPath(const GrPath* path, const SkStroke& stroke, SkPath::FillType fill) {
     this->handleDirtyContext();
 
     // TODO: make this more effecient (don't copy and copy back)
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index f9fd779..d3a0012 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -15,6 +15,8 @@
 #include "GrRefCnt.h"
 #include "GrClipMaskManager.h"
 
+#include "SkPath.h"
+
 class GrContext;
 class GrIndexBufferAllocPool;
 class GrPath;
@@ -473,10 +475,10 @@
     // necessary to stencil the path. These are still subject to filtering by
     // the clip mask manager.
     virtual void setStencilPathSettings(const GrPath&,
-                                        GrPathFill,
+                                        SkPath::FillType,
                                         GrStencilSettings* settings) = 0;
     // overridden by backend-specific derived class to perform the path stenciling.
-    virtual void onGpuStencilPath(const GrPath*, GrPathFill) = 0;
+    virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) = 0;
 
     // overridden by backend-specific derived class to perform flush
     virtual void onForceRenderTargetFlush() = 0;
@@ -568,7 +570,8 @@
     virtual void onDrawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) SK_OVERRIDE;
-    virtual void onStencilPath(const GrPath* path, GrPathFill fill) SK_OVERRIDE;
+    virtual void onStencilPath(const GrPath* path, const SkStroke& stroke,
+                               SkPath::FillType) SK_OVERRIDE;
 
     // readies the pools to provide vertex/index data.
     void prepareVertexPool();
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index b2f7963..4147b3b 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -487,7 +487,8 @@
     draw->fIndexBuffer = NULL;
 }
 
-void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, GrPathFill fill) {
+void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, const SkStroke& stroke,
+                                        SkPath::FillType fill) {
     if (this->needsNewClip()) {
         this->recordClip();
     }
@@ -499,6 +500,7 @@
     sp->fPath.reset(path);
     path->ref();
     sp->fFill = fill;
+    sp->fStroke = stroke;
 }
 
 void GrInOrderDrawBuffer::clear(const GrIRect* rect,
@@ -610,7 +612,7 @@
             }
             case kStencilPath_Cmd: {
                 const StencilPath& sp = fStencilPaths[currStencilPath];
-                target->stencilPath(sp.fPath.get(), sp.fFill);
+                target->stencilPath(sp.fPath.get(), sp.fStroke, sp.fFill);
                 ++currStencilPath;
                 break;
             }
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index e80a2b4..20f0c84 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -17,6 +17,7 @@
 #include "GrPath.h"
 
 #include "SkClipStack.h"
+#include "SkStroke.h"
 #include "SkTemplates.h"
 
 class GrGpu;
@@ -158,7 +159,8 @@
 
     struct StencilPath {
         SkAutoTUnref<const GrPath>  fPath;
-        GrPathFill                  fFill;
+        SkStroke                    fStroke;
+        SkPath::FillType            fFill;
     };
 
     struct Clear {
@@ -179,7 +181,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType primitiveType,
                                   int startVertex,
                                   int vertexCount) SK_OVERRIDE;
-    virtual void onStencilPath(const GrPath*, GrPathFill) SK_OVERRIDE;
+    virtual void onStencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType) SK_OVERRIDE;
     virtual bool onReserveVertexSpace(GrVertexLayout layout,
                                       int vertexCount,
                                       void** vertices) SK_OVERRIDE;
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/GrPathRenderer.h
index fc3d672..afcd3c9 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -16,6 +16,7 @@
 #include "SkTArray.h"
 
 class SkPath;
+class SkStroke;
 
 struct GrPoint;
 
@@ -57,10 +58,9 @@
      * the target's stencil settings but use those already set on target. The
      * target is passed as a param in case the answer depends upon draw state.
      *
-     * @param target target that the path will be rendered to
-     * @param path   the path that will be drawn
-     * @param fill   the fill rule that will be used, will never be an inverse
-     *               rule.
+     * @param target    target that the path will be rendered to
+     * @param path      the path that will be drawn
+     * @param stroke    the stroke information (width, join, cap).
      *
      * @return false if this path renderer can generate interior-only fragments
      *         without changing the stencil settings on the target. If it
@@ -68,7 +68,7 @@
      *         clips.
      */
     virtual bool requiresStencilPass(const SkPath& path,
-                                     GrPathFill fill,
+                                     const SkStroke& stroke,
                                      const GrDrawTarget* target) const {
         return false;
     }
@@ -80,14 +80,14 @@
      * rendering a path.
      *
      * @param path       The path to draw
-     * @param fill       The fill rule to use
+     * @param stroke     The stroke information (width, join, cap)
      * @param target     The target that the path will be rendered to
      * @param antiAlias  True if anti-aliasing is required.
      *
      * @return  true if the path can be drawn by this object, false otherwise.
      */
     virtual bool canDrawPath(const SkPath& path,
-                             GrPathFill fill,
+                             const SkStroke& stroke,
                              const GrDrawTarget* target,
                              bool antiAlias) const = 0;
     /**
@@ -96,22 +96,22 @@
      * path renderer didn't claim that it needs to use the stencil internally).
      *
      * @param path                  the path to draw.
-     * @param fill                  the path filling rule to use.
+     * @param stroke                the stroke information (width, join, cap)
      * @param target                target that the path will be rendered to
      * @param antiAlias             true if anti-aliasing is required.
      */
     virtual bool drawPath(const SkPath& path,
-                          GrPathFill fill,
+                          const SkStroke& stroke,
                           GrDrawTarget* target,
                           bool antiAlias) {
-        GrAssert(this->canDrawPath(path, fill, target, antiAlias));
-        return this->onDrawPath(path, fill, target, antiAlias);
+        GrAssert(this->canDrawPath(path, stroke, target, antiAlias));
+        return this->onDrawPath(path, stroke, target, antiAlias);
     }
 
     /**
      * Draws the path to the stencil buffer. Assume the writable stencil bits
      * are already initialized to zero. Fill will always be either
-     * kWinding_GrPathFill or kEvenOdd_GrPathFill.
+     * kWinding_FillType or kEvenOdd_FillType.
      *
      * Only called if requiresStencilPass returns true for the same combo of
      * target, path, and fill. Never called with an inverse fill.
@@ -121,7 +121,7 @@
      *
      */
     virtual void drawPathToStencil(const SkPath& path,
-                                   GrPathFill fill,
+                                   const SkStroke& stroke,
                                    GrDrawTarget* target) {
         GrCrash("Unexpected call to drawPathToStencil.");
     }
@@ -131,12 +131,12 @@
      * Draws the path into the draw target.
      *
      * @param path                  the path to draw.
-     * @param fill                  the path filling rule to use.
+     * @param stroke                the stroke information (width, join, cap)
      * @param target                target that the path will be rendered to
      * @param antiAlias             whether antialiasing is enabled or not.
      */
     virtual bool onDrawPath(const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) = 0;
 
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index 2814f99..8ccafcf 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -34,14 +34,14 @@
 }
 
 GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path,
-                                                     GrPathFill fill,
+                                                     const SkStroke& stroke,
                                                      const GrDrawTarget* target,
                                                      bool antiAlias) {
     if (!fInit) {
         this->init();
     }
     for (int i = 0; i < fChain.count(); ++i) {
-        if (fChain[i]->canDrawPath(path, fill, target, antiAlias)) {
+        if (fChain[i]->canDrawPath(path, stroke, target, antiAlias)) {
             return fChain[i];
         }
     }
diff --git a/src/gpu/GrPathRendererChain.h b/src/gpu/GrPathRendererChain.h
index e5ccabb..dfc696d 100644
--- a/src/gpu/GrPathRendererChain.h
+++ b/src/gpu/GrPathRendererChain.h
@@ -17,6 +17,7 @@
 class GrContext;
 
 class SkPath;
+class SkStroke;
 class GrPathRenderer;
 
 /**
@@ -42,7 +43,7 @@
     GrPathRenderer* addPathRenderer(GrPathRenderer* pr);
 
     GrPathRenderer* getPathRenderer(const SkPath& path,
-                                    GrPathFill fill,
+                                    const SkStroke& stroke,
                                     const GrDrawTarget* target,
                                     bool antiAlias);
 
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 4aad051..02868ef 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -9,6 +9,8 @@
 #include "GrDrawState.h"
 #include "GrGpu.h"
 
+#include "SkStroke.h"
+
 // TODO: try to remove this #include
 #include "GrContext.h"
 
@@ -30,23 +32,6 @@
     return modeMap[op];
 }
 
-////////////////////////////////////////////////////////////////////////////////
-SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
-    switch (fill) {
-        case kWinding_GrPathFill:
-            return SkPath::kWinding_FillType;
-        case kEvenOdd_GrPathFill:
-            return SkPath::kEvenOdd_FillType;
-        case kInverseWinding_GrPathFill:
-            return SkPath::kInverseWinding_FillType;
-        case kInverseEvenOdd_GrPathFill:
-            return SkPath::kInverseEvenOdd_FillType;
-        default:
-            GrCrash("Unexpected fill.");
-            return SkPath::kWinding_FillType;
-    }
-}
-
 }
 
 /**
@@ -70,22 +55,22 @@
 /**
  * Draw a single path element of the clip stack into the accumulation bitmap
  */
-void GrSWMaskHelper::draw(const SkPath& path, SkRegion::Op op,
-                          GrPathFill fill, bool antiAlias, uint8_t alpha) {
+void GrSWMaskHelper::draw(const SkPath& path, const SkStroke& stroke, SkRegion::Op op,
+                          bool antiAlias, uint8_t alpha) {
 
     SkPaint paint;
-    SkPath tmpPath;
-    const SkPath* pathToDraw = &path;
-    if (kHairLine_GrPathFill == fill) {
+    SkScalar width = stroke.getWidthIfStroked();
+    if (0 == width) {
         paint.setStyle(SkPaint::kStroke_Style);
         paint.setStrokeWidth(SK_Scalar1);
     } else {
-        paint.setStyle(SkPaint::kFill_Style);
-        SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
-        if (skfill != pathToDraw->getFillType()) {
-            tmpPath = *pathToDraw;
-            tmpPath.setFillType(skfill);
-            pathToDraw = &tmpPath;
+        if (stroke.getDoFill()) {
+            paint.setStyle(SkPaint::kFill_Style);
+        } else {
+            paint.setStyle(SkPaint::kStroke_Style);
+            paint.setStrokeJoin(stroke.getJoin());
+            paint.setStrokeCap(stroke.getCap());
+            paint.setStrokeWidth(width);
         }
     }
     SkXfermode* mode = SkXfermode::Create(op_to_mode(op));
@@ -94,7 +79,7 @@
     paint.setAntiAlias(antiAlias);
     paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
 
-    fDraw.drawPath(*pathToDraw, paint);
+    fDraw.drawPath(path, paint);
 
     SkSafeUnref(mode);
 }
@@ -174,8 +159,8 @@
  */
 GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
                                                  const SkPath& path,
+                                                 const SkStroke& stroke,
                                                  const GrIRect& resultBounds,
-                                                 GrPathFill fill,
                                                  bool antiAlias,
                                                  SkMatrix* matrix) {
     GrAutoScratchTexture ast;
@@ -186,7 +171,7 @@
         return NULL;
     }
 
-    helper.draw(path, SkRegion::kReplace_Op, fill, antiAlias, 0xFF);
+    helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF);
 
     if (!helper.getTexture(&ast)) {
         return NULL;
diff --git a/src/gpu/GrSWMaskHelper.h b/src/gpu/GrSWMaskHelper.h
index 3c35794..3ceaad3 100644
--- a/src/gpu/GrSWMaskHelper.h
+++ b/src/gpu/GrSWMaskHelper.h
@@ -21,6 +21,7 @@
 class GrContext;
 class GrTexture;
 class SkPath;
+class SkStroke;
 class GrDrawTarget;
 
 /**
@@ -54,8 +55,8 @@
               bool antiAlias, uint8_t alpha);
 
     // Draw a single path into the accumuation bitmap using the specified op
-    void draw(const SkPath& path, SkRegion::Op op,
-              GrPathFill fill, bool antiAlias, uint8_t alpha);
+    void draw(const SkPath& path, const SkStroke& stroke, SkRegion::Op op,
+              bool antiAlias, uint8_t alpha);
 
     // Helper function to get a scratch texture suitable for capturing the
     // result (i.e., right size & format)
@@ -74,8 +75,8 @@
     // to the GPU. The result is returned in "result".
     static GrTexture* DrawPathMaskToTexture(GrContext* context,
                                             const SkPath& path,
+                                            const SkStroke& stroke,
                                             const GrIRect& resultBounds,
-                                            GrPathFill fill,
                                             bool antiAlias,
                                             SkMatrix* matrix);
 
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 6d91ef9..a521eef 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -12,7 +12,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
-                                         GrPathFill fill,
+                                         const SkStroke& stroke,
                                          const GrDrawTarget* target,
                                          bool antiAlias) const {
     if (!antiAlias || NULL == fContext) {
@@ -107,7 +107,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // return true on success; false on failure
 bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
-                                        GrPathFill fill,
+                                        const SkStroke& stroke,
                                         GrDrawTarget* target,
                                         bool antiAlias) {
 
@@ -122,15 +122,15 @@
     GrIRect devPathBounds, devClipBounds;
     if (!get_path_and_clip_bounds(target, path, vm,
                                   &devPathBounds, &devClipBounds)) {
-        if (GrIsFillInverted(fill)) {
+        if (path.isInverseFillType()) {
             draw_around_inv_path(target, devClipBounds, devPathBounds);
         }
         return true;
     }
 
     SkAutoTUnref<GrTexture> texture(
-            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path,
-                                                  devPathBounds, fill,
+            GrSWMaskHelper::DrawPathMaskToTexture(fContext, path, stroke,
+                                                  devPathBounds,
                                                   antiAlias, &vm));
     if (NULL == texture) {
         return false;
@@ -138,7 +138,7 @@
 
     GrSWMaskHelper::DrawToTargetWithPathMask(texture, target, devPathBounds);
 
-    if (GrIsFillInverted(fill)) {
+    if (path.isInverseFillType()) {
         draw_around_inv_path(target, devClipBounds, devPathBounds);
     }
 
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index fdcc7bd..7c7382c 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -25,12 +25,12 @@
     }
 
     virtual bool canDrawPath(const SkPath& path,
-                            GrPathFill fill,
-                            const GrDrawTarget* target,
-                            bool antiAlias) const SK_OVERRIDE;
+                             const SkStroke& stroke,
+                             const GrDrawTarget* target,
+                             bool antiAlias) const SK_OVERRIDE;
 protected:
     virtual bool onDrawPath(const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index 9749f1d..28e18ed 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -11,6 +11,7 @@
 #include "GrContext.h"
 #include "GrGpu.h"
 #include "GrPath.h"
+#include "SkStroke.h"
 
 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
     GrAssert(NULL != context);
@@ -33,42 +34,42 @@
 }
 
 bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
-                                                GrPathFill fill,
+                                                const SkStroke& stroke,
                                                 const GrDrawTarget* target,
                                                 bool antiAlias) const {
-    return kHairLine_GrPathFill != fill &&
+    return stroke.getDoFill() &&
            !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
            target->getDrawState().getStencil().isDisabled();
 }
 
 bool GrStencilAndCoverPathRenderer::requiresStencilPass(const SkPath& path,
-                                                        GrPathFill fill,
+                                                        const SkStroke& stroke,
                                                         const GrDrawTarget* target) const {
     return true;
 }
 
 void GrStencilAndCoverPathRenderer::drawPathToStencil(const SkPath& path,
-                                                      GrPathFill fill,
+                                                      const SkStroke& stroke,
                                                       GrDrawTarget* target) {
-    GrAssert(kEvenOdd_GrPathFill == fill || kWinding_GrPathFill == fill);
+    GrAssert(!path.isInverseFillType());
     SkAutoTUnref<GrPath> p(fGpu->createPath(path));
-    target->stencilPath(p, fill);
+    target->stencilPath(p, stroke, path.getFillType());
 }
 
 bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
-                                               GrPathFill fill,
+                                               const SkStroke& stroke,
                                                GrDrawTarget* target,
                                                bool antiAlias) {
     GrAssert(!antiAlias);
-    GrAssert(kHairLine_GrPathFill != fill);
+    GrAssert(0 != stroke.getWidthIfStroked());
 
     GrDrawState* drawState = target->drawState();
     GrAssert(drawState->getStencil().isDisabled());
 
     SkAutoTUnref<GrPath> p(fGpu->createPath(path));
 
-    GrPathFill nonInvertedFill = GrNonInvertedFill(fill);
-    target->stencilPath(p, nonInvertedFill);
+    SkPath::FillType nonInvertedFill = SkPath::NonInverseFill(path.getFillType());
+    target->stencilPath(p, stroke, nonInvertedFill);
 
     // TODO: Use built in cover operation rather than a rect draw. This will require making our
     // fragment shaders be able to eat varyings generated by a matrix.
@@ -78,7 +79,7 @@
     SkScalar bloat = drawState->getViewMatrix().getMaxStretch() * SK_ScalarHalf;
     GrDrawState::AutoDeviceCoordDraw adcd;
 
-    if (nonInvertedFill == fill) {
+    if (nonInvertedFill == path.getFillType()) {
         GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
             kZero_StencilOp,
             kZero_StencilOp,
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.h b/src/gpu/GrStencilAndCoverPathRenderer.h
index e44ddb2..9a8dd57 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.h
+++ b/src/gpu/GrStencilAndCoverPathRenderer.h
@@ -26,21 +26,21 @@
     virtual ~GrStencilAndCoverPathRenderer();
 
     virtual bool canDrawPath(const SkPath& path,
-                             GrPathFill fill,
+                             const SkStroke& stroke,
                              const GrDrawTarget* target,
                              bool antiAlias) const SK_OVERRIDE;
 
     virtual bool requiresStencilPass(const SkPath& path,
-                                     GrPathFill fill,
+                                     const SkStroke& stroke,
                                      const GrDrawTarget* target) const SK_OVERRIDE;
 
     virtual void drawPathToStencil(const SkPath& path,
-                                   GrPathFill fill,
+                                   const SkStroke& stroke,
                                    GrDrawTarget* target) SK_OVERRIDE;
 
 protected:
     virtual bool onDrawPath(const SkPath& path,
-                            GrPathFill fill,
+                            const SkStroke& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index bb434b6..fdb5d37 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -179,7 +179,7 @@
                                SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
         GrPaint tmpPaint(fPaint);
         am.setPreConcat(fContext, translate, &tmpPaint);
-        fContext->drawPath(tmpPaint, *glyph->fPath, kWinding_GrPathFill);
+        fContext->drawPath(tmpPaint, *glyph->fPath, false);
         return;
     }
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 13fb99c..5d04995 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -741,22 +741,6 @@
 // helpers for applying mask filters
 namespace {
 
-GrPathFill skToGrFillType(SkPath::FillType fillType) {
-    switch (fillType) {
-        case SkPath::kWinding_FillType:
-            return kWinding_GrPathFill;
-        case SkPath::kEvenOdd_FillType:
-            return kEvenOdd_GrPathFill;
-        case SkPath::kInverseWinding_FillType:
-            return kInverseWinding_GrPathFill;
-        case SkPath::kInverseEvenOdd_FillType:
-            return kInverseEvenOdd_GrPathFill;
-        default:
-            SkDebugf("Unsupported path fill type\n");
-            return kHairLine_GrPathFill;
-    }
-}
-
 // We prefer to blur small rect with small radius via CPU.
 #define MIN_GPU_BLUR_SIZE SkIntToScalar(64)
 #define MIN_GPU_BLUR_RADIUS SkIntToScalar(32)
@@ -769,9 +753,9 @@
     return false;
 }
 
-bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath,
+bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, bool doHairLine,
                            SkMaskFilter* filter, const SkRegion& clip,
-                           SkBounder* bounder, GrPaint* grp, GrPathFill pathFillType) {
+                           SkBounder* bounder, GrPaint* grp) {
     SkMaskFilter::BlurInfo info;
     SkMaskFilter::BlurType blurType = filter->asABlur(&info);
     if (SkMaskFilter::kNone_BlurType == blurType) {
@@ -854,7 +838,7 @@
         SkMatrix translate;
         translate.setTranslate(offset.fX, offset.fY);
         am.set(context, translate);
-        context->drawPath(tempPaint, devPath, pathFillType);
+        context->drawPath(tempPaint, devPath, doHairLine);
 
         // If we're doing a normal blur, we can clobber the pathTexture in the
         // gaussianBlur.  Otherwise, we need to save it for later compositing.
@@ -980,7 +964,7 @@
     CHECK_FOR_NODRAW_ANNOTATION(paint);
     CHECK_SHOULD_DRAW(draw, false);
 
-    bool             doFill = true;
+    bool             doHairLine = false;
 
     GrPaint grPaint;
     SkAutoCachedTexture textures[GrPaint::kMaxColorStages];
@@ -996,7 +980,7 @@
     // if we can, we draw lots faster (raster device does this same test)
     SkScalar hairlineCoverage;
     if (SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage)) {
-        doFill = false;
+        doHairLine = true;
         grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
     }
 
@@ -1022,11 +1006,11 @@
     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
 
     if (paint.getPathEffect() ||
-        (doFill && paint.getStyle() != SkPaint::kFill_Style)) {
+        (!doHairLine && paint.getStyle() != SkPaint::kFill_Style)) {
         // it is safe to use tmpPath here, even if we already used it for the
         // prepathmatrix, since getFillPath can take the same object for its
         // input and output safely.
-        doFill = paint.getFillPath(*pathPtr, &tmpPath);
+        doHairLine = !paint.getFillPath(*pathPtr, &tmpPath);
         pathPtr = &tmpPath;
     }
 
@@ -1036,41 +1020,17 @@
 
         // transform the path into device space
         pathPtr->transform(fContext->getMatrix(), devPathPtr);
-        GrPathFill pathFillType = doFill ?
-            skToGrFillType(devPathPtr->getFillType()) : kHairLine_GrPathFill;
-        if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
-                                   *draw.fClip, draw.fBounder, &grPaint, pathFillType)) {
-            SkPaint::Style style = doFill ? SkPaint::kFill_Style :
-                SkPaint::kStroke_Style;
+        if (!drawWithGPUMaskFilter(fContext, *devPathPtr, doHairLine, paint.getMaskFilter(),
+                                   *draw.fClip, draw.fBounder, &grPaint)) {
+            SkPaint::Style style = doHairLine ? SkPaint::kStroke_Style :
+                                                SkPaint::kFill_Style;
             drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
                                *draw.fClip, draw.fBounder, &grPaint, style);
         }
         return;
     }
 
-    GrPathFill fill = kHairLine_GrPathFill;
-
-    if (doFill) {
-        switch (pathPtr->getFillType()) {
-            case SkPath::kWinding_FillType:
-                fill = kWinding_GrPathFill;
-                break;
-            case SkPath::kEvenOdd_FillType:
-                fill = kEvenOdd_GrPathFill;
-                break;
-            case SkPath::kInverseWinding_FillType:
-                fill = kInverseWinding_GrPathFill;
-                break;
-            case SkPath::kInverseEvenOdd_FillType:
-                fill = kInverseEvenOdd_GrPathFill;
-                break;
-            default:
-                SkDebugf("Unsupported path fill type\n");
-                return;
-        }
-    }
-
-    fContext->drawPath(grPaint, *pathPtr, fill);
+    fContext->drawPath(grPaint, *pathPtr, doHairLine);
 }
 
 namespace {
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index eb60539..f01fd3f 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1681,13 +1681,13 @@
 
 
 void GrGpuGL::setStencilPathSettings(const GrPath&,
-                                     GrPathFill fill,
+                                     SkPath::FillType fill,
                                      GrStencilSettings* settings) {
     switch (fill) {
-        case kEvenOdd_GrPathFill:
+        case SkPath::kEvenOdd_FillType:
             *settings = even_odd_nv_path_stencil_settings();
             return;
-        case kWinding_GrPathFill:
+        case SkPath::kWinding_FillType:
             *settings = winding_nv_path_stencil_settings();
             return;
         default:
@@ -1695,7 +1695,7 @@
     }
 }
 
-void GrGpuGL::onGpuStencilPath(const GrPath* path, GrPathFill fill) {
+void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
     GrAssert(fCaps.pathStencilingSupport());
 
     GrGLuint id = static_cast<const GrGLPath*>(path)->pathID();
@@ -1711,14 +1711,14 @@
     GrAssert(!fStencilSettings.isTwoSided());
     GrGLenum fillMode;
     switch (fill) {
-        case kWinding_GrPathFill:
+        case SkPath::kWinding_FillType:
             fillMode = GR_GL_COUNT_UP;
             GrAssert(kIncClamp_StencilOp ==
                      fStencilSettings.passOp(GrStencilSettings::kFront_Face));
             GrAssert(kIncClamp_StencilOp ==
                      fStencilSettings.failOp(GrStencilSettings::kFront_Face));
             break;
-        case kEvenOdd_GrPathFill:
+        case SkPath::kEvenOdd_FillType:
             fillMode = GR_GL_INVERT;
             GrAssert(kInvert_StencilOp ==
                      fStencilSettings.passOp(GrStencilSettings::kFront_Face));
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 7f74d8e..33834cf 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -104,10 +104,10 @@
                                      uint32_t numVertices) SK_OVERRIDE;
 
     virtual void setStencilPathSettings(const GrPath&,
-                                        GrPathFill,
+                                        SkPath::FillType,
                                         GrStencilSettings* settings)
                                         SK_OVERRIDE;
-    virtual void onGpuStencilPath(const GrPath*, GrPathFill) SK_OVERRIDE;
+    virtual void onGpuStencilPath(const GrPath*, SkPath::FillType) SK_OVERRIDE;
 
     virtual void clearStencil() SK_OVERRIDE;
     virtual void clearStencilClip(const GrIRect& rect,