SkPath::Direction serves two masters:
- input param to addFoo (e.g. addRect), where only CW or CCW are valid)
- output param from computing functions, that sometimes return kUnknown

This CL's intent is to split these into distinct enums/features:
- Direction (public) loses kUnknown, and is only used for input
- FirstDirection (private) is used for computing the first direction we see when analyzing a contour

BUG=skia:

Review URL: https://codereview.chromium.org/1176953002
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index c9bcb8f..defedd2 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -9,7 +9,7 @@
 #include "SkErrorInternals.h"
 #include "SkGeometry.h"
 #include "SkMath.h"
-#include "SkPath.h"
+#include "SkPathPriv.h"
 #include "SkPathRef.h"
 #include "SkRRect.h"
 #include "SkThread.h"
@@ -37,16 +37,16 @@
 class SkAutoDisableDirectionCheck {
 public:
     SkAutoDisableDirectionCheck(SkPath* path) : fPath(path) {
-        fSaved = static_cast<SkPath::Direction>(fPath->fDirection);
+        fSaved = static_cast<SkPathPriv::FirstDirection>(fPath->fFirstDirection);
     }
 
     ~SkAutoDisableDirectionCheck() {
-        fPath->fDirection = fSaved;
+        fPath->fFirstDirection = fSaved;
     }
 
 private:
-    SkPath*              fPath;
-    SkPath::Direction    fSaved;
+    SkPath*                     fPath;
+    SkPathPriv::FirstDirection  fSaved;
 };
 #define SkAutoDisableDirectionCheck(...) SK_REQUIRE_LOCAL_VAR(SkAutoDisableDirectionCheck)
 
@@ -135,7 +135,7 @@
     fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
     fFillType = kWinding_FillType;
     fConvexity = kUnknown_Convexity;
-    fDirection = kUnknown_Direction;
+    fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
 
     // We don't touch Android's fSourcePath.  It's used to track texture garbage collection, so we
     // don't want to muck with it if it's been set to something non-NULL.
@@ -167,7 +167,7 @@
     fLastMoveToIndex = that.fLastMoveToIndex;
     fFillType        = that.fFillType;
     fConvexity       = that.fConvexity;
-    fDirection       = that.fDirection;
+    fFirstDirection  = that.fFirstDirection;
     fIsVolatile      = that.fIsVolatile;
 }
 
@@ -184,7 +184,7 @@
         SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
         SkTSwap<uint8_t>(fFillType, that.fFillType);
         SkTSwap<uint8_t>(fConvexity, that.fConvexity);
-        SkTSwap<uint8_t>(fDirection, that.fDirection);
+        SkTSwap<uint8_t>(fFirstDirection, that.fFirstDirection);
         SkTSwap<SkBool8>(fIsVolatile, that.fIsVolatile);
     }
 }
