Title: [142749] trunk/Source/WebCore
Revision
142749
Author
[email protected]
Date
2013-02-13 08:12:44 -0800 (Wed, 13 Feb 2013)

Log Message

[GTK][AC] Implement basic transform animations with clutter ac backend
https://bugs.webkit.org/show_bug.cgi?id=109363

Patch by ChangSeok Oh <[email protected]> on 2013-02-13
Reviewed by Gustavo Noronha Silva.

Implement basic transform animation with clutter ac backend.
GraphicsLayerClutter is almost same with GraphicsLayerCA. And PlatformClutterAnimation
interfaces are also similar with PlatformCAAnimation, but they are implemented
with native clutter APIs. Clutter backend AC supports a basic single transform animation
with this patch now, but additive animation combination and keyframe animation
are not supported yet.

Covered by existing animation tests.

* platform/graphics/clutter/GraphicsLayerActor.cpp:
(graphicsLayerActorSetTransform):
* platform/graphics/clutter/GraphicsLayerClutter.cpp:
(WebCore::isTransformTypeTransformationMatrix):
(WebCore):
(WebCore::isTransformTypeFloatPoint3D):
(WebCore::isTransformTypeNumber):
(WebCore::getTransformFunctionValue):
(WebCore::getValueFunctionNameForTransformOperation):
(WebCore::GraphicsLayerClutter::setTransformAnimationEndpoints):
(WebCore::GraphicsLayerClutter::appendToUncommittedAnimations):
(WebCore::GraphicsLayerClutter::createTransformAnimationsFromKeyframes):
* platform/graphics/clutter/GraphicsLayerClutter.h:
(GraphicsLayerClutter):
* platform/graphics/clutter/PlatformClutterAnimation.cpp:
(WebCore::toClutterActorPropertyString):
(WebCore):
(WebCore::PlatformClutterAnimation::supportsValueFunction):
(WebCore::PlatformClutterAnimation::duration):
(WebCore::PlatformClutterAnimation::setDuration):
(WebCore::PlatformClutterAnimation::setAdditive):
(WebCore::PlatformClutterAnimation::valueFunction):
(WebCore::PlatformClutterAnimation::setValueFunction):
(WebCore::PlatformClutterAnimation::setFromValue):
(WebCore::PlatformClutterAnimation::setToValue):
(WebCore::PlatformClutterAnimation::timeline):
(WebCore::PlatformClutterAnimation::addClutterTransitionForProperty):
(WebCore::PlatformClutterAnimation::addOpacityTransition):
(WebCore::PlatformClutterAnimation::addTransformTransition):
(WebCore::PlatformClutterAnimation::addAnimationForKey):
* platform/graphics/clutter/PlatformClutterAnimation.h:
(PlatformClutterAnimation):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (142748 => 142749)


