OSDN Git Service

Refactoring of animation
authorNicolas Roard <nicolas@android.com>
Wed, 15 Dec 2010 01:00:56 +0000 (17:00 -0800)
committerNicolas Roard <nicolas@android.com>
Wed, 15 Dec 2010 18:00:17 +0000 (10:00 -0800)
We use Webkit animation classes instead of using our own.
Implements keyframes animation for transform.
Simplify LayerAndroid to remove the individual
scaling/translate/rotation attributes and use a TransformationMatrix
instead.
Also cleaned up the style.

Change-Id: I9a4d5c064c30bba568c37ced946405ed60019d33

WebCore/platform/graphics/android/AndroidAnimation.cpp
WebCore/platform/graphics/android/AndroidAnimation.h
WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
WebCore/platform/graphics/android/GraphicsLayerAndroid.h
WebCore/platform/graphics/android/LayerAndroid.cpp
WebCore/platform/graphics/android/LayerAndroid.h

index 0daef46..e01bf55 100644 (file)
 
 #include "Timer.h"
 #include "TimingFunction.h"
+#include "TranslateTransformOperation.h"
 #include "UnitBezier.h"
 
 #include <wtf/CurrentTime.h>
 
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+
 namespace WebCore {
 
 static long gDebugAndroidAnimationInstances;
@@ -38,13 +55,14 @@ long AndroidAnimation::instancesCount()
 }
 
 AndroidAnimation::AndroidAnimation(const Animation* animation,
-                                   double beginTime) :
-    m_beginTime(beginTime),
-    m_duration(animation->duration()),
-    m_iterationCount(animation->iterationCount()),
-    m_currentIteration(0),
-    m_direction(animation->direction()),
-    m_timingFunction(animation->timingFunction())
+                                   double beginTime)
+    : m_beginTime(beginTime)
+    , m_duration(animation->duration())
+    , m_iterationCount(animation->iterationCount())
+    , m_currentIteration(0)
+    , m_direction(animation->direction())
+    , m_currentDirection(false)
+    , m_timingFunction(animation->timingFunction())
 {
     ASSERT(m_timingFunction);
 
@@ -54,13 +72,14 @@ AndroidAnimation::AndroidAnimation(const Animation* animation,
     gDebugAndroidAnimationInstances++;
 }
 
-AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) :
-    m_beginTime(anim->m_beginTime),
-    m_duration(anim->m_duration),
-    m_iterationCount(anim->m_iterationCount),
-    m_currentIteration(0),
-    m_direction(anim->m_direction),
-    m_timingFunction(anim->m_timingFunction)
+AndroidAnimation::AndroidAnimation(AndroidAnimation* anim)
+    : m_beginTime(anim->m_beginTime)
+    , m_duration(anim->m_duration)
+    , m_iterationCount(anim->m_iterationCount)
+    , m_currentIteration(0)
+    , m_direction(anim->m_direction)
+    , m_currentDirection(false)
+    , m_timingFunction(anim->m_timingFunction)
 {
     gDebugAndroidAnimationInstances++;
 }
@@ -129,15 +148,16 @@ PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create(
 AndroidOpacityAnimation::AndroidOpacityAnimation(float fromValue, float toValue,
                                                  const Animation* animation,
                                                  double beginTime)
-    : AndroidAnimation(animation, beginTime),
-      m_fromValue(fromValue), m_toValue(toValue)
+    : AndroidAnimation(animation, beginTime)
+    , m_fromValue(fromValue)
+    , m_toValue(toValue)
 {
 }
 
 AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim)
-    : AndroidAnimation(anim),
-    m_fromValue(anim->m_fromValue),
-    m_toValue(anim->m_toValue)
+    : AndroidAnimation(anim)
+    , m_fromValue(anim->m_fromValue)
+    m_toValue(anim->m_toValue)
 {
 }
 
@@ -146,13 +166,6 @@ PassRefPtr<AndroidAnimation> AndroidOpacityAnimation::copy()
     return adoptRef(new AndroidOpacityAnimation(this));
 }
 
-void AndroidOpacityAnimation::swapDirection()
-{
-    float v = m_toValue;
-    m_toValue = m_fromValue;
-    m_fromValue = m_toValue;
-}
-
 bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time)
 {
     float progress;
@@ -169,31 +182,23 @@ bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time)
 
 PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create(
                                                      const Animation* animation,
+                                                     KeyframeValueList* operations,
                                                      double beginTime)
 {
-    return adoptRef(new AndroidTransformAnimation(animation, beginTime));
+    return adoptRef(new AndroidTransformAnimation(animation, operations, beginTime));
 }
 
 AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation,
+                                                     KeyframeValueList* operations,
                                                      double beginTime)
-    : AndroidAnimation(animation, beginTime),
-    m_doTranslation(false),
-    m_doScaling(false),
-    m_doRotation(false)
+    : AndroidAnimation(animation, beginTime)
+    , m_operations(operations)
 {
 }
 
 AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim)
-    : AndroidAnimation(anim),
-    m_doTranslation(anim->m_doTranslation),
-    m_doScaling(anim->m_doScaling),
-    m_doRotation(anim->m_doRotation),
-    m_position(anim->m_position),
-    m_fromX(anim->m_fromX), m_fromY(anim->m_fromY), m_fromZ(anim->m_fromZ),
-    m_toX(anim->m_toX), m_toY(anim->m_toY), m_toZ(anim->m_toZ),
-    m_fromAngle(anim->m_fromAngle), m_toAngle(anim->m_toAngle),
-    m_fromScaleX(anim->m_fromScaleX), m_fromScaleY(anim->m_fromScaleY), m_fromScaleZ(anim->m_fromScaleZ),
-    m_toScaleX(anim->m_toScaleX), m_toScaleY(anim->m_toScaleY), m_toScaleZ(anim->m_toScaleZ)
+    : AndroidAnimation(anim)
+    , m_operations(anim->m_operations)
 {
 }
 
