CCKeyframedAnimationCurve.cpp [plain text]
#include "config.h"
#include "cc/CCKeyframedAnimationCurve.h"
#include "IdentityTransformOperation.h"
#include "Matrix3DTransformOperation.h"
#include "MatrixTransformOperation.h"
#include "PerspectiveTransformOperation.h"
#include "RotateTransformOperation.h"
#include "ScaleTransformOperation.h"
#include "SkewTransformOperation.h"
#include "TranslateTransformOperation.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
namespace {
template <class Keyframe>
void insertKeyframe(PassOwnPtr<Keyframe> popKeyframe, Vector<OwnPtr<Keyframe> >& keyframes)
{
OwnPtr<Keyframe> keyframe = popKeyframe;
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.release());
return;
}
}
}
keyframes.append(keyframe.release());
}
PassOwnPtr<CCTimingFunction> cloneTimingFunction(const CCTimingFunction* timingFunction)
{
ASSERT(timingFunction);
OwnPtr<CCAnimationCurve> curve(timingFunction->clone());
return adoptPtr(static_cast<CCTimingFunction*>(curve.leakPtr()));
}
}
CCKeyframe::CCKeyframe(double time, PassOwnPtr<CCTimingFunction> timingFunction)
: m_time(time)
, m_timingFunction(timingFunction)
{
}
CCKeyframe::~CCKeyframe()
{
}
double CCKeyframe::time() const
{
return m_time;
}
const CCTimingFunction* CCKeyframe::timingFunction() const
{
return m_timingFunction.get();
}
PassOwnPtr<CCFloatKeyframe> CCFloatKeyframe::create(double time, float value, PassOwnPtr<CCTimingFunction> timingFunction)
{
return adoptPtr(new CCFloatKeyframe(time, value, timingFunction));
}
CCFloatKeyframe::CCFloatKeyframe(double time, float value, PassOwnPtr<CCTimingFunction> timingFunction)
: CCKeyframe(time, timingFunction)
, m_value(value)
{
}
CCFloatKeyframe::~CCFloatKeyframe()
{
}
float CCFloatKeyframe::value() const
{
return m_value;
}
PassOwnPtr<CCFloatKeyframe> CCFloatKeyframe::clone() const
{
return CCFloatKeyframe::create(time(), value(), timingFunction() ? cloneTimingFunction(timingFunction()) : nullptr);
}
PassOwnPtr<CCTransformKeyframe> CCTransformKeyframe::create(double time, const TransformOperations& value, PassOwnPtr<CCTimingFunction> timingFunction)
{
return adoptPtr(new CCTransformKeyframe(time, value, timingFunction));
}
CCTransformKeyframe::CCTransformKeyframe(double time, const TransformOperations& value, PassOwnPtr<CCTimingFunction> timingFunction)
: CCKeyframe(time, timingFunction)
, m_value(value)
{
}
CCTransformKeyframe::~CCTransformKeyframe()
{
}
const TransformOperations& CCTransformKeyframe::value() const
{
return m_value;
}
PassOwnPtr<CCTransformKeyframe> CCTransformKeyframe::clone() const
{
TransformOperations operations;
for (size_t j = 0; j < m_value.size(); ++j) {
TransformOperation::OperationType operationType = m_value.operations()[j]->getOperationType();
switch (operationType) {
case TransformOperation::SCALE_X:
case TransformOperation::SCALE_Y:
case TransformOperation::SCALE_Z:
case TransformOperation::SCALE_3D:
case TransformOperation::SCALE: {
ScaleTransformOperation* transform = static_cast<ScaleTransformOperation*>(m_value.operations()[j].get());
operations.operations().append(ScaleTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType));
break;
}
case TransformOperation::TRANSLATE_X:
case TransformOperation::TRANSLATE_Y:
case TransformOperation::TRANSLATE_Z:
case TransformOperation::TRANSLATE_3D:
case TransformOperation::TRANSLATE: {
TranslateTransformOperation* transform = static_cast<TranslateTransformOperation*>(m_value.operations()[j].get());
operations.operations().append(TranslateTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType));
break;
}
case TransformOperation::ROTATE_X:
case TransformOperation::ROTATE_Y:
case TransformOperation::ROTATE_3D:
case TransformOperation::ROTATE: {
RotateTransformOperation* transform = static_cast<RotateTransformOperation*>(m_value.operations()[j].get());
operations.operations().append(RotateTransformOperation::create(transform->x(), transform->y(), transform->z(), transform->angle(), operationType));
break;
}
case TransformOperation::SKEW_X:
case TransformOperation::SKEW_Y:
case TransformOperation::SKEW: {
SkewTransformOperation* transform = static_cast<SkewTransformOperation*>(m_value.operations()[j].get());
operations.operations().append(SkewTransformOperation::create(transform->angleX(), transform->angleY(), operationType));
break;
}
case TransformOperation::MATRIX: {
MatrixTransformOperation* transform = static_cast<MatrixTransformOperation*>(m_value.operations()[j].get());
TransformationMatrix m = transform->matrix();
operations.operations().append(MatrixTransformOperation::create(m.a(), m.b(), m.c(), m.d(), m.e(), m.f()));
break;
}
case TransformOperation::MATRIX_3D: {
Matrix3DTransformOperation* transform = static_cast<Matrix3DTransformOperation*>(m_value.operations()[j].get());
operations.operations().append(Matrix3DTransformOperation::create(transform->matrix()));
break;
}
case TransformOperation::PERSPECTIVE: {
PerspectiveTransformOperation* transform = static_cast<PerspectiveTransformOperation*>(m_value.operations()[j].get());
operations.operations().append(PerspectiveTransformOperation::create(transform->perspective()));
break;
}
case TransformOperation::IDENTITY: {
operations.operations().append(IdentityTransformOperation::create());
break;
}
case TransformOperation::NONE:
break;
} }
return CCTransformKeyframe::create(time(), operations, timingFunction() ? cloneTimingFunction(timingFunction()) : nullptr);
}
PassOwnPtr<CCKeyframedFloatAnimationCurve> CCKeyframedFloatAnimationCurve::create()
{
return adoptPtr(new CCKeyframedFloatAnimationCurve);
}
CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve()
{
}
CCKeyframedFloatAnimationCurve::~CCKeyframedFloatAnimationCurve()
{
}
void CCKeyframedFloatAnimationCurve::addKeyframe(PassOwnPtr<CCFloatKeyframe> keyframe)
{
insertKeyframe(keyframe, m_keyframes);
}
double CCKeyframedFloatAnimationCurve::duration() const
{
return m_keyframes.last()->time() - m_keyframes.first()->time();
}
PassOwnPtr<CCAnimationCurve> CCKeyframedFloatAnimationCurve::clone() const
{
OwnPtr<CCKeyframedFloatAnimationCurve> toReturn(CCKeyframedFloatAnimationCurve::create());
for (size_t i = 0; i < m_keyframes.size(); ++i)
toReturn->addKeyframe(m_keyframes[i]->clone());
return toReturn.release();
}
float CCKeyframedFloatAnimationCurve::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<float>((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;
}
PassOwnPtr<CCKeyframedTransformAnimationCurve> CCKeyframedTransformAnimationCurve::create()
{
return adoptPtr(new CCKeyframedTransformAnimationCurve);
}
CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve()
{
}
CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve()
{
}
void CCKeyframedTransformAnimationCurve::addKeyframe(PassOwnPtr<CCTransformKeyframe> keyframe)
{
insertKeyframe(keyframe, m_keyframes);
}
double CCKeyframedTransformAnimationCurve::duration() const
{
return m_keyframes.last()->time() - m_keyframes.first()->time();
}
PassOwnPtr<CCAnimationCurve> CCKeyframedTransformAnimationCurve::clone() const
{
OwnPtr<CCKeyframedTransformAnimationCurve> toReturn(CCKeyframedTransformAnimationCurve::create());
for (size_t i = 0; i < m_keyframes.size(); ++i)
toReturn->addKeyframe(m_keyframes[i]->clone());
return toReturn.release();
}
TransformationMatrix CCKeyframedTransformAnimationCurve::getValue(double t, const IntSize& layerSize) const
{
TransformationMatrix transformMatrix;
if (t <= m_keyframes.first()->time()) {
m_keyframes.first()->value().apply(layerSize, transformMatrix);
return transformMatrix;
}
if (t >= m_keyframes.last()->time()) {
m_keyframes.last()->value().apply(layerSize, transformMatrix);
return transformMatrix;
}
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);
if (m_keyframes[i]->value().operationsMatch(m_keyframes[i+1]->value())) {
for (size_t j = 0; j < m_keyframes[i+1]->value().size(); ++j)
m_keyframes[i+1]->value().operations()[j]->blend(m_keyframes[i]->value().at(j), progress)->apply(transformMatrix, layerSize);
} else {
TransformationMatrix source;
m_keyframes[i]->value().apply(layerSize, source);
m_keyframes[i+1]->value().apply(layerSize, transformMatrix);
transformMatrix.blend(source, progress);
}
return transformMatrix;
}
}