| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/ambient/ui/ambient_animation_attribution_transformer.h" |
| |
| #include <memory> |
| #include <string> |
| #include <string_view> |
| |
| #include "ash/ambient/test/ambient_test_util.h" |
| #include "base/check.h" |
| |
| #include "cc/paint/skottie_resource_metadata.h" |
| #include "cc/paint/skottie_text_property_value.h" |
| #include "cc/paint/skottie_transform_property_value.h" |
| #include "cc/paint/skottie_wrapper.h" |
| #include "cc/test/lottie_test_data.h" |
| #include "cc/test/skia_common.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/geometry/point.h" |
| #include "ui/gfx/geometry/point_f.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/rect_conversions.h" |
| #include "ui/gfx/geometry/rect_f.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "ui/gfx/geometry/test/geometry_util.h" |
| #include "ui/gfx/geometry/vector2d_f.h" |
| #include "ui/lottie/animation.h" |
| #include "ui/views/controls/animated_image_view.h" |
| |
| namespace ash { |
| namespace { |
| |
| using ::testing::Eq; |
| |
| constexpr float kTextBoxCoordinatesTolerance = 0.5f; |
| |
| class AmbientAnimationAttributionTransformerTest : public ::testing::Test { |
| protected: |
| AmbientAnimationAttributionTransformerTest() |
| : AmbientAnimationAttributionTransformerTest( |
| GenerateLottieCustomizableIdForTesting(/*unique_id=*/1), |
| GenerateLottieCustomizableIdForTesting(/*unique_id=*/2)) {} |
| |
| AmbientAnimationAttributionTransformerTest(std::string_view text_node_1_name, |
| std::string_view text_node_2_name) |
| : text_node_1_name_(text_node_1_name), |
| text_node_2_name_(text_node_2_name) { |
| view_.SetAnimatedImage(std::make_unique<lottie::Animation>( |
| cc::CreateSkottieFromString(cc::CreateCustomLottieDataWith2TextNodes( |
| text_node_1_name_, text_node_2_name_)))); |
| view_.SetHorizontalAlignment(views::ImageViewBase::Alignment::kCenter); |
| view_.SetVerticalAlignment(views::ImageViewBase::Alignment::kCenter); |
| animation_original_size_ = view_.animated_image()->GetOriginalSize(); |
| } |
| |
| gfx::RectF GetAbsoluteTextBoxCoordinates(std::string_view text_node_name) { |
| cc::SkottieResourceIdHash text_node_id = |
| cc::HashSkottieResourceId(text_node_name); |
| cc::SkottieTransformPropertyValueMap transform_properties = |
| view_.animated_image()->skottie()->GetCurrentTransformPropertyValues(); |
| CHECK(transform_properties.contains(text_node_id)) |
| << "Transform property not found for " << text_node_name; |
| const cc::SkottieTextPropertyValueMap& text_map = |
| view_.animated_image()->text_map(); |
| CHECK(text_map.contains(text_node_id)) |
| << "Text property not found for " << text_node_name; |
| return text_map.at(text_node_id).box() + |
| transform_properties.at(text_node_id).position.OffsetFromOrigin(); |
| } |
| |
| const std::string text_node_1_name_; |
| const std::string text_node_2_name_; |
| views::AnimatedImageView view_; |
| gfx::Size animation_original_size_; |
| }; |
| |
| class AmbientAnimationAttributionTransformerTestWithStaticText |
| : public AmbientAnimationAttributionTransformerTest { |
| protected: |
| AmbientAnimationAttributionTransformerTestWithStaticText() |
| : AmbientAnimationAttributionTransformerTest( |
| cc::kLottieDataWith2TextNode1, |
| cc::kLottieDataWith2TextNode2) {} |
| }; |
| |
| TEST_F(AmbientAnimationAttributionTransformerTest, ViewSmallerThanAnimation) { |
| const gfx::Rect view_bounds(animation_original_size_.width() / 2, |
| animation_original_size_.height() / 2); |
| view_.SetBoundsRect(view_bounds); |
| AmbientAnimationAttributionTransformer::TransformTextBox(view_); |
| |
| gfx::RectF expected_box; |
| expected_box.set_width((animation_original_size_.width() / 4) + |
| (view_bounds.width() - 24)); |
| expected_box.set_height(cc::kLottieDataWith2TextNode1Box.height()); |
| expected_box.set_x(0); |
| expected_box.set_y((animation_original_size_.height() / 4) + |
| (view_bounds.height() - 24 - expected_box.height())); |
| EXPECT_RECTF_NEAR(GetAbsoluteTextBoxCoordinates(text_node_1_name_), |
| expected_box, kTextBoxCoordinatesTolerance); |
| |
| expected_box.set_height(cc::kLottieDataWith2TextNode2Box.height()); |
| expected_box.set_y((animation_original_size_.height() / 4) + |
| (view_bounds.height() - 24 - expected_box.height())); |
| EXPECT_RECTF_NEAR(GetAbsoluteTextBoxCoordinates(text_node_2_name_), |
| expected_box, kTextBoxCoordinatesTolerance); |
| } |
| |
| TEST_F(AmbientAnimationAttributionTransformerTest, ViewLargerThanAnimation) { |
| const gfx::Rect view_bounds(animation_original_size_.width() * 2, |
| animation_original_size_.height() * 2); |
| view_.SetBoundsRect(view_bounds); |
| AmbientAnimationAttributionTransformer::TransformTextBox(view_); |
| gfx::RectF expected_box; |
| expected_box.set_width(animation_original_size_.width()); |
| expected_box.set_height(cc::kLottieDataWith2TextNode1Box.height()); |
| expected_box.set_x(0); |
| expected_box.set_y(animation_original_size_.height() - expected_box.height()); |
| EXPECT_RECTF_NEAR(GetAbsoluteTextBoxCoordinates(text_node_1_name_), |
| expected_box, kTextBoxCoordinatesTolerance); |
| } |
| |
| TEST_F(AmbientAnimationAttributionTransformerTestWithStaticText, |
| ViewLargerThanAnimation) { |
| view_.SetBoundsRect(gfx::Rect(animation_original_size_)); |
| AmbientAnimationAttributionTransformer::TransformTextBox(view_); |
| // Static text nodes shouldn't change. |
| EXPECT_RECTF_EQ(view_.animated_image() |
| ->text_map() |
| .at(cc::HashSkottieResourceId(text_node_1_name_)) |
| .box(), |
| cc::kLottieDataWith2TextNode1Box); |
| EXPECT_RECTF_EQ(view_.animated_image() |
| ->text_map() |
| .at(cc::HashSkottieResourceId(text_node_2_name_)) |
| .box(), |
| cc::kLottieDataWith2TextNode2Box); |
| } |
| |
| } // namespace |
| } // namespace ash |