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