12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <algorithm>
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/animation/keyframed_animation_curve.h"
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ui/gfx/animation/tween.h"
93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "ui/gfx/box_f.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template <class Keyframe>
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    ScopedPtrVector<Keyframe>& keyframes) {
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Usually, the keyframes will be added in order, so this loop would be
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // unnecessary and we should skip it if possible.
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (size_t i = 0; i < keyframes.size(); ++i) {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (keyframe->Time() < keyframes[i]->Time()) {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        keyframes.insert(keyframes.begin() + i, keyframe.Pass());
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  keyframes.push_back(keyframe.Pass());
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)template <class Keyframes>
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)float GetProgress(double t, size_t i, const Keyframes& keyframes) {
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float progress =
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      static_cast<float>((t - keyframes[i]->Time()) /
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         (keyframes[i + 1]->Time() - keyframes[i]->Time()));
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (keyframes[i]->timing_function())
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    progress = keyframes[i]->timing_function()->GetValue(progress);
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return progress;
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Keyframe::Keyframe(double time, scoped_ptr<TimingFunction> timing_function)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : time_(time),
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      timing_function_(timing_function.Pass()) {}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Keyframe::~Keyframe() {}
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double Keyframe::Time() const {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return time_;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)scoped_ptr<ColorKeyframe> ColorKeyframe::Create(
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    double time,
571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    SkColor value,
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<TimingFunction> timing_function) {
591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return make_scoped_ptr(
601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ColorKeyframe(time, value, timing_function.Pass()));
611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ColorKeyframe::ColorKeyframe(double time,
641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             SkColor value,
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             scoped_ptr<TimingFunction> timing_function)
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    : Keyframe(time, timing_function.Pass()),
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      value_(value) {}
681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ColorKeyframe::~ColorKeyframe() {}
701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)SkColor ColorKeyframe::Value() const { return value_; }
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const {
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<TimingFunction> func;
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (timing_function())
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    func = timing_function()->Clone();
771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return ColorKeyframe::Create(Time(), Value(), func.Pass());
781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<FloatKeyframe> FloatKeyframe::Create(
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double time,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float value,
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<TimingFunction> timing_function) {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new FloatKeyframe(time, value, timing_function.Pass()));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FloatKeyframe::FloatKeyframe(double time,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             float value,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             scoped_ptr<TimingFunction> timing_function)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : Keyframe(time, timing_function.Pass()),
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value_(value) {}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FloatKeyframe::~FloatKeyframe() {}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)float FloatKeyframe::Value() const {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return value_;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<FloatKeyframe> FloatKeyframe::Clone() const {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TimingFunction> func;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (timing_function())
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    func = timing_function()->Clone();
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return FloatKeyframe::Create(Time(), Value(), func.Pass());
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<TransformKeyframe> TransformKeyframe::Create(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double time,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const TransformOperations& value,
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<TimingFunction> timing_function) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new TransformKeyframe(time, value, timing_function.Pass()));
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TransformKeyframe::TransformKeyframe(double time,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const TransformOperations& value,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     scoped_ptr<TimingFunction> timing_function)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : Keyframe(time, timing_function.Pass()),
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      value_(value) {}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TransformKeyframe::~TransformKeyframe() {}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const TransformOperations& TransformKeyframe::Value() const {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return value_;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<TransformKeyframe> TransformKeyframe::Clone() const {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TimingFunction> func;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (timing_function())
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    func = timing_function()->Clone();
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return TransformKeyframe::Create(Time(), Value(), func.Pass());
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochscoped_ptr<FilterKeyframe> FilterKeyframe::Create(
135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    double time,
136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const FilterOperations& value,
137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_ptr<TimingFunction> timing_function) {
138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return make_scoped_ptr(
139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new FilterKeyframe(time, value, timing_function.Pass()));
140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochFilterKeyframe::FilterKeyframe(double time,
143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               const FilterOperations& value,
144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               scoped_ptr<TimingFunction> timing_function)
145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : Keyframe(time, timing_function.Pass()),
146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      value_(value) {}
147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochFilterKeyframe::~FilterKeyframe() {}
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst FilterOperations& FilterKeyframe::Value() const {
151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return value_;
152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochscoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const {
155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<TimingFunction> func;
156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (timing_function())
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    func = timing_function()->Clone();
158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return FilterKeyframe::Create(Time(), Value(), func.Pass());
159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve::
1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    Create() {
1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return make_scoped_ptr(new KeyframedColorAnimationCurve);
1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {}
1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {}
1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void KeyframedColorAnimationCurve::AddKeyframe(
1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    scoped_ptr<ColorKeyframe> keyframe) {
1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  InsertKeyframe(keyframe.Pass(), keyframes_);
1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)double KeyframedColorAnimationCurve::Duration() const {
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return keyframes_.back()->Time() - keyframes_.front()->Time();
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_ptr<KeyframedColorAnimationCurve> to_return(
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      KeyframedColorAnimationCurve::Create());
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (size_t i = 0; i < keyframes_.size(); ++i)
1831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    to_return->AddKeyframe(keyframes_[i]->Clone());
1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return to_return.PassAs<AnimationCurve>();
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (t <= keyframes_.front()->Time())
1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return keyframes_.front()->Value();
1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (t >= keyframes_.back()->Time())
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return keyframes_.back()->Value();
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  size_t i = 0;
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (; i < keyframes_.size() - 1; ++i) {
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (t < keyframes_[i + 1]->Time())
1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float progress = GetProgress(t, i, keyframes_);
2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return gfx::Tween::ColorValueBetween(
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// KeyframedFloatAnimationCurve
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve::
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Create() {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(new KeyframedFloatAnimationCurve);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() {}
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() {}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KeyframedFloatAnimationCurve::AddKeyframe(
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<FloatKeyframe> keyframe) {
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InsertKeyframe(keyframe.Pass(), keyframes_);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double KeyframedFloatAnimationCurve::Duration() const {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return keyframes_.back()->Time() - keyframes_.front()->Time();
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<KeyframedFloatAnimationCurve> to_return(
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      KeyframedFloatAnimationCurve::Create());
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < keyframes_.size(); ++i)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    to_return->AddKeyframe(keyframes_[i]->Clone());
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return to_return.PassAs<AnimationCurve>();
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)float KeyframedFloatAnimationCurve::GetValue(double t) const {
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (t <= keyframes_.front()->Time())
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return keyframes_.front()->Value();
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (t >= keyframes_.back()->Time())
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return keyframes_.back()->Value();
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t i = 0;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; i < keyframes_.size() - 1; ++i) {
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (t < keyframes_[i+1]->Time())
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  float progress = GetProgress(t, i, keyframes_);
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return keyframes_[i]->Value() +
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<KeyframedTransformAnimationCurve> KeyframedTransformAnimationCurve::
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Create() {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return make_scoped_ptr(new KeyframedTransformAnimationCurve);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() {}
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() {}
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void KeyframedTransformAnimationCurve::AddKeyframe(
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<TransformKeyframe> keyframe) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InsertKeyframe(keyframe.Pass(), keyframes_);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double KeyframedTransformAnimationCurve::Duration() const {
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return keyframes_.back()->Time() - keyframes_.front()->Time();
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<KeyframedTransformAnimationCurve> to_return(
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      KeyframedTransformAnimationCurve::Create());
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < keyframes_.size(); ++i)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    to_return->AddKeyframe(keyframes_[i]->Clone());
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return to_return.PassAs<AnimationCurve>();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochtemplate<typename ValueType, typename KeyframeType>
281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                               double t) {
283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  size_t i = 0;
284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (; i < keyframes->size() - 1; ++i) {
285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (t < (*keyframes)[i+1]->Time())
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  double progress = (t - (*keyframes)[i]->Time()) /
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if ((*keyframes)[i]->timing_function())
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    progress = (*keyframes)[i]->timing_function()->GetValue(progress);
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (t <= keyframes_.front()->Time())
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return keyframes_.front()->Value().Apply();
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (t >= keyframes_.back()->Time())
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return keyframes_.back()->Value().Apply();
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const gfx::BoxF& box,
3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    gfx::BoxF* bounds) const {
3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_GE(keyframes_.size(), 2ul);
3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  *bounds = gfx::BoxF();
3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < keyframes_.size() - 1; ++i) {
3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    gfx::BoxF bounds_for_step;
3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    float min_progress = 0.0;
3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    float max_progress = 1.0;
3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (keyframes_[i]->timing_function())
3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      keyframes_[i]->timing_function()->Range(&min_progress, &max_progress);
3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!keyframes_[i+1]->Value().BlendedBoundsForBox(box,
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      keyframes_[i]->Value(),
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      min_progress,
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      max_progress,
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                      &bounds_for_step))
3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    bounds->Union(bounds_for_step);
3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
330e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochbool KeyframedTransformAnimationCurve::AffectsScale() const {
331e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (size_t i = 0; i < keyframes_.size(); ++i) {
332e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    if (keyframes_[i]->Value().AffectsScale())
333e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      return true;
334e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
335e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return false;
336e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
337e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool KeyframedTransformAnimationCurve::IsTranslation() const {
339c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < keyframes_.size(); ++i) {
340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!keyframes_[i]->Value().IsTranslation() &&
341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        !keyframes_[i]->Value().IsIdentity())
342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return false;
343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
344c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
345c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
346c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3471675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdochbool KeyframedTransformAnimationCurve::MaximumTargetScale(
3481675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    bool forward_direction,
3491675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    float* max_scale) const {
350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK_GE(keyframes_.size(), 2ul);
351c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  *max_scale = 0.f;
352c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3531675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // If |forward_direction| is true, then skip the first frame, otherwise
3541675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  // skip the last frame, since that is the original position in the animation.
3551675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  size_t start = 1;
3561675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  size_t end = keyframes_.size();
3571675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  if (!forward_direction) {
3581675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    --start;
3591675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    --end;
3601675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  }
3611675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch
3621675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch  for (size_t i = start; i < end; ++i) {
3631675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    gfx::Vector3dF target_scale_for_segment;
3641675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    if (!keyframes_[i]->Value().ScaleComponent(&target_scale_for_segment))
3651675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      return false;
3661675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    float max_scale_for_segment =
3671675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch        fmax(std::abs(target_scale_for_segment.x()),
3681675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch             fmax(std::abs(target_scale_for_segment.y()),
3691675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch                  std::abs(target_scale_for_segment.z())));
3701675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch    *max_scale = fmax(*max_scale, max_scale_for_segment);
371c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return true;
373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochscoped_ptr<KeyframedFilterAnimationCurve> KeyframedFilterAnimationCurve::
376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Create() {
377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return make_scoped_ptr(new KeyframedFilterAnimationCurve);
378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochKeyframedFilterAnimationCurve::KeyframedFilterAnimationCurve() {}
381ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochKeyframedFilterAnimationCurve::~KeyframedFilterAnimationCurve() {}
383ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid KeyframedFilterAnimationCurve::AddKeyframe(
385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_ptr<FilterKeyframe> keyframe) {
386ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  InsertKeyframe(keyframe.Pass(), keyframes_);
387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
388ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochdouble KeyframedFilterAnimationCurve::Duration() const {
390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return keyframes_.back()->Time() - keyframes_.front()->Time();
391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
393ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochscoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
394ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<KeyframedFilterAnimationCurve> to_return(
395ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      KeyframedFilterAnimationCurve::Create());
396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (size_t i = 0; i < keyframes_.size(); ++i)
397ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    to_return->AddKeyframe(keyframes_[i]->Clone());
398ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return to_return.PassAs<AnimationCurve>();
399ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
400ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochFilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
402ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (t <= keyframes_.front()->Time())
403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return keyframes_.front()->Value();
404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (t >= keyframes_.back()->Time())
406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return keyframes_.back()->Value();
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < keyframes_.size(); ++i) {
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (keyframes_[i]->Value().HasFilterThatMovesPixels()) {
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return true;
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return false;
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
421