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