--- trunk/Source/WebCore/ChangeLog	2013-02-13 15:57:14 UTC (rev 142748)
+++ trunk/Source/WebCore/ChangeLog	2013-02-13 16:12:44 UTC (rev 142749)
@@ -1,3 +1,52 @@
+2013-02-13  ChangSeok Oh  <[email protected]>
+
+        [GTK][AC] Implement basic transform animations with clutter ac backend
+        https://bugs.webkit.org/show_bug.cgi?id=109363
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Implement basic transform animation with clutter ac backend.
+        GraphicsLayerClutter is almost same with GraphicsLayerCA. And PlatformClutterAnimation
+        interfaces are also similar with PlatformCAAnimation, but they are implemented
+        with native clutter APIs. Clutter backend AC supports a basic single transform animation
+        with this patch now, but additive animation combination and keyframe animation
+        are not supported yet.
+
+        Covered by existing animation tests.
+
+        * platform/graphics/clutter/GraphicsLayerActor.cpp:
+        (graphicsLayerActorSetTransform):
+        * platform/graphics/clutter/GraphicsLayerClutter.cpp:
+        (WebCore::isTransformTypeTransformationMatrix):
+        (WebCore):
+        (WebCore::isTransformTypeFloatPoint3D):
+        (WebCore::isTransformTypeNumber):
+        (WebCore::getTransformFunctionValue):
+        (WebCore::getValueFunctionNameForTransformOperation):
+        (WebCore::GraphicsLayerClutter::setTransformAnimationEndpoints):
+        (WebCore::GraphicsLayerClutter::appendToUncommittedAnimations):
+        (WebCore::GraphicsLayerClutter::createTransformAnimationsFromKeyframes):
+        * platform/graphics/clutter/GraphicsLayerClutter.h:
+        (GraphicsLayerClutter):
+        * platform/graphics/clutter/PlatformClutterAnimation.cpp:
+        (WebCore::toClutterActorPropertyString):
+        (WebCore):
+        (WebCore::PlatformClutterAnimation::supportsValueFunction):
+        (WebCore::PlatformClutterAnimation::duration):
+        (WebCore::PlatformClutterAnimation::setDuration):
+        (WebCore::PlatformClutterAnimation::setAdditive):
+        (WebCore::PlatformClutterAnimation::valueFunction):
+        (WebCore::PlatformClutterAnimation::setValueFunction):
+        (WebCore::PlatformClutterAnimation::setFromValue):
+        (WebCore::PlatformClutterAnimation::setToValue):
+        (WebCore::PlatformClutterAnimation::timeline):
+        (WebCore::PlatformClutterAnimation::addClutterTransitionForProperty):
+        (WebCore::PlatformClutterAnimation::addOpacityTransition):
+        (WebCore::PlatformClutterAnimation::addTransformTransition):
+        (WebCore::PlatformClutterAnimation::addAnimationForKey):
+        * platform/graphics/clutter/PlatformClutterAnimation.h:
+        (PlatformClutterAnimation):
+
 2013-02-13  Ilya Tikhonovsky  <[email protected]>
 
         Web Inspector: Native Memory Instrumentation: reportLeaf method doesn't report the leaf node properly.

Modified: trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerActor.cpp (142748 => 142749)


--- trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerActor.cpp	2013-02-13 15:57:14 UTC (rev 142748)
+++ trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerActor.cpp	2013-02-13 16:12:44 UTC (rev 142749)
@@ -392,7 +392,7 @@
         needToRedraw = true;
     }
 
