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>
This commit is contained in:
parent
2091fe26fe
commit
8b0ef635fd
@ -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();
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user