+2012-02-23 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Implement keyframed animations for the cc thread.
+ https://bugs.webkit.org/show_bug.cgi?id=77229
+
+ Reviewed by James Robinson.
+
+ * WebCore.gypi:
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::hasActiveAnimation):
+ (WebCore):
+ * platform/graphics/chromium/LayerChromium.h:
+ (LayerChromium):
+ * platform/graphics/chromium/cc/CCActiveAnimation.cpp:
+ (WebCore::CCActiveAnimation::CCActiveAnimation):
+ (WebCore::CCActiveAnimation::isFinishedAt):
+ (WebCore::CCActiveAnimation::trimTimeToCurrentIteration):
+ (WebCore::CCActiveAnimation::cloneForImplThread):
+ * platform/graphics/chromium/cc/CCActiveAnimation.h:
+ (WebCore::CCActiveAnimation::curve):
+ (CCActiveAnimation):
+ * platform/graphics/chromium/cc/CCKeyframedAnimationCurve.cpp: Added.
+ (WebCore::CCKeyframedFloatAnimationCurve::create):
+ (WebCore):
+ (WebCore::CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve):
+ (WebCore::CCKeyframedFloatAnimationCurve::~CCKeyframedFloatAnimationCurve):
+ (WebCore::CCKeyframedFloatAnimationCurve::duration):
+ (WebCore::CCKeyframedFloatAnimationCurve::clone):
+ (WebCore::CCKeyframedFloatAnimationCurve::getValue):
+ (WebCore::CCKeyframedTransformAnimationCurve::create):
+ (WebCore::CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve):
+ (WebCore::CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve):
+ (WebCore::CCKeyframedTransformAnimationCurve::duration):
+ (WebCore::CCKeyframedTransformAnimationCurve::clone):
+ (WebCore::CCKeyframedTransformAnimationCurve::getValue):
+ * platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h: Added.
+ (WebCore):
+ (WebCore::CCFloatKeyframe::CCFloatKeyframe):
+ (CCFloatKeyframe):
+ (WebCore::CCTransformKeyframe::CCTransformKeyframe):
+ (CCTransformKeyframe):
+ (CCKeyframedFloatAnimationCurve):
+ (CCKeyframedTransformAnimationCurve):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
+ (WebCore::CCLayerAnimationController::addAnimation):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.h:
+ (WebCore::CCLayerAnimationController::hasActiveAnimation):
+ (CCLayerAnimationController):
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp:
+ (WebCore::CCLayerAnimationControllerImpl::tickAnimations):
+
2012-02-23 Raymond Toy <rtoy@google.com>
Use MathExtras round() in timeToSampleFrame
'platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp',
'platform/graphics/chromium/cc/CCHeadsUpDisplay.h',
'platform/graphics/chromium/cc/CCInputHandler.h',
+ 'platform/graphics/chromium/cc/CCKeyframedAnimationCurve.cpp',
+ 'platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h',
'platform/graphics/chromium/cc/CCLayerAnimationController.h',
'platform/graphics/chromium/cc/CCLayerAnimationController.cpp',
'platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h',
setNeedsCommit();
}
+bool LayerChromium::hasActiveAnimation() const
+{
+ return m_layerAnimationController->hasActiveAnimation();
+}
+
void LayerChromium::setIsNonCompositedContent(bool isNonCompositedContent)
{
m_isNonCompositedContent = isNonCompositedContent;
CCLayerAnimationController* layerAnimationController() { return m_layerAnimationController.get(); }
void setLayerAnimationController(PassOwnPtr<CCLayerAnimationController>);
+ bool hasActiveAnimation() const;
protected:
friend class CCLayerImpl;
}
CCActiveAnimation::CCActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int animationId, int groupId, TargetProperty targetProperty)
- : m_animationCurve(curve)
+ : m_curve(curve)
, m_id(animationId)
, m_group(groupId)
, m_targetProperty(targetProperty)
return m_runState == Running
&& m_iterations >= 0
- && m_iterations * m_animationCurve->duration() <= time - startTime() - m_totalPausedTime;
+ && m_iterations * m_curve->duration() <= time - startTime() - m_totalPausedTime;
}
bool CCActiveAnimation::isWaiting() const
return 0;
// If less than an iteration duration, just return trimmed.
- if (trimmed < m_animationCurve->duration())
+ if (trimmed < m_curve->duration())
return trimmed;
// If greater than or equal to the total duration, return iteration duration.
- if (m_iterations >= 0 && trimmed >= m_animationCurve->duration() * m_iterations)
- return m_animationCurve->duration();
+ if (m_iterations >= 0 && trimmed >= m_curve->duration() * m_iterations)
+ return m_curve->duration();
// Finally, return x where trimmed = x + n * m_animation->duration() for some positive integer n.
- return fmod(trimmed, m_animationCurve->duration());
+ return fmod(trimmed, m_curve->duration());
}
PassOwnPtr<CCActiveAnimation> CCActiveAnimation::cloneForImplThread() const
{
- OwnPtr<CCActiveAnimation> toReturn(adoptPtr(new CCActiveAnimation(m_animationCurve->clone(), m_id, m_group, m_targetProperty)));
+ OwnPtr<CCActiveAnimation> toReturn(adoptPtr(new CCActiveAnimation(m_curve->clone(), m_id, m_group, m_targetProperty)));
toReturn->m_runState = m_runState;
toReturn->m_iterations = m_iterations;
toReturn->m_startTime = m_startTime;
bool isWaiting() const;
bool isRunningOrHasRun() const;
- CCAnimationCurve* animationCurve() { return m_animationCurve.get(); }
- const CCAnimationCurve* animationCurve() const { return m_animationCurve.get(); }
+ CCAnimationCurve* curve() { return m_curve.get(); }
+ const CCAnimationCurve* curve() const { return m_curve.get(); }
// Takes the given absolute time, and using the start time and the number
// of iterations, returns the relative time in the current iteration.
private:
CCActiveAnimation(PassOwnPtr<CCAnimationCurve>, int animationId, int groupId, TargetProperty);
- OwnPtr<CCAnimationCurve> m_animationCurve;
+ OwnPtr<CCAnimationCurve> m_curve;
// IDs are not necessarily unique.
int m_id;
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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>
+bool keyframesAreSorted(const Vector<Keyframe>& keyframes)
+{
+ if (!keyframes.size())
+ return true;
+
+ for (size_t i = 0; i < keyframes.size() - 1; ++i) {
+ if (keyframes[i].time > keyframes[i+1].time)
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+PassOwnPtr<CCKeyframedFloatAnimationCurve> CCKeyframedFloatAnimationCurve::create(const Vector<CCFloatKeyframe>& keyframes)
+{
+ if (!keyframes.size() || !keyframesAreSorted(keyframes))
+ return nullptr;
+
+ return adoptPtr(new CCKeyframedFloatAnimationCurve(keyframes));
+}
+
+CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve(const Vector<CCFloatKeyframe>& keyframes)
+ : m_keyframes(keyframes)
+{
+}
+
+CCKeyframedFloatAnimationCurve::~CCKeyframedFloatAnimationCurve()
+{
+}
+
+double CCKeyframedFloatAnimationCurve::duration() const
+{
+ return m_keyframes.last().time - m_keyframes.first().time;
+}
+
+PassOwnPtr<CCAnimationCurve> CCKeyframedFloatAnimationCurve::clone() const
+{
+ return adoptPtr(new CCKeyframedFloatAnimationCurve(*this));
+}
+
+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));
+ // FIXME: apply timing function here.
+ return m_keyframes[i].value + (m_keyframes[i+1].value - m_keyframes[i].value) * progress;
+}
+
+PassOwnPtr<CCKeyframedTransformAnimationCurve> CCKeyframedTransformAnimationCurve::create(const Vector<CCTransformKeyframe>& keyframes)
+{
+ if (!keyframes.size() || !keyframesAreSorted(keyframes))
+ return nullptr;
+
+ return adoptPtr(new CCKeyframedTransformAnimationCurve(keyframes));
+}
+
+CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve(const Vector<CCTransformKeyframe>& keyframes)
+ : m_keyframes(keyframes)
+{
+}
+
+CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve() { }
+
+double CCKeyframedTransformAnimationCurve::duration() const
+{
+ return m_keyframes.last().time - m_keyframes.first().time;
+}
+
+PassOwnPtr<CCAnimationCurve> CCKeyframedTransformAnimationCurve::clone() const
+{
+ Vector<CCTransformKeyframe> keyframes;
+ // We need to do a deep copy of all of the keyframes since they contain ref
+ // pointers to TransformOperation objects.
+ for (size_t i = 0; i < m_keyframes.size(); ++i) {
+ CCTransformKeyframe keyframe(m_keyframes[i].time);
+ for (size_t j = 0; j < m_keyframes[i].value.size(); ++j) {
+ TransformOperation::OperationType operationType = m_keyframes[i].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_keyframes[i].value.operations()[j].get());
+ keyframe.value.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_keyframes[i].value.operations()[j].get());
+ keyframe.value.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_keyframes[i].value.operations()[j].get());
+ keyframe.value.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_keyframes[i].value.operations()[j].get());
+ keyframe.value.operations().append(SkewTransformOperation::create(transform->angleX(), transform->angleY(), operationType));
+ break;
+ }
+ case TransformOperation::MATRIX: {
+ MatrixTransformOperation* transform = static_cast<MatrixTransformOperation*>(m_keyframes[i].value.operations()[j].get());
+ TransformationMatrix m = transform->matrix();
+ keyframe.value.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_keyframes[i].value.operations()[j].get());
+ keyframe.value.operations().append(Matrix3DTransformOperation::create(transform->matrix()));
+ break;
+ }
+ case TransformOperation::PERSPECTIVE: {
+ PerspectiveTransformOperation* transform = static_cast<PerspectiveTransformOperation*>(m_keyframes[i].value.operations()[j].get());
+ keyframe.value.operations().append(PerspectiveTransformOperation::create(transform->perspective()));
+ break;
+ }
+ case TransformOperation::IDENTITY: {
+ keyframe.value.operations().append(IdentityTransformOperation::create());
+ break;
+ }
+ case TransformOperation::NONE:
+ // Do nothing.
+ break;
+ } // switch
+ } // for each operation
+ keyframes.append(keyframe);
+ }
+ return CCKeyframedTransformAnimationCurve::create(keyframes);
+}
+
+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;
+ }
+
+ // FIXME: apply timing function here.
+ double progress = (t - m_keyframes[i].time) / (m_keyframes[i+1].time - m_keyframes[i].time);
+
+ 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;
+}
+
+} // namespace WebCore
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CCKeyframedAnimationCurve_h
+#define CCKeyframedAnimationCurve_h
+
+#include "TransformOperations.h"
+#include "cc/CCAnimationCurve.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+struct CCFloatKeyframe {
+ CCFloatKeyframe(double time, float value)
+ : time(time)
+ , value(value)
+ {
+ }
+
+ double time;
+ float value;
+};
+
+struct CCTransformKeyframe {
+ explicit CCTransformKeyframe(double time)
+ : time(time)
+ {
+ }
+
+ CCTransformKeyframe(double time, const TransformOperations& value)
+ : time(time)
+ , value(value)
+ {
+ }
+
+ double time;
+ TransformOperations value;
+};
+
+class CCKeyframedFloatAnimationCurve : public CCFloatAnimationCurve {
+public:
+ // It is required that the keyframes be sorted by time.
+ static PassOwnPtr<CCKeyframedFloatAnimationCurve> create(const Vector<CCFloatKeyframe>& keyframes);
+
+ virtual ~CCKeyframedFloatAnimationCurve();
+
+ // CCAnimationCurve implementation
+ virtual double duration() const;
+ virtual PassOwnPtr<CCAnimationCurve> clone() const;
+
+ // CCFloatAnimationCurve implementation
+ virtual float getValue(double t) const;
+
+private:
+ explicit CCKeyframedFloatAnimationCurve(const Vector<CCFloatKeyframe>&);
+
+ // Always sorted in order of increasing time. No two keyframes have the
+ // same time.
+ Vector<CCFloatKeyframe> m_keyframes;
+};
+
+class CCKeyframedTransformAnimationCurve : public CCTransformAnimationCurve {
+public:
+ // It is required that the keyframes be sorted by time.
+ static PassOwnPtr<CCKeyframedTransformAnimationCurve> create(const Vector<CCTransformKeyframe>& keyframes);
+
+ virtual ~CCKeyframedTransformAnimationCurve();
+
+ // CCAnimationCurve implementation
+ virtual double duration() const;
+ virtual PassOwnPtr<CCAnimationCurve> clone() const;
+
+ // CCTransformAnimationCurve implementation
+ virtual TransformationMatrix getValue(double t, const IntSize&) const;
+
+private:
+ explicit CCKeyframedTransformAnimationCurve(const Vector<CCTransformKeyframe>&);
+
+ // Always sorted in order of increasing time. No two keyframes have the
+ // same time.
+ Vector<CCTransformKeyframe> m_keyframes;
+};
+
+} // namespace WebCore
+
+#endif // CCKeyframedAnimationCurve_h
#include "GraphicsLayer.h" // for KeyframeValueList
#include "cc/CCActiveAnimation.h"
+#include "cc/CCKeyframedAnimationCurve.h"
#include "cc/CCLayerAnimationControllerImpl.h"
+#include <wtf/CurrentTime.h>
#include <wtf/HashMap.h>
namespace WebCore {
+namespace {
+
+template <typename Keyframe, typename Value>
+void appendKeyframe(Vector<Keyframe>& keyframes, double keyTime, const Value* value)
+{
+ keyframes.append(Keyframe(keyTime, value->value()));
+}
+
+template <>
+void appendKeyframe<CCTransformKeyframe, TransformAnimationValue>(Vector<CCTransformKeyframe>& keyframes, double keyTime, const TransformAnimationValue* value)
+{
+ keyframes.append(CCTransformKeyframe(keyTime, *value->value()));
+}
+
+template <class Value, class Keyframe, class Curve>
+PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& valueList, const Animation* animation, size_t animationId, size_t groupId, double timeOffset, CCActiveAnimation::TargetProperty targetProperty)
+{
+ // FIXME: add support for different directions.
+ if (animation && animation->isDirectionSet() && animation->direction() == Animation::AnimationDirectionAlternate)
+ return nullptr;
+
+ // FIXME: add support for delay
+ if (animation && animation->isDelaySet() && animation->delay() > 0)
+ return nullptr;
+
+ // FIXME: add support for fills forwards and fills backwards
+ if (animation && animation->isFillModeSet() && (animation->fillsForwards() || animation->fillsBackwards()))
+ return nullptr;
+
+ Vector<Keyframe> keyframes;
+
+ for (size_t i = 0; i < valueList.size(); i++) {
+ const Value* originalValue = static_cast<const Value*>(valueList.at(i));
+
+ // FIXME: add support for timing functions.
+ if (originalValue->timingFunction() && originalValue->timingFunction()->type() != TimingFunction::LinearFunction)
+ return nullptr;
+
+ double duration = (animation && animation->isDurationSet()) ? animation->duration() : 1;
+ appendKeyframe(keyframes, originalValue->keyTime() * duration, originalValue);
+ }
+
+ OwnPtr<Curve> curve = Curve::create(keyframes);
+
+ OwnPtr<CCActiveAnimation> anim = CCActiveAnimation::create(curve.release(), animationId, groupId, targetProperty);
+
+ ASSERT(anim.get());
+
+ if (anim.get()) {
+ int iterations = (animation && animation->isIterationCountSet()) ? animation->iterationCount() : 1;
+ anim->setIterations(iterations);
+ }
+
+ return anim.release();
+}
+
+} // namepace
+
CCLayerAnimationController::CCLayerAnimationController()
{
}
return adoptPtr(new CCLayerAnimationController);
}
-bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList,
- const IntSize&,
- const Animation* animation,
- int animationId,
- int groupId,
- double timeOffset)
+bool CCLayerAnimationController::addAnimation(const KeyframeValueList& valueList, const IntSize&, const Animation* animation, int animationId, int groupId, double timeOffset)
{
+ if (!animation)
+ return false;
+
+ OwnPtr<CCActiveAnimation> toAdd;
+ if (valueList.property() == AnimatedPropertyWebkitTransform)
+ toAdd = createActiveAnimation<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Transform);
+ else if (valueList.property() == AnimatedPropertyOpacity)
+ toAdd = createActiveAnimation<FloatAnimationValue, CCFloatKeyframe, CCKeyframedFloatAnimationCurve>(valueList, animation, animationId, groupId, timeOffset, CCActiveAnimation::Opacity);
+
+ if (toAdd.get()) {
+ m_activeAnimations.append(toAdd.release());
+ return true;
+ }
+
return false;
}
// are kept in sync. This function does not take ownership of the impl thread controller.
virtual void synchronizeAnimations(CCLayerAnimationControllerImpl*);
- // This is for testing purposes only.
- Vector<OwnPtr<CCActiveAnimation> >& activeAnimations() { return m_activeAnimations; }
+ bool hasActiveAnimation() const { return m_activeAnimations.size(); }
+ CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
protected:
CCLayerAnimationController();
void removeAnimationsCompletedOnMainThread(CCLayerAnimationControllerImpl*);
void pushAnimationProperties(CCLayerAnimationControllerImpl*);
- CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
void remove(int groupId, CCActiveAnimation::TargetProperty);
Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations;
switch (m_activeAnimations[i]->targetProperty()) {
case CCActiveAnimation::Transform: {
- const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->animationCurve()->toTransformAnimationCurve();
+ const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve();
const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds());
if (m_activeAnimations[i]->isFinishedAt(now))
m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now);
}
case CCActiveAnimation::Opacity: {
- const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->animationCurve()->toFloatAnimationCurve();
+ const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve();
const float opacity = floatAnimationCurve->getValue(trimmed);
if (m_activeAnimations[i]->isFinishedAt(now))
m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now);
+2012-02-23 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Implement keyframed animations for the cc thread.
+ https://bugs.webkit.org/show_bug.cgi?id=77229
+
+ Reviewed by James Robinson.
+
+ * WebKit.gypi:
+ * tests/CCAnimationTestCommon.cpp:
+ (WebCore):
+ (WebCore::addOpacityTransition):
+ (WebKitTests::addOpacityTransitionToController):
+ (WebKitTests::addOpacityTransitionToLayer):
+ * tests/CCAnimationTestCommon.h:
+ (WebCore):
+ (WebKitTests):
+ * tests/CCKeyframedAnimationCurveTest.cpp: Added.
+ (WebCore):
+ (WebCore::expectTranslateX):
+ (WebCore::TEST):
+ * tests/CCLayerAnimationControllerTest.cpp:
+ (WebKitTests::expectTranslateX):
+ (WebKitTests):
+ (WebKitTests::TEST):
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF::CCLayerTreeHostTest::dispatchAddAnimation):
+ (WTF::CCLayerTreeHostTest::doBeginTest):
+
2012-02-23 James Robinson <jamesr@chromium.org>
[chromium] Clean up GraphicsContext3D initialization paths
'tests/CCDamageTrackerTest.cpp',
'tests/CCDelayBasedTimeSourceTest.cpp',
'tests/CCFrameRateControllerTest.cpp',
+ 'tests/CCKeyframedAnimationCurveTest.cpp',
'tests/CCLayerAnimationControllerImplTest.cpp',
'tests/CCLayerAnimationControllerTest.cpp',
'tests/CCLayerImplTest.cpp',
#include "GraphicsLayer.h"
#include "LayerChromium.h"
+#include "cc/CCLayerAnimationController.h"
using namespace WebCore;
+namespace {
+
+template <class Target>
+void addOpacityTransition(Target& target, double duration, float startOpacity, float endOpacity)
+{
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ if (duration > 0)
+ values.insert(new FloatAnimationValue(0, startOpacity));
+ values.insert(new FloatAnimationValue(duration, endOpacity));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+
+ target.addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+}
+
+} // namespace
+
namespace WebKitTests {
FakeFloatAnimationCurve::FakeFloatAnimationCurve()
return adoptPtr(new FakeFloatTransition(*this));
}
-void addOpacityTransition(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity)
+void addOpacityTransitionToController(WebCore::CCLayerAnimationController& controller, double duration, float startOpacity, float endOpacity)
{
- WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
- if (duration > 0)
- values.insert(new FloatAnimationValue(0, startOpacity));
- values.insert(new FloatAnimationValue(duration, endOpacity));
-
- RefPtr<Animation> animation = Animation::create();
- animation->setDuration(1);
-
- IntSize boxSize;
+ addOpacityTransition(controller, duration, startOpacity, endOpacity);
+}
- layer.addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+void addOpacityTransitionToLayer(WebCore::LayerChromium& layer, double duration, float startOpacity, float endOpacity)
+{
+ addOpacityTransition(layer, duration, startOpacity, endOpacity);
}
} // namespace WebKitTests
#include <wtf/OwnPtr.h>
namespace WebCore {
+class CCLayerAnimationController;
class LayerChromium;
}
WebCore::IntSize m_bounds;
};
-void addOpacityTransition(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity);
+void addOpacityTransitionToController(WebCore::CCLayerAnimationController&, double duration, float startOpacity, float endOpacity);
+
+void addOpacityTransitionToLayer(WebCore::LayerChromium&, double duration, float startOpacity, float endOpacity);
} // namespace WebKitTests
--- /dev/null
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "cc/CCKeyframedAnimationCurve.h"
+
+#include "Length.h"
+#include "TranslateTransformOperation.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+using namespace WebCore;
+
+namespace {
+
+void expectTranslateX(double translateX, const TransformationMatrix& matrix)
+{
+ TransformationMatrix::DecomposedType decomposedType;
+ matrix.decompose(decomposedType);
+ EXPECT_FLOAT_EQ(translateX, decomposedType.translateX);
+}
+
+// Tests that a float animation with one keyframe works as expected.
+TEST(CCKeyframedAnimationCurveTest, OneFloatKeyframe)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ keyframes.append(CCFloatKeyframe(0, 2));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+ EXPECT_FLOAT_EQ(2, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0.5));
+ EXPECT_FLOAT_EQ(2, curve->getValue(1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(2));
+}
+
+// Tests that a float animation with two keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, TwoFloatKeyframe)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ keyframes.append(CCFloatKeyframe(0, 2));
+ keyframes.append(CCFloatKeyframe(1, 4));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+ EXPECT_FLOAT_EQ(2, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0));
+ EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
+ EXPECT_FLOAT_EQ(4, curve->getValue(1));
+ EXPECT_FLOAT_EQ(4, curve->getValue(2));
+}
+
+// Tests that a float animation with three keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, ThreeFloatKeyframe)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ keyframes.append(CCFloatKeyframe(0, 2));
+ keyframes.append(CCFloatKeyframe(1, 4));
+ keyframes.append(CCFloatKeyframe(2, 8));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+ EXPECT_FLOAT_EQ(2, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(2, curve->getValue(0));
+ EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
+ EXPECT_FLOAT_EQ(4, curve->getValue(1));
+ EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
+ EXPECT_FLOAT_EQ(8, curve->getValue(2));
+ EXPECT_FLOAT_EQ(8, curve->getValue(3));
+}
+
+// Tests that a float animation with multiple keys at a given time works sanely.
+TEST(CCKeyframedAnimationCurveTest, RepeatedFloatKeyTimes)
+{
+ Vector<CCFloatKeyframe> keyframes;
+ // A step function.
+ keyframes.append(CCFloatKeyframe(0, 4));
+ keyframes.append(CCFloatKeyframe(1, 4));
+ keyframes.append(CCFloatKeyframe(1, 6));
+ keyframes.append(CCFloatKeyframe(2, 6));
+ OwnPtr<CCKeyframedFloatAnimationCurve> curve(CCKeyframedFloatAnimationCurve::create(keyframes));
+
+ EXPECT_FLOAT_EQ(4, curve->getValue(-1));
+ EXPECT_FLOAT_EQ(4, curve->getValue(0));
+ EXPECT_FLOAT_EQ(4, curve->getValue(0.5));
+
+ // There is a discontinuity at 1. Any value between 4 and 6 is valid.
+ float value = curve->getValue(1);
+ EXPECT_TRUE(value >= 4 && value <= 6);
+
+ EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
+ EXPECT_FLOAT_EQ(6, curve->getValue(2));
+ EXPECT_FLOAT_EQ(6, curve->getValue(3));
+}
+
+
+// Tests that a transform animation with one keyframe works as expected.
+TEST(CCKeyframedAnimationCurveTest, OneTransformKeyframe)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ TransformOperations operations;
+ operations.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+ IntSize layerSize; // ignored
+ expectTranslateX(2, curve->getValue(-1, layerSize));
+ expectTranslateX(2, curve->getValue(0, layerSize));
+ expectTranslateX(2, curve->getValue(0.5, layerSize));
+ expectTranslateX(2, curve->getValue(1, layerSize));
+ expectTranslateX(2, curve->getValue(2, layerSize));
+}
+
+// Tests that a transform animation with two keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, TwoTransformKeyframe)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations1));
+ keyframes.append(CCTransformKeyframe(1, operations2));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+ IntSize layerSize; // ignored
+ expectTranslateX(2, curve->getValue(-1, layerSize));
+ expectTranslateX(2, curve->getValue(0, layerSize));
+ expectTranslateX(3, curve->getValue(0.5, layerSize));
+ expectTranslateX(4, curve->getValue(1, layerSize));
+ expectTranslateX(4, curve->getValue(2, layerSize));
+}
+
+// Tests that a transform animation with three keyframes works as expected.
+TEST(CCKeyframedAnimationCurveTest, ThreeTransformKeyframe)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations3;
+ operations3.operations().append(TranslateTransformOperation::create(Length(8, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations1));
+ keyframes.append(CCTransformKeyframe(1, operations2));
+ keyframes.append(CCTransformKeyframe(2, operations3));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+ IntSize layerSize; // ignored
+ expectTranslateX(2, curve->getValue(-1, layerSize));
+ expectTranslateX(2, curve->getValue(0, layerSize));
+ expectTranslateX(3, curve->getValue(0.5, layerSize));
+ expectTranslateX(4, curve->getValue(1, layerSize));
+ expectTranslateX(6, curve->getValue(1.5, layerSize));
+ expectTranslateX(8, curve->getValue(2, layerSize));
+ expectTranslateX(8, curve->getValue(3, layerSize));
+}
+
+// Tests that a transform animation with multiple keys at a given time works sanely.
+TEST(CCKeyframedAnimationCurveTest, RepeatedTransformKeyTimes)
+{
+ Vector<CCTransformKeyframe> keyframes;
+ // A step function.
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations3;
+ operations3.operations().append(TranslateTransformOperation::create(Length(6, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations4;
+ operations4.operations().append(TranslateTransformOperation::create(Length(6, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ keyframes.append(CCTransformKeyframe(0, operations1));
+ keyframes.append(CCTransformKeyframe(1, operations2));
+ keyframes.append(CCTransformKeyframe(1, operations3));
+ keyframes.append(CCTransformKeyframe(2, operations4));
+ OwnPtr<CCKeyframedTransformAnimationCurve> curve(CCKeyframedTransformAnimationCurve::create(keyframes));
+
+ IntSize layerSize; // ignored
+
+ expectTranslateX(4, curve->getValue(-1, layerSize));
+ expectTranslateX(4, curve->getValue(0, layerSize));
+ expectTranslateX(4, curve->getValue(0.5, layerSize));
+
+ // There is a discontinuity at 1. Any value between 4 and 6 is valid.
+ TransformationMatrix value = curve->getValue(1, layerSize);
+ TransformationMatrix::DecomposedType decomposedType;
+ value.decompose(decomposedType);
+ EXPECT_TRUE(decomposedType.translateX >= 4 && decomposedType.translateX <= 6);
+
+ expectTranslateX(6, curve->getValue(1.5, layerSize));
+ expectTranslateX(6, curve->getValue(2, layerSize));
+ expectTranslateX(6, curve->getValue(3, layerSize));
+}
+
+// Tests that invalid lists of keyframes result in nothing being returned from ::create.
+TEST(CCKeyframedAnimationCurveTest, InvalidKeyframes)
+{
+ // It is invalid to pass an empty vector of keyframes to create.
+ Vector<CCTransformKeyframe> transformKeyframes;
+ OwnPtr<CCKeyframedTransformAnimationCurve> transformCurve = CCKeyframedTransformAnimationCurve::create(transformKeyframes);
+ EXPECT_FALSE(transformCurve.get());
+
+ Vector<CCFloatKeyframe> floatKeyframes;
+ OwnPtr<CCKeyframedFloatAnimationCurve> floatCurve = CCKeyframedFloatAnimationCurve::create(floatKeyframes);
+ EXPECT_FALSE(floatCurve.get());
+
+ // It is invalid to pass a vector of unsorted keyframes to create;
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ transformKeyframes.append(CCTransformKeyframe(1, operations1));
+ transformKeyframes.append(CCTransformKeyframe(0, operations2));
+ transformCurve = CCKeyframedTransformAnimationCurve::create(transformKeyframes);
+ EXPECT_FALSE(transformCurve.get());
+
+ floatKeyframes.append(CCFloatKeyframe(1, 2));
+ floatKeyframes.append(CCFloatKeyframe(0, 4));
+ floatCurve = CCKeyframedFloatAnimationCurve::create(floatKeyframes);
+ EXPECT_FALSE(floatCurve.get());
+}
+
+
+} // namespace
#include "cc/CCLayerAnimationController.h"
#include "CCAnimationTestCommon.h"
+#include "GraphicsLayer.h"
+#include "Length.h"
+#include "TranslateTransformOperation.h"
+#include "cc/CCActiveAnimation.h"
+#include "cc/CCAnimationCurve.h"
+
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <wtf/Vector.h>
namespace {
+void expectTranslateX(double translateX, const TransformationMatrix& matrix)
+{
+ TransformationMatrix::DecomposedType decomposedType;
+ matrix.decompose(decomposedType);
+ EXPECT_FLOAT_EQ(translateX, decomposedType.translateX);
+}
+
PassOwnPtr<CCActiveAnimation> createActiveAnimation(PassOwnPtr<CCAnimationCurve> curve, int id, CCActiveAnimation::TargetProperty property)
{
return CCActiveAnimation::create(curve, 0, id, property);
}
+TEST(CCLayerAnimationControllerTest, createOpacityAnimation)
+{
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
+ values.insert(new FloatAnimationValue(0, 0));
+ values.insert(new FloatAnimationValue(duration, 1));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+ controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+
+ EXPECT_TRUE(controller->hasActiveAnimation());
+
+ CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Opacity);
+ EXPECT_TRUE(activeAnimation);
+
+ EXPECT_EQ(1, activeAnimation->iterations());
+ EXPECT_EQ(CCActiveAnimation::Opacity, activeAnimation->targetProperty());
+
+ EXPECT_EQ(CCAnimationCurve::Float, activeAnimation->curve()->type());
+
+ const CCFloatAnimationCurve* curve = activeAnimation->curve()->toFloatAnimationCurve();
+ EXPECT_TRUE(curve);
+
+ EXPECT_EQ(0, curve->getValue(0));
+ EXPECT_EQ(1, curve->getValue(duration));
+}
+
+TEST(CCLayerAnimationControllerTest, createTransformAnimation)
+{
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
+
+ TransformOperations operations1;
+ operations1.operations().append(TranslateTransformOperation::create(Length(2, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ values.insert(new TransformAnimationValue(0, &operations1));
+
+ TransformOperations operations2;
+ operations2.operations().append(TranslateTransformOperation::create(Length(4, Fixed), Length(0, Fixed), TransformOperation::TRANSLATE_X));
+ values.insert(new TransformAnimationValue(duration, &operations2));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+ controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0);
+
+ EXPECT_TRUE(controller->hasActiveAnimation());
+
+ CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Transform);
+ EXPECT_TRUE(activeAnimation);
+
+ EXPECT_EQ(1, activeAnimation->iterations());
+ EXPECT_EQ(CCActiveAnimation::Transform, activeAnimation->targetProperty());
+
+ EXPECT_EQ(CCAnimationCurve::Transform, activeAnimation->curve()->type());
+
+ const CCTransformAnimationCurve* curve = activeAnimation->curve()->toTransformAnimationCurve();
+ EXPECT_TRUE(curve);
+
+ expectTranslateX(2, curve->getValue(0, boxSize));
+ expectTranslateX(4, curve->getValue(duration, boxSize));
+}
+
TEST(CCLayerAnimationControllerTest, syncNewAnimation)
{
FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
- CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(
- CCLayerAnimationController::create());
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+ addOpacityTransitionToController(*controller, 1, 0, 1);
controller->synchronizeAnimations(controllerImpl.get());
TEST(CCLayerAnimationControllerTest, syncAnimationProperties)
{
FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
- CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(
- CCLayerAnimationController::create());
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+ addOpacityTransitionToController(*controller, 1, 0, 1);
controller->synchronizeAnimations(controllerImpl.get());
TEST(CCLayerAnimationControllerTest, syncAbortedAnimation)
{
FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
- CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(
- CCLayerAnimationController::create());
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+ addOpacityTransitionToController(*controller, 1, 0, 1);
controller->synchronizeAnimations(controllerImpl.get());
TEST(CCLayerAnimationControllerTest, syncCompletedAnimation)
{
FakeLayerAnimationControllerImplClient dummy;
- OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(
- CCLayerAnimationControllerImpl::create(&dummy));
- OwnPtr<CCLayerAnimationController> controller(
- CCLayerAnimationController::create());
+ OwnPtr<CCLayerAnimationControllerImpl> controllerImpl(CCLayerAnimationControllerImpl::create(&dummy));
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create());
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- controller->activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatAnimationCurve()), 0, 0, CCActiveAnimation::Opacity));
+ addOpacityTransitionToController(*controller, 1, 0, 1);
controller->synchronizeAnimations(controllerImpl.get());
controllerImpl->animate(2, *events);
EXPECT_FALSE(controllerImpl->getActiveAnimation(0, CCActiveAnimation::Opacity));
- EXPECT_EQ(size_t(1), controller->activeAnimations().size());
+ EXPECT_TRUE(controller->hasActiveAnimation());
controller->synchronizeAnimations(controllerImpl.get());
- EXPECT_EQ(size_t(0), controller->activeAnimations().size());
+ EXPECT_FALSE(controller->hasActiveAnimation());
}
} // namespace
TestHooks* m_testHooks;
};
-// Adapts CCLayerAnimationController for test. Adds a dummy implementation of addAnimation that inserts a float animation.
-// FIXME: once CCLayerAnimationController::addAnimation is implemented, that function should be called directly and this
-// class can be removed.
-class MockLayerAnimationController : public CCLayerAnimationController {
-public:
- static PassOwnPtr<MockLayerAnimationController> create()
- {
- return adoptPtr(new MockLayerAnimationController);
- }
-
-private:
- virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, int animationId, int groupId, double timeOffset)
- {
- double duration = 0;
- activeAnimations().append(CCActiveAnimation::create(adoptPtr(new FakeFloatTransition(duration, 1, 0)), animationId, groupId, CCActiveAnimation::Opacity));
- return true;
- }
-};
-
class CompositorFakeWebGraphicsContext3DWithTextureTracking : public CompositorFakeWebGraphicsContext3D {
public:
static PassOwnPtr<CompositorFakeWebGraphicsContext3DWithTextureTracking> create(Attributes attrs)
CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
ASSERT(test);
if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
- test->m_layerTreeHost->rootLayer()->addAnimation(KeyframeValueList(AnimatedPropertyOpacity), IntSize(), 0, 0, 0, 0.0);
+ addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 1);
}
static void dispatchSetNeedsAnimateAndCommit(void* self)
m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
ASSERT_TRUE(m_layerTreeHost);
rootLayer->setLayerTreeHost(m_layerTreeHost.get());
- rootLayer->setLayerAnimationController(MockLayerAnimationController::create());
m_beginning = true;
beginTest();