-    if (!cogl_matrix_is_identity(matrix)) {
+    if (matrix && !cogl_matrix_is_identity(matrix)) {
         priv->matrix = cogl_matrix_copy(matrix);
         needToRedraw = true;
     } else

Modified: trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp (142748 => 142749)


--- trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp	2013-02-13 15:57:14 UTC (rev 142748)
+++ trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp	2013-02-13 16:12:44 UTC (rev 142749)
@@ -53,6 +53,148 @@
 // So send a very small value instead.
 static const float cAnimationAlmostZeroDuration = 1e-3f;
 
+static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
+{
+    switch (transformType) {
+    case TransformOperation::SKEW_X:
+    case TransformOperation::SKEW_Y:
+    case TransformOperation::SKEW:
+    case TransformOperation::MATRIX:
+    case TransformOperation::ROTATE_3D:
+    case TransformOperation::MATRIX_3D:
+    case TransformOperation::PERSPECTIVE:
+    case TransformOperation::IDENTITY:
+    case TransformOperation::NONE:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
+{
+    switch (transformType) {
+    case TransformOperation::SCALE:
+    case TransformOperation::SCALE_3D:
+    case TransformOperation::TRANSLATE:
+    case TransformOperation::TRANSLATE_3D:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
+{
+    return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
+}
+
+static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value)
+{
+    switch (transformType) {
+    case TransformOperation::ROTATE:
+    case TransformOperation::ROTATE_X:
+    case TransformOperation::ROTATE_Y:
+        value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0;
+        break;
+    case TransformOperation::SCALE_X:
+        value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1;
+        break;
+    case TransformOperation::SCALE_Y:
+        value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1;
+        break;
+    case TransformOperation::SCALE_Z:
+        value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1;
+        break;
+    case TransformOperation::TRANSLATE_X:
+        value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0;
+        break;
+    case TransformOperation::TRANSLATE_Y:
+        value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0;
+        break;
+    case TransformOperation::TRANSLATE_Z:
+        value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0;
+        break;
+    default:
+        break;
+    }
+}
+
+static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value)
+{
+    switch (transformType) {
+    case TransformOperation::SCALE:
+    case TransformOperation::SCALE_3D:
+        value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1);
+        value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1);
+        value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1);
+        break;
+    case TransformOperation::TRANSLATE:
+    case TransformOperation::TRANSLATE_3D:
+        value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0);
+        value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0);
+        value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0);
+        break;
+    default:
+        break;
+    }
+}
+
+static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value)
+{
+    switch (transformType) {
+    case TransformOperation::SKEW_X:
+    case TransformOperation::SKEW_Y:
+    case TransformOperation::SKEW:
+    case TransformOperation::MATRIX:
+    case TransformOperation::ROTATE_3D:
+    case TransformOperation::MATRIX_3D:
+    case TransformOperation::PERSPECTIVE:
+    case TransformOperation::IDENTITY:
+    case TransformOperation::NONE:
+        if (transformOp)
+            transformOp->apply(value, size);
+        else
+            value.makeIdentity();
+        break;
+    default:
+        break;
+    }
+}
+
+static PlatformClutterAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
+{
+    // Use literal strings to avoid link-time dependency on those symbols.
+    switch (transformType) {
+    case TransformOperation::ROTATE_X:
+        return PlatformClutterAnimation::RotateX;
+    case TransformOperation::ROTATE_Y:
+        return PlatformClutterAnimation::RotateY;
+    case TransformOperation::ROTATE:
+        return PlatformClutterAnimation::RotateZ;
+    case TransformOperation::SCALE_X:
+        return PlatformClutterAnimation::ScaleX;
+    case TransformOperation::SCALE_Y:
+        return PlatformClutterAnimation::ScaleY;
+    case TransformOperation::SCALE_Z:
+        return PlatformClutterAnimation::ScaleZ;
+    case TransformOperation::TRANSLATE_X:
+        return PlatformClutterAnimation::TranslateX;
+    case TransformOperation::TRANSLATE_Y:
+        return PlatformClutterAnimation::TranslateY;
+    case TransformOperation::TRANSLATE_Z:
+        return PlatformClutterAnimation::TranslateZ;
+    case TransformOperation::SCALE:
+    case TransformOperation::SCALE_3D:
+        return PlatformClutterAnimation::Scale;
+    case TransformOperation::TRANSLATE:
+    case TransformOperation::TRANSLATE_3D:
+        return PlatformClutterAnimation::Translate;
+    default:
+        return PlatformClutterAnimation::NoValueFunction;
+    }
+}
+
 static String propertyIdToString(AnimatedPropertyID property)
 {
     switch (property) {
@@ -618,14 +760,122 @@
 
 bool GraphicsLayerClutter::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* animation, PlatformClutterAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
 {
-    notImplemented();
-    return false;
+    ASSERT(valueList.size() == 2);
+
+    bool forwards = animation->directionIsForwards();
+
+    unsigned fromIndex = !forwards;
+    unsigned toIndex = forwards;
+
+    const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(fromIndex));
+    const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(toIndex));
+
+    if (isMatrixAnimation) {
+        TransformationMatrix fromTransform, toTransform;
+        startValue->value()->apply(boxSize, fromTransform);
+        endValue->value()->apply(boxSize, toTransform);
+
+        // FIXME: If any matrix is singular, CA won't animate it correctly.
+        // So fall back to software animation, But it's not sure in clutter case.
+        // We need to investigate it more.
+        if (!fromTransform.isInvertible() || !toTransform.isInvertible())
+            return false;
+
+        basicAnim->setFromValue(fromTransform);
+        basicAnim->setToValue(toTransform);
+    } else {
+        if (isTransformTypeNumber(transformOpType)) {
+            float fromValue;
+            getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue);
+            basicAnim->setFromValue(fromValue);
+
+            float toValue;
+            getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue);
+            basicAnim->setToValue(toValue);
+        } else if (isTransformTypeFloatPoint3D(transformOpType)) {
+            FloatPoint3D fromValue;
+            getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue);
+            basicAnim->setFromValue(fromValue);
+
+            FloatPoint3D toValue;
+            getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue);
+            basicAnim->setToValue(toValue);
+        } else {
+            TransformationMatrix fromValue;
+            getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, fromValue);
+            basicAnim->setFromValue(fromValue);
+
+            TransformationMatrix toValue;
+            getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, toValue);
+            basicAnim->setToValue(toValue);
+        }
+    }
+
+    // This codepath is used for 2-keyframe animations, so we still need to look in the start
+    // for a timing function. Even in the reversing animation case, the first keyframe provides the timing function.
+    const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), animation);
+    basicAnim->setTimingFunction(timingFunction, !forwards);
+
+    PlatformClutterAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
+    if (valueFunction != PlatformClutterAnimation::NoValueFunction)
+        basicAnim->setValueFunction(valueFunction);
+
+    return true;
 }
 
