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. 4 5#include "cc/layers/layer_utils.h" 6 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 "cc/test/test_shared_bitmap_manager.h" 13#include "testing/gtest/include/gtest/gtest.h" 14#include "ui/gfx/box_f.h" 15#include "ui/gfx/test/gfx_util.h" 16 17namespace cc { 18namespace { 19 20float diagonal(float width, float height) { 21 return std::sqrt(width * width + height * height); 22} 23 24class LayerUtilsGetAnimationBoundsTest : public testing::Test { 25 public: 26 LayerUtilsGetAnimationBoundsTest() 27 : host_impl_(&proxy_, &shared_bitmap_manager_), 28 root_(CreateThreeNodeTree(host_impl_)), 29 parent_(root_->children()[0]), 30 child_(parent_->children()[0]) {} 31 32 LayerImpl* root() { return root_.get(); } 33 LayerImpl* parent() { return parent_; } 34 LayerImpl* child() { return child_; } 35 36 private: 37 static scoped_ptr<LayerImpl> CreateThreeNodeTree( 38 LayerTreeHostImpl& host_impl) { 39 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); 40 root->AddChild(LayerImpl::Create(host_impl.active_tree(), 2)); 41 root->children()[0] 42 ->AddChild(LayerImpl::Create(host_impl.active_tree(), 3)); 43 return root.Pass(); 44 } 45 46 FakeImplProxy proxy_; 47 TestSharedBitmapManager shared_bitmap_manager_; 48 FakeLayerTreeHostImpl host_impl_; 49 scoped_ptr<LayerImpl> root_; 50 LayerImpl* parent_; 51 LayerImpl* child_; 52}; 53 54TEST_F(LayerUtilsGetAnimationBoundsTest, ScaleRoot) { 55 double duration = 1.0; 56 57 TransformOperations start; 58 start.AppendScale(1.f, 1.f, 1.f); 59 TransformOperations end; 60 end.AppendScale(2.f, 2.f, 1.f); 61 AddAnimatedTransformToLayer(root(), duration, start, end); 62 63 root()->SetPosition(gfx::PointF()); 64 parent()->SetPosition(gfx::PointF()); 65 parent()->SetBounds(gfx::Size(350, 200)); 66 67 child()->SetDrawsContent(true); 68 child()->draw_properties().screen_space_transform_is_animating = true; 69 child()->SetPosition(gfx::PointF(150.f, 50.f)); 70 child()->SetBounds(gfx::Size(100, 200)); 71 72 gfx::BoxF box; 73 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 74 EXPECT_TRUE(success); 75 gfx::BoxF expected(150.f, 50.f, 0.f, 350.f, 450.f, 0.f); 76 EXPECT_BOXF_EQ(expected, box); 77} 78 79TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateParentLayer) { 80 double duration = 1.0; 81 82 TransformOperations start; 83 start.AppendTranslate(0.f, 0.f, 0.f); 84 TransformOperations end; 85 end.AppendTranslate(50.f, 50.f, 0.f); 86 AddAnimatedTransformToLayer(parent(), duration, start, end); 87 88 parent()->SetBounds(gfx::Size(350, 200)); 89 90 child()->SetDrawsContent(true); 91 child()->draw_properties().screen_space_transform_is_animating = true; 92 child()->SetPosition(gfx::PointF(150.f, 50.f)); 93 child()->SetBounds(gfx::Size(100, 200)); 94 95 gfx::BoxF box; 96 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 97 EXPECT_TRUE(success); 98 gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f); 99 EXPECT_BOXF_EQ(expected, box); 100} 101 102TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateChildLayer) { 103 double duration = 1.0; 104 105 TransformOperations start; 106 start.AppendTranslate(0.f, 0.f, 0.f); 107 TransformOperations end; 108 end.AppendTranslate(50.f, 50.f, 0.f); 109 AddAnimatedTransformToLayer(child(), duration, start, end); 110 111 parent()->SetBounds(gfx::Size(350, 200)); 112 113 child()->SetDrawsContent(true); 114 child()->draw_properties().screen_space_transform_is_animating = true; 115 child()->SetPosition(gfx::PointF(150.f, 50.f)); 116 child()->SetBounds(gfx::Size(100, 200)); 117 118 gfx::BoxF box; 119 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 120 EXPECT_TRUE(success); 121 gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f); 122 EXPECT_BOXF_EQ(expected, box); 123} 124 125TEST_F(LayerUtilsGetAnimationBoundsTest, TranslateBothLayers) { 126 double duration = 1.0; 127 128 TransformOperations start; 129 start.AppendTranslate(0.f, 0.f, 0.f); 130 TransformOperations child_end; 131 child_end.AppendTranslate(50.f, 0.f, 0.f); 132 AddAnimatedTransformToLayer(parent(), duration, start, child_end); 133 134 TransformOperations grand_child_end; 135 grand_child_end.AppendTranslate(0.f, 50.f, 0.f); 136 AddAnimatedTransformToLayer(child(), duration, start, grand_child_end); 137 138 parent()->SetBounds(gfx::Size(350, 200)); 139 140 child()->SetDrawsContent(true); 141 child()->draw_properties().screen_space_transform_is_animating = true; 142 child()->SetPosition(gfx::PointF(150.f, 50.f)); 143 child()->SetBounds(gfx::Size(100, 200)); 144 145 gfx::BoxF box; 146 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 147 EXPECT_TRUE(success); 148 gfx::BoxF expected(150.f, 50.f, 0.f, 150.f, 250.f, 0.f); 149 EXPECT_BOXF_EQ(expected, box); 150} 151 152TEST_F(LayerUtilsGetAnimationBoundsTest, RotateXNoPerspective) { 153 double duration = 1.0; 154 155 TransformOperations start; 156 start.AppendRotate(1.f, 0.f, 0.f, 0.f); 157 TransformOperations end; 158 end.AppendRotate(1.f, 0.f, 0.f, 90.f); 159 AddAnimatedTransformToLayer(child(), duration, start, end); 160 161 parent()->SetBounds(gfx::Size(350, 200)); 162 163 gfx::Size bounds(100, 100); 164 child()->SetDrawsContent(true); 165 child()->draw_properties().screen_space_transform_is_animating = true; 166 child()->SetPosition(gfx::PointF(150.f, 50.f)); 167 child()->SetBounds(bounds); 168 child()->SetTransformOrigin( 169 gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0)); 170 171 gfx::BoxF box; 172 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 173 EXPECT_TRUE(success); 174 gfx::BoxF expected(150.f, 50.f, -50.f, 100.f, 100.f, 100.f); 175 EXPECT_BOXF_EQ(expected, box); 176} 177 178TEST_F(LayerUtilsGetAnimationBoundsTest, RotateXWithPerspective) { 179 double duration = 1.0; 180 181 TransformOperations start; 182 start.AppendRotate(1.f, 0.f, 0.f, 0.f); 183 TransformOperations end; 184 end.AppendRotate(1.f, 0.f, 0.f, 90.f); 185 AddAnimatedTransformToLayer(child(), duration, start, end); 186 187 // Make the anchor point not the default 0.5 value and line up with the 188 // child center to make the math easier. 189 parent()->SetTransformOrigin( 190 gfx::Point3F(0.375f * 400.f, 0.375f * 400.f, 0.f)); 191 parent()->SetBounds(gfx::Size(400, 400)); 192 193 gfx::Transform perspective; 194 perspective.ApplyPerspectiveDepth(100.f); 195 parent()->SetTransform(perspective); 196 197 gfx::Size bounds(100, 100); 198 child()->SetDrawsContent(true); 199 child()->draw_properties().screen_space_transform_is_animating = true; 200 child()->SetPosition(gfx::PointF(100.f, 100.f)); 201 child()->SetBounds(bounds); 202 child()->SetTransformOrigin( 203 gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0)); 204 205 gfx::BoxF box; 206 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 207 EXPECT_TRUE(success); 208 gfx::BoxF expected(50.f, 50.f, -33.333336f, 200.f, 200.f, 133.333344f); 209 EXPECT_BOXF_EQ(expected, box); 210} 211 212TEST_F(LayerUtilsGetAnimationBoundsTest, RotateZ) { 213 double duration = 1.0; 214 215 TransformOperations start; 216 start.AppendRotate(0.f, 0.f, 1.f, 0.f); 217 TransformOperations end; 218 end.AppendRotate(0.f, 0.f, 1.f, 90.f); 219 AddAnimatedTransformToLayer(child(), duration, start, end); 220 221 parent()->SetBounds(gfx::Size(350, 200)); 222 223 gfx::Size bounds(100, 100); 224 child()->SetDrawsContent(true); 225 child()->draw_properties().screen_space_transform_is_animating = true; 226 child()->SetPosition(gfx::PointF(150.f, 50.f)); 227 child()->SetBounds(bounds); 228 child()->SetTransformOrigin( 229 gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0)); 230 231 gfx::BoxF box; 232 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 233 EXPECT_TRUE(success); 234 float diag = diagonal(bounds.width(), bounds.height()); 235 gfx::BoxF expected(150.f + 0.5f * (bounds.width() - diag), 236 50.f + 0.5f * (bounds.height() - diag), 237 0.f, 238 diag, 239 diag, 240 0.f); 241 EXPECT_BOXF_EQ(expected, box); 242} 243 244TEST_F(LayerUtilsGetAnimationBoundsTest, MismatchedTransforms) { 245 double duration = 1.0; 246 247 TransformOperations start; 248 start.AppendTranslate(5, 6, 7); 249 TransformOperations end; 250 end.AppendRotate(0.f, 0.f, 1.f, 90.f); 251 AddAnimatedTransformToLayer(child(), duration, start, end); 252 253 parent()->SetBounds(gfx::Size(350, 200)); 254 255 gfx::Size bounds(100, 100); 256 child()->SetDrawsContent(true); 257 child()->draw_properties().screen_space_transform_is_animating = true; 258 child()->SetPosition(gfx::PointF(150.f, 50.f)); 259 child()->SetBounds(bounds); 260 261 gfx::BoxF box; 262 bool success = LayerUtils::GetAnimationBounds(*child(), &box); 263 EXPECT_FALSE(success); 264} 265 266} // namespace 267} // namespace cc 268