1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/layers/layer_position_constraint.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/layers/layer_impl.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/test/fake_impl_proxy.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/test/fake_layer_tree_host_impl.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/test/geometry_test_utils.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/trees/layer_tree_host_common.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace cc {
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SetLayerPropertiesForTesting(LayerImpl* layer,
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const gfx::Transform& transform,
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  const gfx::Transform& sublayer_transform,
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  gfx::PointF anchor,
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  gfx::PointF position,
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  gfx::Size bounds,
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  bool preserves3d) {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetTransform(transform);
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetSublayerTransform(sublayer_transform);
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetAnchorPoint(anchor);
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetPosition(position);
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetBounds(bounds);
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetPreserves3d(preserves3d);
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  layer->SetContentBounds(bounds);
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExecuteCalculateDrawProperties(LayerImpl* root_layer,
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    float device_scale_factor,
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    float page_scale_factor,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    LayerImpl* page_scale_application_layer,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    bool can_use_lcd_text) {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform identity_matrix;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<LayerImpl*> dummy_render_surface_layer_list;
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Size device_viewport_size =
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Size(root_layer->bounds().width() * device_scale_factor,
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                root_layer->bounds().height() * device_scale_factor);
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We are probably not testing what is intended if the root_layer bounds are
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // empty.
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!root_layer->bounds().IsEmpty());
49558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs(
50558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      root_layer, device_viewport_size, &dummy_render_surface_layer_list);
51558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  inputs.device_scale_factor = device_scale_factor;
52558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  inputs.page_scale_factor = page_scale_factor;
53558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  inputs.page_scale_application_layer = page_scale_application_layer;
54558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  inputs.can_use_lcd_text = can_use_lcd_text;
55558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  LayerTreeHostCommon::CalculateDrawProperties(&inputs);
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ExecuteCalculateDrawProperties(LayerImpl* root_layer) {
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* page_scale_application_layer = NULL;
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      root_layer, 1.f, 1.f, page_scale_application_layer, false);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class LayerPositionConstraintTest : public testing::Test {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerPositionConstraintTest()
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : host_impl_(&proxy_) {
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root_ = CreateTreeForTest();
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fixed_to_top_left_.set_is_fixed_position(true);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fixed_to_bottom_right_.set_is_fixed_position(true);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fixed_to_bottom_right_.set_is_fixed_to_right_edge(true);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fixed_to_bottom_right_.set_is_fixed_to_bottom_edge(true);
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<LayerImpl> CreateTreeForTest() {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<LayerImpl> root =
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        LayerImpl::Create(host_impl_.active_tree(), 1);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<LayerImpl> child =
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        LayerImpl::Create(host_impl_.active_tree(), 2);
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<LayerImpl> grand_child =
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        LayerImpl::Create(host_impl_.active_tree(), 3);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<LayerImpl> great_grand_child =
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        LayerImpl::Create(host_impl_.active_tree(), 4);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Transform IdentityMatrix;
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::PointF anchor;
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::PointF position;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Size bounds(100, 100);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetLayerPropertiesForTesting(root.get(),
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 anchor,
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 position,
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bounds,
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 false);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetLayerPropertiesForTesting(child.get(),
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 anchor,
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 position,
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bounds,
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 false);
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetLayerPropertiesForTesting(grand_child.get(),
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 anchor,
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 position,
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bounds,
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 false);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetLayerPropertiesForTesting(great_grand_child.get(),
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 IdentityMatrix,
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 anchor,
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 position,
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bounds,
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 false);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    root->SetScrollable(true);
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    child->SetMaxScrollOffset(gfx::Vector2d(100, 100));
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    child->SetScrollable(true);
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    grand_child->SetMaxScrollOffset(gfx::Vector2d(100, 100));
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    grand_child->SetScrollable(true);
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    grand_child->AddChild(great_grand_child.Pass());
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    child->AddChild(grand_child.Pass());
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root->AddChild(child.Pass());
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return root.Pass();
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FakeImplProxy proxy_;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FakeLayerTreeHostImpl host_impl_;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<LayerImpl> root_;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerPositionConstraint fixed_to_top_left_;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerPositionConstraint fixed_to_bottom_right_;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithDirectContainer) {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container is the direct parent of the fixed-position layer.
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_top_left_);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform = expected_child_transform;
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 10
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 10));
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Here the child is affected by scroll delta, but the fixed position
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // grand_child should not be affected.
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -10.0);
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_bottom_right_);
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(20.0, 20.0);
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithTransformedDirectContainer) {
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container is the direct parent of the fixed-position layer, but that
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container is transformed.  In this case, the fixed position element
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // inherits the container's transform, but the scroll delta that has to be
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // undone should not be affected by that transform.
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Transforms are in general non-commutative; using something like a
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // non-uniform scale helps to verify that translations and non-uniform scales
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // are applied in the correct order.
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This scale will cause child and grand_child to be effectively 200 x 800
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // with respect to the render target.
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform non_uniform_scale;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  non_uniform_scale.Scale(2.0, 8.0);
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetTransform(non_uniform_scale);
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_top_left_);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.PreconcatTransform(non_uniform_scale);
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform = expected_child_transform;
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 20
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 20));
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The child should be affected by scroll delta, but the fixed position
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // grand_child should not be affected.
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -20.0);  // scroll delta
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.PreconcatTransform(non_uniform_scale);
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_bottom_right_);
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply child layer transform.
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(non_uniform_scale);
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(20.0, 20.0);
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithDistantContainer) {
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container is NOT the direct parent of the fixed-position layer.
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* great_grand_child = grand_child->children()[0];
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPosition(gfx::PointF(8.f, 6.f));
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_top_left_);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(8.0, 6.0);
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_great_grand_child_transform =
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_grand_child_transform;
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 10
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 10));
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Here the child and grand_child are affected by scroll delta, but the fixed
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position great_grand_child should not be affected.
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -10.0);
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(-2.0, -4.0);
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.MakeIdentity();
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(20.0, 20.0);
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply layer position from the grand child layer.
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(8.0, 6.0);
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithDistantContainerAndTransforms) {
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container is NOT the direct parent of the fixed-position layer, and the
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // hierarchy has various transforms that have to be processed in the correct
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // order.
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* great_grand_child = grand_child->children()[0];
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform rotation_about_z;
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_about_z.RotateAboutZAxis(90.0);
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetTransform(rotation_about_z);
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPosition(gfx::PointF(8.f, 6.f));
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetTransform(rotation_about_z);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // great_grand_child is positioned upside-down with respect to the render
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // target.
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_top_left_);
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.PreconcatTransform(rotation_about_z);
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // child's local transform is inherited
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // translation because of position occurs before layer's local transform.
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(8.0, 6.0);
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // grand_child's local transform
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_great_grand_child_transform =
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_grand_child_transform;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 20
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 20));
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Here the child and grand_child are affected by scroll delta, but the fixed
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position great_grand_child should not be affected.
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -20.0);  // scroll delta
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.PreconcatTransform(rotation_about_z);
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      -10.0, -20.0);      // child's scroll delta is inherited
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // child's local transform is inherited
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // translation because of position occurs before layer's local transform.
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(8.0, 6.0);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // grand_child's local transform
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.MakeIdentity();
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply child layer transform.
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(20.0, 20.0);
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply layer position from the grand child layer.
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(8.0, 6.0);
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply grand child layer transform.
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithMultipleScrollDeltas) {
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container has multiple ancestors that have nonzero scroll delta before
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // reaching the space where the layer is fixed.  In this test, each scroll
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // delta occurs in a different space because of each layer's local transform.
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container is NOT the direct parent of the fixed-position layer, and the
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // hierarchy has various transforms that have to be processed in the correct
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // order.
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* great_grand_child = grand_child->children()[0];
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform rotation_about_z;
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_about_z.RotateAboutZAxis(90.0);
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetTransform(rotation_about_z);
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPosition(gfx::PointF(8.f, 6.f));
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetTransform(rotation_about_z);
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // great_grand_child is positioned upside-down with respect to the render
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // target.
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_top_left_);
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.PreconcatTransform(rotation_about_z);
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // child's local transform is inherited
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // translation because of position occurs before layer's local transform.
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(8.0, 6.0);
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // grand_child's local transform
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_great_grand_child_transform =
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_grand_child_transform;
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 20
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 0));
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetScrollDelta(gfx::Vector2d(5, 0));
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Here the child and grand_child are affected by scroll delta, but the fixed
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position great_grand_child should not be affected.
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, 0.0);  // scroll delta
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.PreconcatTransform(rotation_about_z);
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      -10.0, 0.0);        // child's scroll delta is inherited
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // child's local transform is inherited
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(-5.0,
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           0.0);  // grand_child's scroll delta
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // translation because of position occurs before layer's local transform.
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(8.0, 6.0);
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // grand_child's local transform
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.MakeIdentity();
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply child layer transform.
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(20.0, 20.0);
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply layer position from the grand child layer.
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(8.0, 6.0);
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply grand child layer transform.
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionWithIntermediateSurfaceAndTransforms) {
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container contributes to a different render surface than the fixed-position
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // layer. In this case, the surface draw transforms also have to be accounted
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // for when checking the scroll delta.
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
590c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* great_grand_child = grand_child->children()[0];
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPosition(gfx::PointF(8.f, 6.f));
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetForceRenderSurface(true);
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_top_left_);
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetDrawsContent(true);
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform rotation_about_z;
599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_about_z.RotateAboutZAxis(90.0);
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetTransform(rotation_about_z);
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_surface_draw_transform;
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.Translate(8.0, 6.0);
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.PreconcatTransform(rotation_about_z);
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_great_grand_child_transform;
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(grand_child->render_surface());
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_surface_draw_transform,
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      grand_child->render_surface()->draw_transform());
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 30
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 30));
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Here the grand_child remains unchanged, because it scrolls along with the
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // render surface, and the translation is actually in the render surface. But,
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the fixed position great_grand_child is more awkward: its actually being
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // drawn with respect to the render surface, but it needs to remain fixed with
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // resepct to a container beyond that surface. So, the net result is that,
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // unlike previous tests where the fixed position layer's transform remains
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // unchanged, here the fixed position layer's transform explicitly contains
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the translation that cancels out the scroll.
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -30.0);  // scroll delta
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.MakeIdentity();
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.Translate(-10.0, -30.0);  // scroll delta
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.Translate(8.0, 6.0);
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.PreconcatTransform(rotation_about_z);
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The rotation and its inverse are needed to place the scroll delta
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // compensation in the correct space. This test will fail if the
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // rotation/inverse are backwards, too, so it requires perfect order of
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // operations.
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.MakeIdentity();
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Inverse(rotation_about_z));
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // explicit canceling out the scroll delta that gets embedded in the fixed
651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position layer's surface.
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(10.0, 30.0);
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(grand_child->render_surface());
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_surface_draw_transform,
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      grand_child->render_surface()->draw_transform());
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPositionConstraint(fixed_to_bottom_right_);
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.MakeIdentity();
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The rotation and its inverse are needed to place the scroll delta
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // compensation in the correct space. This test will fail if the
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // rotation/inverse are backwards, too, so it requires perfect order of
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // operations.
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Inverse(rotation_about_z));
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // explicit canceling out the scroll delta that gets embedded in the fixed
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position layer's surface.
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(10.0, 30.0);
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Also apply size delta in the child(container) layer space.
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.Translate(20.0, 20.0);
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_transform.PreconcatTransform(rotation_about_z);
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithMultipleIntermediateSurfaces) {
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container contributes to a different render surface than the fixed-position
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // layer, with additional render surfaces in-between. This checks that the
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // conversion to ancestor surfaces is accumulated properly in the final matrix
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // transform.
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* great_grand_child = grand_child->children()[0];
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add one more layer to the test tree for this scenario.
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Transform identity;
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<LayerImpl> fixed_position_child =
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        LayerImpl::Create(host_impl_.active_tree(), 5);
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetLayerPropertiesForTesting(fixed_position_child.get(),
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 identity,
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 identity,
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 gfx::PointF(),
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 gfx::PointF(),
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 gfx::Size(100, 100),
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 false);
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    great_grand_child->AddChild(fixed_position_child.Pass());
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* fixed_position_child = great_grand_child->children()[0];
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Actually set up the scenario here.
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPosition(gfx::PointF(8.f, 6.f));
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetForceRenderSurface(true);
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetPosition(gfx::PointF(40.f, 60.f));
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetForceRenderSurface(true);
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fixed_position_child->SetPositionConstraint(fixed_to_top_left_);
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fixed_position_child->SetDrawsContent(true);
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The additional rotations, which are non-commutative with translations, help
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to verify that we have correct order-of-operations in the final scroll
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // compensation.  Note that rotating about the center of the layer ensures we
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // do not accidentally clip away layers that we want to test.
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform rotation_about_z;
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_about_z.Translate(50.0, 50.0);
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_about_z.RotateAboutZAxis(90.0);
748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_about_z.Translate(-50.0, -50.0);
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetTransform(rotation_about_z);
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  great_grand_child->SetTransform(rotation_about_z);
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_surface_draw_transform;
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_surface_draw_transform.Translate(8.0, 6.0);
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_surface_draw_transform.PreconcatTransform(
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_great_grand_child_surface_draw_transform;
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_surface_draw_transform.Translate(40.0, 60.0);
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_great_grand_child_surface_draw_transform.PreconcatTransform(
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_great_grand_child_transform;
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_fixed_position_child_transform;
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(grand_child->render_surface());
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(great_grand_child->render_surface());
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_grand_child_surface_draw_transform,
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      grand_child->render_surface()->draw_transform());
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_great_grand_child_surface_draw_transform,
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      great_grand_child->render_surface()->draw_transform());
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  fixed_position_child->draw_transform());
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 30
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 30));
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -30.0);  // scroll delta
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_surface_draw_transform.MakeIdentity();
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_surface_draw_transform.Translate(-10.0,
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                        -30.0);  // scroll delta
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_surface_draw_transform.Translate(8.0, 6.0);
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_surface_draw_transform.PreconcatTransform(
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // grand_child, great_grand_child, and great_grand_child's surface are not
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // expected to change, since they are all not fixed, and they are all drawn
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // with respect to grand_child's surface that already has the scroll delta
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // accounted for.
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // But the great-great grandchild, "fixed_position_child", should have a
811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // transform that explicitly cancels out the scroll delta.  The expected
812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // transform is: compound_draw_transform.Inverse() * translate(positive scroll
813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // delta) * compound_origin_transform from great_grand_childSurface's origin
814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to the root surface.
815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform compound_draw_transform;
816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  compound_draw_transform.Translate(8.0,
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                    6.0);  // origin translation of grand_child
818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  compound_draw_transform.PreconcatTransform(
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);                   // rotation of grand_child
820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  compound_draw_transform.Translate(
821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      40.0, 60.0);        // origin translation of great_grand_child
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  compound_draw_transform.PreconcatTransform(
823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      rotation_about_z);  // rotation of great_grand_child
824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.MakeIdentity();
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.PreconcatTransform(
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Inverse(compound_draw_transform));
828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // explicit canceling out the scroll delta that gets embedded in the fixed
829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position layer's surface.
830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.Translate(10.0, 30.0);
831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.PreconcatTransform(
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      compound_draw_transform);
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(grand_child->render_surface());
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(great_grand_child->render_surface());
836c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(
839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_grand_child_surface_draw_transform,
840c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      grand_child->render_surface()->draw_transform());
841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
842c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(
844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected_great_grand_child_surface_draw_transform,
845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      great_grand_child->render_surface()->draw_transform());
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  fixed_position_child->draw_transform());
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  fixed_position_child->draw_transform());
865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fixed_position_child->SetPositionConstraint(fixed_to_bottom_right_);
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.MakeIdentity();
872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.PreconcatTransform(
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Inverse(compound_draw_transform));
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // explicit canceling out the scroll delta that gets embedded in the fixed
875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // position layer's surface.
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.Translate(10.0, 30.0);
877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Also apply size delta in the child(container) layer space.
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.Translate(20.0, 20.0);
879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_fixed_position_child_transform.PreconcatTransform(
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      compound_draw_transform);
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_great_grand_child_transform,
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  great_grand_child->draw_transform());
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_fixed_position_child_transform,
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  fixed_position_child->draw_transform());
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerWithContainerLayerThatHasSurface) {
894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks for correct scroll compensation when the fixed-position
895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // container itself has a render surface. In this case, the container layer
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // should be treated like a layer that contributes to a render target, and
897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // that render target is completely irrelevant; it should not affect the
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // scroll compensation.
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetForceRenderSurface(true);
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_top_left_);
905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetDrawsContent(true);
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_surface_draw_transform;
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.Translate(0.0, 0.0);
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(child->render_surface());
916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform,
917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->render_surface()->draw_transform());
918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 10
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 10));
925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The surface is translated by scroll delta, the child transform doesn't
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // change because it scrolls along with the surface, but the fixed position
929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // grand_child needs to compensate for the scroll translation.
930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.MakeIdentity();
931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_surface_draw_transform.Translate(-10.0, -10.0);
932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(10.0, 10.0);
934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_TRUE(child->render_surface());
936c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_surface_draw_transform,
937c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->render_surface()->draw_transform());
938c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
939c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
940c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
941c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
942c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
943c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
944c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
945c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
946c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
947c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
948c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
949c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
950c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
951c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
952c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
953c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
954c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_bottom_right_);
955c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
956c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
957c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
958c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
959c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The surface is translated by scroll delta, the child transform doesn't
960c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // change because it scrolls along with the surface, but the fixed position
961c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // grand_child needs to compensate for the scroll translation.
962c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(10.0, 10.0);
963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
964c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(20.0, 20.0);
965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
971c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerThatIsAlsoFixedPositionContainer) {
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks the scenario where a fixed-position layer also happens to
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // be a container itself for a descendant fixed position layer. In particular,
976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the layer should not accidentally be fixed to itself.
977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
980c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetIsContainerForFixedPositionLayers(true);
981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_top_left_);
982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This should not confuse the grand_child. If correct, the grand_child would
984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // still be considered fixed to its container (i.e. "child").
985c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetIsContainerForFixedPositionLayers(true);
986c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: scroll delta of 0, 0
988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(0, 0));
989c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_child_transform;
992c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform expected_grand_child_transform;
993c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
994c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
997c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
998c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: scroll delta of 10, 10
999c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetScrollDelta(gfx::Vector2d(10, 10));
1000c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1001c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1002c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Here the child is affected by scroll delta, but the fixed position
1003c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // grand_child should not be affected.
1004c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.MakeIdentity();
1005c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_child_transform.Translate(-10.0, -10.0);
1006c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1007c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
1008c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1009c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1010c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1011c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
1012c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  child->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
1013c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1014c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1015c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
1016c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1017c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
1018c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1019c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1020c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1021c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
1022c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_bottom_right_);
1023c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1024c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1025c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Bottom-right fixed-position layer moves as container resizes.
1026c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.MakeIdentity();
1027c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Apply size delta from the child(container) layer.
1028c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  expected_grand_child_transform.Translate(20.0, 20.0);
1029c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1030c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1031c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  child->draw_transform());
1032c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1033c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1034c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1035c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1036c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(LayerPositionConstraintTest,
1037c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     ScrollCompensationForFixedPositionLayerThatHasNoContainer) {
1038c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This test checks scroll compensation when a fixed-position layer does not
1039c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // find any ancestor that is a "containerForFixedPositionLayers". In this
1040868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // situation, the layer should be fixed to the root layer.
1041c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* child = root_->children()[0];
1042c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LayerImpl* grand_child = child->children()[0];
1043c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1044c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform rotation_by_z;
1045c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rotation_by_z.RotateAboutZAxis(90.0);
1046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_->SetTransform(rotation_by_z);
1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_top_left_);
1049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 1: root scroll delta of 0, 0
1051c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_->SetScrollDelta(gfx::Vector2d(0, 0));
1052c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1053c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1054c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Transform identity_matrix;
1055c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1056868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z, child->draw_transform());
1057868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z,
1058c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1059c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1060c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 2: root scroll delta of 10, 10
1061c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_->SetScrollDelta(gfx::Vector2d(10, 20));
1062c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1063c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1064868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::Transform expected_child_transform;
1065868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  expected_child_transform.Translate(-10.0, -20.0);
1066868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  expected_child_transform.PreconcatTransform(rotation_by_z);
1067c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1068868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1069868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  child->draw_transform());
1070868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z,
1071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1072c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1073c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 3: fixed-container size delta of 20, 20
1074c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_->SetFixedContainerSizeDelta(gfx::Vector2d(20, 20));
1075c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1076c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1077c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Top-left fixed-position layer should not be affected by container size.
1078868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1079868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  child->draw_transform());
1080868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(rotation_by_z,
1081c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1082c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1083c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Case 4: Bottom-right fixed-position layer.
1084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  grand_child->SetPositionConstraint(fixed_to_bottom_right_);
1085c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExecuteCalculateDrawProperties(root_.get());
1086c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1087868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::Transform expected_grand_child_transform;
1088868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  expected_grand_child_transform.Translate(-20.0, 20.0);
1089868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  expected_grand_child_transform.PreconcatTransform(rotation_by_z);
1090868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_child_transform,
1092868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  child->draw_transform());
1093c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRANSFORMATION_MATRIX_EQ(expected_grand_child_transform,
1094c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                  grand_child->draw_transform());
1095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1096c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1097c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
1098c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace cc
1099