harden pathmeasure and fix empty case

change int to unsigned (just make it uniform,
part of it was already unsigned)

change path by pointer to path by value
since it will be copied on write; fixes bug
where path changes from underneath measure

Allow empty paths to still initialize measure state.
This fixes the GM failure from the earlier check-in attempt
in CL 113269.

R=reed@google.com
Bug: skia:7675
Change-Id: I6296bbf75296ead826e54662b025277dd226e2b8
Reviewed-on: https://skia-review.googlesource.com/113246
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/include/core/SkPathMeasure.h b/include/core/SkPathMeasure.h
index 1044f7e..287c292 100644
--- a/include/core/SkPathMeasure.h
+++ b/include/core/SkPathMeasure.h
@@ -84,10 +84,10 @@
 
 private:
     SkPath::Iter    fIter;
-    const SkPath*   fPath;
+    SkPath          fPath;
     SkScalar        fTolerance;
     SkScalar        fLength;            // relative to the current contour
-    int             fFirstPtIndex;      // relative to the current contour
+    unsigned        fFirstPtIndex;      // relative to the current contour
     bool            fIsClosed;          // relative to the current contour
     bool            fForceClosed;
 
@@ -107,12 +107,12 @@
 
     void     buildSegments();
     SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
-                                int mint, int maxt, int ptIndex);
+                                int mint, int maxt, unsigned ptIndex);
     SkScalar compute_conic_segs(const SkConic&, SkScalar distance,
                                 int mint, const SkPoint& minPt,
-                                int maxt, const SkPoint& maxPt, int ptIndex);
+                                int maxt, const SkPoint& maxPt, unsigned ptIndex);
     SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
-                                int mint, int maxt, int ptIndex);
+                                int mint, int maxt, unsigned ptIndex);
     const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
     bool quad_too_curvy(const SkPoint pts[3]);
     bool conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTPt,const SkPoint& lastPt);
diff --git a/src/core/SkPathMeasure.cpp b/src/core/SkPathMeasure.cpp
index 0da448f..7d6c0ff 100644
--- a/src/core/SkPathMeasure.cpp
+++ b/src/core/SkPathMeasure.cpp
@@ -228,7 +228,7 @@
 }
 
 SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3],
-                          SkScalar distance, int mint, int maxt, int ptIndex) {
+                          SkScalar distance, int mint, int maxt, unsigned ptIndex) {
     if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) {
         SkPoint tmp[5];
         int     halft = (mint + maxt) >> 1;
@@ -253,7 +253,7 @@
 
 SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, SkScalar distance,
                                            int mint, const SkPoint& minPt,
-                                           int maxt, const SkPoint& maxPt, int ptIndex) {
+                                           int maxt, const SkPoint& maxPt, unsigned ptIndex) {
     int halft = (mint + maxt) >> 1;
     SkPoint halfPt = conic.evalAt(tValue2Scalar(halft));
     if (tspan_big_enough(maxt - mint) && conic_too_curvy(minPt, halfPt, maxPt)) {
@@ -275,7 +275,7 @@
 }
 
 SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4],
-                           SkScalar distance, int mint, int maxt, int ptIndex) {
+                           SkScalar distance, int mint, int maxt, unsigned ptIndex) {
     if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) {
         SkPoint tmp[7];
         int     halft = (mint + maxt) >> 1;
@@ -300,10 +300,10 @@
 
 void SkPathMeasure::buildSegments() {
     SkPoint         pts[4];
-    int             ptIndex = fFirstPtIndex;
+    unsigned        ptIndex = fFirstPtIndex;
     SkScalar        distance = 0;
     bool            isClosed = fForceClosed;
-    bool            firstMoveTo = ptIndex < 0;
+    bool            firstMoveTo = ptIndex == (unsigned) -1;
     Segment*        seg;
 
     /*  Note:
@@ -471,7 +471,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 SkPathMeasure::SkPathMeasure() {
-    fPath = nullptr;
     fTolerance = CHEAP_DIST_LIMIT;
     fLength = -1;   // signal we need to compute it
     fForceClosed = false;
@@ -479,13 +478,13 @@
 }
 
 SkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale) {
-    fPath = &path;
+    fPath = path;
     fTolerance = CHEAP_DIST_LIMIT * SkScalarInvert(resScale);
     fLength = -1;   // signal we need to compute it
     fForceClosed = forceClosed;
     fFirstPtIndex = -1;
 
-    fIter.setPath(path, forceClosed);
+    fIter.setPath(fPath, forceClosed);
 }
 
 SkPathMeasure::~SkPathMeasure() {}
@@ -493,22 +492,21 @@
 /** Assign a new path, or null to have none.
 */
 void SkPathMeasure::setPath(const SkPath* path, bool forceClosed) {
-    fPath = path;
+    if (path) {
+        fPath = *path;
+    } else {
+        fPath.reset();
+    }
     fLength = -1;   // signal we need to compute it
     fForceClosed = forceClosed;
     fFirstPtIndex = -1;
 
-    if (path) {
-        fIter.setPath(*path, forceClosed);
-    }
+    fIter.setPath(fPath, forceClosed);
     fSegments.reset();
     fPts.reset();
 }
 
 SkScalar SkPathMeasure::getLength() {
-    if (fPath == nullptr) {
-        return 0;
-    }
     if (fLength < 0) {
         this->buildSegments();
     }
@@ -582,10 +580,6 @@
 }
 
 bool SkPathMeasure::getPosTan(SkScalar distance, SkPoint* pos, SkVector* tangent) {
-    if (nullptr == fPath) {
-        return false;
-    }
-
     SkScalar    length = this->getLength(); // call this to force computing it
     int         count = fSegments.count();
 
@@ -609,10 +603,6 @@
 
 bool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix,
                               MatrixFlags flags) {
-    if (nullptr == fPath) {
-        return false;
-    }
-
     SkPoint     position;
     SkVector    tangent;