diff options
author | reed <reed@chromium.org> | 2015-03-19 10:18:47 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-19 10:18:47 -0700 |
commit | 65cb2cd2f7ad4146f055810b8bd77bff03a4e76e (patch) | |
tree | 25634a85ad23f0010314b65ef31a5826a7f5ec54 | |
parent | e053ca4380713a5b9e6a31119a1bdd6d529208aa (diff) |
alt SkEvalQuadAt that returns its answer, using Sk2f
BUG=skia:
Review URL: https://codereview.chromium.org/1011493003
-rw-r--r-- | bench/GeometryBench.cpp | 46 | ||||
-rw-r--r-- | src/core/SkGeometry.cpp | 40 | ||||
-rw-r--r-- | src/core/SkGeometry.h | 6 | ||||
-rw-r--r-- | tests/GeometryTest.cpp | 25 |
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); } |