diff options
author | Yuqian Li <liyuqian@google.com> | 2018-03-08 13:39:27 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-03-08 19:07:31 +0000 |
commit | 8b0ef635fdec43d14b2be58ab95afaea5323c6dd (patch) | |
tree | d6e3d31f62a21fdc5c25b9cddeafc9caf1b35da4 /src/core/SkScan_DAAPath.cpp | |
parent | 2091fe26fe9d01cb2d15a4c96c1a0fe87370cba0 (diff) |
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>
Diffstat (limited to 'src/core/SkScan_DAAPath.cpp')
-rw-r--r-- | src/core/SkScan_DAAPath.cpp | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/core/SkScan_DAAPath.cpp b/src/core/SkScan_DAAPath.cpp index 343c4c73f1..cce759d680 100644 --- a/src/core/SkScan_DAAPath.cpp +++ b/src/core/SkScan_DAAPath.cpp @@ -150,21 +150,23 @@ public: }; 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 @@ void gen_alpha_deltas(const SkPath& path, const SkIRect& clipBounds, Deltas& res 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 @@ void gen_alpha_deltas(const SkPath& path, const SkIRect& clipBounds, Deltas& res 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 @@ void gen_alpha_deltas(const SkPath& path, const SkIRect& clipBounds, Deltas& res // 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 @@ void SkScan::DAAFillPath(const SkPath& path, SkBlitter* blitter, const SkIRect& 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; } } |