Follow up on the previous patch :
- Moved the SkStrokeRec class in its own file
- Replaced SkStroke by SkStrokeRec in Ganesh
- Moved path stroking to the Ganesh level in some cases (everytime it isn't required to do it directly in SkGpuDevice). PathEffect and MaskFilter still require path stroking at the SkGpuDevice for now.
- Renamed static functions in SkPath with proper names

* No functionality shold have changed with this patch. This is a step towards enabling Ganesh Path Renderers to decide whether or not to stroke the path rather than always receiving the stroked path as an input argument.

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

git-svn-id: http://skia.googlecode.com/svn/trunk@6861 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 7a67224..4830645 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -158,6 +158,7 @@
         '<(skia_src_path)/core/SkString.cpp',
         '<(skia_src_path)/core/SkStroke.h',
         '<(skia_src_path)/core/SkStroke.cpp',
+        '<(skia_src_path)/core/SkStrokeRec.cpp',
         '<(skia_src_path)/core/SkStrokerPriv.cpp',
         '<(skia_src_path)/core/SkStrokerPriv.h',
         '<(skia_src_path)/core/SkTemplatesPriv.h',
@@ -251,6 +252,7 @@
         '<(skia_include_path)/core/SkShader.h',
         '<(skia_include_path)/core/SkStream.h',
         '<(skia_include_path)/core/SkString.h',
+        '<(skia_include_path)/core/SkStrokeRec.h',
         '<(skia_include_path)/core/SkTArray.h',
         '<(skia_include_path)/core/SkTDArray.h',
         '<(skia_include_path)/core/SkTDStack.h',
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index 98d7752..9d7e6a1 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -89,7 +89,7 @@
     }
 
     /** Returns true if the filltype is one of the Inverse variants */
-    bool isInverseFillType() const { return IsInverseFill((FillType)fFillType); }
+    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
 
     /**
      *  Toggle between inverse and normal filltypes. This reverse the return
@@ -524,8 +524,13 @@
 
     /**
      *  Returns whether or not a fill type is inverted
+     *
+     *  kWinding_FillType        -> false
+     *  kEvenOdd_FillType        -> false
+     *  kInverseWinding_FillType -> true
+     *  kInverseEvenOdd_FillType -> true
      */