@@ -192,10 +192,10 @@
 static inline bool check_edge_against_rect(const SkPoint& p0,
                                            const SkPoint& p1,
                                            const SkRect& rect,
-                                           SkPath::Direction dir) {
+                                           SkPathPriv::FirstDirection dir) {
     const SkPoint* edgeBegin;
     SkVector v;
-    if (SkPath::kCW_Direction == dir) {
+    if (SkPathPriv::kCW_FirstDirection == dir) {
         v = p1 - p0;
         edgeBegin = &p0;
     } else {
@@ -221,8 +221,8 @@
         return false;
     }
 
-    Direction direction;
-    if (!this->cheapComputeDirection(&direction)) {
+    SkPathPriv::FirstDirection direction;
+    if (!SkPathPriv::CheapComputeFirstDirection(*this, &direction)) {
         return false;
     }
 
@@ -662,10 +662,10 @@
 //////////////////////////////////////////////////////////////////////////////
 //  Construction methods
 
-#define DIRTY_AFTER_EDIT                 \
-    do {                                 \
-        fConvexity = kUnknown_Convexity; \
-        fDirection = kUnknown_Direction; \
+#define DIRTY_AFTER_EDIT                                        \
+    do {                                                        \
+        fConvexity = kUnknown_Convexity;                        \
+        fFirstDirection = SkPathPriv::kUnknown_FirstDirection;  \
     } while (0)
 
 void SkPath::incReserve(U16CPU inc) {
@@ -848,7 +848,8 @@
 void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
                      SkScalar bottom, Direction dir) {
     assert_known_direction(dir);
-    fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction;
+    fFirstDirection = this->hasOnlyMoveTos() ?
+                        (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnknown_FirstDirection;
     SkAutoDisableDirectionCheck addc(this);
 
     SkAutoPathBoundsUpdate apbu(this, left, top, right, bottom);
@@ -988,7 +989,8 @@
     } else if (rrect.isOval()) {
         this->addOval(bounds, dir);
     } else {
-        fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction;
+        fFirstDirection = this->hasOnlyMoveTos() ?
+                            (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnknown_FirstDirection;
 
         SkAutoPathBoundsUpdate apbu(this, bounds);
         SkAutoDisableDirectionCheck addc(this);
@@ -1077,9 +1079,9 @@
      */
     bool isOval = hasOnlyMoveTos();
     if (isOval) {
-        fDirection = dir;
+        fFirstDirection = (SkPathPriv::FirstDirection)dir;
     } else {
-        fDirection = kUnknown_Direction;
+        fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
     }
 
     SkAutoDisableDirectionCheck addc(this);
@@ -1477,7 +1479,7 @@
         dst->swap(tmp);
         SkPathRef::Editor ed(&dst->fPathRef);
         matrix.mapPoints(ed.points(), ed.pathRef()->countPoints());
-        dst->fDirection = kUnknown_Direction;
+        dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
     } else {
         SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix);
 
@@ -1487,19 +1489,19 @@
             dst->fIsVolatile = fIsVolatile;
         }
 
-        if (kUnknown_Direction == fDirection) {
-            dst->fDirection = kUnknown_Direction;
+        if (SkPathPriv::kUnknown_FirstDirection == fFirstDirection) {
+            dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
         } else {
             SkScalar det2x2 =
                 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix::kMScaleY)) -
                 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix::kMSkewY));
             if (det2x2 < 0) {
-                dst->fDirection = SkPath::OppositeDirection(static_cast<Direction>(fDirection));
+                dst->fFirstDirection = SkPathPriv::OppositeFirstDirection((SkPathPriv::FirstDirection)fFirstDirection);
             } else if (det2x2 > 0) {
-                dst->fDirection = fDirection;
+                dst->fFirstDirection = fFirstDirection;
             } else {
                 dst->fConvexity = kUnknown_Convexity;
-                dst->fDirection = kUnknown_Direction;
+                dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
             }
         }
 
@@ -1858,7 +1860,7 @@
 
     int32_t packed = (fConvexity << kConvexity_SerializationShift) |
                      (fFillType << kFillType_SerializationShift) |
-                     (fDirection << kDirection_SerializationShift) |
+                     (fFirstDirection << kDirection_SerializationShift) |
                      (fIsVolatile << kIsVolatile_SerializationShift);
 
     buffer.write32(packed);
@@ -1879,7 +1881,7 @@
 
     fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
     fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
-    fDirection = (packed >> kDirection_SerializationShift) & 0x3;
+    fFirstDirection = (packed >> kDirection_SerializationShift) & 0x3;
     fIsVolatile = (packed >> kIsVolatile_SerializationShift) & 0x1;
     SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
 
@@ -2061,7 +2063,7 @@
     Convexicator()
     : fPtCount(0)
     , fConvexity(SkPath::kConvex_Convexity)
-    , fDirection(SkPath::kUnknown_Direction)
+    , fFirstDirection(SkPathPriv::kUnknown_FirstDirection)
     , fIsFinite(true)
     , fIsCurve(false) {
         fExpectedDir = kInvalid_DirChange;
@@ -2078,7 +2080,7 @@
     SkPath::Convexity getConvexity() const { return fConvexity; }
 
     /** The direction returned is only valid if the path is determined convex */
-    SkPath::Direction getDirection() const { return fDirection; }
+    SkPathPriv::FirstDirection getFirstDirection() const { return fFirstDirection; }
 
     void addPt(const SkPoint& pt) {
         if (SkPath::kConcave_Convexity == fConvexity || !fIsFinite) {
@@ -2179,11 +2181,11 @@
             case kRight_DirChange:
                 if (kInvalid_DirChange == fExpectedDir) {
                     fExpectedDir = dir;
-                    fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Direction
-                                                           : SkPath::kCCW_Direction;
+                    fFirstDirection = (kRight_DirChange == dir) ? SkPathPriv::kCW_FirstDirection
+                                                                : SkPathPriv::kCCW_FirstDirection;
                 } else if (dir != fExpectedDir) {
                     fConvexity = SkPath::kConcave_Convexity;
-                    fDirection = SkPath::kUnknown_Direction;
+                    fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
                 }
                 fLastVec = vec;
                 break;
@@ -2192,7 +2194,7 @@
             case kBackwards_DirChange:
                 if (fIsCurve) {
                     fConvexity = SkPath::kConcave_Convexity;
-                    fDirection = SkPath::kUnknown_Direction;
+                    fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
                 }
                 fLastVec = vec;
                 break;
@@ -2211,7 +2213,7 @@
     int                 fPtCount;   // non-degenerate points
     DirChange           fExpectedDir;
     SkPath::Convexity   fConvexity;
-    SkPath::Direction   fDirection;
+    SkPathPriv::FirstDirection   fFirstDirection;
     int                 fDx, fDy, fSx, fSy;
     bool                fIsFinite;
     bool                fIsCurve;
@@ -2277,8 +2279,8 @@
         }
     }
     fConvexity = state.getConvexity();
-    if (kConvex_Convexity == fConvexity && kUnknown_Direction == fDirection) {
-        fDirection = state.getDirection();
+    if (kConvex_Convexity == fConvexity && SkPathPriv::kUnknown_FirstDirection == fFirstDirection) {
+        fFirstDirection = state.getFirstDirection();
     }
     return static_cast<Convexity>(fConvexity);
 }
@@ -2439,8 +2441,8 @@
     return minIndex;
 }
 
-static void crossToDir(SkScalar cross, SkPath::Direction* dir) {
-    *dir = cross > 0 ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
+static void crossToDir(SkScalar cross, SkPathPriv::FirstDirection* dir) {
+    *dir = cross > 0 ? SkPathPriv::kCW_FirstDirection : SkPathPriv::kCCW_FirstDirection;
 }
 
 /*
@@ -2451,24 +2453,24 @@
  *  that is outer most (or at least has the global y-max) before we can consider
  *  its cross product.
  */
-bool SkPath::cheapComputeDirection(Direction* dir) const {
-    if (kUnknown_Direction != fDirection) {
-        *dir = static_cast<Direction>(fDirection);
+bool SkPathPriv::CheapComputeFirstDirection(const SkPath& path, FirstDirection* dir) {
+    if (kUnknown_FirstDirection != path.fFirstDirection) {
+        *dir = static_cast<FirstDirection>(path.fFirstDirection);
         return true;
     }
 
     // don't want to pay the cost for computing this if it
     // is unknown, so we don't call isConvex()
-    if (kConvex_Convexity == this->getConvexityOrUnknown()) {
-        SkASSERT(kUnknown_Direction == fDirection);
-        *dir = static_cast<Direction>(fDirection);
+    if (SkPath::kConvex_Convexity == path.getConvexityOrUnknown()) {
+        SkASSERT(kUnknown_FirstDirection == path.fFirstDirection);
+        *dir = static_cast<FirstDirection>(path.fFirstDirection);
         return false;
     }
 
-    ContourIter iter(*fPathRef.get());
+    ContourIter iter(*path.fPathRef.get());
 
     // initialize with our logical y-min
-    SkScalar ymax = this->getBounds().fTop;
+    SkScalar ymax = path.getBounds().fTop;
     SkScalar ymaxCross = 0;
 
     for (; !iter.done(); iter.next()) {
@@ -2534,7 +2536,7 @@
     }
     if (ymaxCross) {
         crossToDir(ymaxCross, dir);
-        fDirection = *dir;
+        path.fFirstDirection = *dir;
         return true;
     } else {
         return false;
diff --git a/src/core/SkPathPriv.h b/src/core/SkPathPriv.h
new file mode 100644
index 0000000..98e50e3
--- /dev/null
+++ b/src/core/SkPathPriv.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathPriv_DEFINED
+#define SkPathPriv_DEFINED
+
+#include "SkPath.h"
+
+class SkPathPriv {
+public:
+    enum FirstDirection {
+        kCW_FirstDirection,         // == SkPath::kCW_Direction
+        kCCW_FirstDirection,        // == SkPath::kCCW_Direction
+        kUnknown_FirstDirection,
+    };
+
+    static FirstDirection AsFirstDirection(SkPath::Direction dir) {
+        // since we agree numerically for the values in Direction, we can just cast.
+        return (FirstDirection)dir;
+    }
+
+    /**
+     *  Return the opposite of the specified direction. kUnknown is its own
+     *  opposite.
+     */
+    static FirstDirection OppositeFirstDirection(FirstDirection dir) {
+        static const FirstDirection gOppositeDir[] = {
+            kCCW_FirstDirection, kCW_FirstDirection, kUnknown_FirstDirection, 
+        };
+        return gOppositeDir[dir];
+    }
+
+    /**
+     *  Tries to quickly compute the direction of the first non-degenerate
+     *  contour. If it can be computed, return true and set dir to that
+     *  direction. If it cannot be (quickly) determined, return false and ignore
+     *  the dir parameter. If the direction was determined, it is cached to make
+     *  subsequent calls return quickly.
+     */
+    static bool CheapComputeFirstDirection(const SkPath&, FirstDirection* dir);
+
+    /**
+     *  Returns true if the path's direction can be computed via
+     *  cheapComputDirection() and if that computed direction matches the
+     *  specified direction. If dir is kUnknown, returns true if the direction
+     *  cannot be computed.
+     */
+    static bool CheapIsFirstDirection(const SkPath& path, FirstDirection dir) {
+        FirstDirection computedDir = kUnknown_FirstDirection;
+        (void)CheapComputeFirstDirection(path, &computedDir);
+        return computedDir == dir;
+    }
+
+};
+
+#endif
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 6e25dd2..183c647 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -10,6 +10,7 @@
 
 #include "SkCanvas.h"
 #include "SkDrawable.h"
+#include "SkPathPriv.h"
 #include "SkPicture.h"
 #include "SkTextBlob.h"
 
@@ -215,8 +216,8 @@
     PreCachedPath() {}
     explicit PreCachedPath(const SkPath& path) : SkPath(path) {
         this->updateBoundsCache();
-        SkPath::Direction junk;
-        (void)this->cheapComputeDirection(&junk);
+        SkPathPriv::FirstDirection junk;
+        (void)SkPathPriv::CheapComputeFirstDirection(*this, &junk);
     }
 };
 
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 2296315..86c0571 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -7,7 +7,7 @@
 
 #include "SkStrokerPriv.h"
 #include "SkGeometry.h"
-#include "SkPath.h"
+#include "SkPathPriv.h"
 
 enum {
     kTangent_RecursiveLimit,
@@ -1344,7 +1344,7 @@
     stroker.done(dst, lastSegment == SkPath::kLine_Verb);
 
     if (fDoFill) {
-        if (src.cheapIsDirection(SkPath::kCCW_Direction)) {
+        if (SkPathPriv::CheapIsFirstDirection(src, SkPathPriv::kCCW_FirstDirection)) {
             dst->reverseAddPath(src);
         } else {
             dst->addPath(src);
@@ -1379,8 +1379,8 @@
 }
 
 static SkPath::Direction reverse_direction(SkPath::Direction dir) {
-    SkASSERT(SkPath::kUnknown_Direction != dir);
-    return SkPath::kCW_Direction == dir ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
+    static const SkPath::Direction gOpposite[] = { SkPath::kCCW_Direction, SkPath::kCW_Direction };
+    return gOpposite[dir];
 }
 
 static void addBevel(SkPath* path, const SkRect& r, const SkRect& outer, SkPath::Direction dir) {
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 5d08aa5..45a4ca3 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -22,6 +22,7 @@
 #include "GrPipelineBuilder.h"
 #include "GrStrokeInfo.h"
 #include "SkGeometry.h"
+#include "SkPathPriv.h"
 #include "SkString.h"
 #include "SkTraceEvent.h"
 #include "gl/GrGLProcessor.h"
@@ -116,7 +117,7 @@
 
 static void compute_vectors(SegmentArray* segments,
                             SkPoint* fanPt,
-                            SkPath::Direction dir,
+                            SkPathPriv::FirstDirection dir,
                             int* vCount,
                             int* iCount) {
     center_of_mass(*segments, fanPt);
@@ -124,7 +125,7 @@
 
     // Make the normals point towards the outside
     SkPoint::Side normSide;
-    if (dir == SkPath::kCCW_Direction) {
+    if (dir == SkPathPriv::kCCW_FirstDirection) {
         normSide = SkPoint::kRight_Side;
     } else {
         normSide = SkPoint::kLeft_Side;
@@ -212,8 +213,9 @@
     }
 }
 
-static inline bool get_direction(const SkPath& path, const SkMatrix& m, SkPath::Direction* dir) {
-    if (!path.cheapComputeDirection(dir)) {
+static inline bool get_direction(const SkPath& path, const SkMatrix& m,
+                                 SkPathPriv::FirstDirection* dir) {
+    if (!SkPathPriv::CheapComputeFirstDirection(path, dir)) {
         return false;
     }
     // check whether m reverses the orientation
@@ -221,7 +223,7 @@
     SkScalar det2x2 = SkScalarMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) -
                       SkScalarMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY));
     if (det2x2 < 0) {
-        *dir = SkPath::OppositeDirection(*dir);
+        *dir = SkPathPriv::OppositeFirstDirection(*dir);
     }
     return true;
 }
@@ -248,7 +250,7 @@
 }
 
 static inline void add_cubic_segments(const SkPoint pts[4],
-                                      SkPath::Direction dir,
+                                      SkPathPriv::FirstDirection dir,
                                       SegmentArray* segments) {
     SkSTArray<15, SkPoint, true> quads;
     GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads);
@@ -273,7 +275,7 @@
     // line paths. We detect paths that are very close to a line (zero area) and
     // draw nothing.
     DegenerateTestData degenerateData;
-    SkPath::Direction dir;
+    SkPathPriv::FirstDirection dir;
     // get_direction can fail for some degenerate paths.
     if (!get_direction(path, m, &dir)) {
         return false;
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index b7cb237..da60a6c 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -345,7 +345,7 @@
                 if (SkIRect::Intersects(devClipBounds, ibounds)) {
                     PREALLOC_PTARRAY(32) q;
                     // we don't need a direction if we aren't constraining the subdivision
-                    static const SkPath::Direction kDummyDir = SkPath::kCCW_Direction;
+                    const SkPathPriv::FirstDirection kDummyDir = SkPathPriv::kCCW_FirstDirection;
                     // We convert cubics to quadratics (for now).
                     // In perspective have to do conversion in src space.
                     if (persp) {
diff --git a/src/gpu/GrPathUtils.cpp b/src/gpu/GrPathUtils.cpp
index 3e2c3bf..21d1155 100644
--- a/src/gpu/GrPathUtils.cpp
+++ b/src/gpu/GrPathUtils.cpp
@@ -365,16 +365,16 @@
                                     const SkVector& ab,
                                     const SkVector& dc,
                                     const SkPoint& d,
-                                    SkPath::Direction dir,
+                                    SkPathPriv::FirstDirection dir,
                                     const SkPoint p) {
     SkVector ap = p - a;
     SkScalar apXab = ap.cross(ab);
-    if (SkPath::kCW_Direction == dir) {
+    if (SkPathPriv::kCW_FirstDirection == dir) {
         if (apXab > 0) {
             return false;
         }
     } else {
-        SkASSERT(SkPath::kCCW_Direction == dir);
+        SkASSERT(SkPathPriv::kCCW_FirstDirection == dir);
         if (apXab < 0) {
             return false;
         }
@@ -382,12 +382,12 @@
 
     SkVector dp = p - d;
     SkScalar dpXdc = dp.cross(dc);
-    if (SkPath::kCW_Direction == dir) {
+    if (SkPathPriv::kCW_FirstDirection == dir) {
         if (dpXdc < 0) {
             return false;
         }
     } else {
-        SkASSERT(SkPath::kCCW_Direction == dir);
+        SkASSERT(SkPathPriv::kCCW_FirstDirection == dir);
         if (dpXdc > 0) {
             return false;
         }
@@ -398,7 +398,7 @@
 void convert_noninflect_cubic_to_quads(const SkPoint p[4],
                                        SkScalar toleranceSqd,
                                        bool constrainWithinTangents,
-                                       SkPath::Direction dir,
+                                       SkPathPriv::FirstDirection dir,
                                        SkTArray<SkPoint, true>* quads,
                                        int sublevel = 0) {
 
@@ -546,7 +546,7 @@
 void GrPathUtils::convertCubicToQuads(const SkPoint p[4],
                                       SkScalar tolScale,
                                       bool constrainWithinTangents,
-                                      SkPath::Direction dir,
+                                      SkPathPriv::FirstDirection dir,
                                       SkTArray<SkPoint, true>* quads) {
     SkPoint chopped[10];
     int count = SkChopCubicAtInflections(p, chopped);
diff --git a/src/gpu/GrPathUtils.h b/src/gpu/GrPathUtils.h
index 250b0a2..8e52e33 100644
--- a/src/gpu/GrPathUtils.h
+++ b/src/gpu/GrPathUtils.h
@@ -9,7 +9,7 @@
 #define GrPathUtils_DEFINED
 
 #include "SkRect.h"
-#include "SkPath.h"
+#include "SkPathPriv.h"
 #include "SkTArray.h"
 
 class SkMatrix;
@@ -121,7 +121,7 @@
     void convertCubicToQuads(const SkPoint p[4],
                              SkScalar tolScale,
                              bool constrainWithinTangents,
-                             SkPath::Direction dir,
+                             SkPathPriv::FirstDirection dir,
                              SkTArray<SkPoint, true>* quads);
 
     // Chops the cubic bezier passed in by src, at the double point (intersection point)
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 0cef3fa..0048279 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -7,7 +7,7 @@
 
 #include "GrConvexPolyEffect.h"
 #include "GrInvariantOutput.h"
-#include "SkPath.h"
+#include "SkPathPriv.h"
 #include "gl/GrGLProcessor.h"
 #include "gl/GrGLSL.h"
 #include "gl/builders/GrGLProgramBuilder.h"
@@ -279,8 +279,8 @@
     SkPoint pts[kMaxEdges];
     SkScalar edges[3 * kMaxEdges];
 
-    SkPath::Direction dir;
-    SkAssertResult(path.cheapComputeDirection(&dir));
+    SkPathPriv::FirstDirection dir;
+    SkAssertResult(SkPathPriv::CheapComputeFirstDirection(path, &dir));
 
     SkVector t;
     if (NULL == offset) {
@@ -295,7 +295,7 @@
         if (pts[lastPt] != pts[i]) {
             SkVector v = pts[i] - pts[lastPt];
             v.normalize();
-            if (SkPath::kCCW_Direction == dir) {
+            if (SkPathPriv::kCCW_FirstDirection == dir) {
                 edges[3 * n] = v.fY;
                 edges[3 * n + 1] = -v.fX;
             } else {
diff --git a/src/pathops/SkOpBuilder.cpp b/src/pathops/SkOpBuilder.cpp
index 5cc3fbd..a434fbc 100644
--- a/src/pathops/SkOpBuilder.cpp
+++ b/src/pathops/SkOpBuilder.cpp
@@ -7,7 +7,7 @@
 
 #include "SkMatrix.h"
 #include "SkOpEdgeBuilder.h"
-#include "SkPath.h"
+#include "SkPathPriv.h"
 #include "SkPathOps.h"
 #include "SkPathOpsCommon.h"
 
@@ -32,9 +32,9 @@
     } else if (fillType == SkPath::kEvenOdd_FillType) {
         fillType = SkPath::kWinding_FillType;
     }
-    SkPath::Direction dir;
-    if (one_contour(*path) && path->cheapComputeDirection(&dir)) {
-        if (dir != SkPath::kCCW_Direction) {
+    SkPathPriv::FirstDirection dir;
+    if (one_contour(*path) && SkPathPriv::CheapComputeFirstDirection(*path, &dir)) {
+        if (dir != SkPathPriv::kCCW_FirstDirection) {
             SkPath temp;
             temp.reverseAddPath(*path);
             *path = temp;
@@ -106,7 +106,7 @@
     SkPath original = *result;
     int count = fOps.count();
     bool allUnion = true;
-    SkPath::Direction firstDir;
+    SkPathPriv::FirstDirection firstDir;
     for (int index = 0; index < count; ++index) {
         SkPath* test = &fPathRefs[index];
         if (kUnion_SkPathOp != fOps[index] || test->isInverseFillType()) {
@@ -115,8 +115,8 @@
         }
         // If all paths are convex, track direction, reversing as needed.
         if (test->isConvex()) {
-            SkPath::Direction dir;
-            if (!test->cheapComputeDirection(&dir)) {
+            SkPathPriv::FirstDirection dir;
+            if (!SkPathPriv::CheapComputeFirstDirection(*test, &dir)) {
                 allUnion = false;
                 break;
             }