add two nested rect detector to path

Tease apart existing one rect path detector so
that a new variant can detect two nested rects as well.

Add tests to verify that both one and two rect
detectors both work and return the correct results.

Suppress other warnings in PathTest.
Review URL: https://codereview.appspot.com/6850059

git-svn-id: http://skia.googlecode.com/svn/trunk@6475 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 3b1b518..dbdd448 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -488,11 +488,11 @@
 FIXME: If the API passes fill-only, return true if the filled stroke
        is a rectangle, though the caller failed to close the path.
  */
-bool SkPath::isRect(SkRect* rect) const {
-    SkDEBUGCODE(this->validate();)
-
+bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** ptsPtr) const {
     int corners = 0;
     SkPoint first, last;
+    const SkPoint* pts = *ptsPtr;
+    const SkPoint* savePts;
     first.set(0, 0);
     last.set(0, 0);
     int firstDirection = 0;
@@ -500,13 +500,12 @@
     int nextDirection = 0;
     bool closedOrMoved = false;
     bool autoClose = false;
-    const SkPoint* pts = fPathRef->points();
     int verbCnt = fPathRef->countVerbs();
-    int currVerb = 0;
-    while (currVerb < verbCnt) {
-        switch (fPathRef->atVerb(currVerb++)) {
+    while (*currVerb < verbCnt && (!allowPartial || !autoClose)) {
+        switch (fPathRef->atVerb(*currVerb)) {
             case kClose_Verb:
-                pts = fPathRef->points();
+                savePts = pts;
+                pts = *ptsPtr;
                 autoClose = true;
             case kLine_Verb: {
                 SkScalar left = last.fX;
@@ -561,16 +560,57 @@
                 closedOrMoved = true;
                 break;
         }
+        *currVerb += 1;
         lastDirection = nextDirection;
     }
     // Success if 4 corners and first point equals last
     bool result = 4 == corners && first == last;
+    *ptsPtr = savePts;
+    return result;
+}
+
+bool SkPath::isRect(SkRect* rect) const {
+    SkDEBUGCODE(this->validate();)
+    int currVerb = 0;
+    const SkPoint* pts = fPathRef->points();
+    bool result = isRectContour(false, &currVerb, &pts);
     if (result && rect) {
         *rect = getBounds();
     }
     return result;
 }
 
+bool SkPath::isNestedRects(SkRect rects[2]) const {
+    SkDEBUGCODE(this->validate();)
+    int currVerb = 0;
+    const SkPoint* pts = fPathRef->points();
+    const SkPoint* first = pts;
+    if (!isRectContour(true, &currVerb, &pts)) {
+        return false;
+    }
+    const SkPoint* last = pts;
+    SkRect testRects[2];
+    if (isRectContour(false, &currVerb, &pts)) {
+        testRects[0].set(first, last - first);
+        testRects[1].set(last, pts - last);
+        if (testRects[0].contains(testRects[1])) {
+            if (rects) {
+                rects[0] = testRects[0];
+                rects[1] = testRects[1];
+            }
+            return true;
+        }
+        if (testRects[1].contains(testRects[0])) {
+            if (rects) {
+                rects[0] = testRects[1];
+                rects[1] = testRects[0];
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
 int SkPath::countPoints() const {
     return fPathRef->countPoints();
 }