-    static bool IsInverseFill(FillType fill) {
+    static bool IsInverseFillType(FillType fill) {
         SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
         SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
         SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
@@ -535,8 +540,13 @@
 
     /**
      *  Returns the equivalent non-inverted fill type to the given fill type
+     *
+     *  kWinding_FillType        -> kWinding_FillType
+     *  kEvenOdd_FillType        -> kEvenOdd_FillType
+     *  kInverseWinding_FillType -> kWinding_FillType
+     *  kInverseEvenOdd_FillType -> kEvenOdd_FillType
      */
-    static FillType NonInverseFill(FillType fill) {
+    static FillType ConvertToNonInverseFillType(FillType fill) {
         SK_COMPILE_ASSERT(0 == kWinding_FillType, fill_type_mismatch);
         SK_COMPILE_ASSERT(1 == kEvenOdd_FillType, fill_type_mismatch);
         SK_COMPILE_ASSERT(2 == kInverseWinding_FillType, fill_type_mismatch);
diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h
index fa29a34..736ea98 100644
--- a/include/core/SkPathEffect.h
+++ b/include/core/SkPathEffect.h
@@ -11,91 +11,14 @@
 #define SkPathEffect_DEFINED
 
 #include "SkFlattenable.h"
-#include "SkPaint.h"
 #include "SkPath.h"
 #include "SkPoint.h"
 #include "SkRect.h"
+#include "SkStrokeRec.h"
 #include "SkTDArray.h"
 
 class SkPath;
 
-class SkStrokeRec {
-public:
-    enum InitStyle {
-        kHairline_InitStyle,
-        kFill_InitStyle
-    };
-    SkStrokeRec(InitStyle style);
-
-    SkStrokeRec(const SkStrokeRec&);
-    explicit SkStrokeRec(const SkPaint&);
-
-    enum Style {
-        kHairline_Style,
-        kFill_Style,
-        kStroke_Style,
-        kStrokeAndFill_Style
-    };
-
-    Style getStyle() const;
-    SkScalar getWidth() const { return fWidth; }
-    SkScalar getMiter() const { return fMiterLimit; }
-    SkPaint::Cap getCap() const { return fCap; }
-    SkPaint::Join getJoin() const { return fJoin; }
-
-    bool isHairlineStyle() const {
-        return kHairline_Style == this->getStyle();
-    }
-
-    bool isFillStyle() const {
-        return kFill_Style == this->getStyle();
-    }
-
-    void setFillStyle();
-    void setHairlineStyle();
-    /**
-     *  Specify the strokewidth, and optionally if you want stroke + fill.
-     *  Note, if width==0, then this request is taken to mean:
-     *      strokeAndFill==true -> new style will be Fill
-     *      strokeAndFill==false -> new style will be Hairline
-     */
-    void setStrokeStyle(SkScalar width, bool strokeAndFill = false);
-
-    void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
-        fCap = cap;
-        fJoin = join;
-        fMiterLimit = miterLimit;
-    }
-
-    /**
-     *  Returns true if this specifes any thick stroking, i.e. applyToPath()
-     *  will return true.
-     */
-    bool needToApply() const {
-        Style style = this->getStyle();
-        return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
-    }
-
-    /**
-     *  Apply these stroke parameters to the src path, returning the result
-     *  in dst.
-     *
-     *  If there was no change (i.e. style == hairline or fill) this returns
-     *  false and dst is unchanged. Otherwise returns true and the result is
-     *  stored in dst.
-     *
-     *  src and dst may be the same path.
-     */
-    bool applyToPath(SkPath* dst, const SkPath& src) const;
-
-private:
-    SkScalar        fWidth;
-    SkScalar        fMiterLimit;
-    SkPaint::Cap    fCap;
-    SkPaint::Join   fJoin;
-    bool            fStrokeAndFill;
-};
-
 /** \class SkPathEffect
 
     SkPathEffect is the base class for objects in the SkPaint that affect
diff --git a/include/core/SkStrokeRec.h b/include/core/SkStrokeRec.h
new file mode 100644
index 0000000..c5b47c2
--- /dev/null
+++ b/include/core/SkStrokeRec.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkStrokeRec_DEFINED
+#define SkStrokeRec_DEFINED
+
+#include "SkPaint.h"
+
+class SkPath;
+
+class SkStrokeRec {
+public:
+    enum InitStyle {
+        kHairline_InitStyle,
+        kFill_InitStyle
+    };
+    SkStrokeRec(InitStyle style);
+
+    SkStrokeRec(const SkStrokeRec&);
+    explicit SkStrokeRec(const SkPaint&);
+
+    enum Style {
+        kHairline_Style,
+        kFill_Style,
+        kStroke_Style,
+        kStrokeAndFill_Style
+    };
+
+    Style getStyle() const;
+    SkScalar getWidth() const { return fWidth; }
+    SkScalar getMiter() const { return fMiterLimit; }
+    SkPaint::Cap getCap() const { return fCap; }
+    SkPaint::Join getJoin() const { return fJoin; }
+
+    bool isHairlineStyle() const {
+        return kHairline_Style == this->getStyle();
+    }
+
+    bool isFillStyle() const {
+        return kFill_Style == this->getStyle();
+    }
+
+    void setFillStyle();
+    void setHairlineStyle();
+    /**
+     *  Specify the strokewidth, and optionally if you want stroke + fill.
+     *  Note, if width==0, then this request is taken to mean:
+     *      strokeAndFill==true -> new style will be Fill
+     *      strokeAndFill==false -> new style will be Hairline
+     */
+    void setStrokeStyle(SkScalar width, bool strokeAndFill = false);
+
+    void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {
+        fCap = cap;
+        fJoin = join;
+        fMiterLimit = miterLimit;
+    }
+
+    /**
+     *  Returns true if this specifes any thick stroking, i.e. applyToPath()
+     *  will return true.
+     */
+    bool needToApply() const {
+        Style style = this->getStyle();
+        return (kStroke_Style == style) || (kStrokeAndFill_Style == style);
+    }
+
+    /**
+     *  Apply these stroke parameters to the src path, returning the result
+     *  in dst.
+     *
+     *  If there was no change (i.e. style == hairline or fill) this returns
+     *  false and dst is unchanged. Otherwise returns true and the result is
+     *  stored in dst.
+     *
+     *  src and dst may be the same path.
+     */
+    bool applyToPath(SkPath* dst, const SkPath& src) const;
+
+private:
+    SkScalar        fWidth;
+    SkScalar        fMiterLimit;
+    SkPaint::Cap    fCap;
+    SkPaint::Join   fJoin;
+    bool            fStrokeAndFill;
+};
+
+#endif
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 8f2ed62..06d2682 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -39,7 +39,7 @@
 class GrVertexBuffer;
 class GrVertexBufferAllocPool;
 class GrSoftwarePathRenderer;
-class SkStroke;
+class SkStrokeRec;
 
 class GR_API GrContext : public GrRefCnt {
 public:
@@ -411,9 +411,9 @@
      *
      * @param paint         describes how to color pixels.
      * @param path          the path to draw
-     * @param doHairLine    whether the stroke can be optimized as a hairline
+     * @param stroke        the stroke information (width, join, cap)
      */
-    void drawPath(const GrPaint& paint, const SkPath& path, bool doHairLine);
+    void drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke);
 
     /**
      * Draws vertices with a paint.
@@ -846,7 +846,7 @@
 
     GrPathRenderer* getPathRenderer(
                     const SkPath& path,
-                    const SkStroke& stroke,
+                    const SkStrokeRec& stroke,
                     const GrDrawTarget* target,
                     bool allowSW,
                     GrPathRendererChain::DrawType drawType = GrPathRendererChain::kColor_DrawType,
@@ -910,7 +910,7 @@
     /// draw state is left unmodified.
     GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw);
 
-    void internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStroke& stroke);
+    void internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke);
 
     GrTexture* createResizedTexture(const GrTextureDesc& desc,
                                     const GrCacheData& cacheData,
diff --git a/include/gpu/GrPathRendererChain.h b/include/gpu/GrPathRendererChain.h
index 1032240..d51a4bb 100644
--- a/include/gpu/GrPathRendererChain.h
+++ b/include/gpu/GrPathRendererChain.h
@@ -17,7 +17,7 @@
 class GrDrawTarget;
 class GrPathRenderer;
 class SkPath;
-class SkStroke;
+class SkStrokeRec;
 
 /**
  * Keeps track of an ordered list of path renderers. When a path needs to be
@@ -58,7 +58,7 @@
         whether the path can be rendered with arbitrary stencil rules or not. See comments on
         StencilSupport in GrPathRenderer.h. */
     GrPathRenderer* getPathRenderer(const SkPath& path,
-                                    const SkStroke& stroke,
+                                    const SkStrokeRec& rec,
                                     const GrDrawTarget* target,
                                     DrawType drawType,
                                     StencilSupport* stencilSupport);
diff --git a/src/core/SkPathEffect.cpp b/src/core/SkPathEffect.cpp
index 9e84b2f..8fbe5bf 100644
--- a/src/core/SkPathEffect.cpp
+++ b/src/core/SkPathEffect.cpp
@@ -6,107 +6,9 @@
  * found in the LICENSE file.
  */
 
-
 #include "SkPathEffect.h"
 #include "SkPath.h"
 #include "SkFlattenableBuffers.h"
-#include "SkPaintDefaults.h"
-
-// must be < 0, since ==0 means hairline, and >0 means normal stroke
-#define kStrokeRec_FillStyleWidth     (-SK_Scalar1)
-
-SkStrokeRec::SkStrokeRec(InitStyle s) {
-    fWidth          = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
-    fMiterLimit     = SkPaintDefaults_MiterLimit;
-    fCap            = SkPaint::kDefault_Cap;
-    fJoin           = SkPaint::kDefault_Join;
-    fStrokeAndFill  = false;
-}
-
-SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
-    memcpy(this, &src, sizeof(src));
-}
-
-SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
-    switch (paint.getStyle()) {
-        case SkPaint::kFill_Style:
-            fWidth = kStrokeRec_FillStyleWidth;
-            fStrokeAndFill = false;
-            break;
-        case SkPaint::kStroke_Style:
-            fWidth = paint.getStrokeWidth();
-            fStrokeAndFill = false;
-            break;
-        case SkPaint::kStrokeAndFill_Style:
-            if (0 == paint.getStrokeWidth()) {
-                // hairline+fill == fill
-                fWidth = kStrokeRec_FillStyleWidth;
-                fStrokeAndFill = false;
-            } else {
-                fWidth = paint.getStrokeWidth();
-                fStrokeAndFill = true;
-            }
-            break;
-        default:
-            SkASSERT(!"unknown paint style");
-            // fall back on just fill
-            fWidth = kStrokeRec_FillStyleWidth;
-            fStrokeAndFill = false;
-            break;
-    }
-
-    // copy these from the paint, regardless of our "style"
-    fMiterLimit = paint.getStrokeMiter();
-    fCap        = paint.getStrokeCap();
-    fJoin       = paint.getStrokeJoin();
-}
-
-SkStrokeRec::Style SkStrokeRec::getStyle() const {
-    if (fWidth < 0) {
-        return kFill_Style;
-    } else if (0 == fWidth) {
-        return kHairline_Style;
-    } else {
-        return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
-    }
-}
-
-void SkStrokeRec::setFillStyle() {
-    fWidth = kStrokeRec_FillStyleWidth;
-    fStrokeAndFill = false;
-}
-
-void SkStrokeRec::setHairlineStyle() {
-    fWidth = 0;
-    fStrokeAndFill = false;
-}
-
-void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
-    if (strokeAndFill && (0 == width)) {
-        // hairline+fill == fill
-        this->setFillStyle();
-    } else {
-        fWidth = width;
-        fStrokeAndFill = strokeAndFill;
-    }
-}
-
-#include "SkStroke.h"
-
-bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
-    if (fWidth <= 0) {  // hairline or fill
-        return false;
-    }
-
-    SkStroke stroker;
-    stroker.setCap(fCap);
-    stroker.setJoin(fJoin);
-    stroker.setMiterLimit(fMiterLimit);
-    stroker.setWidth(fWidth);
-    stroker.setDoFill(fStrokeAndFill);
-    stroker.strokePath(src, dst);
-    return true;
-}
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 31ee3ec..e7f5ce8 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -643,7 +643,7 @@
 
     // kDrawComplete will be the signal that we have reached the end of
     // the command stream
