diff options
author | Chris Dalton <csmartdalton@google.com> | 2017-11-08 17:04:47 -0700 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-11-09 16:08:44 +0000 |
commit | fc31be40cede4dfd5b06ecaffb551b06aea85693 (patch) | |
tree | e4eeb8ba07f58f12eb8c17bfea66676b82efbacc /tests | |
parent | fdab576a75c636dbcd5ff44c3f5f57205cc26a6f (diff) |
Harden SkClassifyCubic
BUG=chromium:743617
Change-Id: Idfb89832b48ebd60fd9109cd526bdd5cd5931ada
Reviewed-on: https://skia-review.googlesource.com/68980
Reviewed-by: Cary Clark <caryclark@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/GeometryTest.cpp | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/tests/GeometryTest.cpp b/tests/GeometryTest.cpp index a9265016ac..e434a7856f 100644 --- a/tests/GeometryTest.cpp +++ b/tests/GeometryTest.cpp @@ -10,6 +10,7 @@ #include "SkRandom.h" #include "Test.h" #include <array> +#include <numeric> static bool nearly_equal(const SkPoint& a, const SkPoint& b) { return SkScalarNearlyEqual(a.fX, b.fX) && SkScalarNearlyEqual(a.fY, b.fY); @@ -208,9 +209,81 @@ static void test_cubic_tangents(skiatest::Reporter* reporter) { } static void check_cubic_type(skiatest::Reporter* reporter, - const std::array<SkPoint, 4>& bezierPoints, SkCubicType expectedType) { + const std::array<SkPoint, 4>& bezierPoints, SkCubicType expectedType, + bool undefined = false) { + // Classify the cubic even if the results will be undefined: check for crashes and asserts. SkCubicType actualType = SkClassifyCubic(bezierPoints.data()); - REPORTER_ASSERT(reporter, actualType == expectedType); + if (!undefined) { + REPORTER_ASSERT(reporter, actualType == expectedType); + } +} + +static void check_cubic_around_rect(skiatest::Reporter* reporter, + float x1, float y1, float x2, float y2, + bool undefined = false) { + static constexpr SkCubicType expectations[24] = { + SkCubicType::kLoop, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLocalCusp, + SkCubicType::kLocalCusp, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLoop, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLoop, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLoop, + SkCubicType::kLocalCusp, + SkCubicType::kLocalCusp, + SkCubicType::kLocalCusp, + SkCubicType::kLocalCusp, + SkCubicType::kLoop, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLoop, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLoop, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLocalCusp, + SkCubicType::kLocalCusp, + SkCubicType::kCuspAtInfinity, + SkCubicType::kLoop, + }; + SkPoint points[] = {{x1, y1}, {x2, y1}, {x2, y2}, {x1, y2}}; + std::array<SkPoint, 4> bezier; + for (int i=0; i < 4; ++i) { + bezier[0] = points[i]; + for (int j=0; j < 3; ++j) { + int jidx = (j < i) ? j : j+1; + bezier[1] = points[jidx]; + for (int k=0, kidx=0; k < 2; ++k, ++kidx) { + for (int n = 0; n < 2; ++n) { + kidx = (kidx == i || kidx == jidx) ? kidx+1 : kidx; + } + bezier[2] = points[kidx]; + for (int l = 0; l < 4; ++l) { + if (l != i && l != jidx && l != kidx) { + bezier[3] = points[l]; + break; + } + } + check_cubic_type(reporter, bezier, expectations[i*6 + j*2 + k], undefined); + } + } + } + for (int i=0; i < 4; ++i) { + bezier[0] = points[i]; + for (int j=0; j < 3; ++j) { + int jidx = (j < i) ? j : j+1; + bezier[1] = points[jidx]; + bezier[2] = points[jidx]; + for (int k=0, kidx=0; k < 2; ++k, ++kidx) { + for (int n = 0; n < 2; ++n) { + kidx = (kidx == i || kidx == jidx) ? kidx+1 : kidx; + } + bezier[3] = points[kidx]; + check_cubic_type(reporter, bezier, SkCubicType::kSerpentine, undefined); + } + } + } } static void test_classify_cubic(skiatest::Reporter* reporter) { @@ -223,6 +296,35 @@ static void test_classify_cubic(skiatest::Reporter* reporter) { check_cubic_type(reporter, {{{4.873f, 5.581f}, {5.083f, 5.2783f}, {5.182f, 4.8593f}, {5.177f, 4.3242f}}}, SkCubicType::kSerpentine); + check_cubic_around_rect(reporter, 0, 0, 1, 1); + check_cubic_around_rect(reporter, + -std::numeric_limits<float>::max(), + -std::numeric_limits<float>::max(), + +std::numeric_limits<float>::max(), + +std::numeric_limits<float>::max()); + check_cubic_around_rect(reporter, 1, 1, + +std::numeric_limits<float>::min(), + +std::numeric_limits<float>::max()); + check_cubic_around_rect(reporter, + -std::numeric_limits<float>::min(), + -std::numeric_limits<float>::min(), + +std::numeric_limits<float>::min(), + +std::numeric_limits<float>::min()); + check_cubic_around_rect(reporter, +1, -std::numeric_limits<float>::min(), -1, -1); + check_cubic_around_rect(reporter, + -std::numeric_limits<float>::infinity(), + -std::numeric_limits<float>::infinity(), + +std::numeric_limits<float>::infinity(), + +std::numeric_limits<float>::infinity(), + true); + check_cubic_around_rect(reporter, 0, 0, 1, +std::numeric_limits<float>::infinity(), true); + check_cubic_around_rect(reporter, + -std::numeric_limits<float>::quiet_NaN(), + -std::numeric_limits<float>::quiet_NaN(), + +std::numeric_limits<float>::quiet_NaN(), + +std::numeric_limits<float>::quiet_NaN(), + true); + check_cubic_around_rect(reporter, 0, 0, 1, +std::numeric_limits<float>::quiet_NaN(), true); } DEF_TEST(Geometry, reporter) { |