OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/interpolated_transform.h" | 5 #include "ui/gfx/interpolated_transform.h" |
6 | 6 |
| 7 #include <cmath> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "ui/base/animation/tween.h" | 10 #include "ui/base/animation/tween.h" |
9 | 11 |
| 12 namespace { |
| 13 |
| 14 static const float EPSILON = 1e-6f; |
| 15 |
| 16 } // namespace |
| 17 |
10 namespace ui { | 18 namespace ui { |
11 | 19 |
12 /////////////////////////////////////////////////////////////////////////////// | 20 /////////////////////////////////////////////////////////////////////////////// |
13 // InterpolatedTransform | 21 // InterpolatedTransform |
14 // | 22 // |
15 | 23 |
16 InterpolatedTransform::InterpolatedTransform() | 24 InterpolatedTransform::InterpolatedTransform() |
17 : start_time_(0.0f), | 25 : start_time_(0.0f), |
18 end_time_(1.0f) { | 26 end_time_(1.0f) { |
19 } | 27 } |
(...skipping 11 matching lines...) Expand all Loading... |
31 if (child_.get()) { | 39 if (child_.get()) { |
32 result.ConcatTransform(child_->Interpolate(t)); | 40 result.ConcatTransform(child_->Interpolate(t)); |
33 } | 41 } |
34 return result; | 42 return result; |
35 } | 43 } |
36 | 44 |
37 void InterpolatedTransform::SetChild(InterpolatedTransform* child) { | 45 void InterpolatedTransform::SetChild(InterpolatedTransform* child) { |
38 child_.reset(child); | 46 child_.reset(child); |
39 } | 47 } |
40 | 48 |
| 49 bool InterpolatedTransform::FactorTRS(const ui::Transform& transform, |
| 50 gfx::Point* translation, |
| 51 float* rotation, |
| 52 gfx::Point3f* scale) { |
| 53 const SkMatrix44& m = transform.matrix(); |
| 54 float m00 = m.get(0, 0); |
| 55 float m01 = m.get(0, 1); |
| 56 float m10 = m.get(1, 0); |
| 57 float m11 = m.get(1, 1); |
| 58 |
| 59 // A factorable 2D TRS matrix must be of the form: |
| 60 // [ sx*cos_theta -(sy*sin_theta) 0 tx ] |
| 61 // [ sx*sin_theta sy*cos_theta 0 ty ] |
| 62 // [ 0 0 1 0 ] |
| 63 // [ 0 0 0 1 ] |
| 64 if (m.get(0, 2) != 0 || |
| 65 m.get(1, 2) != 0 || |
| 66 m.get(2, 0) != 0 || |
| 67 m.get(2, 1) != 0 || |
| 68 m.get(2, 2) != 1 || |
| 69 m.get(2, 3) != 0 || |
| 70 m.get(3, 0) != 0 || |
| 71 m.get(3, 1) != 0 || |
| 72 m.get(3, 2) != 0 || |
| 73 m.get(3, 3) != 1) { |
| 74 return false; |
| 75 } |
| 76 |
| 77 float scale_x = sqrt(m00 * m00 + m10 * m10); |
| 78 float scale_y = sqrt(m01 * m01 + m11 * m11); |
| 79 |
| 80 if (scale_x == 0 || scale_y == 0) |
| 81 return false; |
| 82 |
| 83 float cos_theta = m00 / scale_x; |
| 84 float sin_theta = m10 / scale_x; |
| 85 |
| 86 if ((fabs(cos_theta - (m11 / scale_y))) > EPSILON || |
| 87 (fabs(sin_theta + (m01 / scale_y))) > EPSILON || |
| 88 (fabs(cos_theta*cos_theta + sin_theta*sin_theta - 1.0f) > EPSILON)) { |
| 89 return false; |
| 90 } |
| 91 |
| 92 float radians = atan2(sin_theta, cos_theta); |
| 93 |
| 94 if (translation) |
| 95 *translation = gfx::Point(m.get(0, 3), m.get(1, 3)); |
| 96 if (rotation) |
| 97 *rotation = radians * 180 / M_PI; |
| 98 if (scale) |
| 99 *scale = gfx::Point3f(scale_x, scale_y, 1.0f); |
| 100 |
| 101 return true; |
| 102 } |
| 103 |
41 inline float InterpolatedTransform::ValueBetween(float time, | 104 inline float InterpolatedTransform::ValueBetween(float time, |
42 float start_value, | 105 float start_value, |
43 float end_value) const { | 106 float end_value) const { |
44 // can't handle NaN | 107 // can't handle NaN |
45 DCHECK(time == time && start_time_ == start_time_ && end_time_ == end_time_); | 108 DCHECK(time == time && start_time_ == start_time_ && end_time_ == end_time_); |
46 if (time != time || start_time_ != start_time_ || end_time_ != end_time_) | 109 if (time != time || start_time_ != start_time_ || end_time_ != end_time_) |
47 return start_value; | 110 return start_value; |
48 | 111 |
49 // Ok if equal -- we'll get a step function. Note: if end_time_ == | 112 // Ok if equal -- we'll get a step function. Note: if end_time_ == |
50 // start_time_ == x, then if none of the numbers are NaN, then it | 113 // start_time_ == x, then if none of the numbers are NaN, then it |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 ui::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const { | 150 ui::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const { |
88 ui::Transform result; | 151 ui::Transform result; |
89 result.SetRotate(ValueBetween(t, start_degrees_, end_degrees_)); | 152 result.SetRotate(ValueBetween(t, start_degrees_, end_degrees_)); |
90 return result; | 153 return result; |
91 } | 154 } |
92 | 155 |
93 /////////////////////////////////////////////////////////////////////////////// | 156 /////////////////////////////////////////////////////////////////////////////// |
94 // InterpolatedScale | 157 // InterpolatedScale |
95 // | 158 // |
96 | 159 |
97 InterpolatedScale::InterpolatedScale(float start_scale, | 160 InterpolatedScale::InterpolatedScale(float start_scale, float end_scale) |
98 float end_scale) | 161 : InterpolatedTransform(), |
| 162 start_scale_(gfx::Point3f(start_scale, start_scale, start_scale)), |
| 163 end_scale_(gfx::Point3f(end_scale, end_scale, end_scale)) { |
| 164 } |
| 165 |
| 166 InterpolatedScale::InterpolatedScale(float start_scale, float end_scale, |
| 167 float start_time, float end_time) |
| 168 : InterpolatedTransform(start_time, end_time), |
| 169 start_scale_(gfx::Point3f(start_scale, start_scale, start_scale)), |
| 170 end_scale_(gfx::Point3f(end_scale, end_scale, end_scale)) { |
| 171 } |
| 172 |
| 173 InterpolatedScale::InterpolatedScale(const gfx::Point3f& start_scale, |
| 174 const gfx::Point3f& end_scale) |
99 : InterpolatedTransform(), | 175 : InterpolatedTransform(), |
100 start_scale_(start_scale), | 176 start_scale_(start_scale), |
101 end_scale_(end_scale) { | 177 end_scale_(end_scale) { |
102 } | 178 } |
103 | 179 |
104 InterpolatedScale::InterpolatedScale(float start_scale, | 180 InterpolatedScale::InterpolatedScale(const gfx::Point3f& start_scale, |
105 float end_scale, | 181 const gfx::Point3f& end_scale, |
106 float start_time, | 182 float start_time, |
107 float end_time) | 183 float end_time) |
108 : InterpolatedTransform(start_time, end_time), | 184 : InterpolatedTransform(start_time, end_time), |
109 start_scale_(start_scale), | 185 start_scale_(start_scale), |
110 end_scale_(end_scale) { | 186 end_scale_(end_scale) { |
111 } | 187 } |
112 | 188 |
113 InterpolatedScale::~InterpolatedScale() {} | 189 InterpolatedScale::~InterpolatedScale() {} |
114 | 190 |
115 ui::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const { | 191 ui::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const { |
116 ui::Transform result; | 192 ui::Transform result; |
117 float interpolated_scale = ValueBetween(t, start_scale_, end_scale_); | 193 float scale_x = ValueBetween(t, start_scale_.x(), end_scale_.x()); |
| 194 float scale_y = ValueBetween(t, start_scale_.y(), end_scale_.y()); |
118 // TODO(vollick) 3d xforms. | 195 // TODO(vollick) 3d xforms. |
119 result.SetScale(interpolated_scale, interpolated_scale); | 196 result.SetScale(scale_x, scale_y); |
120 return result; | 197 return result; |
121 } | 198 } |
122 | 199 |
123 /////////////////////////////////////////////////////////////////////////////// | 200 /////////////////////////////////////////////////////////////////////////////// |
124 // InterpolatedTranslation | 201 // InterpolatedTranslation |
125 // | 202 // |
126 | 203 |
127 InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos, | 204 InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos, |
128 const gfx::Point& end_pos) | 205 const gfx::Point& end_pos) |
129 : InterpolatedTransform(), | 206 : InterpolatedTransform(), |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 Init(pivot, transform); | 266 Init(pivot, transform); |
190 } | 267 } |
191 | 268 |
192 InterpolatedTransformAboutPivot::~InterpolatedTransformAboutPivot() {} | 269 InterpolatedTransformAboutPivot::~InterpolatedTransformAboutPivot() {} |
193 | 270 |
194 ui::Transform | 271 ui::Transform |
195 InterpolatedTransformAboutPivot::InterpolateButDoNotCompose(float t) const { | 272 InterpolatedTransformAboutPivot::InterpolateButDoNotCompose(float t) const { |
196 if (transform_.get()) { | 273 if (transform_.get()) { |
197 return transform_->Interpolate(t); | 274 return transform_->Interpolate(t); |
198 } | 275 } |
199 return ui::Transform(); | 276 return Transform(); |
200 } | 277 } |
201 | 278 |
202 void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot, | 279 void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot, |
203 InterpolatedTransform* xform) { | 280 InterpolatedTransform* xform) { |
204 ui::Transform to_pivot; | 281 ui::Transform to_pivot; |
205 ui::Transform from_pivot; | 282 ui::Transform from_pivot; |
206 to_pivot.SetTranslate(-pivot.x(), -pivot.y()); | 283 to_pivot.SetTranslate(-pivot.x(), -pivot.y()); |
207 from_pivot.SetTranslate(pivot.x(), pivot.y()); | 284 from_pivot.SetTranslate(pivot.x(), pivot.y()); |
208 | 285 |
209 scoped_ptr<InterpolatedTransform> pre_transform( | 286 scoped_ptr<InterpolatedTransform> pre_transform( |
210 new InterpolatedConstantTransform(to_pivot)); | 287 new InterpolatedConstantTransform(to_pivot)); |
211 scoped_ptr<InterpolatedTransform> post_transform( | 288 scoped_ptr<InterpolatedTransform> post_transform( |
212 new InterpolatedConstantTransform(from_pivot)); | 289 new InterpolatedConstantTransform(from_pivot)); |
213 | 290 |
214 pre_transform->SetChild(xform); | 291 pre_transform->SetChild(xform); |
215 xform->SetChild(post_transform.release()); | 292 xform->SetChild(post_transform.release()); |
216 transform_.reset(pre_transform.release()); | 293 transform_.reset(pre_transform.release()); |
217 } | 294 } |
218 | 295 |
| 296 InterpolatedTRSTransform::InterpolatedTRSTransform( |
| 297 const ui::Transform& start_transform, |
| 298 const ui::Transform& end_transform) |
| 299 : InterpolatedTransform() { |
| 300 Init(start_transform, end_transform); |
| 301 } |
| 302 |
| 303 InterpolatedTRSTransform::InterpolatedTRSTransform( |
| 304 const ui::Transform& start_transform, |
| 305 const ui::Transform& end_transform, |
| 306 float start_time, |
| 307 float end_time) |
| 308 : InterpolatedTransform() { |
| 309 Init(start_transform, end_transform); |
| 310 } |
| 311 |
| 312 InterpolatedTRSTransform::~InterpolatedTRSTransform() {} |
| 313 |
| 314 ui::Transform |
| 315 InterpolatedTRSTransform::InterpolateButDoNotCompose(float t) const { |
| 316 if (transform_.get()) { |
| 317 return transform_->Interpolate(t); |
| 318 } |
| 319 return Transform(); |
| 320 } |
| 321 |
| 322 void InterpolatedTRSTransform::Init(const Transform& start_transform, |
| 323 const Transform& end_transform) { |
| 324 gfx::Point start_translation, end_translation; |
| 325 gfx::Point3f start_scale, end_scale; |
| 326 float start_degrees, end_degrees; |
| 327 if (FactorTRS(start_transform, |
| 328 &start_translation, |
| 329 &start_degrees, |
| 330 &start_scale) && |
| 331 FactorTRS(end_transform, |
| 332 &end_translation, |
| 333 &end_degrees, |
| 334 &end_scale)) { |
| 335 scoped_ptr<InterpolatedTranslation> translation( |
| 336 new InterpolatedTranslation(start_translation, end_translation, |
| 337 start_time(), end_time())); |
| 338 |
| 339 scoped_ptr<InterpolatedScale> scale( |
| 340 new InterpolatedScale(start_scale, end_scale, |
| 341 start_time(), end_time())); |
| 342 |
| 343 scoped_ptr<InterpolatedRotation> rotation( |
| 344 new InterpolatedRotation(start_degrees, end_degrees, |
| 345 start_time(), end_time())); |
| 346 |
| 347 rotation->SetChild(translation.release()); |
| 348 scale->SetChild(rotation.release()); |
| 349 transform_.reset(scale.release()); |
| 350 } else { |
| 351 transform_.reset(new InterpolatedConstantTransform(end_transform)); |
| 352 } |
| 353 } |
| 354 |
219 } // namespace ui | 355 } // namespace ui |
OLD | NEW |