Correct edges_too_close

If the next edge has 0 fDX, we should add a SLACK = 1 so two edges
with fX less than 1 pixel apart should be considered close, and
noRealBlitter should be true to force the use of AdditiveBlitter and
the cumulation of alpha.  The changed GM will show bleed through if
SLACK is 0.

The artifact without the fix can be seen at:
https://fiddle.skia.org/c/f6912f1af6c14e054f5b5935a93380ea

Bug: skia:
Change-Id: I15f9c3aef25a0357cd11d447e7bf0b4fbac0ce67
Reviewed-on: https://skia-review.googlesource.com/67804
Commit-Queue: Yuqian Li <liyuqian@google.com>
Reviewed-by: Cary Clark <caryclark@google.com>
This commit is contained in:
Yuqian Li 2017-11-07 11:19:52 -05:00 committed by Skia Commit-Bot
parent 63bc48d093
commit fbe0793526
2 changed files with 30 additions and 2 deletions

View File

@ -123,6 +123,22 @@ protected:
p.setStrokeWidth(5);
canvas->drawPath(path, p);
canvas->restore();
// The following two paths test if we correctly cumulates the alpha on the middle pixel
// column where the left rect and the right rect abut.
p.setStyle(SkPaint::kFill_Style);
canvas->translate(0, 300);
path.reset();
path.addRect({20, 20, 100.4999f, 100});
path.addRect({100.5001f, 20, 200, 100});
canvas->drawPath(path, p);
canvas->translate(300, 0);
path.reset();
path.addRect({20, 20, 100.1f, 100});
path.addRect({100.9f, 20, 200, 100});
canvas->drawPath(path, p);
}
private:

View File

@ -1282,15 +1282,27 @@ static void validate_edges_for_y(const SkAnalyticEdge* edge, SkFixed y) {
// Return true if prev->fX, next->fX are too close in the current pixel row.
static inline bool edges_too_close(SkAnalyticEdge* prev, SkAnalyticEdge* next, SkFixed lowerY) {
// When next->fDX == 0, prev->fX >= next->fX - SkAbs32(next->fDX) would be false
// even if prev->fX and next->fX are close and within one pixel (e.g., prev->fX == 0.1,
// next->fX == 0.9). Adding SLACK = 1 to the formula would guarantee it to be true if two
// edges prev and next are within one pixel.
constexpr SkFixed SLACK =
#ifdef SK_SUPPORT_LEGACY_AA_BEHAVIOR
0;
#else
SK_Fixed1;
#endif
// Note that even if the following test failed, the edges might still be very close to each
// other at some point within the current pixel row because of prev->fDX and next->fDX.
// However, to handle that case, we have to sacrafice more performance.
// I think the current quality is good enough (mainly by looking at Nebraska-StateSeal.svg)
// so I'll ignore fDX for performance tradeoff.
return next && prev && next->fUpperY < lowerY && prev->fX >= next->fX - SkAbs32(next->fDX);
return next && prev && next->fUpperY < lowerY && prev->fX + SLACK >=
next->fX - SkAbs32(next->fDX);
// The following is more accurate but also slower.
// return (prev && prev->fPrev && next && next->fNext != nullptr && next->fUpperY < lowerY &&
// prev->fX + SkAbs32(prev->fDX) >= next->fX - SkAbs32(next->fDX));
// prev->fX + SkAbs32(prev->fDX) + SLACK >= next->fX - SkAbs32(next->fDX));
}
// This function exists for the case where the previous rite edge is removed because