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 11 namespace cc { 12 13 namespace { 14 15 template <class Keyframe> 16 void 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 32 template <class Keyframes> 33 float 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 45 Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function) 46 : time_(time), 47 timing_function_(timing_function.Pass()) {} 48 49 Keyframe::~Keyframe() {} 50 51 double Keyframe::Time() const { 52 return time_; 53 } 54 55 scoped_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 63 ColorKeyframe::ColorKeyframe(double time, 64 SkColor value, 65 scoped_ptr<TimingFunction> timing_function) 66 : Keyframe(time, timing_function.Pass()), 67 value_(value) {} 68 69 ColorKeyframe::~ColorKeyframe() {} 70 71 SkColor ColorKeyframe::Value() const { return value_; } 72 73 scoped_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 80 scoped_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 88 FloatKeyframe::FloatKeyframe(double time, 89 float value, 90 scoped_ptr<TimingFunction> timing_function) 91 : Keyframe(time, timing_function.Pass()), 92 value_(value) {} 93 94 FloatKeyframe::~FloatKeyframe() {} 95 96 float FloatKeyframe::Value() const { 97 return value_; 98 } 99 100 scoped_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 107 scoped_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 115 TransformKeyframe::TransformKeyframe(double time, 116 const TransformOperations& value, 117 scoped_ptr<TimingFunction> timing_function) 118 : Keyframe(time, timing_function.Pass()), 119 value_(value) {} 120 121 TransformKeyframe::~TransformKeyframe() {} 122 123 const TransformOperations& TransformKeyframe::Value() const { 124 return value_; 125 } 126 127 scoped_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 134 scoped_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 142 FilterKeyframe::FilterKeyframe(double time, 143 const FilterOperations& value, 144 scoped_ptr<TimingFunction> timing_function) 145 : Keyframe(time, timing_function.Pass()), 146 value_(value) {} 147 148 FilterKeyframe::~FilterKeyframe() {} 149 150 const FilterOperations& FilterKeyframe::Value() const { 151 return value_; 152 } 153 154 scoped_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 161 scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve:: 162 Create() { 163 return make_scoped_ptr(new KeyframedColorAnimationCurve); 164 } 165 166 KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {} 167 168 KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {} 169 170 void KeyframedColorAnimationCurve::AddKeyframe( 171 scoped_ptr<ColorKeyframe> keyframe) { 172 InsertKeyframe(keyframe.Pass(), keyframes_); 173 } 174 175 double KeyframedColorAnimationCurve::Duration() const { 176 return keyframes_.back()->Time() - keyframes_.front()->Time(); 177 } 178 179 scoped_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 187 SkColor 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 208 scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: 209 Create() { 210 return make_scoped_ptr(new KeyframedFloatAnimationCurve); 211 } 212 213 KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {} 214 215 KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {} 216 217 void KeyframedFloatAnimationCurve::AddKeyframe( 218 scoped_ptr<FloatKeyframe> keyframe) { 219 InsertKeyframe(keyframe.Pass(), keyframes_); 220 } 221 222 double KeyframedFloatAnimationCurve::Duration() const { 223 return keyframes_.back()->Time() - keyframes_.front()->Time(); 224 } 225 226 scoped_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 234 float 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 253 scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve:: 254 Create() { 255 return make_scoped_ptr(new KeyframedTransformAnimationCurve); 256 } 257 258 KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {} 259 260 KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {} 261 262 void KeyframedTransformAnimationCurve::AddKeyframe( 263 scoped_ptr<TransformKeyframe> keyframe) { 264 InsertKeyframe(keyframe.Pass(), keyframes_); 265 } 266 267 double KeyframedTransformAnimationCurve::Duration() const { 268 return keyframes_.back()->Time() - keyframes_.front()->Time(); 269 } 270 271 scoped_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(). 280 template<typename ValueType, typename KeyframeType> 281 static 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 298 gfx::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 308 bool 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 330 bool 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 338 bool 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 347 bool 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 375 scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve:: 376 Create() { 377 return make_scoped_ptr(new KeyframedFilterAnimationCurve); 378 } 379 380 KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {} 381 382 KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {} 383 384 void KeyframedFilterAnimationCurve::AddKeyframe( 385 scoped_ptr<FilterKeyframe> keyframe) { 386 InsertKeyframe(keyframe.Pass(), keyframes_); 387 } 388 389 double KeyframedFilterAnimationCurve::Duration() const { 390 return keyframes_.back()->Time() - keyframes_.front()->Time(); 391 } 392 393 scoped_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 401 FilterOperations 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 411 bool 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