#include "cc/animation/keyframed_animation_curve.h"
#include "ui/gfx/animation/tween.h"
-#include "ui/gfx/box_f.h"
+#include "ui/gfx/geometry/box_f.h"
namespace cc {
namespace {
-template <class Keyframe>
-void InsertKeyframe(scoped_ptr<Keyframe> keyframe,
- ScopedPtrVector<Keyframe>& keyframes) {
+template <class KeyframeType>
+void InsertKeyframe(scoped_ptr<KeyframeType> keyframe,
+ ScopedPtrVector<KeyframeType>* keyframes) {
// Usually, the keyframes will be added in order, so this loop would be
// unnecessary and we should skip it if possible.
- if (!keyframes.empty() && keyframe->Time() < keyframes.back()->Time()) {
- for (size_t i = 0; i < keyframes.size(); ++i) {
- if (keyframe->Time() < keyframes[i]->Time()) {
- keyframes.insert(keyframes.begin() + i, keyframe.Pass());
+ if (!keyframes->empty() && keyframe->Time() < keyframes->back()->Time()) {
+ for (size_t i = 0; i < keyframes->size(); ++i) {
+ if (keyframe->Time() < keyframes->at(i)->Time()) {
+ keyframes->insert(keyframes->begin() + i, keyframe.Pass());
return;
}
}
}
- keyframes.push_back(keyframe.Pass());
+ keyframes->push_back(keyframe.Pass());
}
-template <class Keyframes>
-float GetProgress(double t, size_t i, const Keyframes& keyframes) {
- float progress =
- static_cast<float>((t - keyframes[i]->Time()) /
- (keyframes[i + 1]->Time() - keyframes[i]->Time()));
+template <typename KeyframeType>
+double TransformedAnimationTime(
+ const ScopedPtrVector<KeyframeType>& keyframes,
+ const scoped_ptr<TimingFunction>& timing_function,
+ double time) {
+ if (timing_function) {
+ double start_time = keyframes.front()->Time();
+ double duration = keyframes.back()->Time() - start_time;
+ double progress = (time - start_time) / duration;
- if (keyframes[i]->timing_function())
+ time = timing_function->GetValue(progress) * duration + start_time;
+ }
+
+ return time;
+}
+
+template <typename KeyframeType>
+size_t GetActiveKeyframe(const ScopedPtrVector<KeyframeType>& keyframes,
+ double time) {
+ DCHECK_GE(keyframes.size(), 2ul);
+ size_t i = 0;
+ for (; i < keyframes.size() - 2; ++i) { // Last keyframe is never active.
+ if (time < keyframes[i + 1]->Time())
+ break;
+ }
+
+ return i;
+}
+
+template <typename KeyframeType>
+double TransformedKeyframeProgress(
+ const ScopedPtrVector<KeyframeType>& keyframes,
+ double time,
+ size_t i) {
+ double progress = (time - keyframes[i]->Time()) /
+ (keyframes[i + 1]->Time() - keyframes[i]->Time());
+
+ if (keyframes[i]->timing_function()) {
progress = keyframes[i]->timing_function()->GetValue(progress);
+ }
+
return progress;
}
void KeyframedColorAnimationCurve::AddKeyframe(
scoped_ptr<ColorKeyframe> keyframe) {
- InsertKeyframe(keyframe.Pass(), keyframes_);
+ InsertKeyframe(keyframe.Pass(), &keyframes_);
}
double KeyframedColorAnimationCurve::Duration() const {
}
scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const {
- scoped_ptr<KeyframedColorAnimationCurve> to_return(
- KeyframedColorAnimationCurve::Create());
+ scoped_ptr<KeyframedColorAnimationCurve> to_return =
+ KeyframedColorAnimationCurve::Create();
for (size_t i = 0; i < keyframes_.size(); ++i)
to_return->AddKeyframe(keyframes_[i]->Clone());
- return to_return.PassAs<AnimationCurve>();
+
+ if (timing_function_)
+ to_return->SetTimingFunction(timing_function_->Clone());
+
+ return to_return.Pass();
}
SkColor KeyframedColorAnimationCurve::GetValue(double t) const {
if (t >= keyframes_.back()->Time())
return keyframes_.back()->Value();
- size_t i = 0;
- for (; i < keyframes_.size() - 1; ++i) {
- if (t < keyframes_[i + 1]->Time())
- break;
- }
-
- float progress = GetProgress(t, i, keyframes_);
+ t = TransformedAnimationTime(keyframes_, timing_function_, t);
+ size_t i = GetActiveKeyframe(keyframes_, t);
+ double progress = TransformedKeyframeProgress(keyframes_, t, i);
return gfx::Tween::ColorValueBetween(
progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value());
void KeyframedFloatAnimationCurve::AddKeyframe(
scoped_ptr<FloatKeyframe> keyframe) {
- InsertKeyframe(keyframe.Pass(), keyframes_);
+ InsertKeyframe(keyframe.Pass(), &keyframes_);
}
double KeyframedFloatAnimationCurve::Duration() const {
}
scoped_ptr<AnimationCurve> KeyframedFloatAnimationCurve::Clone() const {
- scoped_ptr<KeyframedFloatAnimationCurve> to_return(
- KeyframedFloatAnimationCurve::Create());
+ scoped_ptr<KeyframedFloatAnimationCurve> to_return =
+ KeyframedFloatAnimationCurve::Create();
for (size_t i = 0; i < keyframes_.size(); ++i)
to_return->AddKeyframe(keyframes_[i]->Clone());
- return to_return.PassAs<AnimationCurve>();
+
+ if (timing_function_)
+ to_return->SetTimingFunction(timing_function_->Clone());
+
+ return to_return.Pass();
}
float KeyframedFloatAnimationCurve::GetValue(double t) const {
if (t >= keyframes_.back()->Time())
return keyframes_.back()->Value();
- size_t i = 0;
- for (; i < keyframes_.size() - 1; ++i) {
- if (t < keyframes_[i+1]->Time())
- break;
- }
-
- float progress = GetProgress(t, i, keyframes_);
+ t = TransformedAnimationTime(keyframes_, timing_function_, t);
+ size_t i = GetActiveKeyframe(keyframes_, t);
+ double progress = TransformedKeyframeProgress(keyframes_, t, i);
return keyframes_[i]->Value() +
(keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress;
void KeyframedTransformAnimationCurve::AddKeyframe(
scoped_ptr<TransformKeyframe> keyframe) {
- InsertKeyframe(keyframe.Pass(), keyframes_);
+ InsertKeyframe(keyframe.Pass(), &keyframes_);
}
double KeyframedTransformAnimationCurve::Duration() const {
}
scoped_ptr<AnimationCurve> KeyframedTransformAnimationCurve::Clone() const {
- scoped_ptr<KeyframedTransformAnimationCurve> to_return(
- KeyframedTransformAnimationCurve::Create());
+ scoped_ptr<KeyframedTransformAnimationCurve> to_return =
+ KeyframedTransformAnimationCurve::Create();
for (size_t i = 0; i < keyframes_.size(); ++i)
to_return->AddKeyframe(keyframes_[i]->Clone());
- return to_return.PassAs<AnimationCurve>();
-}
-// Assumes that (*keyframes).front()->Time() < t < (*keyframes).back()-Time().
-template<typename ValueType, typename KeyframeType>
-static ValueType GetCurveValue(const ScopedPtrVector<KeyframeType>* keyframes,
- double t) {
- size_t i = 0;
- for (; i < keyframes->size() - 1; ++i) {
- if (t < (*keyframes)[i+1]->Time())
- break;
- }
-
- double progress = (t - (*keyframes)[i]->Time()) /
- ((*keyframes)[i+1]->Time() - (*keyframes)[i]->Time());
-
- if ((*keyframes)[i]->timing_function())
- progress = (*keyframes)[i]->timing_function()->GetValue(progress);
+ if (timing_function_)
+ to_return->SetTimingFunction(timing_function_->Clone());
- return (*keyframes)[i+1]->Value().Blend((*keyframes)[i]->Value(), progress);
+ return to_return.Pass();
}
gfx::Transform KeyframedTransformAnimationCurve::GetValue(double t) const {
if (t >= keyframes_.back()->Time())
return keyframes_.back()->Value().Apply();
- return GetCurveValue<gfx::Transform, TransformKeyframe>(&keyframes_, t);
+ t = TransformedAnimationTime(keyframes_, timing_function_, t);
+ size_t i = GetActiveKeyframe(keyframes_, t);
+ double progress = TransformedKeyframeProgress(keyframes_, t, i);
+
+ return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress);
}
bool KeyframedTransformAnimationCurve::AnimatedBoundsForBox(
void KeyframedFilterAnimationCurve::AddKeyframe(
scoped_ptr<FilterKeyframe> keyframe) {
- InsertKeyframe(keyframe.Pass(), keyframes_);
+ InsertKeyframe(keyframe.Pass(), &keyframes_);
}
double KeyframedFilterAnimationCurve::Duration() const {
}
scoped_ptr<AnimationCurve> KeyframedFilterAnimationCurve::Clone() const {
- scoped_ptr<KeyframedFilterAnimationCurve> to_return(
- KeyframedFilterAnimationCurve::Create());
+ scoped_ptr<KeyframedFilterAnimationCurve> to_return =
+ KeyframedFilterAnimationCurve::Create();
for (size_t i = 0; i < keyframes_.size(); ++i)
to_return->AddKeyframe(keyframes_[i]->Clone());
- return to_return.PassAs<AnimationCurve>();
+
+ if (timing_function_)
+ to_return->SetTimingFunction(timing_function_->Clone());
+
+ return to_return.Pass();
}
FilterOperations KeyframedFilterAnimationCurve::GetValue(double t) const {
if (t >= keyframes_.back()->Time())
return keyframes_.back()->Value();
- return GetCurveValue<FilterOperations, FilterKeyframe>(&keyframes_, t);
+ t = TransformedAnimationTime(keyframes_, timing_function_, t);
+ size_t i = GetActiveKeyframe(keyframes_, t);
+ double progress = TransformedKeyframeProgress(keyframes_, t, i);
+
+ return keyframes_[i + 1]->Value().Blend(keyframes_[i]->Value(), progress);
}
bool KeyframedFilterAnimationCurve::HasFilterThatMovesPixels() const {