+bool GraphicsLayerClutter::appendToUncommittedAnimations(const KeyframeValueList& valueList, const TransformOperations* operations, const Animation* animation, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation)
+{
+    TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : operations->operations().at(animationIndex)->getOperationType();
+    bool additive = animationIndex > 0;
+    bool isKeyframe = valueList.size() > 2;
+
+    RefPtr<PlatformClutterAnimation> clutterAnimation;
+    bool validMatrices = true;
+    if (isKeyframe) {
+        clutterAnimation = createKeyframeAnimation(animation, propertyIdToString(valueList.property()), additive);
+        validMatrices = setTransformAnimationKeyframes(valueList, animation, clutterAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
+    } else {
+        clutterAnimation = createBasicAnimation(animation, propertyIdToString(valueList.property()), additive);
+        validMatrices = setTransformAnimationEndpoints(valueList, animation, clutterAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
+    }
+
+    if (!validMatrices)
+        return false;
+
+    m_uncomittedAnimations.append(LayerPropertyAnimation(clutterAnimation, animationName, valueList.property(), animationIndex, timeOffset));
+    return true;
+}
+
 bool GraphicsLayerClutter::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize)
 {
-    notImplemented();
-    return false;
+    ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
+
+    bool hasBigRotation;
+    int listIndex = validateTransformOperations(valueList, hasBigRotation);
+    const TransformOperations* operations = (listIndex >= 0) ? static_cast<const TransformAnimationValue*>(valueList.at(listIndex))->value() : 0;
+
+    // We need to fall back to software animation if we don't have setValueFunction:, and
+    // we would need to animate each incoming transform function separately. This is the
+    // case if we have a rotation >= 180 or we have more than one transform function.
+    if ((hasBigRotation || (operations && operations->size() > 1)) && !PlatformClutterAnimation::supportsValueFunction())
+        return false;
+
+    bool validMatrices = true;
+
+    // If function lists don't match we do a matrix animation, otherwise we do a component hardware animation.
+    // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
+    // if that's not true as well.
+    bool isMatrixAnimation = listIndex < 0 || !PlatformClutterAnimation::supportsValueFunction();
+    int numAnimations = isMatrixAnimation ? 1 : operations->size();
+
+    for (int animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
+        if (!appendToUncommittedAnimations(valueList, operations, animation, animationName, boxSize, animationIndex, timeOffset, isMatrixAnimation)) {
+            validMatrices = false;
+            break;
+        }
+    }
+
+    return validMatrices;
 }
 
 bool GraphicsLayerClutter::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)

Modified: trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h (142748 => 142749)


--- trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h	2013-02-13 15:57:14 UTC (rev 142748)
+++ trunk/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.h	2013-02-13 16:12:44 UTC (rev 142749)
@@ -119,6 +119,8 @@
     bool setTransformAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformClutterAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
     bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformClutterAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
 
+    bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperations*, const Animation*, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation);
+
     enum LayerChange {
         NoChange = 0,
         NameChanged = 1 << 1,

Modified: trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.cpp (142748 => 142749)


--- trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.cpp	2013-02-13 15:57:14 UTC (rev 142748)
+++ trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.cpp	2013-02-13 16:12:44 UTC (rev 142749)
@@ -50,6 +50,14 @@
     animation->animationDidStart();
 }
 
