// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "config.h" #include "cc/keyframed_animation_curve.h" using WebKit::WebTransformationMatrix; namespace cc { namespace { template void insertKeyframe(scoped_ptr keyframe, ScopedPtrVector& keyframes) { // Usually, the keyframes will be added in order, so this loop would be unnecessary and // we should skip it if possible. if (!keyframes.isEmpty() && keyframe->time() < keyframes.last()->time()) { for (size_t i = 0; i < keyframes.size(); ++i) { if (keyframe->time() < keyframes[i]->time()) { keyframes.insert(i, keyframe.Pass()); return; } } } keyframes.append(keyframe.Pass()); } scoped_ptr cloneTimingFunction(const TimingFunction* timingFunction) { DCHECK(timingFunction); scoped_ptr curve(timingFunction->clone()); return scoped_ptr(static_cast(curve.release())); } } // namespace Keyframe::Keyframe(double time, scoped_ptr timingFunction) : m_time(time) , m_timingFunction(timingFunction.Pass()) { } Keyframe::~Keyframe() { } double Keyframe::time() const { return m_time; } const TimingFunction* Keyframe::timingFunction() const { return m_timingFunction.get(); } scoped_ptr FloatKeyframe::create(double time, float value, scoped_ptr timingFunction) { return make_scoped_ptr(new FloatKeyframe(time, value, timingFunction.Pass())); } FloatKeyframe::FloatKeyframe(double time, float value, scoped_ptr timingFunction) : Keyframe(time, timingFunction.Pass()) , m_value(value) { } FloatKeyframe::~FloatKeyframe() { } float FloatKeyframe::value() const { return m_value; } scoped_ptr FloatKeyframe::clone() const { scoped_ptr func; if (timingFunction()) func = cloneTimingFunction(timingFunction()); return FloatKeyframe::create(time(), value(), func.Pass()); } scoped_ptr TransformKeyframe::create(double time, const WebKit::WebTransformOperations& value, scoped_ptr timingFunction) { return make_scoped_ptr(new TransformKeyframe(time, value, timingFunction.Pass())); } TransformKeyframe::TransformKeyframe(double time, const WebKit::WebTransformOperations& value, scoped_ptr timingFunction) : Keyframe(time, timingFunction.Pass()) , m_value(value) { } TransformKeyframe::~TransformKeyframe() { } const WebKit::WebTransformOperations& TransformKeyframe::value() const { return m_value; } scoped_ptr TransformKeyframe::clone() const { scoped_ptr func; if (timingFunction()) func = cloneTimingFunction(timingFunction()); return TransformKeyframe::create(time(), value(), func.Pass()); } scoped_ptr KeyframedFloatAnimationCurve::create() { return make_scoped_ptr(new KeyframedFloatAnimationCurve); } KeyframedFloatAnimationCurve::KeyframedFloatAnimationCurve() { } KeyframedFloatAnimationCurve::~KeyframedFloatAnimationCurve() { } void KeyframedFloatAnimationCurve::addKeyframe(scoped_ptr keyframe) { insertKeyframe(keyframe.Pass(), m_keyframes); } double KeyframedFloatAnimationCurve::duration() const { return m_keyframes.last()->time() - m_keyframes.first()->time(); } scoped_ptr KeyframedFloatAnimationCurve::clone() const { scoped_ptr toReturn(KeyframedFloatAnimationCurve::create()); for (size_t i = 0; i < m_keyframes.size(); ++i) toReturn->addKeyframe(m_keyframes[i]->clone()); return toReturn.PassAs(); } float KeyframedFloatAnimationCurve::getValue(double t) const { if (t <= m_keyframes.first()->time()) return m_keyframes.first()->value(); if (t >= m_keyframes.last()->time()) return m_keyframes.last()->value(); size_t i = 0; for (; i < m_keyframes.size() - 1; ++i) { if (t < m_keyframes[i+1]->time()) break; } float progress = static_cast((t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time())); if (m_keyframes[i]->timingFunction()) progress = m_keyframes[i]->timingFunction()->getValue(progress); return m_keyframes[i]->value() + (m_keyframes[i+1]->value() - m_keyframes[i]->value()) * progress; } scoped_ptr KeyframedTransformAnimationCurve::create() { return make_scoped_ptr(new KeyframedTransformAnimationCurve); } KeyframedTransformAnimationCurve::KeyframedTransformAnimationCurve() { } KeyframedTransformAnimationCurve::~KeyframedTransformAnimationCurve() { } void KeyframedTransformAnimationCurve::addKeyframe(scoped_ptr keyframe) { insertKeyframe(keyframe.Pass(), m_keyframes); } double KeyframedTransformAnimationCurve::duration() const { return m_keyframes.last()->time() - m_keyframes.first()->time(); } scoped_ptr KeyframedTransformAnimationCurve::clone() const { scoped_ptr toReturn(KeyframedTransformAnimationCurve::create()); for (size_t i = 0; i < m_keyframes.size(); ++i) toReturn->addKeyframe(m_keyframes[i]->clone()); return toReturn.PassAs(); } WebTransformationMatrix KeyframedTransformAnimationCurve::getValue(double t) const { if (t <= m_keyframes.first()->time()) return m_keyframes.first()->value().apply(); if (t >= m_keyframes.last()->time()) return m_keyframes.last()->value().apply(); size_t i = 0; for (; i < m_keyframes.size() - 1; ++i) { if (t < m_keyframes[i+1]->time()) break; } double progress = (t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time()); if (m_keyframes[i]->timingFunction()) progress = m_keyframes[i]->timingFunction()->getValue(progress); return m_keyframes[i+1]->value().blend(m_keyframes[i]->value(), progress); } } // namespace cc