| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/gfx/animation/keyframe/keyframed_animation_curve.h" |
| |
| #include <memory> |
| |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/animation/tween.h" |
| #include "ui/gfx/geometry/box_f.h" |
| #include "ui/gfx/geometry/test/transform_test_util.h" |
| #include "ui/gfx/geometry/transform_operations.h" |
| #include "ui/gfx/test/gfx_util.h" |
| |
| namespace gfx { |
| namespace { |
| |
| void ExpectTranslateX(SkScalar translate_x, |
| const gfx::TransformOperations& operations) { |
| EXPECT_FLOAT_EQ(translate_x, operations.Apply().matrix().get(0, 3)); |
| } |
| |
| // Tests that a color animation with one keyframe works as expected. |
| TEST(KeyframedAnimationCurveTest, OneColorKeyFrame) { |
| SkColor color = SkColorSetARGB(255, 255, 255, 255); |
| std::unique_ptr<KeyframedColorAnimationCurve> curve( |
| KeyframedColorAnimationCurve::Create()); |
| curve->AddKeyframe(ColorKeyframe::Create(base::TimeDelta(), color, nullptr)); |
| |
| EXPECT_SKCOLOR_EQ(color, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SKCOLOR_EQ(color, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SKCOLOR_EQ(color, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_SKCOLOR_EQ(color, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_SKCOLOR_EQ(color, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a color animation with two keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, TwoColorKeyFrame) { |
| SkColor color_a = SkColorSetARGB(255, 255, 0, 0); |
| SkColor color_b = SkColorSetARGB(255, 0, 255, 0); |
| SkColor color_midpoint = gfx::Tween::ColorValueBetween(0.5, color_a, color_b); |
| std::unique_ptr<KeyframedColorAnimationCurve> curve( |
| KeyframedColorAnimationCurve::Create()); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::TimeDelta(), color_a, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(1.0), color_b, nullptr)); |
| |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SKCOLOR_EQ(color_midpoint, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a color animation with three keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, ThreeColorKeyFrame) { |
| SkColor color_a = SkColorSetARGB(255, 255, 0, 0); |
| SkColor color_b = SkColorSetARGB(255, 0, 255, 0); |
| SkColor color_c = SkColorSetARGB(255, 0, 0, 255); |
| SkColor color_midpoint1 = |
| gfx::Tween::ColorValueBetween(0.5, color_a, color_b); |
| SkColor color_midpoint2 = |
| gfx::Tween::ColorValueBetween(0.5, color_b, color_c); |
| std::unique_ptr<KeyframedColorAnimationCurve> curve( |
| KeyframedColorAnimationCurve::Create()); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::TimeDelta(), color_a, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(1.0), color_b, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(2.0), color_c, nullptr)); |
| |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SKCOLOR_EQ(color_midpoint1, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_SKCOLOR_EQ(color_midpoint2, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a color animation with multiple keys at a given time works sanely. |
| TEST(KeyframedAnimationCurveTest, RepeatedColorKeyFrame) { |
| SkColor color_a = SkColorSetARGB(255, 64, 0, 0); |
| SkColor color_b = SkColorSetARGB(255, 192, 0, 0); |
| |
| std::unique_ptr<KeyframedColorAnimationCurve> curve( |
| KeyframedColorAnimationCurve::Create()); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::TimeDelta(), color_a, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(1.0), color_a, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(1.0), color_b, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(2.0), color_b, nullptr)); |
| |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(base::Seconds(0.5f))); |
| |
| SkColor value = curve->GetValue(base::Seconds(1.0f)); |
| EXPECT_EQ(255u, SkColorGetA(value)); |
| int red_value = SkColorGetR(value); |
| EXPECT_LE(64, red_value); |
| EXPECT_GE(192, red_value); |
| |
| EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a float animation with one keyframe works as expected. |
| TEST(KeyframedAnimationCurveTest, OneFloatKeyframe) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 2.f, nullptr)); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a float animation with two keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, TwoFloatKeyframe) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 2.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 4.f, nullptr)); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ(3.f, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a float animation with three keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, ThreeFloatKeyframe) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 2.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 4.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(2.0), 8.f, nullptr)); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ(3.f, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_FLOAT_EQ(6.f, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_FLOAT_EQ(8.f, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_FLOAT_EQ(8.f, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a float animation with multiple keys at a given time works sanely. |
| TEST(KeyframedAnimationCurveTest, RepeatedFloatKeyTimes) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 4.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 4.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 6.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(2.0), 6.f, nullptr)); |
| |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(0.5f))); |
| |
| // There is a discontinuity at 1. Any value between 4 and 6 is valid. |
| float value = curve->GetValue(base::Seconds(1.f)); |
| EXPECT_TRUE(value >= 4 && value <= 6); |
| |
| EXPECT_FLOAT_EQ(6.f, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_FLOAT_EQ(6.f, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_FLOAT_EQ(6.f, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a transform animation with one keyframe works as expected. |
| TEST(KeyframedAnimationCurveTest, OneTransformKeyframe) { |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| gfx::TransformOperations operations; |
| operations.AppendTranslate(2.f, 0.f, 0.f); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::TimeDelta(), operations, nullptr)); |
| |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(-1.f))); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(0.f))); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(0.5f))); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(1.f))); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a transform animation with two keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, TwoTransformKeyframe) { |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| gfx::TransformOperations operations1; |
| operations1.AppendTranslate(2.f, 0.f, 0.f); |
| gfx::TransformOperations operations2; |
| operations2.AppendTranslate(4.f, 0.f, 0.f); |
| |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::TimeDelta(), operations1, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(1.0), operations2, nullptr)); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(-1.f))); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(0.f))); |
| ExpectTranslateX(3.f, curve->GetValue(base::Seconds(0.5f))); |
| ExpectTranslateX(4.f, curve->GetValue(base::Seconds(1.f))); |
| ExpectTranslateX(4.f, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a transform animation with three keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, ThreeTransformKeyframe) { |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| gfx::TransformOperations operations1; |
| operations1.AppendTranslate(2.f, 0.f, 0.f); |
| gfx::TransformOperations operations2; |
| operations2.AppendTranslate(4.f, 0.f, 0.f); |
| gfx::TransformOperations operations3; |
| operations3.AppendTranslate(8.f, 0.f, 0.f); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::TimeDelta(), operations1, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(1.0), operations2, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(2.0), operations3, nullptr)); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(-1.f))); |
| ExpectTranslateX(2.f, curve->GetValue(base::Seconds(0.f))); |
| ExpectTranslateX(3.f, curve->GetValue(base::Seconds(0.5f))); |
| ExpectTranslateX(4.f, curve->GetValue(base::Seconds(1.f))); |
| ExpectTranslateX(6.f, curve->GetValue(base::Seconds(1.5f))); |
| ExpectTranslateX(8.f, curve->GetValue(base::Seconds(2.f))); |
| ExpectTranslateX(8.f, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a transform animation with multiple keys at a given time works |
| // sanely. |
| TEST(KeyframedAnimationCurveTest, RepeatedTransformKeyTimes) { |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| // A step function. |
| gfx::TransformOperations operations1; |
| operations1.AppendTranslate(4.f, 0.f, 0.f); |
| gfx::TransformOperations operations2; |
| operations2.AppendTranslate(4.f, 0.f, 0.f); |
| gfx::TransformOperations operations3; |
| operations3.AppendTranslate(6.f, 0.f, 0.f); |
| gfx::TransformOperations operations4; |
| operations4.AppendTranslate(6.f, 0.f, 0.f); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::TimeDelta(), operations1, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(1.0), operations2, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(1.0), operations3, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(2.0), operations4, nullptr)); |
| |
| ExpectTranslateX(4.f, curve->GetValue(base::Seconds(-1.f))); |
| ExpectTranslateX(4.f, curve->GetValue(base::Seconds(0.f))); |
| ExpectTranslateX(4.f, curve->GetValue(base::Seconds(0.5f))); |
| |
| // There is a discontinuity at 1. Any value between 4 and 6 is valid. |
| gfx::Transform value = curve->GetValue(base::Seconds(1.f)).Apply(); |
| EXPECT_GE(value.matrix().get(0, 3), 4.f); |
| EXPECT_LE(value.matrix().get(0, 3), 6.f); |
| |
| ExpectTranslateX(6.f, curve->GetValue(base::Seconds(1.5f))); |
| ExpectTranslateX(6.f, curve->GetValue(base::Seconds(2.f))); |
| ExpectTranslateX(6.f, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a discrete transform animation (e.g. where one or more keyframes |
| // is a non-invertible matrix) works as expected. |
| TEST(KeyframedAnimationCurveTest, DiscreteLinearTransformAnimation) { |
| gfx::Transform non_invertible_matrix(0, 0, 0, 0, 0, 0); |
| gfx::Transform identity_matrix; |
| |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| gfx::TransformOperations operations1; |
| operations1.AppendMatrix(non_invertible_matrix); |
| gfx::TransformOperations operations2; |
| operations2.AppendMatrix(identity_matrix); |
| gfx::TransformOperations operations3; |
| operations3.AppendMatrix(non_invertible_matrix); |
| |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::TimeDelta(), operations1, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(1.0), operations2, nullptr)); |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::Seconds(2.0), operations3, nullptr)); |
| |
| gfx::TransformOperations result; |
| |
| // Between 0 and 0.5 seconds, the first keyframe should be returned. |
| result = curve->GetValue(base::Seconds(0.01f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| |
| result = curve->GetValue(base::Seconds(0.49f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| |
| // Between 0.5 and 1.5 seconds, the middle keyframe should be returned. |
| result = curve->GetValue(base::Seconds(0.5f)); |
| ExpectTransformationMatrixEq(identity_matrix, result.Apply()); |
| |
| result = curve->GetValue(base::Seconds(1.49f)); |
| ExpectTransformationMatrixEq(identity_matrix, result.Apply()); |
| |
| // Between 1.5 and 2.0 seconds, the last keyframe should be returned. |
| result = curve->GetValue(base::Seconds(1.5f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| |
| result = curve->GetValue(base::Seconds(2.0f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| } |
| |
| TEST(KeyframedAnimationCurveTest, DiscreteCubicBezierTransformAnimation) { |
| gfx::Transform non_invertible_matrix(0, 0, 0, 0, 0, 0); |
| gfx::Transform identity_matrix; |
| |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| gfx::TransformOperations operations1; |
| operations1.AppendMatrix(non_invertible_matrix); |
| gfx::TransformOperations operations2; |
| operations2.AppendMatrix(identity_matrix); |
| gfx::TransformOperations operations3; |
| operations3.AppendMatrix(non_invertible_matrix); |
| |
| // The cubic-bezier here is a nice fairly strong ease-in curve, where 50% |
| // progression is at approximately 85% of the time. |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::TimeDelta(), operations1, |
| CubicBezierTimingFunction::Create(0.75f, 0.25f, 0.9f, 0.4f))); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(1.0), operations2, |
| CubicBezierTimingFunction::Create(0.75f, 0.25f, 0.9f, 0.4f))); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(2.0), operations3, |
| CubicBezierTimingFunction::Create(0.75f, 0.25f, 0.9f, 0.4f))); |
| |
| gfx::TransformOperations result; |
| |
| // Due to the cubic-bezier, the first keyframe is returned almost all the way |
| // to 1 second. |
| result = curve->GetValue(base::Seconds(0.01f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| |
| result = curve->GetValue(base::Seconds(0.8f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| |
| // Between ~0.85 and ~1.85 seconds, the middle keyframe should be returned. |
| result = curve->GetValue(base::Seconds(0.85f)); |
| ExpectTransformationMatrixEq(identity_matrix, result.Apply()); |
| |
| result = curve->GetValue(base::Seconds(1.8f)); |
| ExpectTransformationMatrixEq(identity_matrix, result.Apply()); |
| |
| // Finally the last keyframe only takes effect after ~1.85 seconds. |
| result = curve->GetValue(base::Seconds(1.85f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| |
| result = curve->GetValue(base::Seconds(2.0f)); |
| ExpectTransformationMatrixEq(non_invertible_matrix, result.Apply()); |
| } |
| |
| // Tests that the keyframes may be added out of order. |
| TEST(KeyframedAnimationCurveTest, UnsortedKeyframes) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(2.f), 8.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 2.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.f), 4.f, nullptr)); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ(3.f, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_FLOAT_EQ(4.f, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_FLOAT_EQ(6.f, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_FLOAT_EQ(8.f, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_FLOAT_EQ(8.f, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a linear timing function works as expected. |
| TEST(KeyframedAnimationCurveTest, LinearTimingFunction) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, |
| LinearTimingFunction::Create())); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 1.f, nullptr)); |
| |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ(0.75f, curve->GetValue(base::Seconds(0.75f))); |
| } |
| |
| // Tests that a cubic bezier timing function works as expected. |
| TEST(KeyframedAnimationCurveTest, CubicBezierTimingFunction) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create( |
| base::TimeDelta(), 0.f, |
| CubicBezierTimingFunction::Create(0.25f, 0.f, 0.75f, 1.f))); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 1.f, nullptr)); |
| |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_LT(0.f, curve->GetValue(base::Seconds(0.25f))); |
| EXPECT_GT(0.25f, curve->GetValue(base::Seconds(0.25f))); |
| EXPECT_NEAR(curve->GetValue(base::Seconds(0.5f)), 0.5f, 0.00015f); |
| EXPECT_LT(0.75f, curve->GetValue(base::Seconds(0.75f))); |
| EXPECT_GT(1.f, curve->GetValue(base::Seconds(0.75f))); |
| EXPECT_FLOAT_EQ(1.f, curve->GetValue(base::Seconds(1.f))); |
| } |
| |
| // Tests a step timing function if the change of values occur at the start. |
| TEST(KeyframedAnimationCurveTest, StepsTimingFunctionStepAtStart) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| const int num_steps = 36; |
| curve->AddKeyframe(FloatKeyframe::Create( |
| base::TimeDelta(), 0.f, |
| StepsTimingFunction::Create(num_steps, |
| StepsTimingFunction::StepPosition::START))); |
| curve->AddKeyframe( |
| FloatKeyframe::Create(base::Seconds(1.0), num_steps, nullptr)); |
| |
| const float time_threshold = 0.0001f; |
| |
| for (float i = 0.f; i < num_steps; i += 1.f) { |
| const base::TimeDelta time1 = base::Seconds(i / num_steps - time_threshold); |
| const base::TimeDelta time2 = base::Seconds(i / num_steps + time_threshold); |
| EXPECT_FLOAT_EQ(std::ceil(i), curve->GetValue(time1)); |
| EXPECT_FLOAT_EQ(std::ceil(i) + 1.f, curve->GetValue(time2)); |
| } |
| EXPECT_FLOAT_EQ(num_steps, curve->GetValue(base::Seconds(1.0))); |
| |
| for (float i = 0.5f; i <= num_steps; i += 1.0f) { |
| const base::TimeDelta time = base::Seconds(i / num_steps); |
| EXPECT_FLOAT_EQ(std::ceil(i), curve->GetValue(time)); |
| } |
| } |
| |
| // Tests a step timing function if the change of values occur at the end. |
| TEST(KeyframedAnimationCurveTest, StepsTimingFunctionStepAtEnd) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| const int num_steps = 36; |
| curve->AddKeyframe(FloatKeyframe::Create( |
| base::TimeDelta(), 0.f, |
| StepsTimingFunction::Create(num_steps, |
| StepsTimingFunction::StepPosition::END))); |
| curve->AddKeyframe( |
| FloatKeyframe::Create(base::Seconds(1.0), num_steps, nullptr)); |
| |
| const float time_threshold = 0.0001f; |
| |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::TimeDelta())); |
| for (float i = 1.f; i <= num_steps; i += 1.f) { |
| const base::TimeDelta time1 = base::Seconds(i / num_steps - time_threshold); |
| const base::TimeDelta time2 = base::Seconds(i / num_steps + time_threshold); |
| EXPECT_FLOAT_EQ(std::floor(i) - 1.f, curve->GetValue(time1)); |
| EXPECT_FLOAT_EQ(std::floor(i), curve->GetValue(time2)); |
| } |
| EXPECT_FLOAT_EQ(num_steps, curve->GetValue(base::Seconds(1.0))); |
| |
| for (float i = 0.5f; i <= num_steps; i += 1.0f) { |
| const base::TimeDelta time = base::Seconds(i / num_steps); |
| EXPECT_FLOAT_EQ(std::floor(i), curve->GetValue(time)); |
| } |
| } |
| |
| // Tests that maximum animation scale is computed as expected. |
| TEST(KeyframedAnimationCurveTest, MaximumScale) { |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve( |
| KeyframedTransformAnimationCurve::Create()); |
| |
| gfx::TransformOperations operations1; |
| curve->AddKeyframe( |
| TransformKeyframe::Create(base::TimeDelta(), operations1, nullptr)); |
| operations1.AppendScale(2.f, -3.f, 1.f); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(1.f), operations1, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| |
| constexpr float kArbitraryScale = 12345.f; |
| float maximum_scale = kArbitraryScale; |
| EXPECT_TRUE(curve->MaximumScale(&maximum_scale)); |
| EXPECT_EQ(3.f, maximum_scale); |
| |
| gfx::TransformOperations operations2; |
| operations2.AppendScale(6.f, 3.f, 2.f); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(2.f), operations2, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| |
| maximum_scale = kArbitraryScale; |
| EXPECT_TRUE(curve->MaximumScale(&maximum_scale)); |
| EXPECT_EQ(6.f, maximum_scale); |
| |
| gfx::TransformOperations operations3; |
| operations3.AppendRotate(1.f, 0.f, 0.f, 90.f); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(3.f), operations3, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| |
| maximum_scale = kArbitraryScale; |
| EXPECT_TRUE(curve->MaximumScale(&maximum_scale)); |
| EXPECT_EQ(6.f, maximum_scale); |
| |
| // All scales are used in computing the max. |
| std::unique_ptr<KeyframedTransformAnimationCurve> curve2( |
| KeyframedTransformAnimationCurve::Create()); |
| |
| gfx::TransformOperations operations5; |
| operations5.AppendScale(0.4f, 0.2f, 0.6f); |
| curve2->AddKeyframe(TransformKeyframe::Create( |
| base::TimeDelta(), operations5, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| gfx::TransformOperations operations6; |
| operations6.AppendScale(0.5f, 0.3f, -0.8f); |
| curve2->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(1.f), operations6, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| |
| maximum_scale = kArbitraryScale; |
| EXPECT_TRUE(curve2->MaximumScale(&maximum_scale)); |
| EXPECT_EQ(0.8f, maximum_scale); |
| } |
| |
| TEST(KeyframeAnimationCurveTest, NonCalculatableMaximumScale) { |
| auto curve = KeyframedTransformAnimationCurve::Create(); |
| gfx::TransformOperations operations4; |
| operations4.AppendPerspective(3.f); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(1.f), operations4, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::Seconds(1.f), operations4, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| |
| constexpr float kArbitraryScale = 12345.f; |
| float maximum_scale = kArbitraryScale; |
| EXPECT_FALSE(curve->MaximumScale(&maximum_scale)); |
| |
| // If the scale of any keyframe can be calculated, the keyframes with |
| // non-calculatable scale will be ignored. |
| gfx::TransformOperations operations; |
| operations.AppendScale(0.4f, 0.2f, 0.6f); |
| curve->AddKeyframe(TransformKeyframe::Create( |
| base::TimeDelta(), operations, |
| CubicBezierTimingFunction::CreatePreset( |
| CubicBezierTimingFunction::EaseType::EASE))); |
| |
| maximum_scale = kArbitraryScale; |
| EXPECT_TRUE(curve->MaximumScale(&maximum_scale)); |
| EXPECT_EQ(0.6f, maximum_scale); |
| } |
| |
| // Tests that an animation with a curve timing function works as expected. |
| TEST(KeyframedAnimationCurveTest, CurveTiming) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.f), 1.f, nullptr)); |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.75f, 0.f, 0.25f, 1.f)); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_NEAR(0.05f, curve->GetValue(base::Seconds(0.25f)), 0.005f); |
| EXPECT_FLOAT_EQ(0.5f, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_NEAR(0.95f, curve->GetValue(base::Seconds(0.75f)), 0.005f); |
| EXPECT_FLOAT_EQ(1.f, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_FLOAT_EQ(1.f, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that an animation with a curve and keyframe timing function works as |
| // expected. |
| TEST(KeyframedAnimationCurveTest, CurveAndKeyframeTiming) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create( |
| base::TimeDelta(), 0.f, |
| CubicBezierTimingFunction::Create(0.35f, 0.f, 0.65f, 1.f))); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.f), 1.f, nullptr)); |
| // Curve timing function producing outputs outside of range [0,1]. |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_FLOAT_EQ( |
| 0.f, curve->GetValue(base::Seconds(0.25f))); // Clamped. c(.25) < 0 |
| EXPECT_NEAR(0.17f, curve->GetValue(base::Seconds(0.42f)), |
| 0.005f); // c(.42)=.27, k(.27)=.17 |
| EXPECT_FLOAT_EQ(0.5f, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_NEAR(0.83f, curve->GetValue(base::Seconds(0.58f)), |
| 0.005f); // c(.58)=.73, k(.73)=.83 |
| EXPECT_FLOAT_EQ( |
| 1.f, curve->GetValue(base::Seconds(0.75f))); // Clamped. c(.75) > 1 |
| EXPECT_FLOAT_EQ(1.f, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_FLOAT_EQ(1.f, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a linear timing function works as expected for inputs outside of |
| // range [0,1] |
| TEST(KeyframedAnimationCurveTest, LinearTimingInputsOutsideZeroOneRange) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 2.f, nullptr)); |
| // Curve timing function producing timing outputs outside of range [0,1]. |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); |
| |
| EXPECT_NEAR(-0.076f, curve->GetValue(base::Seconds(0.25f)), 0.001f); |
| EXPECT_NEAR(2.076f, curve->GetValue(base::Seconds(0.75f)), 0.001f); |
| } |
| |
| // If a curve cubic-bezier timing function produces timing outputs outside |
| // the range [0, 1] then a keyframe cubic-bezier timing function |
| // should consume that input properly (using end-point gradients). |
| TEST(KeyframedAnimationCurveTest, CurveTimingInputsOutsideZeroOneRange) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| // Keyframe timing function with 0.5 gradients at each end. |
| curve->AddKeyframe(FloatKeyframe::Create( |
| base::TimeDelta(), 0.f, |
| CubicBezierTimingFunction::Create(0.5f, 0.25f, 0.5f, 0.75f))); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.f), 1.f, nullptr)); |
| // Curve timing function producing timing outputs outside of range [0,1]. |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); |
| |
| EXPECT_NEAR(-0.02f, curve->GetValue(base::Seconds(0.25f)), |
| 0.002f); // c(.25)=-.04, -.04*0.5=-0.02 |
| EXPECT_NEAR(0.33f, curve->GetValue(base::Seconds(0.46f)), |
| 0.002f); // c(.46)=.38, k(.38)=.33 |
| |
| EXPECT_NEAR(0.67f, curve->GetValue(base::Seconds(0.54f)), |
| 0.002f); // c(.54)=.62, k(.62)=.67 |
| EXPECT_NEAR(1.02f, curve->GetValue(base::Seconds(0.75f)), |
| 0.002f); // c(.75)=1.04 1+.04*0.5=1.02 |
| } |
| |
| // Tests that a step timing function works as expected for inputs outside of |
| // range [0,1] |
| TEST(KeyframedAnimationCurveTest, StepsTimingStartInputsOutsideZeroOneRange) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe( |
| FloatKeyframe::Create(base::TimeDelta(), 0.f, |
| StepsTimingFunction::Create( |
| 4, StepsTimingFunction::StepPosition::START))); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 2.f, nullptr)); |
| // Curve timing function producing timing outputs outside of range [0,1]. |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); |
| |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(0.25f))); |
| EXPECT_FLOAT_EQ(2.5f, curve->GetValue(base::Seconds(0.75f))); |
| } |
| |
| TEST(KeyframedAnimationCurveTest, StepsTimingEndInputsOutsideZeroOneRange) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create( |
| base::TimeDelta(), 0.f, |
| StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::END))); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 2.f, nullptr)); |
| // Curve timing function producing timing outputs outside of range [0,1]. |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); |
| |
| EXPECT_FLOAT_EQ(-0.5f, curve->GetValue(base::Seconds(0.25f))); |
| EXPECT_FLOAT_EQ(2.f, curve->GetValue(base::Seconds(0.75f))); |
| } |
| |
| // Tests that an animation with a curve timing function and multiple keyframes |
| // works as expected. |
| TEST(KeyframedAnimationCurveTest, CurveTimingMultipleKeyframes) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.f), 1.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(2.f), 3.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(3.f), 6.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(4.f), 9.f, nullptr)); |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, 0.f, 0.5f, 1.f)); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_NEAR(0.42f, curve->GetValue(base::Seconds(1.f)), 0.005f); |
| EXPECT_NEAR(1.f, curve->GetValue(base::Seconds(1.455f)), 0.005f); |
| EXPECT_FLOAT_EQ(3.f, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_NEAR(8.72f, curve->GetValue(base::Seconds(3.5f)), 0.01f); |
| EXPECT_FLOAT_EQ(9.f, curve->GetValue(base::Seconds(4.f))); |
| EXPECT_FLOAT_EQ(9.f, curve->GetValue(base::Seconds(5.f))); |
| } |
| |
| // Tests that an animation with a curve timing function that overshoots works as |
| // expected. |
| TEST(KeyframedAnimationCurveTest, CurveTimingOvershootMultipeKeyframes) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.0), 1.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(2.0), 3.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(3.0), 6.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(4.0), 9.f, nullptr)); |
| // Curve timing function producing outputs outside of range [0,1]. |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, -0.5f, 0.5f, 1.5f)); |
| EXPECT_LE(curve->GetValue(base::Seconds(1.f)), |
| 0.f); // c(.25) < 0 |
| EXPECT_GE(curve->GetValue(base::Seconds(3.f)), |
| 9.f); // c(.75) > 1 |
| } |
| |
| // Tests that a float animation with multiple keys works with scaled duration. |
| TEST(KeyframedAnimationCurveTest, ScaledDuration) { |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 0.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(1.f), 1.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(2.f), 3.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(3.f), 6.f, nullptr)); |
| curve->AddKeyframe(FloatKeyframe::Create(base::Seconds(4.f), 9.f, nullptr)); |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.5f, 0.f, 0.5f, 1.f)); |
| |
| const double scale = 1000.0; |
| curve->set_scaled_duration(scale); |
| |
| EXPECT_DOUBLE_EQ(scale * 4, curve->Duration().InSecondsF()); |
| |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(scale * -1.f))); |
| EXPECT_FLOAT_EQ(0.f, curve->GetValue(base::Seconds(scale * 0.f))); |
| EXPECT_NEAR(0.42f, curve->GetValue(base::Seconds(scale * 1.f)), 0.005f); |
| EXPECT_NEAR(1.f, curve->GetValue(base::Seconds(scale * 1.455f)), 0.005f); |
| EXPECT_FLOAT_EQ(3.f, curve->GetValue(base::Seconds(scale * 2.f))); |
| EXPECT_NEAR(8.72f, curve->GetValue(base::Seconds(scale * 3.5f)), 0.01f); |
| EXPECT_FLOAT_EQ(9.f, curve->GetValue(base::Seconds(scale * 4.f))); |
| EXPECT_FLOAT_EQ(9.f, curve->GetValue(base::Seconds(scale * 5.f))); |
| } |
| |
| // Tests that a size animation with one keyframe works as expected. |
| TEST(KeyframedAnimationCurveTest, OneSizeKeyFrame) { |
| gfx::SizeF size = gfx::SizeF(100, 100); |
| std::unique_ptr<KeyframedSizeAnimationCurve> curve( |
| KeyframedSizeAnimationCurve::Create()); |
| curve->AddKeyframe(SizeKeyframe::Create(base::TimeDelta(), size, nullptr)); |
| |
| EXPECT_SIZEF_EQ(size, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SIZEF_EQ(size, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SIZEF_EQ(size, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_SIZEF_EQ(size, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_SIZEF_EQ(size, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a size animation with two keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, TwoSizeKeyFrame) { |
| gfx::SizeF size_a = gfx::SizeF(100, 100); |
| gfx::SizeF size_b = gfx::SizeF(100, 0); |
| gfx::SizeF size_midpoint = gfx::Tween::SizeFValueBetween(0.5, size_a, size_b); |
| std::unique_ptr<KeyframedSizeAnimationCurve> curve( |
| KeyframedSizeAnimationCurve::Create()); |
| curve->AddKeyframe(SizeKeyframe::Create(base::TimeDelta(), size_a, nullptr)); |
| curve->AddKeyframe(SizeKeyframe::Create(base::Seconds(1.0), size_b, nullptr)); |
| |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SIZEF_EQ(size_midpoint, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a size animation with three keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, ThreeSizeKeyFrame) { |
| gfx::SizeF size_a = gfx::SizeF(100, 100); |
| gfx::SizeF size_b = gfx::SizeF(100, 0); |
| gfx::SizeF size_c = gfx::SizeF(200, 0); |
| gfx::SizeF size_midpoint1 = |
| gfx::Tween::SizeFValueBetween(0.5, size_a, size_b); |
| gfx::SizeF size_midpoint2 = |
| gfx::Tween::SizeFValueBetween(0.5, size_b, size_c); |
| std::unique_ptr<KeyframedSizeAnimationCurve> curve( |
| KeyframedSizeAnimationCurve::Create()); |
| curve->AddKeyframe(SizeKeyframe::Create(base::TimeDelta(), size_a, nullptr)); |
| curve->AddKeyframe(SizeKeyframe::Create(base::Seconds(1.0), size_b, nullptr)); |
| curve->AddKeyframe(SizeKeyframe::Create(base::Seconds(2.0), size_c, nullptr)); |
| |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SIZEF_EQ(size_midpoint1, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_SIZEF_EQ(size_midpoint2, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_SIZEF_EQ(size_c, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_SIZEF_EQ(size_c, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a size animation with multiple keys at a given time works sanely. |
| TEST(KeyframedAnimationCurveTest, RepeatedSizeKeyFrame) { |
| gfx::SizeF size_a = gfx::SizeF(100, 64); |
| gfx::SizeF size_b = gfx::SizeF(100, 192); |
| |
| std::unique_ptr<KeyframedSizeAnimationCurve> curve( |
| KeyframedSizeAnimationCurve::Create()); |
| curve->AddKeyframe(SizeKeyframe::Create(base::TimeDelta(), size_a, nullptr)); |
| curve->AddKeyframe(SizeKeyframe::Create(base::Seconds(1.0), size_a, nullptr)); |
| curve->AddKeyframe(SizeKeyframe::Create(base::Seconds(1.0), size_b, nullptr)); |
| curve->AddKeyframe(SizeKeyframe::Create(base::Seconds(2.0), size_b, nullptr)); |
| |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_SIZEF_EQ(size_a, curve->GetValue(base::Seconds(0.5f))); |
| |
| gfx::SizeF value = curve->GetValue(base::Seconds(1.0f)); |
| EXPECT_FLOAT_EQ(100.0f, value.width()); |
| EXPECT_LE(64.0f, value.height()); |
| EXPECT_GE(192.0f, value.height()); |
| |
| EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_SIZEF_EQ(size_b, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a rect animation with one keyframe works as expected. |
| TEST(KeyframedAnimationCurveTest, OneRectKeyFrame) { |
| gfx::Rect rect = gfx::Rect(1, 2, 101, 102); |
| std::unique_ptr<KeyframedRectAnimationCurve> curve( |
| KeyframedRectAnimationCurve::Create()); |
| curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect, nullptr)); |
| |
| EXPECT_EQ(rect, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_EQ(rect, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_EQ(rect, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_EQ(rect, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_EQ(rect, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a rect animation with two keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, TwoRectKeyFrame) { |
| gfx::Rect rect_a = gfx::Rect(1, 2, 100, 100); |
| gfx::Rect rect_b = gfx::Rect(11, 12, 100, 0); |
| gfx::Rect rect_midpoint = gfx::Tween::RectValueBetween(0.5, rect_a, rect_b); |
| std::unique_ptr<KeyframedRectAnimationCurve> curve( |
| KeyframedRectAnimationCurve::Create()); |
| curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect_a, nullptr)); |
| curve->AddKeyframe(RectKeyframe::Create(base::Seconds(1.0), rect_b, nullptr)); |
| |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_EQ(rect_midpoint, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_EQ(rect_b, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_EQ(rect_b, curve->GetValue(base::Seconds(2.f))); |
| } |
| |
| // Tests that a rect animation with three keyframes works as expected. |
| TEST(KeyframedAnimationCurveTest, ThreeRectKeyFrame) { |
| gfx::Rect rect_a = gfx::Rect(1, 2, 100, 100); |
| gfx::Rect rect_b = gfx::Rect(11, 12, 100, 0); |
| gfx::Rect rect_c = gfx::Rect(101, 102, 200, 0); |
| gfx::Rect rect_midpoint1 = gfx::Tween::RectValueBetween(0.5, rect_a, rect_b); |
| gfx::Rect rect_midpoint2 = gfx::Tween::RectValueBetween(0.5, rect_b, rect_c); |
| std::unique_ptr<KeyframedRectAnimationCurve> curve( |
| KeyframedRectAnimationCurve::Create()); |
| curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect_a, nullptr)); |
| curve->AddKeyframe(RectKeyframe::Create(base::Seconds(1.0), rect_b, nullptr)); |
| curve->AddKeyframe(RectKeyframe::Create(base::Seconds(2.0), rect_c, nullptr)); |
| |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_EQ(rect_midpoint1, curve->GetValue(base::Seconds(0.5f))); |
| EXPECT_EQ(rect_b, curve->GetValue(base::Seconds(1.f))); |
| EXPECT_EQ(rect_midpoint2, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_EQ(rect_c, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_EQ(rect_c, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that a rect animation with multiple keys at a given time works sanely. |
| TEST(KeyframedAnimationCurveTest, RepeatedRectKeyFrame) { |
| gfx::Rect rect_a = gfx::Rect(10, 20, 100, 64); |
| gfx::Rect rect_b = gfx::Rect(30, 40, 100, 192); |
| |
| std::unique_ptr<KeyframedRectAnimationCurve> curve( |
| KeyframedRectAnimationCurve::Create()); |
| curve->AddKeyframe(RectKeyframe::Create(base::TimeDelta(), rect_a, nullptr)); |
| curve->AddKeyframe(RectKeyframe::Create(base::Seconds(1.0), rect_a, nullptr)); |
| curve->AddKeyframe(RectKeyframe::Create(base::Seconds(1.0), rect_b, nullptr)); |
| curve->AddKeyframe(RectKeyframe::Create(base::Seconds(2.0), rect_b, nullptr)); |
| |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(-1.f))); |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(0.f))); |
| EXPECT_EQ(rect_a, curve->GetValue(base::Seconds(0.5f))); |
| |
| gfx::Rect value = curve->GetValue(base::Seconds(1.0f)); |
| EXPECT_EQ(100, value.width()); |
| EXPECT_LE(64, value.height()); |
| EXPECT_GE(192, value.height()); |
| EXPECT_LE(10, value.x()); |
| EXPECT_GE(30, value.x()); |
| EXPECT_LE(20, value.y()); |
| EXPECT_GE(40, value.y()); |
| |
| EXPECT_EQ(rect_b, curve->GetValue(base::Seconds(1.5f))); |
| EXPECT_EQ(rect_b, curve->GetValue(base::Seconds(2.f))); |
| EXPECT_EQ(rect_b, curve->GetValue(base::Seconds(3.f))); |
| } |
| |
| // Tests that the computing of tick interval for STEPS TimingFunction works |
| // correctly. |
| TEST(KeyFrameAnimationCurveTest, TickIntervalForStepsTimingFunction) { |
| double kDuration = 1.0; |
| int kNumSteps = 10; |
| std::unique_ptr<KeyframedFloatAnimationCurve> curve( |
| KeyframedFloatAnimationCurve::Create()); |
| curve->AddKeyframe(FloatKeyframe::Create(base::TimeDelta(), 2.0, nullptr)); |
| curve->AddKeyframe( |
| FloatKeyframe::Create(base::Seconds(kDuration), 4.0, nullptr)); |
| curve->SetTimingFunction(StepsTimingFunction::Create( |
| kNumSteps, StepsTimingFunction::StepPosition::START)); |
| EXPECT_FLOAT_EQ(kDuration / kNumSteps, curve->TickInterval().InSecondsF()); |
| } |
| |
| // Tests that the computing of tick interval for CUBIC_BEZIER TimingFunction |
| // works correctly. |
| TEST(KeyFrameAnimationCurveTest, TickIntervalForCubicBezierTimingFunction) { |
| SkColor color_a = SkColorSetARGB(255, 255, 0, 0); |
| SkColor color_b = SkColorSetARGB(255, 0, 255, 0); |
| double kDuration = 1.0; |
| std::unique_ptr<KeyframedColorAnimationCurve> curve( |
| KeyframedColorAnimationCurve::Create()); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::TimeDelta(), color_a, nullptr)); |
| curve->AddKeyframe( |
| ColorKeyframe::Create(base::Seconds(kDuration), color_b, nullptr)); |
| curve->SetTimingFunction( |
| CubicBezierTimingFunction::Create(0.75f, 0.25f, 0.9f, 0.4f)); |
| EXPECT_FLOAT_EQ(0, curve->TickInterval().InSecondsF()); |
| } |
| |
| // Tests that the computing of tick interval for LINEAR TimingFunction works |
| // correctly. |
| TEST(KeyFrameAnimationCurveTest, TickIntervalForLinearTimingFunction) { |
| gfx::SizeF size_a = gfx::SizeF(100, 64); |
| gfx::SizeF size_b = gfx::SizeF(100, 192); |
| gfx::SizeF size_c = gfx::SizeF(100, 218); |
| gfx::SizeF size_d = gfx::SizeF(100, 321); |
| double kDurationAB = 1.0; |
| double kDurationBC = 2.0; |
| double kDurationCD = 1.0; |
| int kNumStepsAB = 10; |
| int kNumStepsBC = 100; |
| std::unique_ptr<KeyframedSizeAnimationCurve> curve( |
| KeyframedSizeAnimationCurve::Create()); |
| curve->AddKeyframe(SizeKeyframe::Create( |
| base::TimeDelta(), size_a, |
| StepsTimingFunction::Create(kNumStepsAB, |
| StepsTimingFunction::StepPosition::START))); |
| curve->AddKeyframe(SizeKeyframe::Create( |
| base::Seconds(kDurationAB), size_b, |
| StepsTimingFunction::Create(kNumStepsBC, |
| StepsTimingFunction::StepPosition::START))); |
| curve->AddKeyframe(SizeKeyframe::Create( |
| base::Seconds(kDurationAB + kDurationBC), size_c, nullptr)); |
| |
| // Without explicitly setting a timing function, the default is linear. |
| EXPECT_FLOAT_EQ(kDurationBC / kNumStepsBC, |
| curve->TickInterval().InSecondsF()); |
| curve->SetTimingFunction(LinearTimingFunction::Create()); |
| EXPECT_FLOAT_EQ(kDurationBC / kNumStepsBC, |
| curve->TickInterval().InSecondsF()); |
| |
| // Add a 4th keyframe. |
| // Now the 3rd keyframe's "easing" into the 4th isn't STEPS. |
| curve->AddKeyframe(SizeKeyframe::Create( |
| base::Seconds(kDurationAB + kDurationBC + kDurationCD), size_d, nullptr)); |
| EXPECT_FLOAT_EQ(0, curve->TickInterval().InSecondsF()); |
| } |
| |
| } // namespace |
| } // namespace gfx |