@@ -202,65 +207,6 @@ PassRefPtr<AndroidAnimation> AndroidTransformAnimation::copy()
     return adoptRef(new AndroidTransformAnimation(this));
 }
 
-void AndroidTransformAnimation::setRotation(float fA, float tA)
-{
-    m_fromAngle = fA;
-    m_toAngle = tA;
-    m_doRotation = true;
-}
-
-void AndroidTransformAnimation::setTranslation(float fX, float fY, float fZ,
-    float tX, float tY, float tZ)
-{
-    m_fromX = fX;
-    m_fromY = fY;
-    m_fromZ = fZ;
-    m_toX = tX;
-    m_toY = tY;
-    m_toZ = tZ;
-    m_doTranslation = true;
-}
-
-void AndroidTransformAnimation::setScale(float fX, float fY, float fZ,
-                                         float tX, float tY, float tZ)
-{
-    m_fromScaleX = fX;
-    m_fromScaleY = fY;
-    m_fromScaleZ = fZ;
-    m_toScaleX   = tX;
-    m_toScaleY   = tY;
-    m_toScaleZ   = tZ;
-    m_doScaling = true;
-}
-
-void AndroidTransformAnimation::swapDirection()
-{
-    if (m_doTranslation) {
-        float tx = m_toX;
-        m_toX = m_fromX;
-        m_fromX = tx;
-        float ty = m_toY;
-        m_toY = m_fromY;
-        m_fromY = ty;
-        float tz = m_toZ;
-        m_toZ = m_fromZ;
-        m_fromZ = tz;
-    }
-    if (m_doScaling) {
-        float sx = m_toScaleX;
-        m_toScaleX = m_fromScaleX;
-        m_fromScaleX = sx;
-        float sy = m_toScaleY;
-        m_toScaleY = m_fromScaleY;
-        m_fromScaleY = sy;
-    }
-    if (m_doRotation) {
-        float a = m_toAngle;
-        m_toAngle = m_fromAngle;
-        m_fromAngle = a;
-    }
-}
-
 bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time)
 {
     float progress;
@@ -270,22 +216,88 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time)
     if (progress < 0) // we still want to be evaluated until we get progress > 0
         return true;
 
-    float x = m_fromX + (m_toX - m_fromX) * progress;
-    float y = m_fromY + (m_toY - m_fromY) * progress;
-    float z = m_fromZ + (m_toZ - m_fromZ) * progress;
-    float sx = m_fromScaleX + (m_toScaleX - m_fromScaleX) * progress;
-    float sy = m_fromScaleY + (m_toScaleY - m_fromScaleY) * progress;
-    float sz = m_fromScaleZ + (m_toScaleZ - m_fromScaleZ) * progress;
-    float a = m_fromAngle + (m_toAngle - m_fromAngle) * progress;
+    IntSize size(layer->getSize().width(), layer->getSize().height());
+    TransformationMatrix matrix;
+    XLOG("Evaluate transforms animations, %d operations, progress %.2f for layer %d (%d, %d)"
+         , m_operations->size(), progress, layer->uniqueId(), size.width(), size.height());
 
-    if (m_doTranslation)
-        layer->setTranslation(x, y);
+    if (!m_operations->size())
+        return true;
+
+    // First, we need to get the from and to values
+
+    TransformAnimationValue* fromValue = 0;
+    TransformAnimationValue* toValue = 0;
+
+    float distance = 0;
+    unsigned int foundAt = 0;
+    for (unsigned int i = 0; i < m_operations->size(); i++) {
+        TransformAnimationValue* value = (TransformAnimationValue*) m_operations->at(i);
+        TransformOperations* values = (TransformOperations*) value->value();
+        float key = value->keyTime();
+        float d = fabs(progress - key);
+        XLOG("[%d] Key %.2f, %d values", i, key, values->size());
+        if (!fromValue || (d < distance && i + 1 < m_operations->size())) {
+            fromValue = value;
+            distance = d;
+            foundAt = i;
+        }
+    }
+
+    if (foundAt + 1 < m_operations->size())
+        toValue = (TransformAnimationValue*) m_operations->at(foundAt + 1);
+    else
+        toValue = fromValue;
+
+    XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f",
+         layer->uniqueId(),
+         fromValue, fromValue->keyTime(),
+         toValue, toValue->keyTime(), progress);
+
+    // We now have the correct two values to work with, let's compute the
+    // progress value
+
+    float delta = toValue->keyTime() - fromValue->keyTime();
+    float rprogress = (progress - fromValue->keyTime()) / delta;
+    XLOG("We picked keys %.2f to %.2f for progress %.2f, real progress %.2f",
+         fromValue->keyTime(), toValue->keyTime(), progress, rprogress);
+    progress = rprogress;
+
+
+    // With both values and the progress, we also need to check out that
+    // the operations are compatible (i.e. we are animating the same number
+    // of values; if not we do a matrix blend)
+
+    TransformationMatrix transformMatrix;
+    bool valid = true;
+    unsigned int fromSize = fromValue->value()->size();
+    if (fromSize) {
+        if (toValue->value()->size() != fromSize)
+            valid = false;
+        else {
+            for (unsigned int j = 0; j < fromSize && valid; j++) {
+                if (!fromValue->value()->operations()[j]->isSameType(
+                    *toValue->value()->operations()[j]))
+                    valid = false;
+            }
+        }
+    }
+
+    if (valid) {
+        for (size_t i = 0; i < toValue->value()->size(); ++i)
+            toValue->value()->operations()[i]->blend(fromValue->value()->at(i),
+                                                     progress)->apply(transformMatrix, size);
+    } else {
+        TransformationMatrix source;
 
-    if (m_doScaling)
-        layer->setScale(sx, sy);
+        fromValue->value()->apply(size, source);
+        toValue->value()->apply(size, transformMatrix);
+
+        transformMatrix.blend(source, progress);
+    }
 
