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