aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkRegion_path.cpp35
-rw-r--r--tests/CanvasTest.cpp16
-rw-r--r--tests/RegionTest.cpp8
3 files changed, 46 insertions, 13 deletions
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 {