-    if (m_doRotation)
-        layer->setRotation(a);
+    // Set the final transform on the layer
+    layer->setTransform(transformMatrix);
 
     return true;
 }
index 358af23..3cc1608 100644 (file)
@@ -26,6 +26,7 @@
 #include "LayerAndroid.h"
 #include "RefPtr.h"
 #include "Timer.h"
+#include "TransformOperation.h"
 #include "Vector.h"
 
 namespace WebCore {
@@ -42,7 +43,7 @@ class AndroidAnimation : public RefCounted<AndroidAnimation> {
     virtual PassRefPtr<AndroidAnimation> copy() = 0;
     float currentProgress(double time);
     bool checkIterationsAndProgress(double time, float* finalProgress);
-    virtual void swapDirection() = 0;
+    virtual void swapDirection() { m_currentDirection = !m_currentDirection; }
     virtual bool evaluate(LayerAndroid* layer, double time) = 0;
     static long instancesCount();
     void setName(const String& name) { m_name = name; }
@@ -55,6 +56,7 @@ class AndroidAnimation : public RefCounted<AndroidAnimation> {
     int m_iterationCount;
     int m_currentIteration;
     int m_direction;
+    bool m_currentDirection;
     RefPtr<TimingFunction> m_timingFunction;
     String m_name;
 };
@@ -71,7 +73,6 @@ class AndroidOpacityAnimation : public AndroidAnimation {
     AndroidOpacityAnimation(AndroidOpacityAnimation* anim);
     virtual PassRefPtr<AndroidAnimation> copy();
 
-    virtual void swapDirection();
     virtual bool evaluate(LayerAndroid* layer, double time);
 
   private:
@@ -83,31 +84,19 @@ class AndroidTransformAnimation : public AndroidAnimation {
   public:
     static PassRefPtr<AndroidTransformAnimation> create(
                                                      const Animation* animation,
+                                                     KeyframeValueList* operations,
                                                      double beginTime);
-    AndroidTransformAnimation(const Animation* animation, double beginTime);
+    AndroidTransformAnimation(const Animation* animation,
+                              KeyframeValueList* operations,
+                              double beginTime);
 
     AndroidTransformAnimation(AndroidTransformAnimation* anim);
     virtual PassRefPtr<AndroidAnimation> copy();
 
-    void setOriginalPosition(FloatPoint position) { m_position = position; }
-    void setRotation(float fA, float tA);
-    void setTranslation(float fX, float fY, float fZ,
-                        float tX, float tY, float tZ);
-    void setScale(float fX, float fY, float fZ,
-                  float tX, float tY, float tZ);
-    virtual void swapDirection();
     virtual bool evaluate(LayerAndroid* layer, double time);
 
   private:
-    bool m_doTranslation;
-    bool m_doScaling;
-    bool m_doRotation;
-    FloatPoint m_position;
-    float m_fromX, m_fromY, m_fromZ;
-    float m_toX, m_toY, m_toZ;
-    float m_fromAngle, m_toAngle;
-    float m_fromScaleX, m_fromScaleY, m_fromScaleZ;
-    float m_toScaleX, m_toScaleY, m_toScaleZ;
+    KeyframeValueList* m_operations;
 };
 
 } // namespace WebCore
index c0ad248..5d1c86a 100644 (file)
@@ -25,7 +25,6 @@
 #include "GraphicsContext.h"
 #include "Image.h"
 #include "Length.h"
-#include "SkLayer.h"
 #include "PlatformBridge.h"
 #include "PlatformGraphicsContext.h"
 #include "RenderLayerBacking.h"
@@ -34,6 +33,7 @@
 #include "ScaleTransformOperation.h"
 #include "ScrollableLayerAndroid.h"
 #include "SkCanvas.h"
+#include "SkLayer.h"
 #include "TransformationMatrix.h"
 #include "TranslateTransformOperation.h"
 
@@ -88,21 +88,24 @@ PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
     return new GraphicsLayerAndroid(client);
 }
 
-SkLength convertLength(Length l) {
-  SkLength length;
-  length.type = SkLength::Undefined;
-  length.value = 0;
-  if (l.type() == WebCore::Percent) {
-    length.type = SkLength::Percent;
-    length.value = l.percent();
-  } if (l.type() == WebCore::Fixed) {
-    length.type = SkLength::Fixed;
-    length.value = l.value();
-  }
-  return length;
+SkLength convertLength(Length len)
+{
+    SkLength length;
+    length.type = SkLength::Undefined;
+    length.value = 0;
+    if (len.type() == WebCore::Percent) {
+        length.type = SkLength::Percent;
+        length.value = len.percent();
+    }
+    if (len.type() == WebCore::Fixed) {
+        length.type = SkLength::Fixed;
+        length.value = len.value();
+    }
+    return length;
 }
 
-static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client) {
+static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
+{
     if (client)
         return static_cast<RenderLayerBacking*>(client)->owningLayer();
     return 0;
@@ -113,23 +116,17 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
     m_needsSyncChildren(false),
     m_needsSyncMask(false),
     m_needsRepaint(false),
-    m_needsDisplay(false),
     m_needsNotifyClient(false),
     m_haveContents(false),
     m_haveImage(false),
-    m_translateX(0),
-    m_translateY(0),
-    m_currentTranslateX(0),
-    m_currentTranslateY(0),
-    m_currentPosition(0, 0),
     m_foregroundLayer(0),
     m_foregroundClipLayer(0)
 {
     m_contentLayer = new LayerAndroid(true);
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
     if (renderLayer) {
-        m_contentLayer->setIsRootLayer(renderLayer->isRootLayer() &&
-                !(renderLayer->renderer()->frame()->ownerElement()));
+        m_contentLayer->setIsRootLayer(renderLayer->isRootLayer()
+            && !(renderLayer->renderer()->frame()->ownerElement()));
     }
     gDebugGraphicsLayerAndroidInstances++;
 }
@@ -264,16 +261,18 @@ void GraphicsLayerAndroid::updateFixedPosition()
 
 void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
 {
-    if (point == m_currentPosition)
+    if (point == m_position)
         return;
-    m_currentPosition = point;
-    m_needsDisplay = true;
+
+    GraphicsLayer::setPosition(point);
+
 #ifdef LAYER_DEBUG_2
     LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
-        this, point.x(), point.y(), m_currentPosition.x(), m_currentPosition.y(),
+        this, point.x(), point.y(), m_position.x(), m_position.y(),
         m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
 #endif
     updateFixedPosition();
+    m_contentLayer->setPosition(point.x(), point.y());
     askForSync();
 }
 
@@ -299,19 +298,13 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size)
 
 void GraphicsLayerAndroid::setTransform(const TransformationMatrix& t)
 {
-    TransformationMatrix::DecomposedType tDecomp;
-    t.decompose(tDecomp);
-    LOG("(%x) setTransform, translate (%.2f, %.2f), mpos(%.2f,%.2f)",
-        this, tDecomp.translateX, tDecomp.translateY,
-        m_position.x(), m_position.y());
-
-    if ((m_currentTranslateX != tDecomp.translateX)
-          || (m_currentTranslateY != tDecomp.translateY)) {
-        m_currentTranslateX = tDecomp.translateX;
-        m_currentTranslateY = tDecomp.translateY;
-        m_needsDisplay = true;
-        askForSync();
-    }
+    if (t == m_transform)
+        return;
+
+    GraphicsLayer::setTransform(t);
+    m_contentLayer->setTransform(t);
+
+    askForSync();
 }
 
 void GraphicsLayerAndroid::setChildrenTransform(const TransformationMatrix& t)
@@ -367,8 +360,8 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
 
                 m_foregroundClipLayer->addChild(m_foregroundLayer);
                 m_contentLayer->addChild(m_foregroundClipLayer);
-            } else if (layer->isRootLayer() &&
-                       layer->renderer()->frame()->ownerRenderer()) {
+            } else if (layer->isRootLayer()
+                       && layer->renderer()->frame()->ownerRenderer()) {
                 // Replace the content layer with a scrollable layer.
                 LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
                 m_contentLayer->unref();
@@ -442,20 +435,23 @@ public:
         : m_layer(layer)
         , m_originalPhase(layer->paintingPhase()) {}
 
-    ~PaintingPhase() {
+    ~PaintingPhase()
+    {
         m_layer->setPaintingPhase(m_originalPhase);
     }
 
-    void set(GraphicsLayerPaintingPhase phase) {
+    void set(GraphicsLayerPaintingPhase phase)
+    {
         m_layer->setPaintingPhase(phase);
     }
 
-    void clear(GraphicsLayerPaintingPhase phase) {
+    void clear(GraphicsLayerPaintingPhase phase)
+    {
         m_layer->setPaintingPhase(
                 (GraphicsLayerPaintingPhase) (m_originalPhase & ~phase));
     }
 private:
-    GraphicsLayer*             m_layer;
+    GraphicsLayer* m_layer;
     GraphicsLayerPaintingPhase m_originalPhase;
 };
 
@@ -541,7 +537,7 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context,
     SkAutoPictureRecord arp(context, rect.width(), rect.height());
     SkCanvas* canvas = arp.getRecordingCanvas();
 
-    if (canvas == 0)
+    if (!canvas)
         return false;
 
     PlatformGraphicsContext platformContext(canvas, 0);
@@ -553,15 +549,6 @@ bool GraphicsLayerAndroid::paintContext(SkPicture* context,
 
 void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect)
 {
-    for (unsigned int i = 0; i < m_children.size(); i++) {
-        GraphicsLayer* layer = m_children[i];
-        if (layer) {
-            FloatRect childrenRect(m_position.x() + m_translateX + rect.x(),
-                                   m_position.y() + m_translateY + rect.y(),
-                                   rect.width(), rect.height());
-            layer->setNeedsDisplayInRect(childrenRect);
-        }
-    }
     if (!m_haveImage && !drawsContent()) {
         LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
             this, rect.x(), rect.y(), rect.width(), rect.height());
@@ -606,7 +593,7 @@ bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
                                         const String& keyframesName,
                                         double beginTime)
 {
-    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() != 2)
+    if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
         return false;
 
     bool createdAnimations = false;
@@ -622,7 +609,8 @@ bool GraphicsLayerAndroid::addAnimation(const KeyframeValueList& valueList,
                                                          keyframesName,
                                                          beginTime);
     }
-    askForSync();
+    if (createdAnimations)
+        askForSync();
     return createdAnimations;
 }
 
@@ -677,174 +665,25 @@ bool GraphicsLayerAndroid::createTransformAnimationsFromKeyframes(const Keyframe
     TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
         keyframesName.latin1().data(), beginTime);
 
-    TransformOperationList functionList;
-    bool listsMatch, hasBigRotation;
-    fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
-
-    // If functionLists 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 = !listsMatch;
-    size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
-    bool isKeyframe = valueList.size() > 2;
-
-    float fromTranslateX = 0;
-    float fromTranslateY = 0;
-    float fromTranslateZ = 0;
-    float toTranslateX   = 0;
-    float toTranslateY   = 0;
-    float toTranslateZ   = 0;
-    float fromAngle      = 0;
-    float toAngle        = 0;
-    float fromScaleX     = 1;
-    float fromScaleY     = 1;
-    float fromScaleZ     = 1;
-    float toScaleX       = 1;
-    float toScaleY       = 1;
-    float toScaleZ       = 1;
-
-    bool doTranslation = false;
-    bool doRotation = false;
-    bool doScaling = false;
-
-    TLOG("(%x) animateTransform, valueList(%d) functionList(%d) duration(%.2f)", this,
-        valueList.size(), functionList.size(), animation->duration());
-
-    // FIXME: add support for the translate 3d operations (when
-    // we'll have an OpenGL backend)
-
+    KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
     for (unsigned int i = 0; i < valueList.size(); i++) {
-        const TransformOperations* operation = ((TransformAnimationValue*)valueList.at(i))->value();
-        Vector<RefPtr<TransformOperation> > ops = operation->operations();
-        TLOG("(%x) animateTransform, dealing with the %d operation, with %d ops", this, i, ops.size());
-        for (unsigned int j = 0; j < ops.size(); j++) {
-            TransformOperation* op = ops[j].get();
-            TLOG("(%x) animateTransform, dealing with the %d:%d operation, current op: %d (translate is %d, rotate %d, scale %d)",
-                this, i, j, op->getOperationType(), TransformOperation::TRANSLATE, TransformOperation::ROTATE, TransformOperation::SCALE);
-            if ((op->getOperationType() == TransformOperation::TRANSLATE) ||
-                (op->getOperationType() == TransformOperation::TRANSLATE_3D)) {
-                TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
-                IntSize bounds(m_size.width(), m_size.height());
-                float x = translateOperation->x(bounds);
-                float y = translateOperation->y(bounds);
-                float z = translateOperation->z(bounds);
-                if (!i) {
-                    fromTranslateX = x;
-                    fromTranslateY = y;
-                    fromTranslateZ = z;
-                } else {
-                    toTranslateX = x;
-                    toTranslateY = y;
-                    toTranslateZ = z;
-                }
-                TLOG("(%x) animateTransform, the %d operation is a translation(%.2f,%.2f,%.2f)",
-                    this, j, x, y, z);
-                doTranslation = true;
-            } else if (op->getOperationType() == TransformOperation::TRANSLATE_X) {
-                TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
-                IntSize bounds(m_size.width(), m_size.height());
-                float x = translateOperation->x(bounds);
-                if (!i)
-                    fromTranslateX = x;
-                else
-                    toTranslateX = x;
-                TLOG("(%x) animateTransform, the %d operation is a translation_x(%.2f)",
-                    this, j, x);
-                doTranslation = true;
-            } else if (op->getOperationType() == TransformOperation::TRANSLATE_Y) {
-                TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
-                IntSize bounds(m_size.width(), m_size.height());
-                float y = translateOperation->y(bounds);
-                if (!i)
-                    fromTranslateY = y;
-                else
-                    toTranslateY = y;
-                TLOG("(%x) animateTransform, the %d operation is a translation_y(%.2f)",
-                    this, j, y);
-                doTranslation = true;
-            } else if (op->getOperationType() == TransformOperation::TRANSLATE_Z) {
-                TranslateTransformOperation* translateOperation = (TranslateTransformOperation*) op;
-                IntSize bounds(m_size.width(), m_size.height());
-                float z = translateOperation->z(bounds);
-                if (!i)
-                    fromTranslateZ = z;
-                else
-                    toTranslateZ = z;
-                TLOG("(%x) animateTransform, the %d operation is a translation_z(%.2f)",
-                    this, j, z);
-                doTranslation = true;
-            } else if ((op->getOperationType() == TransformOperation::ROTATE)
-                          || (op->getOperationType() == TransformOperation::ROTATE_X)
-                          || (op->getOperationType() == TransformOperation::ROTATE_Y)) {
-                LOG("(%x) animateTransform, the %d operation is a rotation", this, j);
-                RotateTransformOperation* rotateOperation = (RotateTransformOperation*) op;
-                float angle = rotateOperation->angle();
-                TLOG("(%x) animateTransform, the %d operation is a rotation (%d), of angle %.2f",
-                    this, j, op->getOperationType(), angle);
-
-                if (!i)
-                    fromAngle = angle;
-                else
-                    toAngle = angle;
-                doRotation = true;
-            } else if (op->getOperationType() == TransformOperation::SCALE_X) {
-                ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
-                if (!i)
-                    fromScaleX = scaleOperation->x();
-                else
-                    toScaleX = scaleOperation->x();
-                doScaling = true;
-            } else if (op->getOperationType() == TransformOperation::SCALE_Y) {
-                ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
-                if (!i)
-                    fromScaleY = scaleOperation->y();
-                else
-                    toScaleY = scaleOperation->y();
-                doScaling = true;
-            } else if (op->getOperationType() == TransformOperation::SCALE_Z) {
-                ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
-                if (!i)
-                    fromScaleZ = scaleOperation->z();
-                else
-                    toScaleZ = scaleOperation->z();
-                doScaling = true;
-            } else if (op->getOperationType() == TransformOperation::SCALE) {
-                ScaleTransformOperation* scaleOperation = (ScaleTransformOperation*) op;
-                if (!i) {
-                    fromScaleX = scaleOperation->x();
-                    fromScaleY = scaleOperation->y();
-                    fromScaleZ = scaleOperation->z();
-                } else {
-                    toScaleX = scaleOperation->x();
-                    toScaleY = scaleOperation->y();
-                    toScaleZ = scaleOperation->z();
-                }
-                doScaling = true;
-            } else {
-                TLOG("(%x) animateTransform, the %d operation is not a rotation (%d)",
-                    this, j, op->getOperationType());
-            }
-        }
+        TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
+        TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
+                                                                     originalValue->value(), 0);
+        // TODO: pass the timing function originalValue->timingFunction());
+        operationsList->insert(value);
     }
 
-    RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation, beginTime);
+    RefPtr<AndroidTransformAnimation> anim = AndroidTransformAnimation::create(animation,
+                                                                               operationsList,
+                                                                               beginTime);
 
     if (keyframesName.isEmpty())
         anim->setName(propertyIdToString(valueList.property()));
     else
         anim->setName(keyframesName);
 
