Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: views/animation/screen_rotation.cc

Issue 7273073: Animated Rotation (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Removed unnecessary include Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "views/animation/screen_rotation.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/message_loop.h"
9 #include "ui/base/animation/slide_animation.h"
10 #include "ui/gfx/interpolated_transform.h"
11 #include "ui/gfx/rect.h"
12 #include "ui/gfx/transform.h"
13 #include "views/view.h"
14
15 namespace {
16
17 class ScreenRotationCompletedTask : public Task {
18 public:
19 ScreenRotationCompletedTask(views::ScreenRotation* rotation)
20 : rotation_(rotation) {
21 }
22
23 virtual void Run() OVERRIDE {
24 rotation_->CleanUp();
25 }
26
27 private:
28 scoped_refptr<views::ScreenRotation> rotation_;
29
30 // copy and assign are allowed
31 };
32
33 } // namespace
34
35 namespace views {
36
37 ////////////////////////////////////////////////////////////////////////////////
38 // ScreenRotation public:
39 //
40
41 ScreenRotation::ScreenRotation(View* root,
42 float old_degrees,
43 float new_degrees)
44 : root_(root),
45 old_degrees_(old_degrees),
46 new_degrees_(new_degrees) {
47 Init();
48 }
49
50 void ScreenRotation::CleanUp() {
51 // TODO(vollick) massage matrix so that entries sufficiently close
52 // to 0, 1, or -1 are clamped to these values. The idea is to fight
53 // accumulated numeric error due to successive rotations.
54 ui::Transform xform = root_->GetTransform();
55 if (root_->layer()) {
56 xform = root_->layer()->transform();
57 }
58 gfx::Point origin;
59 xform.TransformPoint(origin);
60 ui::Transform translation;
61 translation.SetTranslate(new_origin_.x() - origin.x(),
62 new_origin_.y() - origin.y());
63 xform.ConcatTransform(translation);
64 root_->SetTransform(xform);
65 root_->SetBounds(0, 0, new_size_.width(), new_size_.height());
66 root_->set_painting_enabled(true);
67 root_->SchedulePaint();
68 }
69
70
71 ////////////////////////////////////////////////////////////////////////////////
72 // ScreenRotation protected:
73 //
74
75 ScreenRotation::~ScreenRotation() {}
76
77 void ScreenRotation::OnAnimationProgressed(double t) OVERRIDE {
78 if (!interpolated_transform_.get() || !layer())
79 return;
80
81 if (root_->painting_enabled())
82 root_->set_painting_enabled(false);
83
84 layer()->SetTransform(interpolated_transform_->Interpolate(t));
85 layer()->compositor()->SchedulePaint();
86 }
87
88 void ScreenRotation::OnAnimationEnded() OVERRIDE {
89 TRACE_EVENT_END0("ScreenRotation", "Start rotating");
90 if (interpolated_transform_.get() && layer()) {
91 layer()->SetTransform(interpolated_transform_->Interpolate(1.0));
92 layer()->compositor()->SchedulePaint();
93 }
94 MessageLoop::current()->PostDelayedTask(
95 FROM_HERE,
96 new ScreenRotationCompletedTask(this),
97 100);
98 }
99
100 ////////////////////////////////////////////////////////////////////////////////
101 // ScreenRotation private:
102 //
103
104 int ScreenRotation::NormalizeAngle(int degrees) {
105 while (degrees <= -180) degrees += 360;
106 while (degrees > 180) degrees -= 360;
107 return degrees;
108 }
109
110 void ScreenRotation::Init() {
111 TRACE_EVENT_BEGIN0("ScreenRotation", "Start rotating");
112 if (!root_->layer()) {
113 root_->SetPaintToLayer(true);
114 root_->SchedulePaint();
115 }
116
117 int degrees = new_degrees_ - old_degrees_;
118 degrees = NormalizeAngle(degrees);
119
120 // No rotation required.
121 if (degrees == 0)
122 return;
123
124 gfx::Point old_pivot;
125 gfx::Point new_pivot;
126
127 switch (degrees) {
128 case 90:
129 set_duration(500);
130 new_origin_ = new_pivot = gfx::Point(root_->width(), 0);
131 new_size_.SetSize(root_->height(), root_->width());
132 break;
133 case -90:
134 set_duration(500);
135 new_origin_ = new_pivot = gfx::Point(0, root_->height());
136 new_size_.SetSize(root_->height(), root_->width());
137 break;
138 case 180:
139 set_duration(750);
140 new_pivot = old_pivot = gfx::Point(root_->width() / 2,
141 root_->height() / 2);
142 new_origin_.SetPoint(root_->width(), root_->height());
143 new_size_.SetSize(root_->width(), root_->height());
144 break;
145 }
146
147 // Convert points to world space.
148 const ui::Transform& xform = root_->GetTransform();
149 xform.TransformPoint(old_pivot);
150 xform.TransformPoint(new_pivot);
151 xform.TransformPoint(new_origin_);
152
153 scoped_ptr<ui::InterpolatedTransform> rotation(
154 new ui::InterpolatedTransformAboutPivot(
155 old_pivot,
156 new ui::InterpolatedRotation(0, degrees)));
157
158 scoped_ptr<ui::InterpolatedTransform> translation(
159 new ui::InterpolatedTranslation(
160 gfx::Point(0, 0),
161 gfx::Point(new_pivot.x() - old_pivot.x(),
162 new_pivot.y() - old_pivot.y())));
163
164 float scale_factor = 0.9f;
165 scoped_ptr<ui::InterpolatedTransform> scale_down(
166 new ui::InterpolatedScale(1.0f, scale_factor, 0.0f, 0.5f));
167
168 scoped_ptr<ui::InterpolatedTransform> scale_up(
169 new ui::InterpolatedScale(1.0f, 1.0f / scale_factor, 0.5f, 1.0f));
170
171 interpolated_transform_.reset(
172 new ui::InterpolatedConstantTransform(xform));
173
174 scale_up->SetChild(scale_down.release());
175 translation->SetChild(scale_up.release());
176 rotation->SetChild(translation.release());
177 interpolated_transform_->SetChild(rotation.release());
178 }
179
180 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698