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
#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;
}
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);
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++;
}
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)
{
}
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;
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)
{
}
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;
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;
}
#include "LayerAndroid.h"
#include "RefPtr.h"
#include "Timer.h"
+#include "TransformOperation.h"
#include "Vector.h"
namespace WebCore {
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; }
int m_iterationCount;
int m_currentIteration;
int m_direction;
+ bool m_currentDirection;
RefPtr<TimingFunction> m_timingFunction;
String m_name;
};
AndroidOpacityAnimation(AndroidOpacityAnimation* anim);
virtual PassRefPtr<AndroidAnimation> copy();
- virtual void swapDirection();
virtual bool evaluate(LayerAndroid* layer, double time);
private:
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
#include "GraphicsContext.h"
#include "Image.h"
#include "Length.h"
-#include "SkLayer.h"
#include "PlatformBridge.h"
#include "PlatformGraphicsContext.h"
#include "RenderLayerBacking.h"
#include "ScaleTransformOperation.h"
#include "ScrollableLayerAndroid.h"
#include "SkCanvas.h"
+#include "SkLayer.h"
#include "TransformationMatrix.h"
#include "TranslateTransformOperation.h"
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;
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++;
}
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();
}
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)
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();
: 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;
};
SkAutoPictureRecord arp(context, rect.width(), rect.height());
SkCanvas* canvas = arp.getRecordingCanvas();
- if (canvas == 0)
+ if (!canvas)
return false;
PlatformGraphicsContext platformContext(canvas, 0);
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());
const String& keyframesName,
double beginTime)
{
- if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() != 2)
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
return false;
bool createdAnimations = false;
keyframesName,
beginTime);
}
- askForSync();
+ if (createdAnimations)
+ askForSync();
return createdAnimations;
}
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();
}
}
-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++)
syncChildren();
syncMask();
- syncPositionState();
if (!gPaused || WTF::currentTime() >= gPausedDelay)
repaint();
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;
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++;
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;
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++;
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;
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,
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;
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;
}
}
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) {
//
// 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());
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);
}
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);
#include "RefPtr.h"
#include "SkColor.h"
#include "SkLayer.h"
+#include "TransformationMatrix.h"
#include <wtf/HashMap.h>
#include <wtf/text/StringHash.h>
#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;
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;
}
}
};
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;
void setBackgroundColor(SkColor color);
void setMaskLayer(LayerAndroid*);
- void setMasksToBounds(bool masksToBounds) {
+ void setMasksToBounds(bool masksToBounds)
+ {
m_haveClip = masksToBounds;
}
bool masksToBounds() const { return m_haveClip; }
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; }
*/
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); }
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;
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;
#endif // USE(ACCELERATED_COMPOSITING)
-#endif // LayerAndroid_h
+#endif // LayerAndroid_h