From: caryclark Date: Mon, 2 Mar 2015 21:02:34 +0000 (-0800) Subject: add double precision convex test X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~3355 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b421650e13faa2b77d29b018e78ab07ff693ca32;p=platform%2Fupstream%2FlibSkiaSharp.git add double precision convex test BUG=389050 Review URL: https://codereview.chromium.org/975523002 --- diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 738edd9..b92b47f 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -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 diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index aeab7e6..964b7e1 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -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);