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;