Modified: branches/chromium/1132/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp (116999 => 117000)
--- branches/chromium/1132/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp 2012-05-14 21:12:38 UTC (rev 116999)
+++ branches/chromium/1132/Source/WebCore/platform/graphics/chromium/cc/CCActiveAnimation.cpp 2012-05-14 21:17:42 UTC (rev 117000)
@@ -45,6 +45,7 @@
, m_runState(WaitingForTargetAvailability)
, m_iterations(1)
, m_startTime(0)
+ , m_alternatesDirection(false)
, m_timeOffset(0)
, m_needsSynchronizedStartTime(false)
, m_suspended(false)
@@ -119,11 +120,23 @@
return trimmed;
// If greater than or equal to the total duration, return iteration duration.
- if (m_iterations >= 0 && trimmed >= m_curve->duration() * m_iterations)
+ if (m_iterations >= 0 && trimmed >= m_curve->duration() * m_iterations) {
+ if (m_alternatesDirection && !(m_iterations % 2))
+ return 0;
return m_curve->duration();
+ }
- // Finally, return x where trimmed = x + n * m_animation->duration() for some positive integer n.
- return fmod(trimmed, m_curve->duration());
+ // We need to know the current iteration if we're alternating.
+ int iteration = static_cast<int>(trimmed / m_curve->duration());
+
+ // Calculate x where trimmed = x + n * m_curve->duration() for some positive integer n.
+ trimmed = fmod(trimmed, m_curve->duration());
+
+ // If we're alternating and on an odd iteration, reverse the direction.
+ if (m_alternatesDirection && iteration % 2 == 1)
+ return m_curve->duration() - trimmed;
+
+ return trimmed;
}
PassOwnPtr<CCActiveAnimation> CCActiveAnimation::cloneForImplThread() const
@@ -135,6 +148,7 @@
toReturn->m_pauseTime = m_pauseTime;
toReturn->m_totalPausedTime = m_totalPausedTime;
toReturn->m_timeOffset = m_timeOffset;
+ toReturn->m_alternatesDirection = m_alternatesDirection;
return toReturn.release();
}
Modified: branches/chromium/1132/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp (116999 => 117000)
--- branches/chromium/1132/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp 2012-05-14 21:12:38 UTC (rev 116999)
+++ branches/chromium/1132/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp 2012-05-14 21:17:42 UTC (rev 117000)
@@ -52,20 +52,24 @@
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::AnimationDirectionNormal)
- return nullptr;
+ bool alternate = false;
+ bool reverse = false;
+ if (animation && animation->isDirectionSet()) {
+ Animation::AnimationDirection direction = animation->direction();
+ if (direction == Animation::AnimationDirectionAlternate || direction == Animation::AnimationDirectionAlternateReverse)
+ alternate = true;
+ if (direction == Animation::AnimationDirectionReverse || direction == Animation::AnimationDirectionAlternateReverse)
+ reverse = true;
+ }
- // FIXME: add support for fills forwards and fills backwards
- if (animation && animation->isFillModeSet() && (animation->fillsForwards() || animation->fillsBackwards()))
- return nullptr;
-
OwnPtr<Curve> curve = Curve::create();
Vector<Keyframe> keyframes;
for (size_t i = 0; i < valueList.size(); i++) {
- const Value* originalValue = static_cast<const Value*>(valueList.at(i));
+ size_t index = reverse ? valueList.size() - i - 1 : i;
+ const Value* originalValue = static_cast<const Value*>(valueList.at(index));
+
OwnPtr<CCTimingFunction> timingFunction;
const TimingFunction* originalTimingFunction = originalValue->timingFunction();
@@ -91,7 +95,10 @@
timingFunction = CCEaseTimingFunction::create();
double duration = (animation && animation->isDurationSet()) ? animation->duration() : 1;
- appendKeyframe<Value, Keyframe, Curve>(*curve, originalValue->keyTime() * duration, originalValue, timingFunction.release());
+ double keyTime = originalValue->keyTime() * duration;
+ if (reverse)
+ keyTime = duration - keyTime;
+ appendKeyframe<Value, Keyframe, Curve>(*curve, keyTime, originalValue, timingFunction.release());
}
OwnPtr<CCActiveAnimation> anim = CCActiveAnimation::create(curve.release(), animationId, groupId, targetProperty);
@@ -101,6 +108,7 @@
if (anim.get()) {
int iterations = (animation && animation->isIterationCountSet()) ? animation->iterationCount() : 1;
anim->setIterations(iterations);
+ anim->setAlternatesDirection(alternate);
}
// In order to avoid skew, the main thread animation cannot tick until it has received the start time of
Modified: branches/chromium/1132/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp (116999 => 117000)
--- branches/chromium/1132/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp 2012-05-14 21:12:38 UTC (rev 116999)
+++ branches/chromium/1132/Source/WebKit/chromium/tests/CCLayerAnimationControllerTest.cpp 2012-05-14 21:17:42 UTC (rev 117000)
@@ -86,34 +86,45 @@
EXPECT_EQ(1, curve->getValue(duration));
}
-TEST(CCLayerAnimationControllerTest, ignoreUnsupportedAnimationDirections)
+TEST(CCLayerAnimationControllerTest, createTransformAnimation)
{
FakeLayerAnimationControllerClient dummy;
OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
const double duration = 1;
- WebCore::KeyframeValueList values(AnimatedPropertyOpacity);
- values.insert(new FloatAnimationValue(0, 0));
- values.insert(new FloatAnimationValue(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);
- animation->setDirection(Animation::AnimationDirectionAlternate);
- EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+ EXPECT_TRUE(controller->hasActiveAnimation());
- animation->setDirection(Animation::AnimationDirectionAlternateReverse);
- EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+ CCActiveAnimation* activeAnimation = controller->getActiveAnimation(0, CCActiveAnimation::Transform);
+ EXPECT_TRUE(activeAnimation);
- animation->setDirection(Animation::AnimationDirectionReverse);
- EXPECT_FALSE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+ EXPECT_EQ(1, activeAnimation->iterations());
+ EXPECT_EQ(CCActiveAnimation::Transform, activeAnimation->targetProperty());
- animation->setDirection(Animation::AnimationDirectionNormal);
- EXPECT_TRUE(controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0));
+ 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, createTransformAnimation)
+TEST(CCLayerAnimationControllerTest, createReversedAnimation)
{
FakeLayerAnimationControllerClient dummy;
OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
@@ -130,6 +141,7 @@
RefPtr<Animation> animation = Animation::create();
animation->setDuration(duration);
+ animation->setDirection(Animation::AnimationDirectionReverse);
IntSize boxSize;
controller->addAnimation(values, boxSize, animation.get(), 0, 0, 0);
@@ -147,10 +159,92 @@
const CCTransformAnimationCurve* curve = activeAnimation->curve()->toTransformAnimationCurve();
EXPECT_TRUE(curve);
+ expectTranslateX(4, curve->getValue(0, boxSize));
+ expectTranslateX(2, curve->getValue(duration, boxSize));
+}
+
+TEST(CCLayerAnimationControllerTest, createAlternatingAnimation)
+{
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
+ 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);
+ animation->setDirection(Animation::AnimationDirectionAlternate);
+ animation->setIterationCount(2);
+
+ 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_TRUE(activeAnimation->alternatesDirection());
+
+ EXPECT_EQ(2, 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, createReversedAlternatingAnimation)
+{
+ FakeLayerAnimationControllerClient dummy;
+ OwnPtr<CCLayerAnimationController> controller(CCLayerAnimationController::create(&dummy));
+ 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);
+ animation->setDirection(Animation::AnimationDirectionAlternateReverse);
+ animation->setIterationCount(2);
+
+ 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_TRUE(activeAnimation->alternatesDirection());
+
+ EXPECT_EQ(2, 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(4, curve->getValue(0, boxSize));
+ expectTranslateX(2, curve->getValue(duration, boxSize));
+}
+
TEST(CCLayerAnimationControllerTest, syncNewAnimation)
{
FakeLayerAnimationControllerClient dummyImpl;