Preserve convex control point polygon in cubic->quadratic approximation

GM test modified, will require rebaselining.

Review URL: http://codereview.appspot.com/6355088/





git-svn-id: http://skia.googlecode.com/svn/trunk@4518 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index ae4a773..41ab242 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -63,7 +63,7 @@
         p0 = segments[0].endPt();
         SkPoint pi;
         SkPoint pj;
-        // the first and last interation of the below loop would compute
+        // the first and last iteration of the below loop would compute
         // zeros since the starting / ending point is (0,0). So instead we start
         // at i=1 and make the last iteration i=count-2.
         pj = segments[1].endPt() - p0;
@@ -200,24 +200,20 @@
     }
 }
 
-inline SkPath::Direction get_direction(const SkPath& path, const GrMatrix& m) {
-    SkPath::Direction dir;
-    GR_DEBUGCODE(bool succeeded = )
-    path.cheapComputeDirection(&dir);
-    GrAssert(succeeded);
+inline bool get_direction(const SkPath& path, const GrMatrix& m, SkPath::Direction* dir) {
+    if (!path.cheapComputeDirection(dir)) {
+        return false;
+    }
     // check whether m reverses the orientation
     GrAssert(!m.hasPerspective());
-    GrScalar det2x2 =
-        GrMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) -
-        GrMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY));
+    GrScalar det2x2 = GrMul(m.get(SkMatrix::kMScaleX), m.get(SkMatrix::kMScaleY)) -
+                      GrMul(m.get(SkMatrix::kMSkewX), m.get(SkMatrix::kMSkewY));
     if (det2x2 < 0) {
-        GR_STATIC_ASSERT(0 == SkPath::kCW_Direction ||
-                         1 == SkPath::kCW_Direction);
-        GR_STATIC_ASSERT(0 == SkPath::kCCW_Direction ||
-                         1 == SkPath::kCCW_Direction);
-        dir = static_cast<SkPath::Direction>(dir ^ 0x1);
+        GR_STATIC_ASSERT(0 == SkPath::kCW_Direction || 1 == SkPath::kCW_Direction);
+        GR_STATIC_ASSERT(0 == SkPath::kCCW_Direction || 1 == SkPath::kCCW_Direction);
+        *dir = static_cast<SkPath::Direction>(*dir ^ 0x1);
     }
-    return dir;
+    return true;
 }
 
 bool get_segments(const SkPath& path,
@@ -235,6 +231,11 @@
     // line paths. We detect paths that are very close to a line (zero area) and
     // draw nothing.
     DegenerateTestData degenerateData;
+    SkPath::Direction dir;
+    // get_direction can fail for some degenerate paths.
+    if (!get_direction(path, m, &dir)) {
+        return false;
+    }
 
     for (;;) {
         GrPoint pts[4];
@@ -269,7 +270,7 @@
                 // unlike quads and lines, the pts[0] will also be read (in
                 // convertCubicToQuads).
                 SkSTArray<15, SkPoint, true> quads;
-                GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, &quads);
+                GrPathUtils::convertCubicToQuads(pts, SK_Scalar1, true, dir, &quads);
                 int count = quads.count();
                 for (int q = 0; q < count; q += 3) {
                     segments->push_back();
@@ -283,7 +284,6 @@
                 if (degenerateData.isDegenerate()) {
                     return false;
                 } else {
-                    SkPath::Direction dir = get_direction(path, m);
                     compute_vectors(segments, fanPt, dir, vCount, iCount);
                     return true;
                 }