Use clippedIR instead of clipBounds to filter coverage deltas

Due to precision limit, some cubics may generate lines exceeding
the path's IR. Since we created delta list or delta mask using
clippedIR, it's important that we use the stricter clippedIR
instead of clipBounds to filter the coverage deltas.

Bug: oss-fuzz:6189
Change-Id: I775408282fb45ada41968426c2f32d28bb567af1
Reviewed-on: https://skia-review.googlesource.com/113160
Commit-Queue: Yuqian Li <liyuqian@google.com>
Reviewed-by: Cary Clark <caryclark@google.com>
diff --git a/src/core/SkScan_DAAPath.cpp b/src/core/SkScan_DAAPath.cpp
index 343c4c7..cce759d 100644
--- a/src/core/SkScan_DAAPath.cpp
+++ b/src/core/SkScan_DAAPath.cpp
@@ -150,21 +150,23 @@
 };
 
 template<class Deltas> static SK_ALWAYS_INLINE
-void gen_alpha_deltas(const SkPath& path, const SkIRect& clipBounds, Deltas& result,
-        SkBlitter* blitter, bool skipRect, bool pathContainedInClip) {
+void gen_alpha_deltas(const SkPath& path, const SkIRect& clippedIR, const SkIRect& clipBounds,
+        Deltas& result, SkBlitter* blitter, bool skipRect, bool pathContainedInClip) {
     // 1. Build edges
     SkEdgeBuilder builder;
-    SkIRect ir               = path.getBounds().roundOut();
-    int  count               = builder.build_edges(path, &clipBounds, 0, pathContainedInClip,
-                                                   SkEdgeBuilder::kBezier);
+    // We have to use clipBounds instead of clippedIR to build edges because of "canCullToTheRight":
+    // if the builder finds a right edge past the right clip, it won't build that right edge.
+    int  count = builder.build_edges(path, &clipBounds, 0, pathContainedInClip,
+                                     SkEdgeBuilder::kBezier);
+
     if (count == 0) {
         return;
     }
     SkBezier** list = builder.bezierList();
 
     // 2. Try to find the rect part because blitAntiRect is so much faster than blitCoverageDeltas
-    int rectTop = ir.fBottom;   // the rect is initialized to be empty as top = bot
-    int rectBot = ir.fBottom;
+    int rectTop = clippedIR.fBottom;   // the rect is initialized to be empty as top = bot
+    int rectBot = clippedIR.fBottom;
     if (skipRect) {             // only find that rect is skipRect == true
         YLessThan lessThan;     // sort edges in YX order
         SkTQSort(list, list + count - 1, lessThan);
@@ -196,7 +198,7 @@
                         SkAlpha ra = (r.fUpperX - SkIntToFixed(R)) >> 8;
                         result.setAntiRect(L - 1, rectTop, R - L, rectBot - rectTop, la, ra);
                     } else { // too thin to use blitAntiRect; reset the rect region to be emtpy
-                        rectTop = rectBot = ir.fBottom;
+                        rectTop = rectBot = clippedIR.fBottom;
                     }
                 }
                 break;
@@ -265,7 +267,7 @@
             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);
-                if (iy >= clipBounds.fTop && iy < clipBounds.fBottom) {
+                if (iy >= clippedIR.fTop && iy < clippedIR.fBottom) {
                     add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
                 }
                 continue;
@@ -305,7 +307,7 @@
 
             // last partial row
             if (SkIntToFixed(iy) < currE->fLowerY &&
-                    iy >= clipBounds.fTop && iy < clipBounds.fBottom) {
+                    iy >= clippedIR.fTop && iy < clippedIR.fBottom) {
                 rowHeight = currE->fLowerY - SkIntToFixed(iy);
                 nextX = currE->fX + SkFixedMul(currE->fDX, rowHeight);
                 add_coverage_delta_segment<true>(iy, rowHeight, currE, nextX, &result);
@@ -358,14 +360,16 @@
         if (!forceRLE && !isInverse && SkCoverageDeltaMask::Suitable(clippedIR)) {
             record->fType = SkDAARecord::Type::kMask;
             SkCoverageDeltaMask deltaMask(alloc, clippedIR);
-            gen_alpha_deltas(path, clipBounds, deltaMask, blitter, skipRect, containedInClip);
+            gen_alpha_deltas(path, clippedIR, clipBounds, deltaMask, blitter, skipRect,
+                             containedInClip);
             deltaMask.convertCoverageToAlpha(isEvenOdd, isInverse, isConvex);
             record->fMask = deltaMask.prepareSkMask();
         } else {
             record->fType = SkDAARecord::Type::kList;
             SkCoverageDeltaList* deltaList = alloc->make<SkCoverageDeltaList>(
                     alloc, clippedIR.fTop, clippedIR.fBottom, forceRLE);
-            gen_alpha_deltas(path, clipBounds, *deltaList, blitter, skipRect, containedInClip);
+            gen_alpha_deltas(path, clippedIR, clipBounds, *deltaList, blitter, skipRect,
+                             containedInClip);
             record->fList = deltaList;
         }
     }