1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/rotator/screen_rotation.h"
7 #include "base/time/time.h"
8 #include "ui/compositor/layer.h"
9 #include "ui/gfx/interpolated_transform.h"
10 #include "ui/gfx/rect.h"
11 #include "ui/gfx/transform.h"
17 const int k90DegreeTransitionDurationMs
= 350;
18 const int k180DegreeTransitionDurationMs
= 550;
19 const int k360DegreeTransitionDurationMs
= 750;
21 base::TimeDelta
GetTransitionDuration(int degrees
) {
23 return base::TimeDelta::FromMilliseconds(k360DegreeTransitionDurationMs
);
25 return base::TimeDelta::FromMilliseconds(k180DegreeTransitionDurationMs
);
27 return base::TimeDelta::FromMilliseconds(0);
28 return base::TimeDelta::FromMilliseconds(k90DegreeTransitionDurationMs
);
33 ScreenRotation::ScreenRotation(int degrees
, ui::Layer
* layer
)
34 : ui::LayerAnimationElement(GetProperties(),
35 GetTransitionDuration(degrees
)),
40 ScreenRotation::~ScreenRotation() {
43 void ScreenRotation::InitTransform(ui::Layer
* layer
) {
44 // No rotation required, use the identity transform.
46 interpolated_transform_
.reset(
47 new ui::InterpolatedConstantTransform(gfx::Transform()));
51 // Use the target transform/bounds in case the layer is already animating.
52 const gfx::Transform
& current_transform
= layer
->GetTargetTransform();
53 const gfx::Rect
& bounds
= layer
->GetTargetBounds();
58 int width
= bounds
.width();
59 int height
= bounds
.height();
63 new_origin_
= new_pivot
= gfx::Point(width
, 0);
66 new_origin_
= new_pivot
= gfx::Point(0, height
);
70 new_pivot
= old_pivot
= gfx::Point(width
/ 2, height
/ 2);
71 new_origin_
.SetPoint(width
, height
);
75 // Convert points to world space.
76 current_transform
.TransformPoint(old_pivot
);
77 current_transform
.TransformPoint(new_pivot
);
78 current_transform
.TransformPoint(new_origin_
);
80 scoped_ptr
<ui::InterpolatedTransform
> rotation(
81 new ui::InterpolatedTransformAboutPivot(
83 new ui::InterpolatedRotation(0, degrees_
)));
85 scoped_ptr
<ui::InterpolatedTransform
> translation(
86 new ui::InterpolatedTranslation(
88 gfx::Point(new_pivot
.x() - old_pivot
.x(),
89 new_pivot
.y() - old_pivot
.y())));
91 float scale_factor
= 0.9f
;
92 scoped_ptr
<ui::InterpolatedTransform
> scale_down(
93 new ui::InterpolatedScale(1.0f
, scale_factor
, 0.0f
, 0.5f
));
95 scoped_ptr
<ui::InterpolatedTransform
> scale_up(
96 new ui::InterpolatedScale(1.0f
, 1.0f
/ scale_factor
, 0.5f
, 1.0f
));
98 interpolated_transform_
.reset(
99 new ui::InterpolatedConstantTransform(current_transform
));
101 scale_up
->SetChild(scale_down
.release());
102 translation
->SetChild(scale_up
.release());
103 rotation
->SetChild(translation
.release());
104 interpolated_transform_
->SetChild(rotation
.release());
107 void ScreenRotation::OnStart(ui::LayerAnimationDelegate
* delegate
) {
110 bool ScreenRotation::OnProgress(double t
,
111 ui::LayerAnimationDelegate
* delegate
) {
112 delegate
->SetTransformFromAnimation(interpolated_transform_
->Interpolate(t
));
116 void ScreenRotation::OnGetTarget(TargetValue
* target
) const {
117 target
->transform
= interpolated_transform_
->Interpolate(1.0);
120 void ScreenRotation::OnAbort(ui::LayerAnimationDelegate
* delegate
) {
124 const ui::LayerAnimationElement::AnimatableProperties
&
125 ScreenRotation::GetProperties() {
126 static ui::LayerAnimationElement::AnimatableProperties properties
;
127 if (properties
.empty())
128 properties
.insert(ui::LayerAnimationElement::TRANSFORM
);