Handle paths that do not report empty, but have no edges.

patch from issue 999963005 at patchset 1 (http://crrev.com/999963005#ps1)

BUG=skia:3527

Review URL: https://codereview.chromium.org/1008883002
This commit is contained in:
reed 2015-03-13 08:48:26 -07:00 committed by Commit bot
parent f7076a13e2
commit c1b11f1db6
3 changed files with 46 additions and 13 deletions

View File

@ -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;

View File

@ -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();
}

View File

@ -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 {