| // Copyright 2015 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <cmath> |
| |
| #include "base/time.h" |
| #include "cobalt/cssom/calc_value.h" |
| #include "cobalt/cssom/css_transition.h" |
| #include "cobalt/cssom/interpolate_property_value.h" |
| #include "cobalt/cssom/keyword_value.h" |
| #include "cobalt/cssom/length_value.h" |
| #include "cobalt/cssom/matrix_function.h" |
| #include "cobalt/cssom/number_value.h" |
| #include "cobalt/cssom/property_definitions.h" |
| #include "cobalt/cssom/rgba_color_value.h" |
| #include "cobalt/cssom/rotate_function.h" |
| #include "cobalt/cssom/scale_function.h" |
| #include "cobalt/cssom/transform_function_list_value.h" |
| #include "cobalt/cssom/transform_matrix_function_value.h" |
| #include "cobalt/cssom/translate_function.h" |
| #include "cobalt/math/transform_2d.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace cobalt { |
| namespace cssom { |
| |
| namespace { |
| const float kErrorEpsilon = 0.00015f; |
| |
| // Helper function to animate a propertyby a given progress between a given |
| // start and end point. The aniamted value is returned, casted to the passed in |
| // template type parameter. |
| template <typename T> |
| scoped_refptr<T> InterpolatePropertyTyped( |
| float progress, const scoped_refptr<PropertyValue>& start, |
| const scoped_refptr<PropertyValue>& end) { |
| scoped_refptr<PropertyValue> interpolated = |
| InterpolatePropertyValue(progress, start, end); |
| |
| scoped_refptr<T> interpolated_with_type = |
| dynamic_cast<T*>(interpolated.get()); |
| DCHECK(interpolated_with_type); |
| |
| return interpolated_with_type; |
| } |
| } // namespace |
| |
| TEST(InterpolatePropertyValueTest, LengthValuesInterpolate) { |
| scoped_refptr<LengthValue> interpolated = |
| InterpolatePropertyTyped<LengthValue>(0.5f, |
| new LengthValue(0.0f, kPixelsUnit), |
| new LengthValue(4.0f, kPixelsUnit)); |
| |
| EXPECT_NEAR(interpolated->value(), 2.0f, kErrorEpsilon); |
| EXPECT_EQ(interpolated->unit(), kPixelsUnit); |
| } |
| |
| TEST(InterpolatePropertyValueTest, NumberValuesInterpolate) { |
| scoped_refptr<NumberValue> interpolated = |
| InterpolatePropertyTyped<NumberValue>(0.5f, new NumberValue(0.0f), |
| new NumberValue(4.0f)); |
| |
| EXPECT_NEAR(interpolated->value(), 2.0f, kErrorEpsilon); |
| } |
| |
| TEST(InterpolatePropertyValueTest, RGBAColorValuesInterpolate) { |
| scoped_refptr<RGBAColorValue> interpolated = |
| InterpolatePropertyTyped<RGBAColorValue>( |
| 0.25, new RGBAColorValue(0, 100, 0, 100), |
| new RGBAColorValue(100, 0, 100, 0)); |
| |
| EXPECT_EQ(25, interpolated->r()); |
| EXPECT_EQ(75, interpolated->g()); |
| EXPECT_EQ(25, interpolated->b()); |
| EXPECT_EQ(75, interpolated->a()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TransformFromNoneToNoneValuesInterpolate) { |
| scoped_refptr<KeywordValue> interpolated = |
| InterpolatePropertyTyped<KeywordValue>(0.5f, KeywordValue::GetNone(), |
| KeywordValue::GetNone()); |
| |
| EXPECT_EQ(KeywordValue::kNone, interpolated->value()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TransformSingleRotateValuesInterpolate) { |
| struct MakeSingleRotateTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new RotateFunction(1.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new RotateFunction(2.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleRotateTransform::Start(), |
| MakeSingleRotateTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const RotateFunction* single_function = |
| dynamic_cast<const RotateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_NEAR(single_function->clockwise_angle_in_radians(), 1.5f, |
| kErrorEpsilon); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TransformSingleScaleValuesInterpolate) { |
| struct MakeSingleScaleTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new ScaleFunction(1.0f, 2.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new ScaleFunction(3.0f, 4.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleScaleTransform::Start(), |
| MakeSingleScaleTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const ScaleFunction* single_function = |
| dynamic_cast<const ScaleFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_NEAR(single_function->x_factor(), 2.0f, kErrorEpsilon); |
| EXPECT_NEAR(single_function->y_factor(), 3.0f, kErrorEpsilon); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TransformFromNoneToScaleValuesInterpolate) { |
| struct MakeSingleScaleTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| return KeywordValue::GetNone(); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new ScaleFunction(5.0f, 9.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.25f, MakeSingleScaleTransform::Start(), |
| MakeSingleScaleTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const ScaleFunction* single_function = |
| dynamic_cast<const ScaleFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_NEAR(single_function->x_factor(), 2.0f, kErrorEpsilon); |
| EXPECT_NEAR(single_function->y_factor(), 3.0f, kErrorEpsilon); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TransformFromScaleToNoneValuesInterpolate) { |
| struct MakeSingleScaleTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new ScaleFunction(5.0f, 9.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| return KeywordValue::GetNone(); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.25f, MakeSingleScaleTransform::Start(), |
| MakeSingleScaleTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const ScaleFunction* single_function = |
| dynamic_cast<const ScaleFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_NEAR(single_function->x_factor(), 4.0f, kErrorEpsilon); |
| EXPECT_NEAR(single_function->y_factor(), 7.0f, kErrorEpsilon); |
| } |
| |
| void TestTransformSingleTranslateValuesAnimate(TranslateFunction::Axis axis) { |
| struct MakeSingleTranslateTransform { |
| static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new TranslateFunction(axis, new LengthValue(1.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new TranslateFunction(axis, new LengthValue(2.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleTranslateTransform::Start(axis), |
| MakeSingleTranslateTransform::End(axis)); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| const TranslateFunction* single_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_NEAR(single_function->offset_as_length()->value(), 1.5f, |
| kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, single_function->offset_as_length()->unit()); |
| EXPECT_EQ(axis, single_function->axis()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TransformSingleTranslateXValuesInterpolate) { |
| TestTransformSingleTranslateValuesAnimate(TranslateFunction::kXAxis); |
| } |
| TEST(InterpolatePropertyValueTest, TransformSingleTranslateYValuesInterpolate) { |
| TestTransformSingleTranslateValuesAnimate(TranslateFunction::kYAxis); |
| } |
| TEST(InterpolatePropertyValueTest, TransformSingleTranslateZValuesInterpolate) { |
| TestTransformSingleTranslateValuesAnimate(TranslateFunction::kZAxis); |
| } |
| |
| void TestTransformTranslateFromLengthToPercentageValuesAnimate( |
| TranslateFunction::Axis axis) { |
| struct MakeSingleTranslateTransform { |
| static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new TranslateFunction(axis, new LengthValue(1.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new TranslateFunction(axis, new PercentageValue(0.5f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleTranslateTransform::Start(axis), |
| MakeSingleTranslateTransform::End(axis)); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| const TranslateFunction* single_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| ASSERT_EQ(TranslateFunction::kCalc, single_function->offset_type()); |
| EXPECT_NEAR(0.5f, single_function->offset_as_calc()->length_value()->value(), |
| kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, |
| single_function->offset_as_calc()->length_value()->unit()); |
| EXPECT_NEAR(0.25f, |
| single_function->offset_as_calc()->percentage_value()->value(), |
| kErrorEpsilon); |
| EXPECT_EQ(axis, single_function->axis()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| TransformTranslateXFromLengthToPercentageValuesAnimate) { |
| TestTransformTranslateFromLengthToPercentageValuesAnimate( |
| TranslateFunction::kXAxis); |
| } |
| TEST(InterpolatePropertyValueTest, |
| TransformTranslateYFromLengthToPercentageValuesAnimate) { |
| TestTransformTranslateFromLengthToPercentageValuesAnimate( |
| TranslateFunction::kYAxis); |
| } |
| TEST(InterpolatePropertyValueTest, |
| TransformTranslateZFromLengthToPercentageValuesAnimate) { |
| TestTransformTranslateFromLengthToPercentageValuesAnimate( |
| TranslateFunction::kZAxis); |
| } |
| |
| void TestTransformTranslateCalcValuesAnimate(TranslateFunction::Axis axis) { |
| struct MakeSingleTranslateTransform { |
| static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| axis, new CalcValue(new LengthValue(1.0f, kPixelsUnit), |
| new PercentageValue(0.2f)))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| axis, new CalcValue(new LengthValue(2.0f, kPixelsUnit), |
| new PercentageValue(0.4f)))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleTranslateTransform::Start(axis), |
| MakeSingleTranslateTransform::End(axis)); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| const TranslateFunction* single_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| ASSERT_EQ(TranslateFunction::kCalc, single_function->offset_type()); |
| EXPECT_NEAR(1.5f, single_function->offset_as_calc()->length_value()->value(), |
| kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, |
| single_function->offset_as_calc()->length_value()->unit()); |
| EXPECT_NEAR(0.3f, |
| single_function->offset_as_calc()->percentage_value()->value(), |
| kErrorEpsilon); |
| EXPECT_EQ(axis, single_function->axis()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, TestTransformTranslateXCalcValuesAnimate) { |
| TestTransformTranslateCalcValuesAnimate(TranslateFunction::kXAxis); |
| } |
| TEST(InterpolatePropertyValueTest, TestTransformTranslateYCalcValuesAnimate) { |
| TestTransformTranslateCalcValuesAnimate(TranslateFunction::kYAxis); |
| } |
| TEST(InterpolatePropertyValueTest, TestTransformTranslateZCalcValuesAnimate) { |
| TestTransformTranslateCalcValuesAnimate(TranslateFunction::kZAxis); |
| } |
| |
| void TestTransformFromTranslateToNoneValuesAnimate( |
| TranslateFunction::Axis axis) { |
| struct MakeSingleTranslateTransform { |
| static scoped_refptr<PropertyValue> Start(TranslateFunction::Axis axis) { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new TranslateFunction(axis, new LengthValue(1.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| return KeywordValue::GetNone(); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleTranslateTransform::Start(axis), |
| MakeSingleTranslateTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| const TranslateFunction* single_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_NEAR(single_function->offset_as_length()->value(), 0.5f, |
| kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, single_function->offset_as_length()->unit()); |
| EXPECT_EQ(axis, single_function->axis()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| TransformFromTranslateXToNoneValuesInterpolate) { |
| TestTransformFromTranslateToNoneValuesAnimate(TranslateFunction::kXAxis); |
| } |
| TEST(InterpolatePropertyValueTest, |
| TransformFromTranslateYToNoneValuesInterpolate) { |
| TestTransformFromTranslateToNoneValuesAnimate(TranslateFunction::kYAxis); |
| } |
| TEST(InterpolatePropertyValueTest, |
| TransformFromTranslateZToNoneValuesInterpolate) { |
| TestTransformFromTranslateToNoneValuesAnimate(TranslateFunction::kZAxis); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| CanAnimateTransformListWithMultipleElementsButSameSizeAndTypes) { |
| struct MakeSingleScaleTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new RotateFunction(1.0f)); |
| functions.push_back(new ScaleFunction(1.0f, 2.0f)); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, new LengthValue(3.0f, kPixelsUnit))); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kYAxis, new LengthValue(4.0f, kPixelsUnit))); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kZAxis, new LengthValue(5.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new RotateFunction(2.0f)); |
| functions.push_back(new ScaleFunction(7.0f, 8.0f)); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, new LengthValue(9.0f, kPixelsUnit))); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kYAxis, new LengthValue(10.0f, kPixelsUnit))); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kZAxis, new LengthValue(11.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleScaleTransform::Start(), |
| MakeSingleScaleTransform::End()); |
| |
| ASSERT_EQ(5, interpolated->value().size()); |
| |
| const RotateFunction* first_function = |
| dynamic_cast<const RotateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(first_function); |
| EXPECT_NEAR(first_function->clockwise_angle_in_radians(), 1.5f, |
| kErrorEpsilon); |
| |
| const ScaleFunction* second_function = |
| dynamic_cast<const ScaleFunction*>(interpolated->value()[1]); |
| ASSERT_TRUE(second_function); |
| EXPECT_NEAR(second_function->x_factor(), 4.0f, kErrorEpsilon); |
| EXPECT_NEAR(second_function->y_factor(), 5.0f, kErrorEpsilon); |
| |
| const TranslateFunction* third_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[2]); |
| ASSERT_TRUE(third_function); |
| EXPECT_NEAR(third_function->offset_as_length()->value(), 6.0f, kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, third_function->offset_as_length()->unit()); |
| |
| const TranslateFunction* fourth_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[3]); |
| ASSERT_TRUE(fourth_function); |
| EXPECT_NEAR(fourth_function->offset_as_length()->value(), 7.0f, |
| kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, fourth_function->offset_as_length()->unit()); |
| |
| const TranslateFunction* fifth_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[4]); |
| ASSERT_TRUE(fifth_function); |
| EXPECT_NEAR(fifth_function->offset_as_length()->value(), 8.0f, kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, fifth_function->offset_as_length()->unit()); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| TransformSingleRotationMatrixValuesInterpolate) { |
| struct MakeSingleMatrixTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new MatrixFunction(math::RotateMatrix(0.0f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new MatrixFunction(math::RotateMatrix(static_cast<float>(M_PI / 2)))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleMatrixTransform::Start(), |
| MakeSingleMatrixTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const MatrixFunction* single_function = |
| dynamic_cast<const MatrixFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_TRUE(single_function->value().IsNear( |
| math::RotateMatrix(static_cast<float>(M_PI / 4)), kErrorEpsilon)); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| TransformSingleScaleMatrixValuesInterpolate) { |
| struct MakeSingleMatrixTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new MatrixFunction(math::ScaleMatrix(2.0f, 1.0f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new MatrixFunction(math::ScaleMatrix(4.0f, 2.0f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleMatrixTransform::Start(), |
| MakeSingleMatrixTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const MatrixFunction* single_function = |
| dynamic_cast<const MatrixFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_TRUE(single_function->value().IsNear(math::ScaleMatrix(3.0f, 1.5f), |
| kErrorEpsilon)); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| TransformSingleTranslateMatrixValuesInterpolate) { |
| struct MakeSingleMatrixTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new MatrixFunction(math::TranslateMatrix(2.0f, 1.0f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back( |
| new MatrixFunction(math::TranslateMatrix(4.0f, 2.0f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeSingleMatrixTransform::Start(), |
| MakeSingleMatrixTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| |
| const MatrixFunction* single_function = |
| dynamic_cast<const MatrixFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| |
| EXPECT_TRUE(single_function->value().IsNear(math::TranslateMatrix(3.0f, 1.5f), |
| kErrorEpsilon)); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| MultipleMismatchedTransformValuesInterpolate) { |
| struct MakeMultipleMismatchedTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, new LengthValue(2.0f, kPixelsUnit))); |
| functions.push_back(new ScaleFunction(2.0f, 1.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, new LengthValue(4.0f, kPixelsUnit))); |
| functions.push_back(new RotateFunction(static_cast<float>(M_PI / 2))); |
| functions.push_back(new ScaleFunction(4.0f, 2.0f)); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| // Since the original transform list had mismatched types, the result should |
| // be a transform matrix. |
| scoped_refptr<TransformMatrixFunctionValue> interpolated = |
| InterpolatePropertyTyped<TransformMatrixFunctionValue>( |
| 0.75f, MakeMultipleMismatchedTransform::Start(), |
| MakeMultipleMismatchedTransform::End()); |
| EXPECT_TRUE(interpolated->value().percentage_fields_zero()); |
| EXPECT_TRUE( |
| interpolated->value() |
| .ToMatrix3F(math::SizeF()) |
| .IsNear(math::TranslateMatrix(3.5f, 0.0f) * |
| math::RotateMatrix(-static_cast<float>(M_PI * 3 / 8)) * |
| math::ScaleMatrix(3.5f, 1.75f), |
| kErrorEpsilon)); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| RotationTransformMatrixTransitionsFromTransitions) { |
| // Transition from a rotation transformation of 45 degrees to a translate |
| // transformation of 0 (i.e. identity). Since they are of different types, |
| // we will invoke the "decompose to a matrix" path of transitioning a |
| // transform, and then we c an simply test for the correct rotation value. |
| struct MakeMultipleMismatchedTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, new LengthValue(0.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new RotateFunction(static_cast<float>(M_PI / 2))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| // Since the original transform list had mismatched types, the result should |
| // be a matrix. |
| scoped_refptr<TransformMatrixFunctionValue> interpolated = |
| InterpolatePropertyTyped<TransformMatrixFunctionValue>( |
| 0.5f, MakeMultipleMismatchedTransform::Start(), |
| MakeMultipleMismatchedTransform::End()); |
| |
| scoped_refptr<TransformMatrixFunctionValue> next_interpolated = |
| InterpolatePropertyTyped<TransformMatrixFunctionValue>( |
| 0.5f, interpolated, MakeMultipleMismatchedTransform::Start()); |
| |
| EXPECT_TRUE(next_interpolated->value().percentage_fields_zero()); |
| EXPECT_TRUE(next_interpolated->value() |
| .ToMatrix3F(math::SizeF()) |
| .IsNear(math::RotateMatrix(-static_cast<float>(M_PI / 8)), |
| kErrorEpsilon)); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| CanInterpolateFromTranslateLengthToTranslatePercentage) { |
| struct MakeMultipleMismatchedTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, new LengthValue(5.0f, kPixelsUnit))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction(TranslateFunction::kXAxis, |
| new PercentageValue(0.5f))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| scoped_refptr<TransformFunctionListValue> interpolated = |
| InterpolatePropertyTyped<TransformFunctionListValue>( |
| 0.5f, MakeMultipleMismatchedTransform::Start(), |
| MakeMultipleMismatchedTransform::End()); |
| |
| ASSERT_EQ(1, interpolated->value().size()); |
| const TranslateFunction* single_function = |
| dynamic_cast<const TranslateFunction*>(interpolated->value()[0]); |
| ASSERT_TRUE(single_function); |
| EXPECT_EQ(TranslateFunction::kXAxis, single_function->axis()); |
| |
| scoped_refptr<CalcValue> calc_value = single_function->offset_as_calc(); |
| EXPECT_NEAR(2.5f, calc_value->length_value()->value(), kErrorEpsilon); |
| EXPECT_EQ(kPixelsUnit, calc_value->length_value()->unit()); |
| EXPECT_NEAR(0.25f, calc_value->percentage_value()->value(), kErrorEpsilon); |
| } |
| |
| TEST(InterpolatePropertyValueTest, |
| CanInterpolateMatricesWithPercentageAndOffsets) { |
| struct MakeMultipleMismatchedTransform { |
| static scoped_refptr<PropertyValue> Start() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, |
| new CalcValue(new LengthValue(2.0f, kPixelsUnit), |
| new PercentageValue(0.2f)))); |
| functions.push_back(new RotateFunction(static_cast<float>(M_PI / 2))); |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kXAxis, |
| new CalcValue(new LengthValue(10.0f, kPixelsUnit), |
| new PercentageValue(1.0f)))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| static scoped_refptr<PropertyValue> End() { |
| TransformFunctionListValue::Builder functions; |
| functions.push_back(new TranslateFunction( |
| TranslateFunction::kYAxis, |
| new CalcValue(new LengthValue(5.0f, kPixelsUnit), |
| new PercentageValue(0.5f)))); |
| return new TransformFunctionListValue(functions.Pass()); |
| } |
| }; |
| |
| // Since the original transform list had mismatched types, the result should |
| // be a matrix. |
| scoped_refptr<TransformMatrixFunctionValue> interpolated = |
| InterpolatePropertyTyped<TransformMatrixFunctionValue>( |
| 0.5f, MakeMultipleMismatchedTransform::Start(), |
| MakeMultipleMismatchedTransform::End()); |
| |
| const TransformMatrix& value = interpolated->value(); |
| |
| EXPECT_NEAR(cos(M_PI / 4), value.offset_matrix().Get(0, 0), kErrorEpsilon); |
| EXPECT_NEAR(sin(M_PI / 4), value.offset_matrix().Get(1, 0), kErrorEpsilon); |
| EXPECT_NEAR(-sin(M_PI / 4), value.offset_matrix().Get(0, 1), kErrorEpsilon); |
| EXPECT_NEAR(cos(M_PI / 4), value.offset_matrix().Get(1, 1), kErrorEpsilon); |
| EXPECT_NEAR(1.0f, value.offset_matrix().Get(0, 2), kErrorEpsilon); |
| EXPECT_NEAR(7.5f, value.offset_matrix().Get(1, 2), kErrorEpsilon); |
| |
| EXPECT_NEAR(0.1f, value.width_percentage_translation().x(), kErrorEpsilon); |
| EXPECT_NEAR(0.5f, value.width_percentage_translation().y(), kErrorEpsilon); |
| EXPECT_NEAR(0.0f, value.height_percentage_translation().x(), kErrorEpsilon); |
| EXPECT_NEAR(0.25f, value.height_percentage_translation().y(), kErrorEpsilon); |
| } |
| |
| } // namespace cssom |
| } // namespace cobalt |