Modified: trunk/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp (121843 => 121844)
--- trunk/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp 2012-07-04 12:53:48 UTC (rev 121843)
+++ trunk/Source/WebCore/platform/graphics/chromium/AnimationTranslationUtil.cpp 2012-07-04 12:57:58 UTC (rev 121844)
@@ -122,15 +122,54 @@
}
template <class Value, class Keyframe, class Curve>
-bool appendKeyframe(Curve& curve, double keyTime, const Value* value, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize&)
+bool appendKeyframe(Curve& curve, double keyTime, const Value* value, const Value* lastValue, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize&)
{
curve.addKeyframe(Keyframe::create(keyTime, value->value(), timingFunction));
return true;
}
+bool isRotationType(TransformOperation::OperationType transformType)
+{
+ return transformType == TransformOperation::ROTATE
+ || transformType == TransformOperation::ROTATE_X
+ || transformType == TransformOperation::ROTATE_Y
+ || transformType == TransformOperation::ROTATE_Z
+ || transformType == TransformOperation::ROTATE_3D;
+}
+
+bool causesRotationOfAtLeast180Degrees(const TransformAnimationValue* value, const TransformAnimationValue* lastValue)
+{
+ if (!lastValue)
+ return false;
+
+ const TransformOperations& operations = *value->value();
+ const TransformOperations& lastOperations = *lastValue->value();
+
+ // We'll be doing matrix interpolation in this case. No risk of incorrect
+ // rotations here.
+ if (!operations.operationsMatch(lastOperations))
+ return false;
+
+ for (size_t i = 0; i < operations.size(); ++i) {
+ if (!isRotationType(operations.operations()[i]->getOperationType()))
+ continue;
+
+ RotateTransformOperation* rotation = static_cast<RotateTransformOperation*>(operations.operations()[i].get());
+ RotateTransformOperation* lastRotation = static_cast<RotateTransformOperation*>(lastOperations.operations()[i].get());
+
+ if (fabs(rotation->angle() - lastRotation->angle()) >= 180)
+ return true;
+ }
+
+ return false;
+}
+
template <>
-bool appendKeyframe<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(CCKeyframedTransformAnimationCurve& curve, double keyTime, const TransformAnimationValue* value, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize& boxSize)
+bool appendKeyframe<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(CCKeyframedTransformAnimationCurve& curve, double keyTime, const TransformAnimationValue* value, const TransformAnimationValue* lastValue, PassOwnPtr<CCTimingFunction> timingFunction, const FloatSize& boxSize)
{
+ if (causesRotationOfAtLeast180Degrees(value, lastValue))
+ return false;
+
WebTransformOperations operations = toWebTransformOperations(*value->value(), boxSize);
if (operations.apply().isInvertible()) {
curve.addKeyframe(CCTransformKeyframe::create(keyTime, operations, timingFunction));
@@ -159,6 +198,9 @@
size_t index = reverse ? valueList.size() - i - 1 : i;
const Value* originalValue = static_cast<const Value*>(valueList.at(index));
+ const Value* lastOriginalValue = 0;
+ if (valueList.size() > 1 && ((reverse && index + 1 < valueList.size()) || (!reverse && index > 0)))
+ lastOriginalValue = static_cast<const Value*>(valueList.at(reverse ? index + 1 : index - 1));
OwnPtr<CCTimingFunction> timingFunction;
const TimingFunction* originalTimingFunction = originalValue->timingFunction();
@@ -190,7 +232,7 @@
if (reverse)
keyTime = duration - keyTime;
- bool addedKeyframe = appendKeyframe<Value, Keyframe, Curve>(*curve, keyTime, originalValue, timingFunction.release(), boxSize);
+ bool addedKeyframe = appendKeyframe<Value, Keyframe, Curve>(*curve, keyTime, originalValue, lastOriginalValue, timingFunction.release(), boxSize);
if (!addedKeyframe)
return nullptr;
}
Modified: trunk/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp (121843 => 121844)
--- trunk/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp 2012-07-04 12:53:48 UTC (rev 121843)
+++ trunk/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp 2012-07-04 12:57:58 UTC (rev 121844)
@@ -509,14 +509,6 @@
bool GraphicsLayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
{
- // Bail early if we have a large rotation.
- if (values.property() == AnimatedPropertyWebkitTransform) {
- bool hasRotationOfMoreThan180Degrees = false;
- validateTransformOperations(values, hasRotationOfMoreThan180Degrees);
- if (hasRotationOfMoreThan180Degrees)
- return false;
- }
-
primaryLayer().unwrap<LayerChromium>()->setLayerAnimationDelegate(this);
int animationId = mapAnimationNameToId(animationName);
Modified: trunk/Source/WebKit/chromium/tests/GraphicsLayerChromiumTest.cpp (121843 => 121844)
--- trunk/Source/WebKit/chromium/tests/GraphicsLayerChromiumTest.cpp 2012-07-04 12:53:48 UTC (rev 121843)
+++ trunk/Source/WebKit/chromium/tests/GraphicsLayerChromiumTest.cpp 2012-07-04 12:57:58 UTC (rev 121844)
@@ -256,6 +256,50 @@
EXPECT_FALSE(m_platformLayer->layerAnimationController()->hasActiveAnimation());
}
+TEST_F(GraphicsLayerChromiumTest, createTransformAnimationWithRotationInvolvingNegativeAngles)
+{
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
+
+ TransformOperations operations1;
+ operations1.operations().append(RotateTransformOperation::create(-330, TransformOperation::ROTATE));
+ values.insert(new TransformAnimationValue(0, &operations1));
+
+ TransformOperations operations2;
+ operations2.operations().append(RotateTransformOperation::create(-320, TransformOperation::ROTATE));
+ values.insert(new TransformAnimationValue(duration, &operations2));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+ m_graphicsLayer->addAnimation(values, boxSize, animation.get(), "", 0);
+
+ EXPECT_TRUE(m_platformLayer->layerAnimationController()->hasActiveAnimation());
+}
+
+TEST_F(GraphicsLayerChromiumTest, createTransformAnimationWithSmallRotationInvolvingLargeAngles)
+{
+ const double duration = 1;
+ WebCore::KeyframeValueList values(AnimatedPropertyWebkitTransform);
+
+ TransformOperations operations1;
+ operations1.operations().append(RotateTransformOperation::create(270, TransformOperation::ROTATE));
+ values.insert(new TransformAnimationValue(0, &operations1));
+
+ TransformOperations operations2;
+ operations2.operations().append(RotateTransformOperation::create(360, TransformOperation::ROTATE));
+ values.insert(new TransformAnimationValue(duration, &operations2));
+
+ RefPtr<Animation> animation = Animation::create();
+ animation->setDuration(duration);
+
+ IntSize boxSize;
+ m_graphicsLayer->addAnimation(values, boxSize, animation.get(), "", 0);
+
+ EXPECT_TRUE(m_platformLayer->layerAnimationController()->hasActiveAnimation());
+}
+
TEST_F(GraphicsLayerChromiumTest, createTransformAnimationWithSingularMatrix)
{
const double duration = 1;