keyframed_animation_curve.cc revision 3551c9c881056c480085172ff9840cab31610854
16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Copyright 2012 The Chromium Authors. All rights reserved. 26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Use of this source code is governed by a BSD-style license that can be 36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// found in the LICENSE file. 46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cc/animation/keyframed_animation_curve.h" 66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ui/gfx/box_f.h" 76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace cc { 96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace { 116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtemplate <class Keyframe> 136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid InsertKeyframe(scoped_ptr<Keyframe> keyframe, 146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org ScopedPtrVector<Keyframe>& keyframes) { 156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // Usually, the keyframes will be added in order, so this loop would be 166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org // unnecessary and we should skip it if possible. 176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) { 186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org for (size_t i = 0; i < keyframes.size(); ++i) { 196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (keyframe->Time() < keyframes[i]->Time()) { 206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org keyframes.insert(keyframes.begin() + i, keyframe.Pass()); 216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return; 226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org keyframes.push_back(keyframe.Pass()); 276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<TimingFunction> CloneTimingFunction( 306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const TimingFunction* timing_function) { 316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org DCHECK(timing_function); 326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<AnimationCurve> curve(timing_function->Clone()); 336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return scoped_ptr<TimingFunction>( 346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org static_cast<TimingFunction*>(curve.release())); 356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} // namespace 386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgKeyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function) 406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org : time_(time), 416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org timing_function_(timing_function.Pass()) {} 426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgKeyframe::~Keyframe() {} 446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgdouble Keyframe::Time() const { 466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return time_; 476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<FloatKeyframe> FloatKeyframe::Create( 506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org double time, 516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org float value, 526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> timing_function) { 536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return make_scoped_ptr( 546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org new FloatKeyframe(time, value, timing_function.Pass())); 556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgFloatKeyframe::FloatKeyframe(double time, 586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org float value, 596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> timing_function) 606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org : Keyframe(time, timing_function.Pass()), 616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org value_(value) {} 626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgFloatKeyframe::~FloatKeyframe() {} 646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfloat FloatKeyframe::Value() const { 666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return value_; 676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const { 706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> func; 716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (timing_function()) 726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org func = CloneTimingFunction(timing_function()); 736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return FloatKeyframe::Create(Time(), Value(), func.Pass()); 746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<TransformKeyframe> TransformKeyframe::Create( 776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org double time, 786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const TransformOperations& value, 796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> timing_function) { 806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return make_scoped_ptr( 816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org new TransformKeyframe(time, value, timing_function.Pass())); 826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgTransformKeyframe::TransformKeyframe(double time, 856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const TransformOperations& value, 866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> timing_function) 876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org : Keyframe(time, timing_function.Pass()), 886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org value_(value) {} 896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgTransformKeyframe::~TransformKeyframe() {} 916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst TransformOperations& TransformKeyframe::Value() const { 936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return value_; 946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const { 976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> func; 986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (timing_function()) 996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org func = CloneTimingFunction(timing_function()); 1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return TransformKeyframe::Create(Time(), Value(), func.Pass()); 1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<FilterKeyframe> FilterKeyframe::Create( 1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org double time, 1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const FilterOperations& value, 1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> timing_function) { 1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return make_scoped_ptr( 1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org new FilterKeyframe(time, value, timing_function.Pass())); 1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgFilterKeyframe::FilterKeyframe(double time, 1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const FilterOperations& value, 1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> timing_function) 1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org : Keyframe(time, timing_function.Pass()), 1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org value_(value) {} 1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgFilterKeyframe::~FilterKeyframe() {} 1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst FilterOperations& FilterKeyframe::Value() const { 1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return value_; 1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const { 1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org scoped_ptr<TimingFunction> func; 1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (timing_function()) 1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org func = CloneTimingFunction(timing_function()); 1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return FilterKeyframe::Create(Time(), Value(), func.Pass()); 1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgscoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: 1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org Create() { 1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return make_scoped_ptr(new KeyframedFloatAnimationCurve); 1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgKeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {} 136 137KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {} 138 139void KeyframedFloatAnimationCurve::AddKeyframe( 140 scoped_ptr<FloatKeyframe> keyframe) { 141 InsertKeyframe(keyframe.Pass(), keyframes_); 142} 143 144double KeyframedFloatAnimationCurve::Duration() const { 145 return keyframes_.back()->Time() - keyframes_.front()->Time(); 146} 147 148scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const { 149 scoped_ptr<KeyframedFloatAnimationCurve> to_return( 150 KeyframedFloatAnimationCurve::Create()); 151 for (size_t i = 0; i < keyframes_.size(); ++i) 152 to_return->AddKeyframe(keyframes_[i]->Clone()); 153 return to_return.PassAs<AnimationCurve>(); 154} 155 156float KeyframedFloatAnimationCurve::GetValue(double t) const { 157 if (t <= keyframes_.front()->Time()) 158 return keyframes_.front()->Value(); 159 160 if (t >= keyframes_.back()->Time()) 161 return keyframes_.back()->Value(); 162 163 size_t i = 0; 164 for (; i < keyframes_.size() - 1; ++i) { 165 if (t < keyframes_[i+1]->Time()) 166 break; 167 } 168 169 float progress = 170 static_cast<float>((t - keyframes_[i]->Time()) / 171 (keyframes_[i+1]->Time() - keyframes_[i]->Time())); 172 173 if (keyframes_[i]->timing_function()) 174 progress = keyframes_[i]->timing_function()->GetValue(progress); 175 176 return keyframes_[i]->Value() + 177 (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress; 178} 179 180scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve:: 181 Create() { 182 return make_scoped_ptr(new KeyframedTransformAnimationCurve); 183} 184 185KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {} 186 187KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {} 188 189void KeyframedTransformAnimationCurve::AddKeyframe( 190 scoped_ptr<TransformKeyframe> keyframe) { 191 InsertKeyframe(keyframe.Pass(), keyframes_); 192} 193 194double KeyframedTransformAnimationCurve::Duration() const { 195 return keyframes_.back()->Time() - keyframes_.front()->Time(); 196} 197 198scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const { 199 scoped_ptr<KeyframedTransformAnimationCurve> to_return( 200 KeyframedTransformAnimationCurve::Create()); 201 for (size_t i = 0; i < keyframes_.size(); ++i) 202 to_return->AddKeyframe(keyframes_[i]->Clone()); 203 return to_return.PassAs<AnimationCurve>(); 204} 205 206// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time(). 207template<typename ValueType, typename KeyframeType> 208static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes, 209 double t) { 210 size_t i = 0; 211 for (; i < keyframes->size() - 1; ++i) { 212 if (t < (*keyframes)[i+1]->Time()) 213 break; 214 } 215 216 double progress = (t - (*keyframes)[i]->Time()) / 217 ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time()); 218 219 if ((*keyframes)[i]->timing_function()) 220 progress = (*keyframes)[i]->timing_function()->GetValue(progress); 221 222 return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress); 223} 224 225gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const { 226 if (t <= keyframes_.front()->Time()) 227 return keyframes_.front()->Value().Apply(); 228 229 if (t >= keyframes_.back()->Time()) 230 return keyframes_.back()->Value().Apply(); 231 232 return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t); 233} 234 235bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox( 236 const gfx::BoxF& box, 237 gfx::BoxF* bounds) const { 238 DCHECK_GE(keyframes_.size(), 2ul); 239 *bounds = gfx::BoxF(); 240 for (size_t i = 0; i < keyframes_.size() - 1; ++i) { 241 gfx::BoxF bounds_for_step; 242 float min_progress = 0.0; 243 float max_progress = 1.0; 244 if (keyframes_[i]->timing_function()) 245 keyframes_[i]->timing_function()->Range(&min_progress, &max_progress); 246 if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box, 247 keyframes_[i]->Value(), 248 min_progress, 249 max_progress, 250 &bounds_for_step)) 251 return false; 252 bounds->Union(bounds_for_step); 253 } 254 return true; 255} 256 257scoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve:: 258 Create() { 259 return make_scoped_ptr(new KeyframedFilterAnimationCurve); 260} 261 262KeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {} 263 264KeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {} 265 266void KeyframedFilterAnimationCurve::AddKeyframe( 267 scoped_ptr<FilterKeyframe> keyframe) { 268 InsertKeyframe(keyframe.Pass(), keyframes_); 269} 270 271double KeyframedFilterAnimationCurve::Duration() const { 272 return keyframes_.back()->Time() - keyframes_.front()->Time(); 273} 274 275scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const { 276 scoped_ptr<KeyframedFilterAnimationCurve> to_return( 277 KeyframedFilterAnimationCurve::Create()); 278 for (size_t i = 0; i < keyframes_.size(); ++i) 279 to_return->AddKeyframe(keyframes_[i]->Clone()); 280 return to_return.PassAs<AnimationCurve>(); 281} 282 283FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const { 284 if (t <= keyframes_.front()->Time()) 285 return keyframes_.front()->Value(); 286 287 if (t >= keyframes_.back()->Time()) 288 return keyframes_.back()->Value(); 289 290 return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t); 291} 292 293} // namespace cc 294