| OLD | NEW |
| (Empty) |
| 1 // Copyright 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. | |
| 4 | |
| 5 #include <algorithm> | |
| 6 | |
| 7 #include "cc/animation/keyframed_animation_curve.h" | |
| 8 #include "cc/base/time_util.h" | |
| 9 #include "ui/gfx/animation/tween.h" | |
| 10 #include "ui/gfx/geometry/box_f.h" | |
| 11 | |
| 12 namespace cc { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 template <class KeyframeType> | |
| 17 void InsertKeyframe(scoped_ptr<KeyframeType> keyframe, | |
| 18 ScopedPtrVector<KeyframeType>* keyframes) { | |
| 19 // Usually, the keyframes will be added in order, so this loop would be | |
| 20 // unnecessary and we should skip it if possible. | |
| 21 if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) { | |
| 22 for (size_t i = 0; i < keyframes->size(); ++i) { | |
| 23 if (keyframe->Time() < keyframes->at(i)->Time()) { | |
| 24 keyframes->insert(keyframes->begin() + i, keyframe.Pass()); | |
| 25 return; | |
| 26 } | |
| 27 } | |
| 28 } | |
| 29 | |
| 30 keyframes->push_back(keyframe.Pass()); | |
| 31 } | |
| 32 | |
| 33 template <typename KeyframeType> | |
| 34 base::TimeDelta TransformedAnimationTime( | |
| 35 const ScopedPtrVector<KeyframeType>& keyframes, | |
| 36 const scoped_ptr<TimingFunction>& timing_function, | |
| 37 base::TimeDelta time) { | |
| 38 if (timing_function) { | |
| 39 base::TimeDelta start_time = keyframes.front()->Time(); | |
| 40 base::TimeDelta duration = | |
| 41 keyframes.back()->Time() - keyframes.front()->Time(); | |
| 42 double progress = TimeUtil::Divide(time - start_time, duration); | |
| 43 | |
| 44 time = TimeUtil::Scale(duration, timing_function->GetValue(progress)) + | |
| 45 start_time; | |
| 46 } | |
| 47 | |
| 48 return time; | |
| 49 } | |
| 50 | |
| 51 template <typename KeyframeType> | |
| 52 size_t GetActiveKeyframe(const ScopedPtrVector<KeyframeType>& keyframes, | |
| 53 base::TimeDelta time) { | |
| 54 DCHECK_GE(keyframes.size(), 2ul); | |
| 55 size_t i = 0; | |
| 56 for (; i < keyframes.size() - 2; ++i) { // Last keyframe is never active. | |
| 57 if (time < keyframes[i + 1]->Time()) | |
| 58 break; | |
| 59 } | |
| 60 | |
| 61 return i; | |
| 62 } | |
| 63 | |
| 64 template <typename KeyframeType> | |
| 65 double TransformedKeyframeProgress( | |
| 66 const ScopedPtrVector<KeyframeType>& keyframes, | |
| 67 base::TimeDelta time, | |
| 68 size_t i) { | |
| 69 double progress = | |
| 70 TimeUtil::Divide(time - keyframes[i]->Time(), | |
| 71 keyframes[i + 1]->Time() - keyframes[i]->Time()); | |
| 72 | |
| 73 if (keyframes[i]->timing_function()) { | |
| 74 progress = keyframes[i]->timing_function()->GetValue(progress); | |
| 75 } | |
| 76 | |
| 77 return progress; | |
| 78 } | |
| 79 | |
| 80 } // namespace | |
| 81 | |
| 82 Keyframe::Keyframe(base::TimeDelta time, | |
| 83 scoped_ptr<TimingFunction> timing_function) | |
| 84 : time_(time), timing_function_(timing_function.Pass()) { | |
| 85 } | |
| 86 | |
| 87 Keyframe::~Keyframe() {} | |
| 88 | |
| 89 base::TimeDelta Keyframe::Time() const { | |
| 90 return time_; | |
| 91 } | |
| 92 | |
| 93 scoped_ptr<ColorKeyframe> ColorKeyframe::Create( | |
| 94 base::TimeDelta time, | |
| 95 SkColor value, | |
| 96 scoped_ptr<TimingFunction> timing_function) { | |
| 97 return make_scoped_ptr( | |
| 98 new ColorKeyframe(time, value, timing_function.Pass())); | |
| 99 } | |
| 100 | |
| 101 ColorKeyframe::ColorKeyframe(base::TimeDelta time, | |
| 102 SkColor value, | |
| 103 scoped_ptr<TimingFunction> timing_function) | |
| 104 : Keyframe(time, timing_function.Pass()), value_(value) { | |
| 105 } | |
| 106 | |
| 107 ColorKeyframe::~ColorKeyframe() {} | |
| 108 | |
| 109 SkColor ColorKeyframe::Value() const { return value_; } | |
| 110 | |
| 111 scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const { | |
| 112 scoped_ptr<TimingFunction> func; | |
| 113 if (timing_function()) | |
| 114 func = timing_function()->Clone(); | |
| 115 return ColorKeyframe::Create(Time(), Value(), func.Pass()); | |
| 116 } | |
| 117 | |
| 118 scoped_ptr<FloatKeyframe> FloatKeyframe::Create( | |
| 119 base::TimeDelta time, | |
| 120 float value, | |
| 121 scoped_ptr<TimingFunction> timing_function) { | |
| 122 return make_scoped_ptr( | |
| 123 new FloatKeyframe(time, value, timing_function.Pass())); | |
| 124 } | |
| 125 | |
| 126 FloatKeyframe::FloatKeyframe(base::TimeDelta time, | |
| 127 float value, | |
| 128 scoped_ptr<TimingFunction> timing_function) | |
| 129 : Keyframe(time, timing_function.Pass()), value_(value) { | |
| 130 } | |
| 131 | |
| 132 FloatKeyframe::~FloatKeyframe() {} | |
| 133 | |
| 134 float FloatKeyframe::Value() const { | |
| 135 return value_; | |
| 136 } | |
| 137 | |
| 138 scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const { | |
| 139 scoped_ptr<TimingFunction> func; | |
| 140 if (timing_function()) | |
| 141 func = timing_function()->Clone(); | |
| 142 return FloatKeyframe::Create(Time(), Value(), func.Pass()); | |
| 143 } | |
| 144 | |
| 145 scoped_ptr<TransformKeyframe> TransformKeyframe::Create( | |
| 146 base::TimeDelta time, | |
| 147 const TransformOperations& value, | |
| 148 scoped_ptr<TimingFunction> timing_function) { | |
| 149 return make_scoped_ptr( | |
| 150 new TransformKeyframe(time, value, timing_function.Pass())); | |
| 151 } | |
| 152 | |
| 153 TransformKeyframe::TransformKeyframe(base::TimeDelta time, | |
| 154 const TransformOperations& value, | |
| 155 scoped_ptr<TimingFunction> timing_function) | |
| 156 : Keyframe(time, timing_function.Pass()), value_(value) { | |
| 157 } | |
| 158 | |
| 159 TransformKeyframe::~TransformKeyframe() {} | |
| 160 | |
| 161 const TransformOperations& TransformKeyframe::Value() const { | |
| 162 return value_; | |
| 163 } | |
| 164 | |
| 165 scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const { | |
| 166 scoped_ptr<TimingFunction> func; | |
| 167 if (timing_function()) | |
| 168 func = timing_function()->Clone(); | |
| 169 return TransformKeyframe::Create(Time(), Value(), func.Pass()); | |
| 170 } | |
| 171 | |
| 172 scoped_ptr<FilterKeyframe> FilterKeyframe::Create( | |
| 173 base::TimeDelta time, | |
| 174 const FilterOperations& value, | |
| 175 scoped_ptr<TimingFunction> timing_function) { | |
| 176 return make_scoped_ptr( | |
| 177 new FilterKeyframe(time, value, timing_function.Pass())); | |
| 178 } | |
| 179 | |
| 180 FilterKeyframe::FilterKeyframe(base::TimeDelta time, | |
| 181 const FilterOperations& value, | |
| 182 scoped_ptr<TimingFunction> timing_function) | |
| 183 : Keyframe(time, timing_function.Pass()), value_(value) { | |
| 184 } | |
| 185 | |
| 186 FilterKeyframe::~FilterKeyframe() {} | |
| 187 | |
| 188 const FilterOperations& FilterKeyframe::Value() const { | |
| 189 return value_; | |
| 190 } | |
| 191 | |
| 192 scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const { | |
| 193 scoped_ptr<TimingFunction> func; | |
| 194 if (timing_function()) | |
| 195 func = timing_function()->Clone(); | |
| 196 return FilterKeyframe::Create(Time(), Value(), func.Pass()); | |
| 197 } | |
| 198 | |
| 199 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve:: | |
| 200 Create() { | |
| 201 return make_scoped_ptr(new KeyframedColorAnimationCurve); | |
| 202 } | |
| 203 | |
| 204 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {} | |
| 205 | |
| 206 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {} | |
| 207 | |
| 208 void KeyframedColorAnimationCurve::AddKeyframe( | |
| 209 scoped_ptr<ColorKeyframe> keyframe) { | |
| 210 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
| 211 } | |
| 212 | |
| 213 base::TimeDelta KeyframedColorAnimationCurve::Duration() const { | |
| 214 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
| 215 } | |
| 216 | |
| 217 scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const { | |
| 218 scoped_ptr<KeyframedColorAnimationCurve> to_return = | |
| 219 KeyframedColorAnimationCurve::Create(); | |
| 220 for (size_t i = 0; i < keyframes_.size(); ++i) | |
| 221 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
| 222 | |
| 223 if (timing_function_) | |
| 224 to_return->SetTimingFunction(timing_function_->Clone()); | |
| 225 | |
| 226 return to_return.Pass(); | |
| 227 } | |
| 228 | |
| 229 SkColor KeyframedColorAnimationCurve::GetValue(base::TimeDelta t) const { | |
| 230 if (t <= keyframes_.front()->Time()) | |
| 231 return keyframes_.front()->Value(); | |
| 232 | |
| 233 if (t >= keyframes_.back()->Time()) | |
| 234 return keyframes_.back()->Value(); | |
| 235 | |
| 236 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
| 237 size_t i = GetActiveKeyframe(keyframes_, t); | |
| 238 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
| 239 | |
| 240 return gfx::Tween::ColorValueBetween( | |
| 241 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value()); | |
| 242 } | |
| 243 | |
| 244 // KeyframedFloatAnimationCurve | |
| 245 | |
| 246 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: | |
| 247 Create() { | |
| 248 return make_scoped_ptr(new KeyframedFloatAnimationCurve); | |
| 249 } | |
| 250 | |
| 251 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {} | |
| 252 | |
| 253 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {} | |
| 254 | |
| 255 void KeyframedFloatAnimationCurve::AddKeyframe( | |
| 256 scoped_ptr<FloatKeyframe> keyframe) { | |
| 257 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
| 258 } | |
| 259 | |
| 260 base::TimeDelta KeyframedFloatAnimationCurve::Duration() const { | |
| 261 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
| 262 } | |
| 263 | |
| 264 scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const { | |
| 265 scoped_ptr<KeyframedFloatAnimationCurve> to_return = | |
| 266 KeyframedFloatAnimationCurve::Create(); | |
| 267 for (size_t i = 0; i < keyframes_.size(); ++i) | |
| 268 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
| 269 | |
| 270 if (timing_function_) | |
| 271 to_return->SetTimingFunction(timing_function_->Clone()); | |
| 272 | |
| 273 return to_return.Pass(); | |
| 274 } | |
| 275 | |
| 276 float KeyframedFloatAnimationCurve::GetValue(base::TimeDelta t) const { | |
| 277 if (t <= keyframes_.front()->Time()) | |
| 278 return keyframes_.front()->Value(); | |
| 279 | |
| 280 if (t >= keyframes_.back()->Time()) | |
| 281 return keyframes_.back()->Value(); | |
| 282 | |
| 283 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
| 284 size_t i = GetActiveKeyframe(keyframes_, t); | |
| 285 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
| 286 | |
| 287 return keyframes_[i]->Value() + | |
| 288 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress; | |
| 289 } | |
| 290 | |
| 291 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve:: | |
| 292 Create() { | |
| 293 return make_scoped_ptr(new KeyframedTransformAnimationCurve); | |
| 294 } | |
| 295 | |
| 296 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {} | |
| 297 | |
| 298 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {} | |
| 299 | |
| 300 void KeyframedTransformAnimationCurve::AddKeyframe( | |
| 301 scoped_ptr<TransformKeyframe> keyframe) { | |
| 302 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
| 303 } | |
| 304 | |
| 305 base::TimeDelta KeyframedTransformAnimationCurve::Duration() const { | |
| 306 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
| 307 } | |
| 308 | |
| 309 scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const { | |
| 310 scoped_ptr<KeyframedTransformAnimationCurve> to_return = | |
| 311 KeyframedTransformAnimationCurve::Create(); | |
| 312 for (size_t i = 0; i < keyframes_.size(); ++i) | |
| 313 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
| 314 | |
| 315 if (timing_function_) | |
| 316 to_return->SetTimingFunction(timing_function_->Clone()); | |
| 317 | |
| 318 return to_return.Pass(); | |
| 319 } | |
| 320 | |
| 321 gfx::Transform KeyframedTransformAnimationCurve::GetValue( | |
| 322 base::TimeDelta t) const { | |
| 323 if (t <= keyframes_.front()->Time()) | |
| 324 return keyframes_.front()->Value().Apply(); | |
| 325 | |
| 326 if (t >= keyframes_.back()->Time()) | |
| 327 return keyframes_.back()->Value().Apply(); | |
| 328 | |
| 329 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
| 330 size_t i = GetActiveKeyframe(keyframes_, t); | |
| 331 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
| 332 | |
| 333 return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress); | |
| 334 } | |
| 335 | |
| 336 bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox( | |
| 337 const gfx::BoxF& box, | |
| 338 gfx::BoxF* bounds) const { | |
| 339 DCHECK_GE(keyframes_.size(), 2ul); | |
| 340 *bounds = gfx::BoxF(); | |
| 341 for (size_t i = 0; i < keyframes_.size() - 1; ++i) { | |
| 342 gfx::BoxF bounds_for_step; | |
| 343 float min_progress = 0.0; | |
| 344 float max_progress = 1.0; | |
| 345 if (keyframes_[i]->timing_function()) | |
| 346 keyframes_[i]->timing_function()->Range(&min_progress, &max_progress); | |
| 347 if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box, | |
| 348 keyframes_[i]->Value(), | |
| 349 min_progress, | |
| 350 max_progress, | |
| 351 &bounds_for_step)) | |
| 352 return false; | |
| 353 bounds->Union(bounds_for_step); | |
| 354 } | |
| 355 return true; | |
| 356 } | |
| 357 | |
| 358 bool KeyframedTransformAnimationCurve::AffectsScale() const { | |
| 359 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
| 360 if (keyframes_[i]->Value().AffectsScale()) | |
| 361 return true; | |
| 362 } | |
| 363 return false; | |
| 364 } | |
| 365 | |
| 366 bool KeyframedTransformAnimationCurve::PreservesAxisAlignment() const { | |
| 367 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
| 368 if (!keyframes_[i]->Value().PreservesAxisAlignment()) | |
| 369 return false; | |
| 370 } | |
| 371 return true; | |
| 372 } | |
| 373 | |
| 374 bool KeyframedTransformAnimationCurve::IsTranslation() const { | |
| 375 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
| 376 if (!keyframes_[i]->Value().IsTranslation() && | |
| 377 !keyframes_[i]->Value().IsIdentity()) | |
| 378 return false; | |
| 379 } | |
| 380 return true; | |
| 381 } | |
| 382 | |
| 383 bool KeyframedTransformAnimationCurve::MaximumTargetScale( | |
| 384 bool forward_direction, | |
| 385 float* max_scale) const { | |
| 386 DCHECK_GE(keyframes_.size(), 2ul); | |
| 387 *max_scale = 0.f; | |
| 388 | |
| 389 // If |forward_direction| is true, then skip the first frame, otherwise | |
| 390 // skip the last frame, since that is the original position in the animation. | |
| 391 size_t start = 1; | |
| 392 size_t end = keyframes_.size(); | |
| 393 if (!forward_direction) { | |
| 394 --start; | |
| 395 --end; | |
| 396 } | |
| 397 | |
| 398 for (size_t i = start; i < end; ++i) { | |
| 399 gfx::Vector3dF target_scale_for_segment; | |
| 400 if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment)) | |
| 401 return false; | |
| 402 float max_scale_for_segment = | |
| 403 fmax(std::abs(target_scale_for_segment.x()), | |
| 404 fmax(std::abs(target_scale_for_segment.y()), | |
| 405 std::abs(target_scale_for_segment.z()))); | |
| 406 *max_scale = fmax(*max_scale, max_scale_for_segment); | |
| 407 } | |
| 408 return true; | |
| 409 } | |
| 410 | |
| 411 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve:: | |
| 412 Create() { | |
| 413 return make_scoped_ptr(new KeyframedFilterAnimationCurve); | |
| 414 } | |
| 415 | |
| 416 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {} | |
| 417 | |
| 418 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {} | |
| 419 | |
| 420 void KeyframedFilterAnimationCurve::AddKeyframe( | |
| 421 scoped_ptr<FilterKeyframe> keyframe) { | |
| 422 InsertKeyframe(keyframe.Pass(), &keyframes_); | |
| 423 } | |
| 424 | |
| 425 base::TimeDelta KeyframedFilterAnimationCurve::Duration() const { | |
| 426 return keyframes_.back()->Time() - keyframes_.front()->Time(); | |
| 427 } | |
| 428 | |
| 429 scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const { | |
| 430 scoped_ptr<KeyframedFilterAnimationCurve> to_return = | |
| 431 KeyframedFilterAnimationCurve::Create(); | |
| 432 for (size_t i = 0; i < keyframes_.size(); ++i) | |
| 433 to_return->AddKeyframe(keyframes_[i]->Clone()); | |
| 434 | |
| 435 if (timing_function_) | |
| 436 to_return->SetTimingFunction(timing_function_->Clone()); | |
| 437 | |
| 438 return to_return.Pass(); | |
| 439 } | |
| 440 | |
| 441 FilterOperations KeyframedFilterAnimationCurve::GetValue( | |
| 442 base::TimeDelta t) const { | |
| 443 if (t <= keyframes_.front()->Time()) | |
| 444 return keyframes_.front()->Value(); | |
| 445 | |
| 446 if (t >= keyframes_.back()->Time()) | |
| 447 return keyframes_.back()->Value(); | |
| 448 | |
| 449 t = TransformedAnimationTime(keyframes_, timing_function_, t); | |
| 450 size_t i = GetActiveKeyframe(keyframes_, t); | |
| 451 double progress = TransformedKeyframeProgress(keyframes_, t, i); | |
| 452 | |
| 453 return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress); | |
| 454 } | |
| 455 | |
| 456 bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const { | |
| 457 for (size_t i = 0; i < keyframes_.size(); ++i) { | |
| 458 if (keyframes_[i]->Value().HasFilterThatMovesPixels()) { | |
| 459 return true; | |
| 460 } | |
| 461 } | |
| 462 return false; | |
| 463 } | |
| 464 | |
| 465 } // namespace cc | |
| OLD | NEW |