diff --git a/src/core/SkRegion_path.cpp b/src/core/SkRegion_path.cpp index e9224d824e..5b665d4706 100644 --- a/src/core/SkRegion_path.cpp +++ b/src/core/SkRegion_path.cpp @@ -268,7 +268,7 @@ static unsigned verb_to_max_edges(unsigned verb) { return gPathVerbToMaxEdges[verb]; } - +// If returns 0, ignore itop and ibot static int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) { SkPath::Iter iter(path, true); SkPoint pts[4]; @@ -298,13 +298,24 @@ static int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) { } } } - SkASSERT(top <= bot); + if (0 == maxEdges) { + return 0; // we have only moves+closes + } + SkASSERT(top <= bot); *itop = SkScalarRoundToInt(top); *ibot = SkScalarRoundToInt(bot); return maxEdges; } +static bool check_inverse_on_empty_return(SkRegion* dst, const SkPath& path, const SkRegion& clip) { + if (path.isInverseFillType()) { + return dst->set(clip); + } else { + return dst->setEmpty(); + } +} + bool SkRegion::setPath(const SkPath& path, const SkRegion& clip) { SkDEBUGCODE(this->validate();) @@ -313,26 +324,24 @@ bool SkRegion::setPath(const SkPath& path, const SkRegion& clip) { } if (path.isEmpty()) { - if (path.isInverseFillType()) { - return this->set(clip); - } else { - return this->setEmpty(); - } + return check_inverse_on_empty_return(this, path, clip); } // compute worst-case rgn-size for the path int pathTop, pathBot; int pathTransitions = count_path_runtype_values(path, &pathTop, &pathBot); - int clipTop, clipBot; - int clipTransitions; + if (0 == pathTransitions) { + return check_inverse_on_empty_return(this, path, clip); + } - clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); + int clipTop, clipBot; + int clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); int top = SkMax32(pathTop, clipTop); int bot = SkMin32(pathBot, clipBot); - - if (top >= bot) - return this->setEmpty(); + if (top >= bot) { + return check_inverse_on_empty_return(this, path, clip); + } SkRgnBuilder builder; diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp index 98cfbc158d..23d49834c2 100644 --- a/tests/CanvasTest.cpp +++ b/tests/CanvasTest.cpp @@ -747,3 +747,19 @@ DEF_TEST(Canvas_SaveState, reporter) { canvas.restore(); REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount()); } + +DEF_TEST(Canvas_ClipEmptyPath, reporter) { + SkCanvas canvas(10, 10); + canvas.save(); + SkPath path; + canvas.clipPath(path); + canvas.restore(); + canvas.save(); + path.moveTo(5, 5); + canvas.clipPath(path); + canvas.restore(); + canvas.save(); + path.moveTo(7, 7); + canvas.clipPath(path); // should not assert here + canvas.restore(); +} diff --git a/tests/RegionTest.cpp b/tests/RegionTest.cpp index ae58ae6e2e..acb81809de 100644 --- a/tests/RegionTest.cpp +++ b/tests/RegionTest.cpp @@ -5,6 +5,7 @@ * found in the LICENSE file. */ +#include "SkPath.h" #include "SkRandom.h" #include "SkRegion.h" #include "Test.h" @@ -91,6 +92,13 @@ static void test_empties(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !empty.contains(empty2)); REPORTER_ASSERT(reporter, !valid.contains(empty)); REPORTER_ASSERT(reporter, !empty.contains(valid)); + + SkPath emptyPath; + emptyPath.moveTo(1, 5); + emptyPath.close(); + SkRegion openClip; + openClip.setRect(-16000, -16000, 16000, 16000); + empty.setPath(emptyPath, openClip); // should not assert } enum {