Chromium Code Reviews| 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); |
|
danakj
2012/11/16 19:46:12
I didn't like this change with Set at first, but s
| |
| 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 gfx::Vector3dF axis, |
|
danakj
2012/11/16 19:46:12
const&
Ian Vollick
2012/11/16 21:51:24
Done, here and in the other spots.
| |
| 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 gfx::Vector3dF axis, |
|
danakj
2012/11/16 19:46:12
const&
| |
| 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 { |
|
danakj
2012/11/16 19:46:12
Shawn can you double check the mathy bits here? I
shawnsingh
2012/11/16 20:51:25
It seems like the implementation of this function
Ian Vollick
2012/11/16 21:51:24
This class is analogous to WebTransformOperations.
| |
| 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 |