+static String toClutterActorPropertyString(const PlatformClutterAnimation::ValueFunctionType valueFunctionType)
+{
+    // ClutterActor doesn't have 'scale' and 'translate' properties. So we should support
+    // 'scale' and 'translate' ValueFunctionType by combination of existing property animations. 
+    const char* clutterActorProperty[] = { "NoProperty", "rotation-angle-x", "rotation-angle-y", "rotation-angle-z", "scale-x", "scale-y", "scale-z", "NoProperty", "translation-x", "translation-y", "translation-z", "NoProperty" }; 
+    return clutterActorProperty[valueFunctionType];
+}
+
 static ClutterAnimationMode toClutterAnimationMode(const TimingFunction* timingFunction)
 {
     ASSERT(timingFunction);
@@ -124,7 +132,7 @@
 
 bool PlatformClutterAnimation::supportsValueFunction()
 {
-    return false;
+    return true;
 }
 
 double PlatformClutterAnimation::beginTime() const
@@ -140,16 +148,12 @@
 
 double PlatformClutterAnimation::duration() const
 {
-    ASSERT(m_type == Basic);
-
     double duration = clutter_timeline_get_duration(CLUTTER_TIMELINE(m_animation.get()));
     return duration / 1000;
 }
 
 void PlatformClutterAnimation::setDuration(double value)
 {
-    ASSERT(m_type == Basic);
-
     // Clutter Animation sets the duration time in milliseconds.
     gint duration = value * 1000;
     clutter_timeline_set_duration(CLUTTER_TIMELINE(m_animation.get()), duration);
@@ -245,24 +249,28 @@
 {
     if (m_additive == value)
         return;
+
     m_additive = value;
 }
 
 PlatformClutterAnimation::ValueFunctionType PlatformClutterAnimation::valueFunction() const
 {
-    notImplemented();
-    return NoValueFunction;
+    return m_valueFunctionType;
 }
 
 void PlatformClutterAnimation::setValueFunction(ValueFunctionType value)
 {
-    notImplemented();
+    if (m_valueFunctionType == value)
+        return;
+
+    m_valueFunctionType = value;
 }
 
 void PlatformClutterAnimation::setFromValue(float value)
 {
-    if (m_fromValue == value)
+    if (animationType() != Basic || m_fromValue == value)
         return;
+
     m_fromValue = value;
 }
 
@@ -273,7 +281,10 @@
 
 void PlatformClutterAnimation::setFromValue(const FloatPoint3D& value)
 {
-    notImplemented();
+    if (animationType() != Basic || m_fromValue3D == value)
+        return;
+
+    m_fromValue3D = value;
 }
 
 void PlatformClutterAnimation::setFromValue(const WebCore::Color& value)
@@ -288,8 +299,9 @@
 
 void PlatformClutterAnimation::setToValue(float value)
 {
-    if (m_toValue == value)
+    if (animationType() != Basic || m_toValue == value)
         return;
+
     m_toValue = value;
 }
 
@@ -300,7 +312,10 @@
 
 void PlatformClutterAnimation::setToValue(const FloatPoint3D& value)
 {
-    notImplemented();
+    if (animationType() != Basic || m_toValue3D == value)
+        return;
+
+    m_toValue3D = value;
 }
 
 void PlatformClutterAnimation::setToValue(const WebCore::Color& value)
@@ -372,28 +387,80 @@
 ClutterTimeline* PlatformClutterAnimation::timeline() const
 {
     ASSERT(m_animation);
-    ASSERT(m_type == Basic);
     return CLUTTER_TIMELINE(m_animation.get());
 }
 
-void PlatformClutterAnimation::addOpacityTransition()
+void PlatformClutterAnimation::addClutterTransitionForProperty(const String& property, const unsigned fromValue, const unsigned toValue)
 {
-    GRefPtr<ClutterTransition> transition = adoptGRef(clutter_property_transition_new("opacity"));
-    clutter_transition_set_from(transition.get(), G_TYPE_UINT, static_cast<guint8>(255 * m_fromValue));
-    clutter_transition_set_to(transition.get(), G_TYPE_UINT, static_cast<guint8>(255 * m_toValue));
+    ASSERT(property != "NoProperty");
 
+    GRefPtr<ClutterTransition> transition = adoptGRef(clutter_property_transition_new(property.utf8().data()));
+    clutter_transition_set_from(transition.get(), G_TYPE_UINT, fromValue);
+    clutter_transition_set_to(transition.get(), G_TYPE_UINT, toValue);
+
     clutter_transition_group_add_transition(CLUTTER_TRANSITION_GROUP(m_animation.get()), transition.get());
 }
 
+void PlatformClutterAnimation::addClutterTransitionForProperty(const String& property, const float fromValue, const float toValue)
+{
+    ASSERT(property != "NoProperty");
+
+    GRefPtr<ClutterTransition> transition = adoptGRef(clutter_property_transition_new(property.utf8().data()));
+    clutter_transition_set_from(transition.get(), G_TYPE_FLOAT, fromValue);
+    clutter_transition_set_to(transition.get(), G_TYPE_FLOAT, toValue);
+
+    clutter_transition_group_add_transition(CLUTTER_TRANSITION_GROUP(m_animation.get()), transition.get());
+}
+
+void PlatformClutterAnimation::addOpacityTransition()
+{
+    addClutterTransitionForProperty(String("opacity"), static_cast<unsigned>(255 * m_fromValue), static_cast<unsigned>(255 * m_toValue));
+}
+
+void PlatformClutterAnimation::addTransformTransition()
+{
+    switch (m_valueFunctionType) {
+    case RotateX:
+    case RotateY:
+    case RotateZ:
+        addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), rad2deg(m_fromValue), rad2deg(m_toValue));
+        break;
+    case ScaleX:
+    case ScaleY:
+    case ScaleZ:
+    case TranslateX:
+    case TranslateY:
+    case TranslateZ:
+        addClutterTransitionForProperty(toClutterActorPropertyString(m_valueFunctionType), m_fromValue, m_toValue);
+        break;
+    case Scale:
+        addClutterTransitionForProperty(String("scale-x"), m_fromValue3D.x(), m_toValue3D.x());
+        addClutterTransitionForProperty(String("scale-y"), m_fromValue3D.y(), m_toValue3D.y());
+        break;
+    case Translate:
+        addClutterTransitionForProperty(String("translation-x"), m_fromValue3D.x(), m_toValue3D.x());
+        addClutterTransitionForProperty(String("translation-y"), m_fromValue3D.x(), m_toValue3D.y());
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    // If clutter covers valueFunction type animations, we should release keeping transform matrix.
+    // Otherwise, the transformation is applied twice unexpectedly. See graphicsLayerActorApplyTransform.
+    graphicsLayerActorSetTransform(GRAPHICS_LAYER_ACTOR(m_layer.get()), 0);
+}
+
 void PlatformClutterAnimation::addAnimationForKey(GraphicsLayerActor* platformLayer, const String& key)
 {
     ASSERT(animationType() == Basic);
     ASSERT(!g_object_get_data(G_OBJECT(platformLayer), key.utf8().data()));
 
+    m_layer = CLUTTER_ACTOR(platformLayer);
+
     if (m_animatedPropertyType == Opacity)
         addOpacityTransition();
     else if (m_animatedPropertyType == Transform)
-        ASSERT_NOT_REACHED();
+        addTransformTransition();
     else if (m_animatedPropertyType == BackgroundColor)
         ASSERT_NOT_REACHED();
     else
@@ -406,8 +473,6 @@
     g_signal_connect(clutterTimeline, "started", G_CALLBACK(timelineStartedCallback), this);
     g_object_set_data(G_OBJECT(platformLayer), key.utf8().data(), this);
 
-    m_layer = CLUTTER_ACTOR(platformLayer);
-
     clutter_actor_add_transition(m_layer.get(), key.utf8().data(), CLUTTER_TRANSITION(m_animation.get()));
 }
 

Modified: trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.h (142748 => 142749)


--- trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.h	2013-02-13 15:57:14 UTC (rev 142748)
+++ trunk/Source/WebCore/platform/graphics/clutter/PlatformClutterAnimation.h	2013-02-13 16:12:44 UTC (rev 142749)
@@ -138,7 +138,11 @@
     ClutterTimeline* timeline() const;
     AnimatedPropertyType stringToAnimatedPropertyType(const String& keyPath) const;
 
+    void addClutterTransitionForProperty(const String& property, const unsigned fromValue, const unsigned toValue);
+    void addClutterTransitionForProperty(const String& property, const float fromValue, const float toValue);
+
     void addOpacityTransition();
+    void addTransformTransition();
 
     AnimationType m_type;
     AnimatedPropertyType m_animatedPropertyType;
@@ -151,6 +155,9 @@
     float m_fromValue;
     float m_toValue;
 
+    FloatPoint3D m_fromValue3D;
+    FloatPoint3D m_toValue3D;
+
     float m_repeatCount;
 
     const TimingFunction* m_timingFunction;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to