-    anim->setOriginalPosition(m_position);
 
-    if (doTranslation)
-        anim->setTranslation(fromTranslateX, fromTranslateY, fromTranslateZ,
-                         toTranslateX, toTranslateY, toTranslateZ);
-    if (doRotation)
-        anim->setRotation(fromAngle, toAngle);
-    if (doScaling)
-        anim->setScale(fromScaleX, fromScaleY, fromScaleZ,
-                       toScaleX, toScaleY, toScaleZ);
     m_contentLayer->addAnimation(anim.release());
 
     needsNotifyClient();
@@ -952,18 +791,6 @@ void GraphicsLayerAndroid::syncMask()
     }
 }
 
-void GraphicsLayerAndroid::syncPositionState()
-{
-     if (m_needsDisplay) {
-         m_translateX = m_currentTranslateX;
-         m_translateY = m_currentTranslateY;
-         m_position = m_currentPosition;
-         m_contentLayer->setTranslation(m_currentTranslateX, m_currentTranslateY);
-         m_contentLayer->setPosition(m_currentPosition.x(), m_currentPosition.y());
-         m_needsDisplay = false;
-     }
-}
-
 void GraphicsLayerAndroid::syncCompositingState()
 {
     for (unsigned int i = 0; i < m_children.size(); i++)
@@ -971,7 +798,6 @@ void GraphicsLayerAndroid::syncCompositingState()
 
     syncChildren();
     syncMask();
-    syncPositionState();
 
     if (!gPaused || WTF::currentTime() >= gPausedDelay)
         repaint();
index ea8c5c9..1e17f47 100644 (file)
@@ -135,19 +135,11 @@ private:
     bool m_needsSyncChildren;
     bool m_needsSyncMask;
     bool m_needsRepaint;
-    bool m_needsDisplay;
     bool m_needsNotifyClient;
 
     bool m_haveContents;
     bool m_haveImage;
 
-    float m_translateX;
-    float m_translateY;
-    float m_currentTranslateX;
-    float m_currentTranslateY;
-
-    FloatPoint m_currentPosition;
-
     Vector<FloatRect> m_invalidatedRects;
 
     LayerAndroid* m_contentLayer;
index 58d8772..6fe0f78 100644 (file)
@@ -49,16 +49,12 @@ class OpacityDrawFilter : public SkDrawFilter {
 LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
     m_isRootLayer(isRootLayer),
     m_haveClip(false),
-    m_doRotation(false),
     m_isFixed(false),
     m_recordingPicture(0),
     m_contentsImage(0),
     m_extra(0),
     m_uniqueId(++gUniqueId)
 {
-    m_angleTransform = 0;
-    m_translation.set(0, 0);
-    m_scale.set(1, 1);
     m_backgroundColor = 0;
 
     gDebugLayerAndroidInstances++;
@@ -70,14 +66,11 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
     m_extra(0), // deliberately not copied
     m_uniqueId(layer.m_uniqueId)
 {
-    m_doRotation = layer.m_doRotation;
     m_isFixed = layer.m_isFixed;
     m_contentsImage = layer.m_contentsImage;
     m_contentsImage->safeRef();
 
-    m_angleTransform = layer.m_angleTransform;
-    m_translation = layer.m_translation;
-    m_scale = layer.m_scale;
+    m_transform = layer.m_transform;
     m_backgroundColor = layer.m_backgroundColor;
 
     m_fixedLeft = layer.m_fixedLeft;
@@ -106,16 +99,12 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
 LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
     m_isRootLayer(true),
     m_haveClip(false),
-    m_doRotation(false),
     m_isFixed(false),
     m_recordingPicture(picture),
     m_contentsImage(0),
     m_extra(0),
     m_uniqueId(-1)
 {
-    m_angleTransform = 0;
-    m_translation.set(0, 0);
-    m_scale.set(1, 1);
     m_backgroundColor = 0;
     SkSafeRef(m_recordingPicture);
     gDebugLayerAndroidInstances++;
@@ -159,9 +148,8 @@ bool LayerAndroid::evaluateAnimations(double time) const
     for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
         gDebugNbAnims++;
         LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
-        if ((it->second)->evaluate(currentLayer, time)) {
+        if ((it->second)->evaluate(currentLayer, time))
             hasRunningAnimations = true;
-        }
     }
 
     return hasRunningAnimations;
@@ -192,14 +180,33 @@ void LayerAndroid::setBackgroundColor(SkColor color)
 
 static int gDebugChildLevel;
 
+FloatPoint LayerAndroid::translation() const
+{
+    TransformationMatrix::DecomposedType tDecomp;
+    m_transform.decompose(tDecomp);
+    FloatPoint p(tDecomp.translateX, tDecomp.translateY);
+    return p;
+}
+
+SkRect LayerAndroid::bounds() const
+{
+    SkRect rect;
+    bounds(&rect);
+    return rect;
+}
+
 void LayerAndroid::bounds(SkRect* rect) const
 {
     const SkPoint& pos = this->getPosition();
     const SkSize& size = this->getSize();
-    rect->fLeft = pos.fX + m_translation.fX;
-    rect->fTop = pos.fY + m_translation.fY;
-    rect->fRight = rect->fLeft + size.width();
-    rect->fBottom = rect->fTop + size.height();
+
+    // The returned rect has the translation applied
+    FloatPoint p(0, 0);
+    p = m_transform.mapPoint(p);
+    rect->fLeft = p.x();
+    rect->fTop = p.y();
+    rect->fRight = p.x() + size.width();
+    rect->fBottom = p.y() + size.width();
 }
 
 static bool boundsIsUnique(const SkTDArray<SkRect>& region,
@@ -295,7 +302,8 @@ public:
     int bestX() const { return m_bestX; }
     int bestY() const { return m_bestY; }
 
-    bool drew(SkPicture* picture, const SkRect& localBounds) {
+    bool drew(SkPicture* picture, const SkRect& localBounds)
+    {
         m_findCheck.reset();
         SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft;
         SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop;
@@ -313,7 +321,8 @@ public:
     int x() const { return m_x; }
     int y() const { return m_y; }
 
-    void setLocation(int x, int y) {
+    void setLocation(int x, int y)
+    {
         m_x = x;
         m_y = y;
     }
@@ -395,12 +404,12 @@ void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport)
     }
 
     int count = this->countChildren();
-    for (int i = 0; i < count; i++) {
+    for (int i = 0; i < count; i++)
         this->getChild(i)->updateFixedLayersPositions(viewport);
-    }
 }
 
-void LayerAndroid::updatePositions() {
+void LayerAndroid::updatePositions()
+{
     // apply the viewport to us
     SkMatrix matrix;
     if (!m_isFixed) {
@@ -408,26 +417,33 @@ void LayerAndroid::updatePositions() {
         //
         // TODO: this should happen in the caller, and we should remove these
         // fields from our subclass
-        matrix.setTranslate(m_translation.fX, m_translation.fY);
-        if (m_doRotation) {
-            matrix.preRotate(m_angleTransform);
-        }
-        matrix.preScale(m_scale.fX, m_scale.fY);
+        TransformationMatrix::DecomposedType tDecomp;
+        m_transform.decompose(tDecomp);
+        matrix.reset();
+        matrix.setScaleX(tDecomp.scaleX);
+        matrix.setScaleY(tDecomp.scaleY);
+        matrix.setSkewX(tDecomp.skewXZ);
+        matrix.setSkewY(tDecomp.skewYZ);
+        matrix.setTranslateX(tDecomp.translateX);
+        matrix.setTranslateY(tDecomp.translateY);
+        matrix.setPerspX(tDecomp.perspectiveX);
+        matrix.setPerspY(tDecomp.perspectiveY);
         this->setMatrix(matrix);
     }
 
     // now apply it to our children
     int count = this->countChildren();
-    for (int i = 0; i < count; i++) {
+    for (int i = 0; i < count; i++)
         this->getChild(i)->updatePositions();
-    }
 }
 
-void LayerAndroid::setContentsImage(SkBitmapRef* img) {
+void LayerAndroid::setContentsImage(SkBitmapRef* img)
+{
     SkRefCnt_SafeAssign(m_contentsImage, img);
 }
 
-void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity) {
+void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
+{
     if (m_haveClip) {
         SkRect r;
         r.set(0, 0, getSize().width(), getSize().height());
@@ -620,7 +636,8 @@ void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
 
 void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
 {
-    if (!length.defined()) return;
+    if (!length.defined())
+        return;
     writeIndent(file, indentLevel);
     fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
 }
@@ -638,12 +655,7 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
     writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
     writeSize(file, indentLevel + 1, "size", getSize());
     writePoint(file, indentLevel + 1, "position", getPosition());
-    writePoint(file, indentLevel + 1, "translation", m_translation);
     writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
-    writePoint(file, indentLevel + 1, "scale", m_scale);
-
-    if (m_doRotation)
-        writeFloatVal(file, indentLevel + 1, "angle", m_angleTransform);
 
     if (m_isFixed) {
         writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
index 575ada7..1269a1d 100644 (file)
@@ -22,6 +22,7 @@
 #include "RefPtr.h"
 #include "SkColor.h"
 #include "SkLayer.h"
+#include "TransformationMatrix.h"
 
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
@@ -30,7 +31,7 @@
 #define BZERO_DEFINED
 // http://www.opengroup.org/onlinepubs/000095399/functions/bzero.html
 // For maximum portability, it is recommended to replace the function call to bzero() as follows:
-#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+#define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
 #endif
 
 class SkBitmapRef;
@@ -48,23 +49,26 @@ struct SkLength {
     enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic };
     SkLengthType type;
     SkScalar value;
-    SkLength() {
+    SkLength()
+    {
         type = Undefined;
         value = 0;
     }
-    bool defined() const {
+    bool defined() const
+    {
         if (type == Undefined)
             return false;
         return true;
     }
-    float calcFloatValue(float max) const {
+    float calcFloatValue(float max) const
+    {
         switch (type) {
-            case Percent:
-                return (max * value) / 100.0f;
-            case Fixed:
-                return value;
-            default:
-                return value;
+        case Percent:
+            return (max * value) / 100.0f;
+        case Fixed:
+            return value;
+        default:
+            return value;
         }
     }
 };
@@ -83,27 +87,16 @@ public:
 
     static int instancesCount();
 
-    void setTranslation(SkScalar x, SkScalar y) { m_translation.set(x, y); }
-    void setRotation(SkScalar a) { m_angleTransform = a; m_doRotation = true; }
-    void setScale(SkScalar x, SkScalar y) { m_scale.set(x, y); }
-    SkPoint translation() const { return m_translation; }
-    SkRect  bounds() const {
-        const SkPoint& pos = this->getPosition();
-        const SkSize& size = this->getSize();
-        SkRect rect;
-        rect.set(pos.fX, pos.fY,
-                 pos.fX + size.width(),
-                 pos.fY + size.height());
-        rect.offset(m_translation.fX, m_translation.fY);
-        return rect;
-    }
-    void setFixedPosition(SkLength left,   // CSS left property
-                          SkLength top,    // CSS top property
-                          SkLength right,  // CSS right property
+    void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; }
+    FloatPoint translation() const;
+    SkRect bounds() const;
+    void setFixedPosition(SkLength left, // CSS left property
+                          SkLength top, // CSS top property
+                          SkLength right, // CSS right property
                           SkLength bottom, // CSS bottom property
-                          SkLength marginLeft,   // CSS margin-left property
-                          SkLength marginTop,    // CSS margin-top property
-                          SkLength marginRight,  // CSS margin-right property
+                          SkLength marginLeft, // CSS margin-left property
+                          SkLength marginTop, // CSS margin-top property
+                          SkLength marginRight, // CSS margin-right property
                           SkLength marginBottom, // CSS margin-bottom property
                           SkRect viewRect) { // view rect, can be smaller than the layer's
         m_fixedLeft = left;
@@ -121,7 +114,8 @@ public:
 
     void setBackgroundColor(SkColor color);
     void setMaskLayer(LayerAndroid*);
-    void setMasksToBounds(bool masksToBounds) {
+    void setMasksToBounds(bool masksToBounds)
+    {
         m_haveClip = masksToBounds;
     }
     bool masksToBounds() const { return m_haveClip; }
@@ -164,14 +158,16 @@ public:
 
     void clipArea(SkTDArray<SkRect>* region) const;
     const LayerAndroid* find(int* xPtr, int* yPtr, SkPicture* root) const;
-    const LayerAndroid* findById(int uniqueID) const {
+    const LayerAndroid* findById(int uniqueID) const
+    {
         return const_cast<LayerAndroid*>(this)->findById(uniqueID);
     }
     LayerAndroid* findById(int uniqueID);
-    LayerAndroid* getChild(int index) const {
+    LayerAndroid* getChild(int index) const
+    {
         return static_cast<LayerAndroid*>(this->INHERITED::getChild(index));
     }
-    void setExtra(DrawExtra* extra);  // does not assign ownership
+    void setExtra(DrawExtra* extra); // does not assign ownership
     int uniqueId() const { return m_uniqueId; }
     bool isFixed() { return m_isFixed; }
 
@@ -182,7 +178,7 @@ public:
     */
     void setContentsImage(SkBitmapRef* img);
 
-    void bounds(SkRect* ) const;
+    void bounds(SkRect*) const;
 
     virtual bool contentIsScrollable() const { return false; }
     virtual LayerAndroid* copy() const { return new LayerAndroid(*this); }
@@ -196,14 +192,13 @@ private:
     friend class CachedLayer::Debug; // debugging access only
 #endif
 
-    void findInner(FindState& ) const;
+    void findInner(FindState&) const;
     bool prepareContext(bool force = false);
     void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const;
 
     bool m_isRootLayer;
     bool m_drawsContent;
     bool m_haveClip;
-    bool m_doRotation;
     bool m_isFixed;
     bool m_backgroundColorSet;
 
@@ -215,11 +210,10 @@ private:
     SkLength m_fixedMarginTop;
     SkLength m_fixedMarginRight;
     SkLength m_fixedMarginBottom;
-    SkRect   m_fixedRect;
+    SkRect m_fixedRect;
+
+    TransformationMatrix m_transform;
 
-    SkPoint m_translation;
-    SkPoint m_scale;
-    SkScalar m_angleTransform;
     SkColor m_backgroundColor;
 
     // Note that m_recordingPicture and m_contentsImage are mutually exclusive;
@@ -265,4 +259,4 @@ private:
 
 #endif // USE(ACCELERATED_COMPOSITING)
 
-#endif  // LayerAndroid_h
+#endif // LayerAndroid_h