1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/layer_utils.h"
7 #include "cc/animation/transform_operations.h"
8 #include "cc/layers/layer_impl.h"
9 #include "cc/test/animation_test_common.h"
10 #include "cc/test/fake_impl_proxy.h"
11 #include "cc/test/fake_layer_tree_host_impl.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gfx/box_f.h"
14 #include "ui/gfx/test/gfx_util.h"
19 float diagonal(float width, float height) {
20 return std::sqrt(width * width + height * height);
23 class LayerUtilsGetAnimationBoundsTest : public testing::Test {
25 LayerUtilsGetAnimationBoundsTest()
26 : host_impl_(&proxy_),
27 root_(CreateThreeNodeTree(host_impl_)),
28 parent_(root_->children()[0]),
29 child_(parent_->children()[0]) {}
31 LayerImpl* root() { return root_.get(); }
32 LayerImpl* parent() { return parent_; }
33 LayerImpl* child() { return child_; }
36 static scoped_ptr<LayerImpl> CreateThreeNodeTree(
37 LayerTreeHostImpl& host_impl) {
38 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1);
39 root->AddChild(LayerImpl::Create(host_impl.active_tree(), 2));
41 ->AddChild(LayerImpl::Create(host_impl.active_tree(), 3));
46 FakeLayerTreeHostImpl host_impl_;
47 scoped_ptr<LayerImpl> root_;
52 TEST_F(LayerUtilsGetAnimationBoundsTest, ScaleRoot) {
53 double duration = 1.0;
55 TransformOperations start;
56 start.AppendScale(1.f, 1.f, 1.f);
57 TransformOperations end;
58 end.AppendScale(2.f, 2.f, 1.f);
59 AddAnimatedTransformToLayer(root(), duration, start, end);
61 root()->SetPosition(gfx::PointF());
62 parent()->SetPosition(gfx::PointF());
63 parent()->SetBounds(gfx::Size(350, 200));
65 child()->SetDrawsContent(true);
66 child()->draw_properties().screen_space_transform_is_animating = true;
67 child()->SetPosition(gfx::PointF(150.f, 50.f));
68 child()->SetBounds(gfx::Size(100, 200));
71 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
73 gfx::BoxF expected(150.f, 50.f, 0.f, 350.f, 450.f, 0.f);
74 EXPECT_BOXF_EQ(expected, box);
77 TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateParentLayer) {
78 double duration = 1.0;
80 TransformOperations start;
81 start.AppendTranslate(0.f, 0.f, 0.f);
82 TransformOperations end;
83 end.AppendTranslate(50.f, 50.f, 0.f);
84 AddAnimatedTransformToLayer(parent(), duration, start, end);
86 parent()->SetBounds(gfx::Size(350, 200));
88 child()->SetDrawsContent(true);
89 child()->draw_properties().screen_space_transform_is_animating = true;
90 child()->SetPosition(gfx::PointF(150.f, 50.f));
91 child()->SetBounds(gfx::Size(100, 200));
94 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
96 gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f);
97 EXPECT_BOXF_EQ(expected, box);
100 TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateChildLayer) {
101 double duration = 1.0;
103 TransformOperations start;
104 start.AppendTranslate(0.f, 0.f, 0.f);
105 TransformOperations end;
106 end.AppendTranslate(50.f, 50.f, 0.f);
107 AddAnimatedTransformToLayer(child(), duration, start, end);
109 parent()->SetBounds(gfx::Size(350, 200));
111 child()->SetDrawsContent(true);
112 child()->draw_properties().screen_space_transform_is_animating = true;
113 child()->SetPosition(gfx::PointF(150.f, 50.f));
114 child()->SetBounds(gfx::Size(100, 200));
117 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
118 EXPECT_TRUE(success);
119 gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f);
120 EXPECT_BOXF_EQ(expected, box);
123 TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateBothLayers) {
124 double duration = 1.0;
126 TransformOperations start;
127 start.AppendTranslate(0.f, 0.f, 0.f);
128 TransformOperations child_end;
129 child_end.AppendTranslate(50.f, 0.f, 0.f);
130 AddAnimatedTransformToLayer(parent(), duration, start, child_end);
132 TransformOperations grand_child_end;
133 grand_child_end.AppendTranslate(0.f, 50.f, 0.f);
134 AddAnimatedTransformToLayer(child(), duration, start, grand_child_end);
136 parent()->SetBounds(gfx::Size(350, 200));
138 child()->SetDrawsContent(true);
139 child()->draw_properties().screen_space_transform_is_animating = true;
140 child()->SetPosition(gfx::PointF(150.f, 50.f));
141 child()->SetBounds(gfx::Size(100, 200));
144 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
145 EXPECT_TRUE(success);
146 gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f);
147 EXPECT_BOXF_EQ(expected, box);
150 TEST_F(LayerUtilsGetAnimationBoundsTest, RotateXNoPerspective) {
151 double duration = 1.0;
153 TransformOperations start;
154 start.AppendRotate(1.f, 0.f, 0.f, 0.f);
155 TransformOperations end;
156 end.AppendRotate(1.f, 0.f, 0.f, 90.f);
157 AddAnimatedTransformToLayer(child(), duration, start, end);
159 parent()->SetBounds(gfx::Size(350, 200));
161 gfx::Size bounds(100, 100);
162 child()->SetDrawsContent(true);
163 child()->draw_properties().screen_space_transform_is_animating = true;
164 child()->SetPosition(gfx::PointF(150.f, 50.f));
165 child()->SetBounds(bounds);
168 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
169 EXPECT_TRUE(success);
170 gfx::BoxF expected(150.f, 50.f, -50.f, 100.f, 100.f, 100.f);
171 EXPECT_BOXF_EQ(expected, box);
174 TEST_F(LayerUtilsGetAnimationBoundsTest, RotateXWithPerspective) {
175 double duration = 1.0;
177 TransformOperations start;
178 start.AppendRotate(1.f, 0.f, 0.f, 0.f);
179 TransformOperations end;
180 end.AppendRotate(1.f, 0.f, 0.f, 90.f);
181 AddAnimatedTransformToLayer(child(), duration, start, end);
183 // Make the anchor point not the default 0.5 value and line up with the
184 // child center to make the math easier.
185 parent()->SetAnchorPoint(gfx::PointF(0.375f, 0.375f));
186 parent()->SetBounds(gfx::Size(400, 400));
188 gfx::Transform perspective;
189 perspective.ApplyPerspectiveDepth(100.f);
190 parent()->SetSublayerTransform(perspective);
192 gfx::Size bounds(100, 100);
193 child()->SetDrawsContent(true);
194 child()->draw_properties().screen_space_transform_is_animating = true;
195 child()->SetPosition(gfx::PointF(100.f, 100.f));
196 child()->SetBounds(bounds);
199 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
200 EXPECT_TRUE(success);
201 gfx::BoxF expected(50.f, 50.f, -33.333336f, 200.f, 200.f, 133.333344f);
202 EXPECT_BOXF_EQ(expected, box);
205 TEST_F(LayerUtilsGetAnimationBoundsTest, RotateZ) {
206 double duration = 1.0;
208 TransformOperations start;
209 start.AppendRotate(0.f, 0.f, 1.f, 0.f);
210 TransformOperations end;
211 end.AppendRotate(0.f, 0.f, 1.f, 90.f);
212 AddAnimatedTransformToLayer(child(), duration, start, end);
214 parent()->SetBounds(gfx::Size(350, 200));
216 gfx::Size bounds(100, 100);
217 child()->SetDrawsContent(true);
218 child()->draw_properties().screen_space_transform_is_animating = true;
219 child()->SetPosition(gfx::PointF(150.f, 50.f));
220 child()->SetBounds(bounds);
223 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
224 EXPECT_TRUE(success);
225 float diag = diagonal(bounds.width(), bounds.height());
226 gfx::BoxF expected(150.f + 0.5f * (bounds.width() - diag),
227 50.f + 0.5f * (bounds.height() - diag),
232 EXPECT_BOXF_EQ(expected, box);
235 TEST_F(LayerUtilsGetAnimationBoundsTest, MismatchedTransforms) {
236 double duration = 1.0;
238 TransformOperations start;
239 start.AppendTranslate(5, 6, 7);
240 TransformOperations end;
241 end.AppendRotate(0.f, 0.f, 1.f, 90.f);
242 AddAnimatedTransformToLayer(child(), duration, start, end);
244 parent()->SetBounds(gfx::Size(350, 200));
246 gfx::Size bounds(100, 100);
247 child()->SetDrawsContent(true);
248 child()->draw_properties().screen_space_transform_is_animating = true;
249 child()->SetPosition(gfx::PointF(150.f, 50.f));
250 child()->SetBounds(bounds);
253 bool success = LayerUtils::GetAnimationBounds(*child(), &box);
254 EXPECT_FALSE(success);