-    static const int kDrawComplete = SK_MaxU32;
+    static const uint32_t kDrawComplete = SK_MaxU32;
 
     SkReader32 reader(fOpData->bytes(), fOpData->size());
     TextContainer text;
diff --git a/src/core/SkStroke.h b/src/core/SkStroke.h
index 33a7ecb..4880516 100644
--- a/src/core/SkStroke.h
+++ b/src/core/SkStroke.h
@@ -32,7 +32,6 @@
 
     void    setMiterLimit(SkScalar);
     void    setWidth(SkScalar);
-    SkScalar getWidthIfStroked() const { return fDoFill ? -SK_Scalar1 : fWidth; }
 
     bool    getDoFill() const { return SkToBool(fDoFill); }
     void    setDoFill(bool doFill) { fDoFill = SkToU8(doFill); }
diff --git a/src/core/SkStrokeRec.cpp b/src/core/SkStrokeRec.cpp
new file mode 100644
index 0000000..756872b
--- /dev/null
+++ b/src/core/SkStrokeRec.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkStrokeRec.h"
+#include "SkPaintDefaults.h"
+
+// must be < 0, since ==0 means hairline, and >0 means normal stroke
+#define kStrokeRec_FillStyleWidth     (-SK_Scalar1)
+
+SkStrokeRec::SkStrokeRec(InitStyle s) {
+    fWidth          = (kFill_InitStyle == s) ? kStrokeRec_FillStyleWidth : 0;
+    fMiterLimit     = SkPaintDefaults_MiterLimit;
+    fCap            = SkPaint::kDefault_Cap;
+    fJoin           = SkPaint::kDefault_Join;
+    fStrokeAndFill  = false;
+}
+
+SkStrokeRec::SkStrokeRec(const SkStrokeRec& src) {
+    memcpy(this, &src, sizeof(src));
+}
+
+SkStrokeRec::SkStrokeRec(const SkPaint& paint) {
+    switch (paint.getStyle()) {
+        case SkPaint::kFill_Style:
+            fWidth = kStrokeRec_FillStyleWidth;
+            fStrokeAndFill = false;
+            break;
+        case SkPaint::kStroke_Style:
+            fWidth = paint.getStrokeWidth();
+            fStrokeAndFill = false;
+            break;
+        case SkPaint::kStrokeAndFill_Style:
+            if (0 == paint.getStrokeWidth()) {
+                // hairline+fill == fill
+                fWidth = kStrokeRec_FillStyleWidth;
+                fStrokeAndFill = false;
+            } else {
+                fWidth = paint.getStrokeWidth();
+                fStrokeAndFill = true;
+            }
+            break;
+        default:
+            SkASSERT(!"unknown paint style");
+            // fall back on just fill
+            fWidth = kStrokeRec_FillStyleWidth;
+            fStrokeAndFill = false;
+            break;
+    }
+
+    // copy these from the paint, regardless of our "style"
+    fMiterLimit = paint.getStrokeMiter();
+    fCap        = paint.getStrokeCap();
+    fJoin       = paint.getStrokeJoin();
+}
+
+SkStrokeRec::Style SkStrokeRec::getStyle() const {
+    if (fWidth < 0) {
+        return kFill_Style;
+    } else if (0 == fWidth) {
+        return kHairline_Style;
+    } else {
+        return fStrokeAndFill ? kStrokeAndFill_Style : kStroke_Style;
+    }
+}
+
+void SkStrokeRec::setFillStyle() {
+    fWidth = kStrokeRec_FillStyleWidth;
+    fStrokeAndFill = false;
+}
+
+void SkStrokeRec::setHairlineStyle() {
+    fWidth = 0;
+    fStrokeAndFill = false;
+}
+
+void SkStrokeRec::setStrokeStyle(SkScalar width, bool strokeAndFill) {
+    if (strokeAndFill && (0 == width)) {
+        // hairline+fill == fill
+        this->setFillStyle();
+    } else {
+        fWidth = width;
+        fStrokeAndFill = strokeAndFill;
+    }
+}
+
+#include "SkStroke.h"
+
+bool SkStrokeRec::applyToPath(SkPath* dst, const SkPath& src) const {
+    if (fWidth <= 0) {  // hairline or fill
+        return false;
+    }
+
+    SkStroke stroker;
+    stroker.setCap(fCap);
+    stroker.setJoin(fJoin);
+    stroker.setMiterLimit(fMiterLimit);
+    stroker.setWidth(fWidth);
+    stroker.setDoFill(fStrokeAndFill);
+    stroker.strokePath(src, dst);
+    return true;
+}
+
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index f8ded78..e0a80d3 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -12,7 +12,7 @@
 #include "GrDrawState.h"
 #include "GrPathUtils.h"
 #include "SkString.h"
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 #include "SkTrace.h"
 
 GrAAConvexPathRenderer::GrAAConvexPathRenderer() {
@@ -429,15 +429,15 @@
 }
 
 bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
-                                         const SkStroke& stroke,
+                                         const SkStrokeRec& stroke,
                                          const GrDrawTarget* target,
                                          bool antiAlias) const {
     return (target->getCaps().shaderDerivativeSupport() && antiAlias &&
-            stroke.getDoFill() && !path.isInverseFillType() && path.isConvex());
+            stroke.isFillStyle() && !path.isInverseFillType() && path.isConvex());
 }
 
 bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
