diff options
-rw-r--r-- | gm/aaa.cpp | 16 | ||||
-rw-r--r-- | src/core/SkScan_AAAPath.cpp | 16 |
2 files changed, 30 insertions, 2 deletions
diff --git a/gm/aaa.cpp b/gm/aaa.cpp index 614ff84258..4f81fc9a2c 100644 --- a/gm/aaa.cpp +++ b/gm/aaa.cpp @@ -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: diff --git a/src/core/SkScan_AAAPath.cpp b/src/core/SkScan_AAAPath.cpp index f9445d24f2..6362d2f1e0 100644 --- a/src/core/SkScan_AAAPath.cpp +++ b/src/core/SkScan_AAAPath.cpp @@ -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 |