aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkScan_DAAPath.cpp
diff options
context:
space:
mode:
authorGravatar Yuqian Li <liyuqian@google.com>2018-03-08 13:39:27 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-08 19:07:31 +0000
commit8b0ef635fdec43d14b2be58ab95afaea5323c6dd (patch)
treed6e3d31f62a21fdc5c25b9cddeafc9caf1b35da4 /src/core/SkScan_DAAPath.cpp
parent2091fe26fe9d01cb2d15a4c96c1a0fe87370cba0 (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.cpp28
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;
}
}