aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/core.gyp12
-rw-r--r--gyp/tests.gyp1
-rw-r--r--include/core/SkPoint.h11
-rw-r--r--include/core/SkScalar.h8
-rw-r--r--src/core/SkPoint.cpp27
-rw-r--r--tests/core/PointTest.cpp39
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)