No chop at y extrema for cubics

The new Delta AA scan converter does not need the edge to be updated
with monotonic Y so chopping at y extrema is not necessary. Removing
such chopping brings ~10% performance increase to chalkboard.svg which
has tons of small cubics (the same is true for many svgs I saw).

We didn't remove the chopping for quads because that does not bring
a significant speedup. Moreover, dropping those y extremas would make
our strokecircle animation look a little more wobbly (because we would
have fewer divisions for the quads at the top and bottom of the circle).

Bug: skia:
Change-Id: I3984d2619f9f77269ed24e8cbfa9f1429ebca4a8
Reviewed-on: https://skia-review.googlesource.com/31940
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Yuqian Li <liyuqian@google.com>
diff --git a/src/core/SkScan_DAAPath.cpp b/src/core/SkScan_DAAPath.cpp
index 68bc15d..de24e49 100644
--- a/src/core/SkScan_DAAPath.cpp
+++ b/src/core/SkScan_DAAPath.cpp
@@ -226,21 +226,27 @@
         SkAnalyticEdge* currE   = &storage;
         bool edgeSet            = false;
 
+        int originalWinding = 1;
+        bool sortY = true;
         switch (bezier->fCount) {
             case 2: {
                 edgeSet = currE->setLine(bezier->fP0, bezier->fP1);
+                originalWinding = currE->fWinding;
                 break;
             }
             case 3: {
                 SkQuad* quad = static_cast<SkQuad*>(bezier);
                 SkPoint pts[3] = {quad->fP0, quad->fP1, quad->fP2};
                 edgeSet = static_cast<SkAnalyticQuadraticEdge*>(currE)->setQuadratic(pts);
+                originalWinding = static_cast<SkAnalyticQuadraticEdge*>(currE)->fQEdge.fWinding;
                 break;
             }
             case 4: {
+                sortY = false;
                 SkCubic* cubic = static_cast<SkCubic*>(bezier);
                 SkPoint pts[4] = {cubic->fP0, cubic->fP1, cubic->fP2, cubic->fP3};
-                edgeSet = static_cast<SkAnalyticCubicEdge*>(currE)->setCubic(pts);
+                edgeSet = static_cast<SkAnalyticCubicEdge*>(currE)->setCubic(pts, sortY);
+                originalWinding = static_cast<SkAnalyticCubicEdge*>(currE)->fCEdge.fWinding;
                 break;
             }
         }
@@ -259,7 +265,9 @@
             if (lowerCeil <= upperFloor + SK_Fixed1) { // only one row is affected by the currE
                 SkFixed rowHeight = currE->fLowerY - currE->fUpperY;
                 SkFixed nextX = currE->fX + SkFixedMul(currE->fDX, rowHeight);
-                add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
+                if (iy >= clipRect.fTop && iy < clipRect.fBottom) {
+                    add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
+                }
                 continue;
             }
 
@@ -296,12 +304,13 @@
             }
 
             // last partial row
-            if (SkIntToFixed(iy) < currE->fLowerY) {
+            if (SkIntToFixed(iy) < currE->fLowerY && iy >= clipRect.fTop && iy < clipRect.fBottom) {
                 rowHeight = currE->fLowerY - SkIntToFixed(iy);
                 nextX = currE->fX + SkFixedMul(currE->fDX, rowHeight);
                 add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
             }
-        } while (currE->update(currE->fLowerY));
+        // Intended assignment to fWinding to restore the maybe-negated winding (during updateLine)
+        } while ((currE->fWinding = originalWinding) && currE->update(currE->fLowerY, sortY));
     }
 }