diff options
-rw-r--r-- | gyp/core.gyp | 12 | ||||
-rw-r--r-- | gyp/tests.gyp | 1 | ||||
-rw-r--r-- | include/core/SkPoint.h | 11 | ||||
-rw-r--r-- | include/core/SkScalar.h | 8 | ||||
-rw-r--r-- | src/core/SkPoint.cpp | 27 | ||||
-rw-r--r-- | tests/core/PointTest.cpp | 39 |
6 files changed, 78 insertions, 20 deletions
diff --git a/gyp/core.gyp b/gyp/core.gyp index b5bc962122..9017a4f0ae 100644 --- a/gyp/core.gyp +++ b/gyp/core.gyp @@ -330,6 +330,18 @@ 'opts.gyp:opts' ], }, + { + 'target_name': 'core_tests', + 'type': 'static_library', + 'all_dependent_settings': { + 'sources': [ + '../tests/core/PointTest.cpp', + ], + 'include_dirs': [ + '../tests', + ], + }, + }, ], } diff --git a/gyp/tests.gyp b/gyp/tests.gyp index 1888a21497..fa2e17910d 100644 --- a/gyp/tests.gyp +++ b/gyp/tests.gyp @@ -69,6 +69,7 @@ ], 'dependencies': [ 'core.gyp:core', + 'core.gyp:core_tests', 'effects.gyp:effects', 'experimental.gyp:experimental', 'images.gyp:images', diff --git a/include/core/SkPoint.h b/include/core/SkPoint.h index d74435e710..fc0ca3e397 100644 --- a/include/core/SkPoint.h +++ b/include/core/SkPoint.h @@ -207,9 +207,8 @@ struct SK_API SkPoint { SkScalar distanceToOrigin() const { return this->length(); } /** Set the point (vector) to be unit-length in the same direction as it - currently is, and return its old length. If the old length is - degenerately small (nearly zero), do nothing and return false, otherwise - return true. + already points. If the point has a degenerate length (i.e. nearly 0) + then return false and do nothing; otherwise return true. */ bool normalize(); @@ -326,6 +325,11 @@ struct SK_API SkPoint { /** Normalize pt, returning its previous length. If the prev length is too small (degenerate), return 0 and leave pt unchanged. + + Note that this method may be significantly more expensive than + the non-static normalize(), because it has to return the previous length + of the point. If you don't need the previous length, call the + non-static normalize() method instead. */ static SkScalar Normalize(SkPoint* pt); @@ -377,4 +381,3 @@ struct SK_API SkPoint { typedef SkPoint SkVector; #endif - diff --git a/include/core/SkScalar.h b/include/core/SkScalar.h index ba113f41c5..090205925d 100644 --- a/include/core/SkScalar.h +++ b/include/core/SkScalar.h @@ -290,11 +290,17 @@ */ static inline bool SkScalarNearlyZero(SkScalar x, - SkScalar tolerance = SK_ScalarNearlyZero) { + SkScalar tolerance = SK_ScalarNearlyZero) { SkASSERT(tolerance > 0); return SkScalarAbs(x) < tolerance; } +static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y, + SkScalar tolerance = SK_ScalarNearlyZero) { + SkASSERT(tolerance > 0); + return SkScalarAbs(x-y) < tolerance; +} + /** Linearly interpolate between A and B, based on t. If t is 0, return A If t is 1, return B diff --git a/src/core/SkPoint.cpp b/src/core/SkPoint.cpp index b5941d589e..c4163592b9 100644 --- a/src/core/SkPoint.cpp +++ b/src/core/SkPoint.cpp @@ -82,8 +82,6 @@ void SkPoint::scale(SkScalar scale, SkPoint* dst) const { dst->set(SkScalarMul(fX, scale), SkScalarMul(fY, scale)); } -#define kNearlyZero (SK_Scalar1 / 8092) - bool SkPoint::normalize() { return this->setLength(fX, fY, SK_Scalar1); } @@ -96,26 +94,26 @@ bool SkPoint::setLength(SkScalar length) { return this->setLength(fX, fY, length); } -#ifdef SK_SCALAR_IS_FLOAT - -SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) { - return sk_float_sqrt(dx * dx + dy * dy); -} - SkScalar SkPoint::Normalize(SkPoint* pt) { - float mag = SkPoint::Length(pt->fX, pt->fY); - if (mag > kNearlyZero) { - float scale = 1 / mag; - pt->fX *= scale; - pt->fY *= scale; + SkScalar mag = SkPoint::Length(pt->fX, pt->fY); + if (mag > SK_ScalarNearlyZero) { + SkScalar scale = SkScalarInvert(mag); + pt->fX = SkScalarMul(pt->fX, scale); + pt->fY = SkScalarMul(pt->fY, scale); return mag; } return 0; } +#ifdef SK_SCALAR_IS_FLOAT + +SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) { + return sk_float_sqrt(dx * dx + dy * dy); +} + bool SkPoint::setLength(float x, float y, float length) { float mag = sk_float_sqrt(x * x + y * y); - if (mag > kNearlyZero) { + if (mag > SK_ScalarNearlyZero) { length /= mag; fX = x * length; fY = y * length; @@ -401,4 +399,3 @@ SkScalar SkPoint::distanceToLineSegmentBetweenSqd(const SkPoint& a, return SkScalarMulDiv(det, det, uLengthSqd); } } - diff --git a/tests/core/PointTest.cpp b/tests/core/PointTest.cpp new file mode 100644 index 0000000000..dc13b303f0 --- /dev/null +++ b/tests/core/PointTest.cpp @@ -0,0 +1,39 @@ +// Unit tests for src/core/SkPoint.cpp and its header + +#include "SkPoint.h" +#include "Test.h" + +// Tests that SkPoint::length() and SkPoint::Length() both return +// approximately expectedLength for this (x,y). +static void test_length(skiatest::Reporter* reporter, SkScalar x, SkScalar y, + SkScalar expectedLength) { + SkPoint point; + point.set(x, y); + SkScalar s1 = point.length(); + SkScalar s2 = SkPoint::Length(x, y); + REPORTER_ASSERT(reporter, s1 == s2); + REPORTER_ASSERT(reporter, SkScalarNearlyEqual(s1, expectedLength)); +} + +// Tests SkPoint::Normalize() for this (x,y) +static void test_Normalize(skiatest::Reporter* reporter, + SkScalar x, SkScalar y) { + SkPoint point; + point.set(x, y); + SkScalar oldLength = point.length(); + SkScalar returned = SkPoint::Normalize(&point); + SkScalar newLength = point.length(); + REPORTER_ASSERT(reporter, returned == oldLength); + REPORTER_ASSERT(reporter, SkScalarNearlyEqual(newLength, SK_Scalar1)); +} + +void PointTest(skiatest::Reporter* reporter) { + test_length(reporter, SkIntToScalar(3), SkIntToScalar(4), SkIntToScalar(5)); + test_length(reporter, SkFloatToScalar(0.6), SkFloatToScalar(0.8), + SK_Scalar1); + test_Normalize(reporter, SkIntToScalar(3), SkIntToScalar(4)); + test_Normalize(reporter, SkFloatToScalar(0.6), SkFloatToScalar(0.8)); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Point", PointTestClass, PointTest) |