aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@chromium.org>2015-03-19 10:18:47 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-03-19 10:18:47 -0700
commit65cb2cd2f7ad4146f055810b8bd77bff03a4e76e (patch)
tree25634a85ad23f0010314b65ef31a5826a7f5ec54
parente053ca4380713a5b9e6a31119a1bdd6d529208aa (diff)
alt SkEvalQuadAt that returns its answer, using Sk2f
-rw-r--r--bench/GeometryBench.cpp46
-rw-r--r--src/core/SkGeometry.cpp40
-rw-r--r--src/core/SkGeometry.h6
-rw-r--r--tests/GeometryTest.cpp25
4 files changed, 92 insertions, 25 deletions
diff --git a/bench/GeometryBench.cpp b/bench/GeometryBench.cpp
index fd86effc34..1d8575735f 100644
--- a/bench/GeometryBench.cpp
+++ b/bench/GeometryBench.cpp
@@ -129,3 +129,49 @@ DEF_BENCH( return new GeoRectBench_intersect_rect; )
DEF_BENCH( return new GeoRectBench_Intersects; )
DEF_BENCH( return new GeoRectBench_sort; )
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class EvalQuadAt0 : public GeometryBench {
+ SkPoint fPts[3];
+public:
+ EvalQuadAt0() : GeometryBench("evalquadat0") {
+ SkRandom rand;
+ for (int i = 0; i < 3; ++i) {
+ fPts[i].set(rand.nextUScalar1(), rand.nextUScalar1());
+ }
+ }
+
+protected:
+ void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ SkPoint result;
+ for (int outer = 0; outer < loops; ++outer) {
+ for (int i = 0; i < 10000; ++i) {
+ SkEvalQuadAt(fPts, 0.5f, &result);
+ }
+ }
+ }
+};
+DEF_BENCH( return new EvalQuadAt0; )
+
+class EvalQuadAt1 : public GeometryBench {
+ SkPoint fPts[3];
+public:
+ EvalQuadAt1() : GeometryBench("evalquadat1") {
+ SkRandom rand;
+ for (int i = 0; i < 3; ++i) {
+ fPts[i].set(rand.nextUScalar1(), rand.nextUScalar1());
+ }
+ }
+
+protected:
+ void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
+ for (int outer = 0; outer < loops; ++outer) {
+ for (int i = 0; i < 10000; ++i) {
+ SkEvalQuadAt(fPts, 0.5f);
+ }
+ }
+ }
+};
+DEF_BENCH( return new EvalQuadAt1; )
+
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index b4d12dbfa4..063c7822b2 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -114,17 +114,10 @@ static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t) {
return 2 * SkScalarMulAdd(A, t, B);
}
-static SkScalar eval_quad_derivative_at_half(const SkScalar src[]) {
- SkScalar A = src[4] - 2 * src[2] + src[0];
- SkScalar B = src[2] - src[0];
- return A + 2 * B;
-}
-
-void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
- SkVector* tangent) {
+void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tangent) {
SkASSERT(src);
SkASSERT(t >= 0 && t <= SK_Scalar1);
-
+
if (pt) {
pt->set(eval_quad(&src[0].fX, t), eval_quad(&src[0].fY, t));
}
@@ -134,20 +127,25 @@ void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
}
}
-void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt, SkVector* tangent) {
+#include "Sk4x.h"
+
+SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t) {
SkASSERT(src);
+ SkASSERT(t >= 0 && t <= SK_Scalar1);
- if (pt) {
- SkScalar x01 = SkScalarAve(src[0].fX, src[1].fX);
- SkScalar y01 = SkScalarAve(src[0].fY, src[1].fY);
- SkScalar x12 = SkScalarAve(src[1].fX, src[2].fX);
- SkScalar y12 = SkScalarAve(src[1].fY, src[2].fY);
- pt->set(SkScalarAve(x01, x12), SkScalarAve(y01, y12));
- }
- if (tangent) {
- tangent->set(eval_quad_derivative_at_half(&src[0].fX),
- eval_quad_derivative_at_half(&src[0].fY));
- }
+ const Sk4f t2(t);
+ const Sk4f two(2);
+
+ Sk4f P0 = Sk4f::Load2(&src[0].fX);
+ Sk4f P1 = Sk4f::Load2(&src[1].fX);
+ Sk4f P2 = Sk4f::Load2(&src[2].fX);
+
+ Sk4f A = P2.subtract(P1.multiply(two)).add(P0);
+ Sk4f B = P1.subtract(P0).multiply(two);
+
+ SkPoint result;
+ A.multiply(t2).add(B).multiply(t2).add(P0).store2(&result.fX);
+ return result;
}
static void interp_quad_coords(const SkScalar* src, SkScalar* dst, SkScalar t) {
diff --git a/src/core/SkGeometry.h b/src/core/SkGeometry.h
index 4da74f2475..ff863a2294 100644
--- a/src/core/SkGeometry.h
+++ b/src/core/SkGeometry.h
@@ -20,10 +20,8 @@ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]);
/** Set pt to the point on the src quadratic specified by t. t must be
0 <= t <= 1.0
*/
-void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt,
- SkVector* tangent = NULL);
-void SkEvalQuadAtHalf(const SkPoint src[3], SkPoint* pt,
- SkVector* tangent = NULL);
+void SkEvalQuadAt(const SkPoint src[3], SkScalar t, SkPoint* pt, SkVector* tangent = NULL);
+SkPoint SkEvalQuadAt(const SkPoint src[3], SkScalar t);
/** Given a src quadratic bezier, chop it at the specified t value,
where 0 < t < 1, and return the two new quadratics in dst:
diff --git a/tests/GeometryTest.cpp b/tests/GeometryTest.cpp
index 5151b70805..9be6000a0e 100644
--- a/tests/GeometryTest.cpp
+++ b/tests/GeometryTest.cpp
@@ -7,6 +7,7 @@
#include "SkGeometry.h"
#include "Test.h"
+#include "SkRandom.h"
static bool nearly_equal(const SkPoint& a, const SkPoint& b) {
return SkScalarNearlyEqual(a.fX, b.fX) && SkScalarNearlyEqual(a.fY, b.fY);
@@ -33,6 +34,29 @@ static void testChopCubic(skiatest::Reporter* reporter) {
}
}
+static void test_evalquadat(skiatest::Reporter* reporter) {
+ SkRandom rand;
+ for (int i = 0; i < 1000; ++i) {
+ SkPoint pts[3];
+ for (int j = 0; j < 3; ++j) {
+ pts[j].set(rand.nextSScalar1() * 100, rand.nextSScalar1() * 100);
+ }
+ SkScalar t = 0;
+ const SkScalar dt = SK_Scalar1 / 128;
+ for (int j = 0; j < 128; ++j) {
+ SkPoint r0;
+ SkEvalQuadAt(pts, t, &r0);
+ SkPoint r1 = SkEvalQuadAt(pts, t);
+ bool eq = SkScalarNearlyEqual(r0.fX, r1.fX) && SkScalarNearlyEqual(r0.fY, r1.fY);
+ if (!eq) {
+ SkDebugf("[%d %g] p0 [%10.8f %10.8f] p1 [%10.8f %10.8f]\n", i, t, r0.fX, r0.fY, r1.fX, r1.fY);
+ REPORTER_ASSERT(reporter, eq);
+ }
+ t += dt;
+ }
+ }
+}
+
DEF_TEST(Geometry, reporter) {
SkPoint pts[3], dst[5];
@@ -58,4 +82,5 @@ DEF_TEST(Geometry, reporter) {
}
testChopCubic(reporter);
+ test_evalquadat(reporter);
}