From ff8665d820cc087df2b169dc727396c2a57e65ae Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Tue, 14 Dec 2010 17:00:56 -0800 Subject: [PATCH] Refactoring of animation 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 --- .../platform/graphics/android/AndroidAnimation.cpp | 238 ++++++++--------- .../platform/graphics/android/AndroidAnimation.h | 27 +- .../graphics/android/GraphicsLayerAndroid.cpp | 282 ++++----------------- .../graphics/android/GraphicsLayerAndroid.h | 8 - WebCore/platform/graphics/android/LayerAndroid.cpp | 88 ++++--- WebCore/platform/graphics/android/LayerAndroid.h | 78 +++--- 6 files changed, 273 insertions(+), 448 deletions(-) diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp index 0daef460a..e01bf55fe 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -24,10 +24,27 @@ #include "Timer.h" #include "TimingFunction.h" +#include "TranslateTransformOperation.h" #include "UnitBezier.h" #include +#ifdef DEBUG + +#include +#include + +#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::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 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::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 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; } diff --git a/WebCore/platform/graphics/android/AndroidAnimation.h b/WebCore/platform/graphics/android/AndroidAnimation.h index 358af231c..3cc16081d 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/WebCore/platform/graphics/android/AndroidAnimation.h @@ -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 { virtual PassRefPtr 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 { int m_iterationCount; int m_currentIteration; int m_direction; + bool m_currentDirection; RefPtr m_timingFunction; String m_name; }; @@ -71,7 +73,6 @@ class AndroidOpacityAnimation : public AndroidAnimation { AndroidOpacityAnimation(AndroidOpacityAnimation* anim); virtual PassRefPtr copy(); - virtual void swapDirection(); virtual bool evaluate(LayerAndroid* layer, double time); private: @@ -83,31 +84,19 @@ class AndroidTransformAnimation : public AndroidAnimation { public: static PassRefPtr 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 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 diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index c0ad248c1..5d1c86a7d 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -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::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(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 > 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 anim = AndroidTransformAnimation::create(animation, beginTime); + RefPtr 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(); diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index ea8c5c952..1e17f4746 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -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 m_invalidatedRects; LayerAndroid* m_contentLayer; diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 58d87729c..6fe0f7865 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -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(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& 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); diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 575ada747..1269a1d15 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -22,6 +22,7 @@ #include "RefPtr.h" #include "SkColor.h" #include "SkLayer.h" +#include "TransformationMatrix.h" #include #include @@ -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* 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(this)->findById(uniqueID); } LayerAndroid* findById(int uniqueID); - LayerAndroid* getChild(int index) const { + LayerAndroid* getChild(int index) const + { return static_cast(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* 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 -- 2.11.0