-                                        const SkStroke&,
+                                        const SkStrokeRec&,
                                         GrDrawTarget* target,
                                         bool antiAlias) {
 
diff --git a/src/gpu/GrAAConvexPathRenderer.h b/src/gpu/GrAAConvexPathRenderer.h
index a64596c..62394a3 100644
--- a/src/gpu/GrAAConvexPathRenderer.h
+++ b/src/gpu/GrAAConvexPathRenderer.h
@@ -14,13 +14,13 @@
     GrAAConvexPathRenderer();
 
     virtual bool canDrawPath(const SkPath& path,
-                             const SkStroke& stroke,
+                             const SkStrokeRec& stroke,
                              const GrDrawTarget* target,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
     virtual bool onDrawPath(const SkPath& path,
-                            const SkStroke& stroke,
+                            const SkStrokeRec& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 };
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 6424ad5..347e4b5 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -547,10 +547,10 @@
 }
 
 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
-                                           const SkStroke& stroke,
+                                           const SkStrokeRec& stroke,
                                            const GrDrawTarget* target,
                                            bool antiAlias) const {
-    if ((0 != stroke.getWidthIfStroked()) || !antiAlias) {
+    if (!stroke.isHairlineStyle() || !antiAlias) {
         return false;
     }
 
@@ -564,7 +564,7 @@
 }
 
 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
-                                          const SkStroke&,
+                                          const SkStrokeRec&,
                                           GrDrawTarget* target,
                                           bool antiAlias) {
 
diff --git a/src/gpu/GrAAHairLinePathRenderer.h b/src/gpu/GrAAHairLinePathRenderer.h
index 653fd01..20be696 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,
-                             const SkStroke& stroke,
+                             const SkStrokeRec& stroke,
                              const GrDrawTarget* target,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
     virtual bool onDrawPath(const SkPath& path,
-                            const SkStroke& stroke,
+                            const SkStrokeRec& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) SK_OVERRIDE;
 
diff --git a/src/gpu/GrAddPathRenderers_default.cpp b/src/gpu/GrAddPathRenderers_default.cpp
index 9be6768..69be15a 100644
--- a/src/gpu/GrAddPathRenderers_default.cpp
+++ b/src/gpu/GrAddPathRenderers_default.cpp
@@ -10,7 +10,6 @@
 #include "GrStencilAndCoverPathRenderer.h"
 #include "GrAAHairLinePathRenderer.h"
 #include "GrAAConvexPathRenderer.h"
-#include "GrSoftwarePathRenderer.h"
 
 void GrPathRenderer::AddPathRenderers(GrContext* ctx, GrPathRendererChain* chain) {
     if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(ctx)) {
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index fbb1a0e..a596088 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -14,7 +14,7 @@
 #include "GrPathRenderer.h"
 #include "GrPaint.h"
 #include "SkRasterClip.h"
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 #include "GrAAConvexPathRenderer.h"
 #include "GrAAHairLinePathRenderer.h"
 #include "GrSWMaskHelper.h"
@@ -62,7 +62,7 @@
 bool path_needs_SW_renderer(GrContext* context,
                             GrGpu* gpu,
                             const SkPath& origPath,
-                            const SkStroke& stroke,
+                            const SkStrokeRec& stroke,
                             bool doAA) {
     // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
     SkTCopyOnFirstWrite<SkPath> path(origPath);
@@ -89,8 +89,7 @@
     // TODO: generalize this function so that when
     // a clip gets complex enough it can just be done in SW regardless
     // of whether it would invoke the GrSoftwarePathRenderer.
-    SkStroke stroke;
-    stroke.setDoFill(true);
+    SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
 
     for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
         const Element* element = iter.get();
@@ -270,12 +269,11 @@
                            const SkPath& path,
                            bool doAA,
                            const GrIRect& resultBounds) {
-    SkStroke stroke;
-    stroke.setDoFill(true);
+    SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
 
     SkAutoTUnref<GrTexture> texture(
                 GrSWMaskHelper::DrawPathMaskToTexture(context, path,
-                                                      stroke,
+                                                      rec,
                                                       resultBounds,
                                                       doAA, NULL));
     if (NULL == texture) {
@@ -318,8 +316,7 @@
             if (path->isInverseFillType()) {
                 path.writable()->toggleInverseFillType();
             }
-            SkStroke stroke;
-            stroke.setDoFill(true);
+            SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
             if (NULL == pr) {
                 GrPathRendererChain::DrawType type;
                 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
@@ -354,8 +351,7 @@
             if (path->isInverseFillType()) {
                 path.writable()->toggleInverseFillType();
             }
-            SkStroke stroke;
-            stroke.setDoFill(true);
+            SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
             GrPathRendererChain::DrawType type = element->isAA() ?
                 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
                 GrPathRendererChain::kStencilAndColor_DrawType;
@@ -660,8 +656,7 @@
             // stencil with arbitrary stencil settings.
             GrPathRenderer::StencilSupport stencilSupport;
 
-            SkStroke stroke;
-            stroke.setDoFill(true);
+            SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
 
             SkRegion::Op op = element->getOp();
 
@@ -975,8 +970,7 @@
 
     helper.clear(kAllIn_InitialState == initialState ? 0xFF : 0x00);
 
-    SkStroke stroke;
-    stroke.setDoFill(true);
+    SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
 
     for (ElementList::Iter iter(elements.headIter()) ; NULL != iter.get(); iter.next()) {
 
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index f688b7a..d00e062 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -23,10 +23,10 @@
 #include "GrSoftwarePathRenderer.h"
 #include "GrStencilBuffer.h"
 #include "GrTextStrike.h"
+#include "SkStrokeRec.h"
 #include "SkTLazy.h"
 #include "SkTLS.h"
 #include "SkTrace.h"
-#include "SkStroke.h"
 
 SK_DEFINE_INST_COUNT(GrContext)
 SK_DEFINE_INST_COUNT(GrDrawState)
@@ -720,7 +720,7 @@
             return;
         }
         if (width >= 0) {
-            GrVec strokeSize;;
+            GrVec strokeSize;
             if (width > 0) {
                 strokeSize.set(width, width);
                 combinedMatrix.mapVectors(&strokeSize, 1);
@@ -982,11 +982,10 @@
         SkPath path;
         path.addOval(rect);
         path.setFillType(SkPath::kWinding_FillType);
-        SkStroke stroke;
-        if (strokeWidth < 0) {
-            stroke.setDoFill(true);
-        } else {
-            stroke.setWidth(strokeWidth);
+        SkStrokeRec stroke(0 == strokeWidth ? SkStrokeRec::kHairline_InitStyle :
+                                           SkStrokeRec::kFill_InitStyle);
+        if (strokeWidth > 0) {
+            stroke.setStrokeStyle(strokeWidth, true);
         }
         this->internalDrawPath(paint, path, stroke);
         return;
@@ -1058,7 +1057,7 @@
     target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
 }
 
-void GrContext::drawPath(const GrPaint& paint, const SkPath& path, bool doHairLine) {
+void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
 
     if (path.isEmpty()) {
        if (path.isInverseFillType()) {
@@ -1067,24 +1066,27 @@
        return;
     }
 
+    const SkPath* pathPtr = &path;
+    SkPath tmpPath;
+    SkStrokeRec strokeRec(stroke);
+    if (!strokeRec.isHairlineStyle()) {
+        if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
+            pathPtr = &tmpPath;
+            strokeRec.setFillStyle();
+        }
+    }
+
     SkRect ovalRect;
-    if (!path.isInverseFillType() && path.isOval(&ovalRect)) {
-        SkScalar width = doHairLine ? 0 : -SK_Scalar1;
+    if (!pathPtr->isInverseFillType() && pathPtr->isOval(&ovalRect)) {
+        SkScalar width = strokeRec.isHairlineStyle() ? 0 : -SK_Scalar1;
         this->drawOval(paint, ovalRect, width);
         return;
     }
 
-    SkStroke stroke;
-    if (doHairLine) {
-        stroke.setWidth(0);
-    } else {
-        stroke.setDoFill(true);
-    }
-
-    this->internalDrawPath(paint, path, stroke);
+    this->internalDrawPath(paint, *pathPtr, strokeRec);
 }
 
-void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStroke& stroke) {
+void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& 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
@@ -1616,7 +1618,7 @@
  * can be individually allowed/disallowed via the "allowSW" boolean.
  */
 GrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
-                                           const SkStroke& stroke,
+                                           const SkStrokeRec& stroke,
                                            const GrDrawTarget* target,
                                            bool allowSW,
                                            GrPathRendererChain::DrawType drawType,
diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp
index b92b77d..dbed783 100644
--- a/src/gpu/GrDefaultPathRenderer.cpp
+++ b/src/gpu/GrDefaultPathRenderer.cpp
@@ -12,7 +12,7 @@
 #include "GrDrawState.h"
 #include "GrPathUtils.h"
 #include "SkString.h"
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 #include "SkTrace.h"
 
 
@@ -151,11 +151,11 @@
 
 #define STENCIL_OFF     0   // Always disable stencil (even when needed)
 
-static inline bool single_pass_path(const SkPath& path, const SkStroke& stroke) {
+static inline bool single_pass_path(const SkPath& path, const SkStrokeRec& stroke) {
 #if STENCIL_OFF
     return true;
 #else
-    if ((0 != stroke.getWidthIfStroked()) && !path.isInverseFillType()) {
+    if (!stroke.isHairlineStyle() && !path.isInverseFillType()) {
         return path.isConvex();
     }
     return false;
@@ -164,7 +164,7 @@
 
 GrPathRenderer::StencilSupport GrDefaultPathRenderer::onGetStencilSupport(
                                                             const SkPath& path,
-                                                            const SkStroke& stroke,
+                                                            const SkStrokeRec& stroke,
                                                             const GrDrawTarget*) const {
     if (single_pass_path(path, stroke)) {
         return GrPathRenderer::kNoRestriction_StencilSupport;
@@ -188,7 +188,7 @@
 }
 
 bool GrDefaultPathRenderer::createGeom(const SkPath& path,
-                                       const SkStroke& stroke,
+                                       const SkStrokeRec& stroke,
                                        SkScalar srcSpaceTol,
                                        GrDrawTarget* target,
                                        GrPrimitiveType* primType,
@@ -214,7 +214,7 @@
     GrVertexLayout layout = 0;
     bool indexed = contourCnt > 1;
 
-    const bool isHairline = 0 == stroke.getWidthIfStroked();
+    const bool isHairline = stroke.isHairlineStyle();
 
     int maxIdxs = 0;
     if (isHairline) {
@@ -238,7 +238,7 @@
         return false;
     }
 
-    uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());;
+    uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());
     uint16_t* idx = idxBase;
     uint16_t subpathIdxStart = 0;
 
@@ -324,7 +324,7 @@
 }
 
 bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
-                                             const SkStroke& stroke,
+                                             const SkStrokeRec& stroke,
                                              GrDrawTarget* target,
                                              bool stencilOnly) {
 
@@ -360,7 +360,7 @@
     bool                        reverse = false;
     bool                        lastPassIsBounds;
 
-    if (0 == stroke.getWidthIfStroked()) {
+    if (stroke.isHairlineStyle()) {
         passCount = 1;
         if (stencilOnly) {
             passes[0] = &gDirectToStencil;
@@ -495,16 +495,15 @@
 }
 
 bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
-                                        const SkStroke& stroke,
+                                        const SkStrokeRec& stroke,
                                         const GrDrawTarget* target,
                                         bool antiAlias) const {
-    // this class can draw any path with any fill but doesn't do any
-    // anti-aliasing.
-    return (stroke.getWidthIfStroked() <= 0) && !antiAlias;
+    // this class can draw any path with any fill but doesn't do any anti-aliasing.
+    return (stroke.isFillStyle() || stroke.isHairlineStyle()) && !antiAlias;
 }
 
 bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
-                                       const SkStroke& stroke,
+                                       const SkStrokeRec& stroke,
                                        GrDrawTarget* target,
                                        bool antiAlias) {
     return this->internalDrawPath(path,
@@ -514,7 +513,7 @@
 }
 
 void GrDefaultPathRenderer::onStencilPath(const SkPath& path,
-                                          const SkStroke& stroke,
+                                          const SkStrokeRec& stroke,
                                           GrDrawTarget* target) {
     GrAssert(SkPath::kInverseEvenOdd_FillType != path.getFillType());
     GrAssert(SkPath::kInverseWinding_FillType != path.getFillType());
diff --git a/src/gpu/GrDefaultPathRenderer.h b/src/gpu/GrDefaultPathRenderer.h
index 657537a..e602fae 100644
--- a/src/gpu/GrDefaultPathRenderer.h
+++ b/src/gpu/GrDefaultPathRenderer.h
@@ -20,32 +20,32 @@
     GrDefaultPathRenderer(bool separateStencilSupport, bool stencilWrapOpsSupport);
 
     virtual bool canDrawPath(const SkPath&,
-                             const SkStroke&,
+                             const SkStrokeRec&,
                              const GrDrawTarget*,
                              bool antiAlias) const SK_OVERRIDE;
 
 private:
 
     virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStroke&,
+                                               const SkStrokeRec&,
                                                const GrDrawTarget*) const SK_OVERRIDE;
 
     virtual bool onDrawPath(const SkPath&,
-                            const SkStroke&,
+                            const SkStrokeRec&,
                             GrDrawTarget*,
                             bool antiAlias) SK_OVERRIDE;
 
     virtual void onStencilPath(const SkPath&,
-                               const SkStroke&,
+                               const SkStrokeRec&,
                                GrDrawTarget*) SK_OVERRIDE;
 
     bool internalDrawPath(const SkPath&,
-                          const SkStroke&,
+                          const SkStrokeRec&,
                           GrDrawTarget*,
                           bool stencilOnly);
 
     bool createGeom(const SkPath&,
-                    const SkStroke&,
+                    const SkStrokeRec&,
                     SkScalar srcSpaceTol,
                     GrDrawTarget*,
                     GrPrimitiveType*,
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 9ede743..f80a441 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -10,12 +10,11 @@
 
 #include "GrDrawTarget.h"
 #include "GrGpuVertex.h"
-#include "GrIndexBuffer.h"
 #include "GrRenderTarget.h"
 #include "GrTexture.h"
 #include "GrVertexBuffer.h"
 
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 
 SK_DEFINE_INST_COUNT(GrDrawTarget)
 
@@ -785,12 +784,12 @@
     }
 }
 
-void GrDrawTarget::stencilPath(const GrPath* path, const SkStroke& stroke, SkPath::FillType fill) {
+void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
     // TODO: extract portions of checkDraw that are relevant to path stenciling.
     GrAssert(NULL != path);
     GrAssert(fCaps.pathStencilingSupport());
-    GrAssert(0 != stroke.getWidthIfStroked());
-    GrAssert(!SkPath::IsInverseFill(fill));
+    GrAssert(!stroke.isHairlineStyle());
+    GrAssert(!SkPath::IsInverseFillType(fill));
     this->onStencilPath(path, stroke, fill);
 }
 
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 7aba256..a54dd0f 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -28,7 +28,7 @@
 class GrPath;
 class GrVertexBuffer;
 
-class SkStroke;
+class SkStrokeRec;
 
 class GrDrawTarget : public GrRefCnt {
 protected:
@@ -457,7 +457,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*, const SkStroke& stroke, SkPath::FillType fill);
+    void stencilPath(const GrPath*, const SkStrokeRec& stroke, SkPath::FillType fill);
 
     /**
      * Helper function for drawing rects. This does not use the current index
@@ -992,7 +992,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) = 0;
-    virtual void onStencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType fill) = 0;
+    virtual void onStencilPath(const GrPath*, const SkStrokeRec& 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 18013c1..b84b0f1 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, const SkStroke& stroke, SkPath::FillType fill) {
+void GrGpu::onStencilPath(const GrPath* path, const SkStrokeRec&, 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 d3a0012..4bc4c25 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -570,7 +570,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType type,
                                   int startVertex,
                                   int vertexCount) SK_OVERRIDE;
-    virtual void onStencilPath(const GrPath* path, const SkStroke& stroke,
+    virtual void onStencilPath(const GrPath* path, const SkStrokeRec& stroke,
                                SkPath::FillType) SK_OVERRIDE;
 
     // readies the pools to provide vertex/index data.
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 4147b3b..51546e7 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -487,7 +487,9 @@
     draw->fIndexBuffer = NULL;
 }
 
-void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, const SkStroke& stroke,
+GrInOrderDrawBuffer::StencilPath::StencilPath() : fStroke(SkStrokeRec::kFill_InitStyle) {}
+
+void GrInOrderDrawBuffer::onStencilPath(const GrPath* path, const SkStrokeRec& stroke,
                                         SkPath::FillType fill) {
     if (this->needsNewClip()) {
         this->recordClip();
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 20f0c84..17271f8 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -17,7 +17,7 @@
 #include "GrPath.h"
 
 #include "SkClipStack.h"
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 #include "SkTemplates.h"
 
 class GrGpu;
@@ -158,8 +158,10 @@
     };
 
     struct StencilPath {
+        StencilPath();
+
         SkAutoTUnref<const GrPath>  fPath;
-        SkStroke                    fStroke;
+        SkStrokeRec                 fStroke;
         SkPath::FillType            fFill;
     };
 
@@ -181,7 +183,7 @@
     virtual void onDrawNonIndexed(GrPrimitiveType primitiveType,
                                   int startVertex,
                                   int vertexCount) SK_OVERRIDE;
-    virtual void onStencilPath(const GrPath*, const SkStroke& stroke, SkPath::FillType) SK_OVERRIDE;
+    virtual void onStencilPath(const GrPath*, const SkStrokeRec& 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 c84bfa8..fa2112c 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/GrPathRenderer.h
@@ -14,7 +14,7 @@
 #include "GrPathRendererChain.h"
 #include "GrStencil.h"
 
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 #include "SkTArray.h"
 
 class SkPath;
@@ -82,7 +82,7 @@
      * @param stroke    the stroke information (width, join, cap).
      */
     StencilSupport getStencilSupport(const SkPath& path,
-                                     const SkStroke& stroke,
+                                     const SkStrokeRec& stroke,
                                      const GrDrawTarget* target) const {
         GrAssert(!path.isInverseFillType());
         return this->onGetStencilSupport(path, stroke, target);
@@ -101,7 +101,7 @@
      * @return  true if the path can be drawn by this object, false otherwise.
      */
     virtual bool canDrawPath(const SkPath& path,
-                             const SkStroke& stroke,
+                             const SkStrokeRec& rec,
                              const GrDrawTarget* target,
                              bool antiAlias) const = 0;
     /**
@@ -114,7 +114,7 @@
      * @param antiAlias             true if anti-aliasing is required.
      */
     bool drawPath(const SkPath& path,
-                  const SkStroke& stroke,
+                  const SkStrokeRec& stroke,
                   GrDrawTarget* target,
                   bool antiAlias) {
         GrAssert(this->canDrawPath(path, stroke, target, antiAlias));
@@ -131,7 +131,7 @@
      * @param stroke                the stroke information (width, join, cap)
      * @param target                target that the path will be rendered to
      */
-    void stencilPath(const SkPath& path, const SkStroke& stroke, GrDrawTarget* target) {
+    void stencilPath(const SkPath& path, const SkStrokeRec& stroke, GrDrawTarget* target) {
         GrAssert(kNoSupport_StencilSupport != this->getStencilSupport(path, stroke, target));
         this->onStencilPath(path, stroke, target);
     }
@@ -141,7 +141,7 @@
      * Subclass overrides if it has any limitations of stenciling support.
      */
     virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStroke&,
+                                               const SkStrokeRec&,
                                                const GrDrawTarget*) const {
         return kNoRestriction_StencilSupport;
     }
@@ -150,7 +150,7 @@
      * Subclass implementation of drawPath()
      */
     virtual bool onDrawPath(const SkPath& path,
-                            const SkStroke& stroke,
+                            const SkStrokeRec& stroke,
                             GrDrawTarget* target,
                             bool antiAlias) = 0;
 
@@ -158,7 +158,7 @@
      * Subclass implementation of stencilPath(). Subclass must override iff it ever returns
      * kStencilOnly in onGetStencilSupport().
      */
-    virtual void onStencilPath(const SkPath& path,  const SkStroke& stroke, GrDrawTarget* target) {
+    virtual void onStencilPath(const SkPath& path,  const SkStrokeRec& stroke, GrDrawTarget* target) {
         GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
         GrDrawState* drawState = target->drawState();
         GR_STATIC_CONST_SAME_STENCIL(kIncrementStencil,
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index 6cb45fa..23f7576 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -33,7 +33,7 @@
 }
 
 GrPathRenderer* GrPathRendererChain::getPathRenderer(const SkPath& path,
-                                                     const SkStroke& stroke,
+                                                     const SkStrokeRec& stroke,
                                                      const GrDrawTarget* target,
                                                      DrawType drawType,
                                                      StencilSupport* stencilSupport) {
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index e776caa..32a945b 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -9,7 +9,7 @@
 #include "GrDrawState.h"
 #include "GrGpu.h"
 
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 
 // TODO: try to remove this #include
 #include "GrContext.h"
@@ -55,24 +55,24 @@
 /**
  * Draw a single path element of the clip stack into the accumulation bitmap
  */
-void GrSWMaskHelper::draw(const SkPath& path, const SkStroke& stroke, SkRegion::Op op,
+void GrSWMaskHelper::draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op,
                           bool antiAlias, uint8_t alpha) {
 
     SkPaint paint;
-    SkScalar width = stroke.getWidthIfStroked();
-    if (0 == width) {
+    if (stroke.isHairlineStyle()) {
         paint.setStyle(SkPaint::kStroke_Style);
         paint.setStrokeWidth(SK_Scalar1);
     } else {
-        if (stroke.getDoFill()) {
+        if (stroke.isFillStyle()) {
             paint.setStyle(SkPaint::kFill_Style);
         } else {
             paint.setStyle(SkPaint::kStroke_Style);
             paint.setStrokeJoin(stroke.getJoin());
             paint.setStrokeCap(stroke.getCap());
-            paint.setStrokeWidth(width);
+            paint.setStrokeWidth(stroke.getWidth());
         }
     }
+
     SkXfermode* mode = SkXfermode::Create(op_to_mode(op));
 
     paint.setXfermode(mode);
@@ -159,7 +159,7 @@
  */
 GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
                                                  const SkPath& path,
-                                                 const SkStroke& stroke,
+                                                 const SkStrokeRec& stroke,
                                                  const GrIRect& resultBounds,
                                                  bool antiAlias,
                                                  SkMatrix* matrix) {
diff --git a/src/gpu/GrSWMaskHelper.h b/src/gpu/GrSWMaskHelper.h
index 3ceaad3..daf3111 100644
--- a/src/gpu/GrSWMaskHelper.h
+++ b/src/gpu/GrSWMaskHelper.h
@@ -21,7 +21,7 @@
 class GrContext;
 class GrTexture;
 class SkPath;
-class SkStroke;
+class SkStrokeRec;
 class GrDrawTarget;
 
 /**
@@ -55,7 +55,7 @@
               bool antiAlias, uint8_t alpha);
 
     // Draw a single path into the accumuation bitmap using the specified op
-    void draw(const SkPath& path, const SkStroke& stroke, SkRegion::Op op,
+    void draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op,
               bool antiAlias, uint8_t alpha);
 
     // Helper function to get a scratch texture suitable for capturing the
@@ -75,7 +75,7 @@
     // to the GPU. The result is returned in "result".
     static GrTexture* DrawPathMaskToTexture(GrContext* context,
                                             const SkPath& path,
-                                            const SkStroke& stroke,
+                                            const SkStrokeRec& stroke,
                                             const GrIRect& resultBounds,
                                             bool antiAlias,
                                             SkMatrix* matrix);
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 36a4156..36bdcff 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -11,9 +11,9 @@
 #include "GrSWMaskHelper.h"
 
 ////////////////////////////////////////////////////////////////////////////////
-bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
-                                         const SkStroke& stroke,
-                                         const GrDrawTarget* target,
+bool GrSoftwarePathRenderer::canDrawPath(const SkPath&,
+                                         const SkStrokeRec&,
+                                         const GrDrawTarget*,
                                          bool antiAlias) const {
     if (!antiAlias || NULL == fContext) {
         // TODO: We could allow the SW path to also handle non-AA paths but
@@ -30,7 +30,7 @@
 
 GrPathRenderer::StencilSupport GrSoftwarePathRenderer::onGetStencilSupport(
                                                                         const SkPath&,
-                                                                        const SkStroke&,
+                                                                        const SkStrokeRec&,
                                                                         const GrDrawTarget*) const {
     return GrPathRenderer::kNoSupport_StencilSupport;
 }
@@ -114,7 +114,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // return true on success; false on failure
 bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
-                                        const SkStroke& stroke,
+                                        const SkStrokeRec& stroke,
                                         GrDrawTarget* target,
                                         bool antiAlias) {
 
diff --git a/src/gpu/GrSoftwarePathRenderer.h b/src/gpu/GrSoftwarePathRenderer.h
index dd78d6b..f8c5620 100644
--- a/src/gpu/GrSoftwarePathRenderer.h
+++ b/src/gpu/GrSoftwarePathRenderer.h
@@ -25,16 +25,16 @@
     }
 
     virtual bool canDrawPath(const SkPath&,
-                             const SkStroke&,
+                             const SkStrokeRec&,
                              const GrDrawTarget*,
                              bool antiAlias) const SK_OVERRIDE;
 protected:
     virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStroke&,
+                                               const SkStrokeRec&,
                                                const GrDrawTarget*) const SK_OVERRIDE;
 
     virtual bool onDrawPath(const SkPath&,
-                            const SkStroke&,
+                            const SkStrokeRec&,
                             GrDrawTarget*,
                             bool antiAlias) SK_OVERRIDE;
 
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.cpp b/src/gpu/GrStencilAndCoverPathRenderer.cpp
index a9bddda..44da3f9 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/GrStencilAndCoverPathRenderer.cpp
@@ -11,7 +11,7 @@
 #include "GrContext.h"
 #include "GrGpu.h"
 #include "GrPath.h"
-#include "SkStroke.h"
+#include "SkStrokeRec.h"
 
 GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrContext* context) {
     GrAssert(NULL != context);
@@ -34,23 +34,23 @@
 }
 
 bool GrStencilAndCoverPathRenderer::canDrawPath(const SkPath& path,
-                                                const SkStroke& stroke,
+                                                const SkStrokeRec& stroke,
                                                 const GrDrawTarget* target,
                                                 bool antiAlias) const {
-    return stroke.getDoFill() &&
+    return stroke.isFillStyle() &&
            !antiAlias && // doesn't do per-path AA, relies on the target having MSAA
            target->getDrawState().getStencil().isDisabled();
 }
 
 GrPathRenderer::StencilSupport GrStencilAndCoverPathRenderer::onGetStencilSupport(
                                                         const SkPath&,
-                                                        const SkStroke& ,
+                                                        const SkStrokeRec& ,
                                                         const GrDrawTarget*) const {
     return GrPathRenderer::kStencilOnly_StencilSupport;
 }
 
 void GrStencilAndCoverPathRenderer::onStencilPath(const SkPath& path,
-                                                  const SkStroke& stroke,
+                                                  const SkStrokeRec& stroke,
                                                   GrDrawTarget* target) {
     GrAssert(!path.isInverseFillType());
     SkAutoTUnref<GrPath> p(fGpu->createPath(path));
@@ -58,18 +58,18 @@
 }
 
 bool GrStencilAndCoverPathRenderer::onDrawPath(const SkPath& path,
-                                               const SkStroke& stroke,
+                                               const SkStrokeRec& stroke,
                                                GrDrawTarget* target,
                                                bool antiAlias) {
     GrAssert(!antiAlias);
-    GrAssert(0 != stroke.getWidthIfStroked());
+    GrAssert(!stroke.isHairlineStyle());
 
     GrDrawState* drawState = target->drawState();
     GrAssert(drawState->getStencil().isDisabled());
 
     SkAutoTUnref<GrPath> p(fGpu->createPath(path));
 
-    SkPath::FillType nonInvertedFill = SkPath::NonInverseFill(path.getFillType());
+    SkPath::FillType nonInvertedFill = SkPath::ConvertToNonInverseFillType(path.getFillType());
     target->stencilPath(p, stroke, nonInvertedFill);
 
     // TODO: Use built in cover operation rather than a rect draw. This will require making our
diff --git a/src/gpu/GrStencilAndCoverPathRenderer.h b/src/gpu/GrStencilAndCoverPathRenderer.h
index 824d649..9ebcec9 100644
--- a/src/gpu/GrStencilAndCoverPathRenderer.h
+++ b/src/gpu/GrStencilAndCoverPathRenderer.h
@@ -26,22 +26,22 @@
     virtual ~GrStencilAndCoverPathRenderer();
 
     virtual bool canDrawPath(const SkPath&,
-                             const SkStroke&,
+                             const SkStrokeRec&,
                              const GrDrawTarget*,
                              bool antiAlias) const SK_OVERRIDE;
 
 protected:
     virtual StencilSupport onGetStencilSupport(const SkPath&,
-                                               const SkStroke&,
+                                               const SkStrokeRec&,
                                                const GrDrawTarget*) const SK_OVERRIDE;
 
     virtual bool onDrawPath(const SkPath&,
-                            const SkStroke&,
+                            const SkStrokeRec&,
                             GrDrawTarget*,
                             bool antiAlias) SK_OVERRIDE;
 
     virtual void onStencilPath(const SkPath&,
-                               const SkStroke&,
+                               const SkStrokeRec&,
                                GrDrawTarget*) SK_OVERRIDE;
 
 private:
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index fdb5d37..fd7a689 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -17,6 +17,7 @@
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
 #include "SkPath.h"
+#include "SkStrokeRec.h"
 
 enum {
     kGlyphMaskStage = GrPaint::kTotalStages,
@@ -179,7 +180,8 @@
                                SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
         GrPaint tmpPaint(fPaint);
         am.setPreConcat(fContext, translate, &tmpPaint);
-        fContext->drawPath(tmpPaint, *glyph->fPath, false);
+        SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
+        fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
         return;
     }
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 296af4a..7b06d60 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -19,6 +19,8 @@
 #include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkImageFilter.h"
+#include "SkPathEffect.h"
+#include "SkStroke.h"
 #include "SkUtils.h"
 
 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
@@ -753,7 +755,7 @@
     return false;
 }
 
-bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, bool doHairLine,
+bool drawWithGPUMaskFilter(GrContext* context, const SkPath& devPath, const SkStrokeRec& stroke,
                            SkMaskFilter* filter, const SkRegion& clip,
                            SkBounder* bounder, GrPaint* grp) {
     SkMaskFilter::BlurInfo info;
@@ -838,7 +840,7 @@
         SkMatrix translate;
         translate.setTranslate(offset.fX, offset.fY);
         am.set(context, translate);
-        context->drawPath(tempPaint, devPath, doHairLine);
+        context->drawPath(tempPaint, devPath, stroke);
 
         // If we're doing a normal blur, we can clobber the pathTexture in the
         // gaussianBlur.  Otherwise, we need to save it for later compositing.
@@ -964,8 +966,6 @@
     CHECK_FOR_NODRAW_ANNOTATION(paint);
     CHECK_SHOULD_DRAW(draw, false);
 
-    bool             doHairLine = false;
-
     GrPaint grPaint;
     SkAutoCachedTexture textures[GrPaint::kMaxColorStages];
     if (!skPaint2GrPaintShader(this,
@@ -979,8 +979,8 @@
     // can we cheat, and threat a thin stroke as a hairline w/ coverage
     // if we can, we draw lots faster (raster device does this same test)
     SkScalar hairlineCoverage;
-    if (SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage)) {
-        doHairLine = true;
+    bool doHairLine = SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage);
+    if (doHairLine) {
         grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
     }
 
@@ -988,7 +988,7 @@
     // where the original path can in fact be modified in place (even though
     // its parameter type is const).
     SkPath* pathPtr = const_cast<SkPath*>(&origSrcPath);
-    SkPath  tmpPath;
+    SkPath  tmpPath, effectPath;
 
     if (prePathMatrix) {
         SkPath* result = pathPtr;
@@ -1005,32 +1005,40 @@
     // at this point we're done with prePathMatrix
     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
 
-    if (paint.getPathEffect() ||
-        (!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.
-        doHairLine = !paint.getFillPath(*pathPtr, &tmpPath);
-        pathPtr = &tmpPath;
+    SkStrokeRec stroke(paint);
+    SkPathEffect* pathEffect = paint.getPathEffect();
+    if (pathEffect && pathEffect->filterPath(&effectPath, *pathPtr, &stroke)) {
+        pathPtr = &effectPath;
+    }
+
+    if (!pathEffect && doHairLine) {
+        stroke.setHairlineStyle();
     }
 
     if (paint.getMaskFilter()) {
+        if (!stroke.isHairlineStyle()) {
+            if (stroke.applyToPath(&tmpPath, *pathPtr)) {
+                pathPtr = &tmpPath;
+                stroke.setFillStyle();
+            }
+        }
+
         // avoid possibly allocating a new path in transform if we can
         SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
 
         // transform the path into device space
         pathPtr->transform(fContext->getMatrix(), devPathPtr);
-        if (!drawWithGPUMaskFilter(fContext, *devPathPtr, doHairLine, paint.getMaskFilter(),
+        if (!drawWithGPUMaskFilter(fContext, *devPathPtr, stroke, paint.getMaskFilter(),
                                    *draw.fClip, draw.fBounder, &grPaint)) {
-            SkPaint::Style style = doHairLine ? SkPaint::kStroke_Style :
-                                                SkPaint::kFill_Style;
+            SkPaint::Style style = stroke.isHairlineStyle() ? SkPaint::kStroke_Style :
+                                                              SkPaint::kFill_Style;
             drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
                                *draw.fClip, draw.fBounder, &grPaint, style);
         }
         return;
     }
 
-    fContext->drawPath(grPaint, *pathPtr, doHairLine);
+    fContext->drawPath(grPaint, *pathPtr, stroke);
 }
 
 namespace {