keyframed_animation_curve.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2012 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <algorithm> 6a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/animation/keyframed_animation_curve.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/animation/tween.h" 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ui/gfx/box_f.h" 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace cc { 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochtemplate <class Keyframe> 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid InsertKeyframe(scoped_ptr<Keyframe> keyframe, 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ScopedPtrVector<Keyframe>& keyframes) { 18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Usually, the keyframes will be added in order, so this loop would be 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // unnecessary and we should skip it if possible. 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) { 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < keyframes.size(); ++i) { 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (keyframe->Time() < keyframes[i]->Time()) { 23a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch keyframes.insert(keyframes.begin() + i, keyframe.Pass()); 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 25a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch } 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch keyframes.push_back(keyframe.Pass()); 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochtemplate <class Keyframes> 33a3f7b4e666c476898878fa745f637129375cd889Ben Murdochfloat GetProgress(double t, size_t i, const Keyframes& keyframes) { 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch float progress = 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static_cast<float>((t - keyframes[i]->Time()) / 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (keyframes[i + 1]->Time() - keyframes[i]->Time())); 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (keyframes[i]->timing_function()) 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch progress = keyframes[i]->timing_function()->GetValue(progress); 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return progress; 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<TimingFunction> CloneTimingFunction( 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const TimingFunction* timing_function) { 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(timing_function); 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<AnimationCurve> curve(timing_function->Clone()); 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return scoped_ptr<TimingFunction>( 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<TimingFunction*>(curve.release())); 49a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 53a3f7b4e666c476898878fa745f637129375cd889Ben MurdochKeyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function) 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : time_(time), 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch timing_function_(timing_function.Pass()) {} 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochKeyframe::~Keyframe() {} 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochdouble Keyframe::Time() const { 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return time_; 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<ColorKeyframe> ColorKeyframe::Create( 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double time, 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkColor value, 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<TimingFunction> timing_function) { 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return make_scoped_ptr( 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new ColorKeyframe(time, value, timing_function.Pass())); 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochColorKeyframe::ColorKeyframe(double time, 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SkColor value, 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<TimingFunction> timing_function) 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) : Keyframe(time, timing_function.Pass()), 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) value_(value) {} 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 77a3f7b4e666c476898878fa745f637129375cd889Ben MurdochColorKeyframe::~ColorKeyframe() {} 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 79effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSkColor ColorKeyframe::Value() const { return value_; } 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const { 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<TimingFunction> func; 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (timing_function()) 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch func = CloneTimingFunction(timing_function()); 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return ColorKeyframe::Create(Time(), Value(), func.Pass()); 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochscoped_ptr<FloatKeyframe> FloatKeyframe::Create( 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch double time, 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch float value, 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<TimingFunction> timing_function) { 92a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch return make_scoped_ptr( 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new FloatKeyframe(time, value, timing_function.Pass())); 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFloatKeyframe::FloatKeyframe(double time, 97a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch float value, 98 scoped_ptr<TimingFunction> timing_function) 99 : Keyframe(time, timing_function.Pass()), 100 value_(value) {} 101 102FloatKeyframe::~FloatKeyframe() {} 103 104float FloatKeyframe::Value() const { 105 return value_; 106} 107 108scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const { 109 scoped_ptr<TimingFunction> func; 110 if (timing_function()) 111 func = CloneTimingFunction(timing_function()); 112 return FloatKeyframe::Create(Time(), Value(), func.Pass()); 113} 114 115scoped_ptr<TransformKeyframe> TransformKeyframe::Create( 116 double time, 117 const TransformOperations& value, 118 scoped_ptr<TimingFunction> timing_function) { 119 return make_scoped_ptr( 120 new TransformKeyframe(time, value, timing_function.Pass())); 121} 122 123TransformKeyframe::TransformKeyframe(double time, 124 const TransformOperations& value, 125 scoped_ptr<TimingFunction> timing_function) 126 : Keyframe(time, timing_function.Pass()), 127 value_(value) {} 128 129TransformKeyframe::~TransformKeyframe() {} 130 131const TransformOperations& TransformKeyframe::Value() const { 132 return value_; 133} 134 135scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const { 136 scoped_ptr<TimingFunction> func; 137 if (timing_function()) 138 func = CloneTimingFunction(timing_function()); 139 return TransformKeyframe::Create(Time(), Value(), func.Pass()); 140} 141 142scoped_ptr<FilterKeyframe> FilterKeyframe::Create( 143 double time, 144 const FilterOperations& value, 145 scoped_ptr<TimingFunction> timing_function) { 146 return make_scoped_ptr( 147 new FilterKeyframe(time, value, timing_function.Pass())); 148} 149 150FilterKeyframe::FilterKeyframe(double time, 151 const FilterOperations& value, 152 scoped_ptr<TimingFunction> timing_function) 153 : Keyframe(time, timing_function.Pass()), 154 value_(value) {} 155 156FilterKeyframe::~FilterKeyframe() {} 157 158const FilterOperations& FilterKeyframe::Value() const { 159 return value_; 160} 161 162scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const { 163 scoped_ptr<TimingFunction> func; 164 if (timing_function()) 165 func = CloneTimingFunction(timing_function()); 166 return FilterKeyframe::Create(Time(), Value(), func.Pass()); 167} 168 169scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve:: 170 Create() { 171 return make_scoped_ptr(new KeyframedColorAnimationCurve); 172} 173 174KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {} 175 176KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {} 177 178void KeyframedColorAnimationCurve::AddKeyframe( 179 scoped_ptr<ColorKeyframe> keyframe) { 180 InsertKeyframe(keyframe.Pass(), keyframes_); 181} 182 183double KeyframedColorAnimationCurve::Duration() const { 184 return keyframes_.back()->Time() - keyframes_.front()->Time(); 185} 186 187scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const { 188 scoped_ptr<KeyframedColorAnimationCurve> to_return( 189 KeyframedColorAnimationCurve::Create()); 190 for (size_t i = 0; i < keyframes_.size(); ++i) 191 to_return->AddKeyframe(keyframes_[i]->Clone()); 192 return to_return.PassAs<AnimationCurve>(); 193} 194 195SkColor KeyframedColorAnimationCurve::GetValue(double t) const { 196 if (t <= keyframes_.front()->Time()) 197 return keyframes_.front()->Value(); 198 199 if (t >= keyframes_.back()->Time()) 200 return keyframes_.back()->Value(); 201 202 size_t i = 0; 203 for (; i < keyframes_.size() - 1; ++i) { 204 if (t < keyframes_[i + 1]->Time()) 205 break; 206 } 207 208 float progress = GetProgress(t, i, keyframes_); 209 210 return gfx::Tween::ColorValueBetween( 211 progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value()); 212} 213 214// KeyframedFloatAnimationCurve 215 216scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: 217 Create() { 218 return make_scoped_ptr(new KeyframedFloatAnimationCurve); 219} 220 221KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {} 222 223KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {} 224 225void KeyframedFloatAnimationCurve::AddKeyframe( 226 scoped_ptr<FloatKeyframe> keyframe) { 227 InsertKeyframe(keyframe.Pass(), keyframes_); 228} 229 230double KeyframedFloatAnimationCurve::Duration() const { 231 return keyframes_.back()->Time() - keyframes_.front()->Time(); 232} 233 234scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const { 235 scoped_ptr<KeyframedFloatAnimationCurve> to_return( 236 KeyframedFloatAnimationCurve::Create()); 237 for (size_t i = 0; i < keyframes_.size(); ++i) 238 to_return->AddKeyframe(keyframes_[i]->Clone()); 239 return to_return.PassAs<AnimationCurve>(); 240} 241 242float KeyframedFloatAnimationCurve::GetValue(double t) const { 243 if (t <= keyframes_.front()->Time()) 244 return keyframes_.front()->Value(); 245 246 if (t >= keyframes_.back()->Time()) 247 return keyframes_.back()->Value(); 248 249 size_t i = 0; 250 for (; i < keyframes_.size() - 1; ++i) { 251 if (t < keyframes_[i+1]->Time()) 252 break; 253 } 254 255 float progress = GetProgress(t, i, keyframes_); 256 257 return keyframes_[i]->Value() + 258 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress; 259} 260 261scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve:: 262 Create() { 263 return make_scoped_ptr(new KeyframedTransformAnimationCurve); 264} 265 266KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {} 267 268KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {} 269 270void KeyframedTransformAnimationCurve::AddKeyframe( 271 scoped_ptr<TransformKeyframe> keyframe) { 272 InsertKeyframe(keyframe.Pass(), keyframes_); 273} 274 275double KeyframedTransformAnimationCurve::Duration() const { 276 return keyframes_.back()->Time() - keyframes_.front()->Time(); 277} 278 279scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const { 280 scoped_ptr<KeyframedTransformAnimationCurve> to_return( 281 KeyframedTransformAnimationCurve::Create()); 282 for (size_t i = 0; i < keyframes_.size(); ++i) 283 to_return->AddKeyframe(keyframes_[i]->Clone()); 284 return to_return.PassAs<AnimationCurve>(); 285} 286 287// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time(). 288template<typename ValueType, typename KeyframeType> 289static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes, 290 double t) { 291 size_t i = 0; 292 for (; i < keyframes->size() - 1; ++i) { 293 if (t < (*keyframes)[i+1]->Time()) 294 break; 295 } 296 297 double progress = (t - (*keyframes)[i]->Time()) / 298 ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time()); 299 300 if ((*keyframes)[i]->timing_function()) 301 progress = (*keyframes)[i]->timing_function()->GetValue(progress); 302 303 return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress); 304} 305 306gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const { 307 if (t <= keyframes_.front()->Time()) 308 return keyframes_.front()->Value().Apply(); 309 310 if (t >= keyframes_.back()->Time()) 311 return keyframes_.back()->Value().Apply(); 312 313 return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t); 314} 315 316bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox( 317 const gfx::BoxF& box, 318 gfx::BoxF* bounds) const { 319 DCHECK_GE(keyframes_.size(), 2ul); 320 *bounds = gfx::BoxF(); 321 for (size_t i = 0; i < keyframes_.size() - 1; ++i) { 322 gfx::BoxF bounds_for_step; 323 float min_progress = 0.0; 324 float max_progress = 1.0; 325 if (keyframes_[i]->timing_function()) 326 keyframes_[i]->timing_function()->Range(&min_progress, &max_progress); 327 if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box, 328 keyframes_[i]->Value(), 329 min_progress, 330 max_progress, 331 &bounds_for_step)) 332 return false; 333 bounds->Union(bounds_for_step); 334 } 335 return true; 336} 337 338bool KeyframedTransformAnimationCurve::AffectsScale() const { 339 for (size_t i = 0; i < keyframes_.size(); ++i) { 340 if (keyframes_[i]->Value().AffectsScale()) 341 return true; 342 } 343 return false; 344} 345 346bool KeyframedTransformAnimationCurve::IsTranslation() const { 347 for (size_t i = 0; i < keyframes_.size(); ++i) { 348 if (!keyframes_[i]->Value().IsTranslation() && 349 !keyframes_[i]->Value().IsIdentity()) 350 return false; 351 } 352 return true; 353} 354 355bool KeyframedTransformAnimationCurve::MaximumScale(float* max_scale) const { 356 DCHECK_GE(keyframes_.size(), 2ul); 357 *max_scale = 0.f; 358 for (size_t i = 1; i < keyframes_.size(); ++i) { 359 float min_progress = 0.f; 360 float max_progress = 1.f; 361 if (keyframes_[i - 1]->timing_function()) 362 keyframes_[i - 1]->timing_function()->Range(&min_progress, &max_progress); 363 364 float max_scale_for_segment = 0.f; 365 if (!keyframes_[i]->Value().MaximumScale(keyframes_[i - 1]->Value(), 366 min_progress, 367 max_progress, 368 &max_scale_for_segment)) 369 return false; 370 371 *max_scale = std::max(*max_scale, max_scale_for_segment); 372 } 373 return true; 374} 375 376scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve:: 377 Create() { 378 return make_scoped_ptr(new KeyframedFilterAnimationCurve); 379} 380 381KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {} 382 383KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {} 384 385void KeyframedFilterAnimationCurve::AddKeyframe( 386 scoped_ptr<FilterKeyframe> keyframe) { 387 InsertKeyframe(keyframe.Pass(), keyframes_); 388} 389 390double KeyframedFilterAnimationCurve::Duration() const { 391 return keyframes_.back()->Time() - keyframes_.front()->Time(); 392} 393 394scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const { 395 scoped_ptr<KeyframedFilterAnimationCurve> to_return( 396 KeyframedFilterAnimationCurve::Create()); 397 for (size_t i = 0; i < keyframes_.size(); ++i) 398 to_return->AddKeyframe(keyframes_[i]->Clone()); 399 return to_return.PassAs<AnimationCurve>(); 400} 401 402FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const { 403 if (t <= keyframes_.front()->Time()) 404 return keyframes_.front()->Value(); 405 406 if (t >= keyframes_.back()->Time()) 407 return keyframes_.back()->Value(); 408 409 return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t); 410} 411 412bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const { 413 for (size_t i = 0; i < keyframes_.size(); ++i) { 414 if (keyframes_[i]->Value().HasFilterThatMovesPixels()) { 415 return true; 416 } 417 } 418 return false; 419} 420 421} // namespace cc 422