add double precision convex test
BUG=389050 Review URL: https://codereview.chromium.org/975523002
This commit is contained in:
parent
ee1a726aed
commit
b421650e13
@ -2099,30 +2099,11 @@ static bool almost_equal(SkScalar compA, SkScalar compB) {
|
||||
return aBits < bBits + epsilon && bBits < aBits + epsilon;
|
||||
}
|
||||
|
||||
static DirChange direction_change(const SkPoint& lastPt, const SkVector& curPt,
|
||||
const SkVector& lastVec, const SkVector& curVec) {
|
||||
SkScalar cross = SkPoint::CrossProduct(lastVec, curVec);
|
||||
|
||||
SkScalar smallest = SkTMin(curPt.fX, SkTMin(curPt.fY, SkTMin(lastPt.fX, lastPt.fY)));
|
||||
SkScalar largest = SkTMax(curPt.fX, SkTMax(curPt.fY, SkTMax(lastPt.fX, lastPt.fY)));
|
||||
largest = SkTMax(largest, -smallest);
|
||||
|
||||
if (!almost_equal(largest, largest + cross)) {
|
||||
int sign = SkScalarSignAsInt(cross);
|
||||
if (sign) {
|
||||
return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SkScalarNearlyZero(lastVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNearlyZero) &&
|
||||
!SkScalarNearlyZero(curVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNearlyZero) &&
|
||||
lastVec.dot(curVec) < 0.0f) {
|
||||
return kBackwards_DirChange;
|
||||
}
|
||||
|
||||
return kStraight_DirChange;
|
||||
static bool approximately_zero_when_compared_to(double x, double y) {
|
||||
return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
|
||||
}
|
||||
|
||||
|
||||
// only valid for a single contour
|
||||
struct Convexicator {
|
||||
Convexicator()
|
||||
@ -2161,6 +2142,7 @@ struct Convexicator {
|
||||
if (!SkScalarIsFinite(lengthSqd)) {
|
||||
fIsFinite = false;
|
||||
} else if (!SkScalarNearlyZero(lengthSqd, SK_ScalarNearlyZero*SK_ScalarNearlyZero)) {
|
||||
fPriorPt = fLastPt;
|
||||
fLastPt = fCurrPt;
|
||||
fCurrPt = pt;
|
||||
if (++fPtCount == 2) {
|
||||
@ -2190,6 +2172,44 @@ struct Convexicator {
|
||||
}
|
||||
}
|
||||
|
||||
DirChange directionChange(const SkVector& curVec) {
|
||||
SkScalar cross = SkPoint::CrossProduct(fLastVec, curVec);
|
||||
|
||||
SkScalar smallest = SkTMin(fCurrPt.fX, SkTMin(fCurrPt.fY, SkTMin(fLastPt.fX, fLastPt.fY)));
|
||||
SkScalar largest = SkTMax(fCurrPt.fX, SkTMax(fCurrPt.fY, SkTMax(fLastPt.fX, fLastPt.fY)));
|
||||
largest = SkTMax(largest, -smallest);
|
||||
|
||||
if (!almost_equal(largest, largest + cross)) {
|
||||
int sign = SkScalarSignAsInt(cross);
|
||||
if (sign) {
|
||||
return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (cross) {
|
||||
double dLastVecX = SkScalarToDouble(fLastPt.fX) - SkScalarToDouble(fPriorPt.fX);
|
||||
double dLastVecY = SkScalarToDouble(fLastPt.fY) - SkScalarToDouble(fPriorPt.fY);
|
||||
double dCurrVecX = SkScalarToDouble(fCurrPt.fX) - SkScalarToDouble(fLastPt.fX);
|
||||
double dCurrVecY = SkScalarToDouble(fCurrPt.fY) - SkScalarToDouble(fLastPt.fY);
|
||||
double dCross = dLastVecX * dCurrVecY - dLastVecY * dCurrVecX;
|
||||
if (!approximately_zero_when_compared_to(dCross, SkScalarToDouble(largest))) {
|
||||
int sign = SkScalarSignAsInt(SkDoubleToScalar(dCross));
|
||||
if (sign) {
|
||||
return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SkScalarNearlyZero(fLastVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNearlyZero) &&
|
||||
!SkScalarNearlyZero(curVec.lengthSqd(), SK_ScalarNearlyZero*SK_ScalarNearlyZero) &&
|
||||
fLastVec.dot(curVec) < 0.0f) {
|
||||
return kBackwards_DirChange;
|
||||
}
|
||||
|
||||
return kStraight_DirChange;
|
||||
}
|
||||
|
||||
|
||||
bool isFinite() const {
|
||||
return fIsFinite;
|
||||
}
|
||||
@ -2201,7 +2221,7 @@ struct Convexicator {
|
||||
private:
|
||||
void addVec(const SkVector& vec) {
|
||||
SkASSERT(vec.fX || vec.fY);
|
||||
DirChange dir = direction_change(fLastPt, fCurrPt, fLastVec, vec);
|
||||
DirChange dir = this->directionChange(vec);
|
||||
switch (dir) {
|
||||
case kLeft_DirChange: // fall through
|
||||
case kRight_DirChange:
|
||||
@ -2230,6 +2250,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
SkPoint fPriorPt;
|
||||
SkPoint fLastPt;
|
||||
SkPoint fCurrPt;
|
||||
// fLastVec does not necessarily start at fLastPt. We only advance it when the cross product
|
||||
|
@ -1076,6 +1076,34 @@ static void check_convexity(skiatest::Reporter* reporter, const SkPath& path,
|
||||
REPORTER_ASSERT(reporter, c == expected);
|
||||
}
|
||||
|
||||
static void test_path_crbug389050(skiatest::Reporter* reporter) {
|
||||
SkPath tinyConvexPolygon;
|
||||
tinyConvexPolygon.moveTo(600.131559f, 800.112512f);
|
||||
tinyConvexPolygon.lineTo(600.161735f, 800.118627f);
|
||||
tinyConvexPolygon.lineTo(600.148962f, 800.142338f);
|
||||
tinyConvexPolygon.lineTo(600.134891f, 800.137724f);
|
||||
tinyConvexPolygon.close();
|
||||
tinyConvexPolygon.getConvexity();
|
||||
check_convexity(reporter, tinyConvexPolygon, SkPath::kConvex_Convexity);
|
||||
check_direction(reporter, tinyConvexPolygon, SkPath::kCW_Direction);
|
||||
|
||||
SkPath platTriangle;
|
||||
platTriangle.moveTo(0, 0);
|
||||
platTriangle.lineTo(200, 0);
|
||||
platTriangle.lineTo(100, 0.04f);
|
||||
platTriangle.close();
|
||||
platTriangle.getConvexity();
|
||||
check_direction(reporter, platTriangle, SkPath::kCW_Direction);
|
||||
|
||||
platTriangle.reset();
|
||||
platTriangle.moveTo(0, 0);
|
||||
platTriangle.lineTo(200, 0);
|
||||
platTriangle.lineTo(100, 0.03f);
|
||||
platTriangle.close();
|
||||
platTriangle.getConvexity();
|
||||
check_direction(reporter, platTriangle, SkPath::kCW_Direction);
|
||||
}
|
||||
|
||||
static void test_convexity2(skiatest::Reporter* reporter) {
|
||||
SkPath pt;
|
||||
pt.moveTo(0, 0);
|
||||
@ -3739,6 +3767,7 @@ DEF_TEST(Paths, reporter) {
|
||||
PathTest_Private::TestPathTo(reporter);
|
||||
PathRefTest_Private::TestPathRef(reporter);
|
||||
test_dump(reporter);
|
||||
test_path_crbug389050(reporter);
|
||||
test_path_crbugskia2820(reporter);
|
||||
test_skbug_3469(reporter);
|
||||
test_skbug_3239(reporter);
|
||||
|
Loading…
Reference in New Issue
Block a user