OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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> | 7 #include <cmath> |
8 | 8 |
9 #ifndef M_PI | 9 #ifndef M_PI |
10 #define M_PI 3.14159265358979323846 | 10 #define M_PI 3.14159265358979323846 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 if (child_.get()) { | 97 if (child_.get()) { |
98 result.ConcatTransform(child_->Interpolate(t)); | 98 result.ConcatTransform(child_->Interpolate(t)); |
99 } | 99 } |
100 return result; | 100 return result; |
101 } | 101 } |
102 | 102 |
103 void InterpolatedTransform::SetChild(InterpolatedTransform* child) { | 103 void InterpolatedTransform::SetChild(InterpolatedTransform* child) { |
104 child_.reset(child); | 104 child_.reset(child); |
105 } | 105 } |
106 | 106 |
107 bool InterpolatedTransform::FactorTRS(const gfx::Transform& transform, | |
108 gfx::Point* translation, | |
109 float* rotation, | |
110 gfx::Point3F* scale) { | |
111 const SkMatrix44& m = transform.matrix(); | |
112 double m00 = SkMScalarToDouble(m.get(0, 0)); | |
113 double m01 = SkMScalarToDouble(m.get(0, 1)); | |
114 double m10 = SkMScalarToDouble(m.get(1, 0)); | |
115 double m11 = SkMScalarToDouble(m.get(1, 1)); | |
116 | |
117 // A factorable 2D TRS matrix must be of the form: | |
118 // [ sx*cos_theta -(sy*sin_theta) 0 tx ] | |
119 // [ sx*sin_theta sy*cos_theta 0 ty ] | |
120 // [ 0 0 1 0 ] | |
121 // [ 0 0 0 1 ] | |
122 if (!IsApproximatelyZero(SkMScalarToDouble(m.get(0, 2))) || | |
123 !IsApproximatelyZero(SkMScalarToDouble(m.get(1, 2))) || | |
124 !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 0))) || | |
125 !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 1))) || | |
126 !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 2)) - 1) || | |
127 !IsApproximatelyZero(SkMScalarToDouble(m.get(2, 3))) || | |
128 !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 0))) || | |
129 !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 1))) || | |
130 !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 2))) || | |
131 !IsApproximatelyZero(SkMScalarToDouble(m.get(3, 3)) - 1)) { | |
132 return false; | |
133 } | |
134 | |
135 double scale_x = std::sqrt(m00 * m00 + m10 * m10); | |
136 double scale_y = std::sqrt(m01 * m01 + m11 * m11); | |
137 | |
138 if (scale_x == 0 || scale_y == 0) | |
139 return false; | |
140 | |
141 double cos_theta = m00 / scale_x; | |
142 double sin_theta = m10 / scale_x; | |
143 | |
144 if (!IsApproximatelyZero(cos_theta - (m11 / scale_y)) || | |
145 !IsApproximatelyZero(sin_theta + (m01 / scale_y)) || | |
146 !IsApproximatelyZero(cos_theta*cos_theta + sin_theta*sin_theta - 1.0f)) | |
147 return false; | |
148 | |
149 double radians = std::atan2(sin_theta, cos_theta); | |
150 | |
151 if (translation) | |
152 *translation = gfx::Point(SkMScalarToFloat(m.get(0, 3)), | |
153 SkMScalarToFloat(m.get(1, 3))); | |
154 if (rotation) | |
155 *rotation = static_cast<float>(radians * 180.0 / M_PI); | |
156 if (scale) | |
157 *scale = gfx::Point3F(static_cast<float>(scale_x), | |
158 static_cast<float>(scale_y), | |
159 1.0f); | |
160 return true; | |
161 } | |
162 | |
163 inline float InterpolatedTransform::ValueBetween(float time, | 107 inline float InterpolatedTransform::ValueBetween(float time, |
164 float start_value, | 108 float start_value, |
165 float end_value) const { | 109 float end_value) const { |
166 // can't handle NaN | 110 // can't handle NaN |
167 DCHECK(time == time && start_time_ == start_time_ && end_time_ == end_time_); | 111 DCHECK(time == time && start_time_ == start_time_ && end_time_ == end_time_); |
168 if (time != time || start_time_ != start_time_ || end_time_ != end_time_) | 112 if (time != time || start_time_ != start_time_ || end_time_ != end_time_) |
169 return start_value; | 113 return start_value; |
170 | 114 |
171 // Ok if equal -- we'll get a step function. Note: if end_time_ == | 115 // Ok if equal -- we'll get a step function. Note: if end_time_ == |
172 // start_time_ == x, then if none of the numbers are NaN, then it | 116 // start_time_ == x, then if none of the numbers are NaN, then it |
(...skipping 29 matching lines...) Expand all Loading... |
202 : InterpolatedTransform(start_time, end_time), | 146 : InterpolatedTransform(start_time, end_time), |
203 start_degrees_(start_degrees), | 147 start_degrees_(start_degrees), |
204 end_degrees_(end_degrees) { | 148 end_degrees_(end_degrees) { |
205 } | 149 } |
206 | 150 |
207 InterpolatedRotation::~InterpolatedRotation() {} | 151 InterpolatedRotation::~InterpolatedRotation() {} |
208 | 152 |
209 gfx::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const { | 153 gfx::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const { |
210 gfx::Transform result; | 154 gfx::Transform result; |
211 float interpolated_degrees = ValueBetween(t, start_degrees_, end_degrees_); | 155 float interpolated_degrees = ValueBetween(t, start_degrees_, end_degrees_); |
212 result.SetRotate(interpolated_degrees); | 156 result.Rotate(interpolated_degrees); |
213 if (t == 0.0f || t == 1.0f) | 157 if (t == 0.0f || t == 1.0f) |
214 MassageRotationIfMultipleOfNinetyDegrees(&result, interpolated_degrees); | 158 MassageRotationIfMultipleOfNinetyDegrees(&result, interpolated_degrees); |
215 return result; | 159 return result; |
216 } | 160 } |
217 | 161 |
218 /////////////////////////////////////////////////////////////////////////////// | 162 /////////////////////////////////////////////////////////////////////////////// |
219 // InterpolatedAxisAngleRotation | 163 // InterpolatedAxisAngleRotation |
220 // | 164 // |
221 | 165 |
222 InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation( | 166 InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation( |
223 gfx::Point3F axis, | 167 const gfx::Vector3dF& axis, |
224 float start_degrees, | 168 float start_degrees, |
225 float end_degrees) | 169 float end_degrees) |
226 : InterpolatedTransform(), | 170 : InterpolatedTransform(), |
227 axis_(axis), | 171 axis_(axis), |
228 start_degrees_(start_degrees), | 172 start_degrees_(start_degrees), |
229 end_degrees_(end_degrees) { | 173 end_degrees_(end_degrees) { |
230 } | 174 } |
231 | 175 |
232 InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation( | 176 InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation( |
233 gfx::Point3F axis, | 177 const gfx::Vector3dF& axis, |
234 float start_degrees, | 178 float start_degrees, |
235 float end_degrees, | 179 float end_degrees, |
236 float start_time, | 180 float start_time, |
237 float end_time) | 181 float end_time) |
238 : InterpolatedTransform(start_time, end_time), | 182 : InterpolatedTransform(start_time, end_time), |
239 axis_(axis), | 183 axis_(axis), |
240 start_degrees_(start_degrees), | 184 start_degrees_(start_degrees), |
241 end_degrees_(end_degrees) { | 185 end_degrees_(end_degrees) { |
242 } | 186 } |
243 | 187 |
244 InterpolatedAxisAngleRotation::~InterpolatedAxisAngleRotation() {} | 188 InterpolatedAxisAngleRotation::~InterpolatedAxisAngleRotation() {} |
245 | 189 |
246 gfx::Transform | 190 gfx::Transform |
247 InterpolatedAxisAngleRotation::InterpolateButDoNotCompose(float t) const { | 191 InterpolatedAxisAngleRotation::InterpolateButDoNotCompose(float t) const { |
248 gfx::Transform result; | 192 gfx::Transform result; |
249 result.SetRotateAbout(axis_, ValueBetween(t, start_degrees_, end_degrees_)); | 193 result.RotateAbout(axis_, ValueBetween(t, start_degrees_, end_degrees_)); |
250 return result; | 194 return result; |
251 } | 195 } |
252 | 196 |
253 /////////////////////////////////////////////////////////////////////////////// | 197 /////////////////////////////////////////////////////////////////////////////// |
254 // InterpolatedScale | 198 // InterpolatedScale |
255 // | 199 // |
256 | 200 |
257 InterpolatedScale::InterpolatedScale(float start_scale, float end_scale) | 201 InterpolatedScale::InterpolatedScale(float start_scale, float end_scale) |
258 : InterpolatedTransform(), | 202 : InterpolatedTransform(), |
259 start_scale_(gfx::Point3F(start_scale, start_scale, start_scale)), | 203 start_scale_(gfx::Point3F(start_scale, start_scale, start_scale)), |
(...skipping 23 matching lines...) Expand all Loading... |
283 end_scale_(end_scale) { | 227 end_scale_(end_scale) { |
284 } | 228 } |
285 | 229 |
286 InterpolatedScale::~InterpolatedScale() {} | 230 InterpolatedScale::~InterpolatedScale() {} |
287 | 231 |
288 gfx::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const { | 232 gfx::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const { |
289 gfx::Transform result; | 233 gfx::Transform result; |
290 float scale_x = ValueBetween(t, start_scale_.x(), end_scale_.x()); | 234 float scale_x = ValueBetween(t, start_scale_.x(), end_scale_.x()); |
291 float scale_y = ValueBetween(t, start_scale_.y(), end_scale_.y()); | 235 float scale_y = ValueBetween(t, start_scale_.y(), end_scale_.y()); |
292 // TODO(vollick) 3d xforms. | 236 // TODO(vollick) 3d xforms. |
293 result.SetScale(scale_x, scale_y); | 237 result.Scale(scale_x, scale_y); |
294 return result; | 238 return result; |
295 } | 239 } |
296 | 240 |
297 /////////////////////////////////////////////////////////////////////////////// | 241 /////////////////////////////////////////////////////////////////////////////// |
298 // InterpolatedTranslation | 242 // InterpolatedTranslation |
299 // | 243 // |
300 | 244 |
301 InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos, | 245 InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos, |
302 const gfx::Point& end_pos) | 246 const gfx::Point& end_pos) |
303 : InterpolatedTransform(), | 247 : InterpolatedTransform(), |
304 start_pos_(start_pos), | 248 start_pos_(start_pos), |
305 end_pos_(end_pos) { | 249 end_pos_(end_pos) { |
306 } | 250 } |
307 | 251 |
308 InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos, | 252 InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos, |
309 const gfx::Point& end_pos, | 253 const gfx::Point& end_pos, |
310 float start_time, | 254 float start_time, |
311 float end_time) | 255 float end_time) |
312 : InterpolatedTransform(start_time, end_time), | 256 : InterpolatedTransform(start_time, end_time), |
313 start_pos_(start_pos), | 257 start_pos_(start_pos), |
314 end_pos_(end_pos) { | 258 end_pos_(end_pos) { |
315 } | 259 } |
316 | 260 |
317 InterpolatedTranslation::~InterpolatedTranslation() {} | 261 InterpolatedTranslation::~InterpolatedTranslation() {} |
318 | 262 |
319 gfx::Transform | 263 gfx::Transform |
320 InterpolatedTranslation::InterpolateButDoNotCompose(float t) const { | 264 InterpolatedTranslation::InterpolateButDoNotCompose(float t) const { |
321 gfx::Transform result; | 265 gfx::Transform result; |
322 // TODO(vollick) 3d xforms. | 266 // TODO(vollick) 3d xforms. |
323 result.SetTranslate(ValueBetween(t, start_pos_.x(), end_pos_.x()), | 267 result.Translate(ValueBetween(t, start_pos_.x(), end_pos_.x()), |
324 ValueBetween(t, start_pos_.y(), end_pos_.y())); | 268 ValueBetween(t, start_pos_.y(), end_pos_.y())); |
325 return result; | 269 return result; |
326 } | 270 } |
327 | 271 |
328 /////////////////////////////////////////////////////////////////////////////// | 272 /////////////////////////////////////////////////////////////////////////////// |
329 // InterpolatedConstantTransform | 273 // InterpolatedConstantTransform |
330 // | 274 // |
331 | 275 |
332 InterpolatedConstantTransform::InterpolatedConstantTransform( | 276 InterpolatedConstantTransform::InterpolatedConstantTransform( |
333 const gfx::Transform& transform) | 277 const gfx::Transform& transform) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 if (transform_.get()) { | 313 if (transform_.get()) { |
370 return transform_->Interpolate(t); | 314 return transform_->Interpolate(t); |
371 } | 315 } |
372 return gfx::Transform(); | 316 return gfx::Transform(); |
373 } | 317 } |
374 | 318 |
375 void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot, | 319 void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot, |
376 InterpolatedTransform* xform) { | 320 InterpolatedTransform* xform) { |
377 gfx::Transform to_pivot; | 321 gfx::Transform to_pivot; |
378 gfx::Transform from_pivot; | 322 gfx::Transform from_pivot; |
379 to_pivot.SetTranslate(-pivot.x(), -pivot.y()); | 323 to_pivot.Translate(-pivot.x(), -pivot.y()); |
380 from_pivot.SetTranslate(pivot.x(), pivot.y()); | 324 from_pivot.Translate(pivot.x(), pivot.y()); |
381 | 325 |
382 scoped_ptr<InterpolatedTransform> pre_transform( | 326 scoped_ptr<InterpolatedTransform> pre_transform( |
383 new InterpolatedConstantTransform(to_pivot)); | 327 new InterpolatedConstantTransform(to_pivot)); |
384 scoped_ptr<InterpolatedTransform> post_transform( | 328 scoped_ptr<InterpolatedTransform> post_transform( |
385 new InterpolatedConstantTransform(from_pivot)); | 329 new InterpolatedConstantTransform(from_pivot)); |
386 | 330 |
387 pre_transform->SetChild(xform); | 331 pre_transform->SetChild(xform); |
388 xform->SetChild(post_transform.release()); | 332 xform->SetChild(post_transform.release()); |
389 transform_.reset(pre_transform.release()); | 333 transform_.reset(pre_transform.release()); |
390 } | 334 } |
391 | 335 |
392 InterpolatedTRSTransform::InterpolatedTRSTransform( | 336 InterpolatedMatrixTransform::InterpolatedMatrixTransform( |
393 const gfx::Transform& start_transform, | 337 const gfx::Transform& start_transform, |
394 const gfx::Transform& end_transform) | 338 const gfx::Transform& end_transform) |
395 : InterpolatedTransform() { | 339 : InterpolatedTransform() { |
396 Init(start_transform, end_transform); | 340 Init(start_transform, end_transform); |
397 } | 341 } |
398 | 342 |
399 InterpolatedTRSTransform::InterpolatedTRSTransform( | 343 InterpolatedMatrixTransform::InterpolatedMatrixTransform( |
400 const gfx::Transform& start_transform, | 344 const gfx::Transform& start_transform, |
401 const gfx::Transform& end_transform, | 345 const gfx::Transform& end_transform, |
402 float start_time, | 346 float start_time, |
403 float end_time) | 347 float end_time) |
404 : InterpolatedTransform() { | 348 : InterpolatedTransform() { |
405 Init(start_transform, end_transform); | 349 Init(start_transform, end_transform); |
406 } | 350 } |
407 | 351 |
408 InterpolatedTRSTransform::~InterpolatedTRSTransform() {} | 352 InterpolatedMatrixTransform::~InterpolatedMatrixTransform() {} |
409 | 353 |
410 gfx::Transform | 354 gfx::Transform |
411 InterpolatedTRSTransform::InterpolateButDoNotCompose(float t) const { | 355 InterpolatedMatrixTransform::InterpolateButDoNotCompose(float t) const { |
412 if (transform_.get()) { | 356 gfx::DecomposedTransform blended; |
413 return transform_->Interpolate(t); | 357 bool success = gfx::BlendDecomposedTransforms(&blended, |
414 } | 358 end_decomp_, |
415 return gfx::Transform(); | 359 start_decomp_, |
| 360 t); |
| 361 DCHECK(success); |
| 362 return gfx::ComposeTransform(blended); |
416 } | 363 } |
417 | 364 |
418 void InterpolatedTRSTransform::Init(const gfx::Transform& start_transform, | 365 void InterpolatedMatrixTransform::Init(const gfx::Transform& start_transform, |
419 const gfx::Transform& end_transform) { | 366 const gfx::Transform& end_transform) { |
420 gfx::Point start_translation, end_translation; | 367 bool success = gfx::DecomposeTransform(&start_decomp_, start_transform); |
421 gfx::Point3F start_scale, end_scale; | 368 DCHECK(success); |
422 float start_degrees, end_degrees; | 369 success = gfx::DecomposeTransform(&end_decomp_, end_transform); |
423 if (FactorTRS(start_transform, | 370 DCHECK(success); |
424 &start_translation, | |
425 &start_degrees, | |
426 &start_scale) && | |
427 FactorTRS(end_transform, | |
428 &end_translation, | |
429 &end_degrees, | |
430 &end_scale)) { | |
431 scoped_ptr<InterpolatedTranslation> translation( | |
432 new InterpolatedTranslation(start_translation, end_translation, | |
433 start_time(), end_time())); | |
434 | |
435 scoped_ptr<InterpolatedScale> scale( | |
436 new InterpolatedScale(start_scale, end_scale, | |
437 start_time(), end_time())); | |
438 | |
439 scoped_ptr<InterpolatedRotation> rotation( | |
440 new InterpolatedRotation(start_degrees, end_degrees, | |
441 start_time(), end_time())); | |
442 | |
443 rotation->SetChild(translation.release()); | |
444 scale->SetChild(rotation.release()); | |
445 transform_.reset(scale.release()); | |
446 } else { | |
447 transform_.reset(new InterpolatedConstantTransform(end_transform)); | |
448 } | |
449 } | 371 } |
450 | 372 |
451 } // namespace ui | 373 } // namespace ui |
OLD | NEW |