treat backwards quads as not convex

If a quad, cubic, or conic goes back on itself, assume it's not convex.
In a future CL, we could check to see if the curve is linear so that
linear curves are treated the same as lines.

BUG=skia:3469

Review URL: https://codereview.chromium.org/971773002
This commit is contained in:
caryclark 2015-03-02 10:07:56 -08:00 committed by Commit bot
parent 341c808070
commit 5ccef57790
2 changed files with 34 additions and 5 deletions

View File

@ -2129,7 +2129,8 @@ struct Convexicator {
: fPtCount(0)
, fConvexity(SkPath::kConvex_Convexity)
, fDirection(SkPath::kUnknown_Direction)
, fIsFinite(true) {
, fIsFinite(true)
, fIsCurve(false) {
fExpectedDir = kInvalid_DirChange;
// warnings
fLastPt.set(0, 0);
@ -2193,6 +2194,10 @@ struct Convexicator {
return fIsFinite;
}
void setCurve(bool isCurve) {
fIsCurve = isCurve;
}
private:
void addVec(const SkVector& vec) {
SkASSERT(vec.fX || vec.fY);
@ -2213,6 +2218,10 @@ private:
case kStraight_DirChange:
break;
case kBackwards_DirChange:
if (fIsCurve) {
fConvexity = SkPath::kConcave_Convexity;
fDirection = SkPath::kUnknown_Direction;
}
fLastVec = vec;
break;
case kInvalid_DirChange:
@ -2232,6 +2241,7 @@ private:
SkPath::Direction fDirection;
int fDx, fDy, fSx, fSy;
bool fIsFinite;
bool fIsCurve;
};
SkPath::Convexity SkPath::internalGetConvexity() const {
@ -2255,13 +2265,23 @@ SkPath::Convexity SkPath::internalGetConvexity() const {
return kConcave_Convexity;
}
pts[1] = pts[0];
// fall through
case kLine_Verb:
count = 1;
state.setCurve(false);
break;
case kQuad_Verb:
// fall through
case kConic_Verb:
// fall through
case kCubic_Verb:
count = 2 + (kCubic_Verb == verb);
// As an additional enhancement, this could set curve true only
// if the curve is nonlinear
state.setCurve(true);
break;
case kLine_Verb: count = 1; break;
case kQuad_Verb: count = 2; break;
case kConic_Verb: count = 2; break;
case kCubic_Verb: count = 3; break;
case kClose_Verb:
state.setCurve(false);
state.close();
count = 0;
break;

View File

@ -38,6 +38,14 @@ static void test_add_rrect(skiatest::Reporter* reporter, const SkRect& bounds,
REPORTER_ASSERT(reporter, bounds == path.getBounds());
}
static void test_skbug_3469(skiatest::Reporter* reporter) {
SkPath path;
path.moveTo(20, 20);
path.quadTo(20, 50, 80, 50);
path.quadTo(20, 50, 20, 80);
REPORTER_ASSERT(reporter, !path.isConvex());
}
static void test_skbug_3239(skiatest::Reporter* reporter) {
const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */
const float max = SkBits2Float(0x4b7f1c1d); /* 16718877.000000 */
@ -3732,5 +3740,6 @@ DEF_TEST(Paths, reporter) {
PathRefTest_Private::TestPathRef(reporter);
test_dump(reporter);
test_path_crbugskia2820(reporter);
test_skbug_3469(reporter);
test_skbug_3239(reporter);
}