diff options
author | Nicolas Roard <nicolasroard@google.com> | 2011-03-09 13:52:11 -0800 |
---|---|---|
committer | Nicolas Roard <nicolasroard@google.com> | 2011-03-10 15:14:54 -0800 |
commit | ac8d9f13717dd67de94dc7ab18690d6da10b0c99 (patch) | |
tree | 0387c02be91f0e9b652a83f4c8502672ec2dfabb /WebCore/platform/graphics/android/AndroidAnimation.cpp | |
parent | 95cb21b0cde2a64281360f9e45f31f049e583273 (diff) | |
download | external_webkit-ac8d9f13717dd67de94dc7ab18690d6da10b0c99.zip external_webkit-ac8d9f13717dd67de94dc7ab18690d6da10b0c99.tar.gz external_webkit-ac8d9f13717dd67de94dc7ab18690d6da10b0c99.tar.bz2 |
Fix CSS animations
- we were overriding existing animations.
- implement correctly the removeAnimations functions
- refactor AndroidAnimation (share common code)
- fix how we use the timing functions for the animations
- implements timing functions per keyframes
bug:2453890
Change-Id: I367d708338c270171eeaacc7e2fb3729eb78c444
Diffstat (limited to 'WebCore/platform/graphics/android/AndroidAnimation.cpp')
-rw-r--r-- | WebCore/platform/graphics/android/AndroidAnimation.cpp | 187 |
1 files changed, 98 insertions, 89 deletions
diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp index 3280d07..a064d05 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -54,17 +54,17 @@ long AndroidAnimation::instancesCount() return gDebugAndroidAnimationInstances; } -AndroidAnimation::AndroidAnimation(AndroidAnimationType type, +AndroidAnimation::AndroidAnimation(AnimatedPropertyID type, const Animation* animation, + KeyframeValueList* operations, 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()) , m_type(type) + , m_operations(operations) { ASSERT(m_timingFunction); @@ -78,11 +78,10 @@ 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) , m_type(anim->m_type) + , m_operations(anim->m_operations) { gDebugAndroidAnimationInstances++; } @@ -92,7 +91,7 @@ AndroidAnimation::~AndroidAnimation() gDebugAndroidAnimationInstances--; } -float AndroidAnimation::currentProgress(double time) +double AndroidAnimation::elapsedTime(double time) { if (m_beginTime <= 0.000001) // overflow or not correctly set m_beginTime = time; @@ -105,37 +104,69 @@ float AndroidAnimation::currentProgress(double time) if (m_elapsedTime < 0) // animation not yet started. return 0; - return m_elapsedTime / m_duration; + return m_elapsedTime; } bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress) { - float progress = currentProgress(time); + double progress = elapsedTime(time); + double dur = m_duration; + if (m_iterationCount > 0) + dur *= m_iterationCount; - int currentIteration = static_cast<int>(progress); - if (currentIteration != m_currentIteration) - if (m_direction == Animation::AnimationDirectionAlternate) - swapDirection(); - - m_currentIteration = currentIteration; - progress -= m_currentIteration; + if (m_duration <= 0) + return false; - if ((m_currentIteration >= m_iterationCount) - && (m_iterationCount != Animation::IterationCountInfinite)) + // If not infinite, return false if we are done + if (m_iterationCount > 0 && progress > dur) return false; - if (m_timingFunction->isCubicBezierTimingFunction()) { - CubicBezierTimingFunction* bezierFunction = static_cast<CubicBezierTimingFunction*>(m_timingFunction.get()); + double fractionalTime = progress / m_duration; + int integralTime = static_cast<int>(fractionalTime); + + fractionalTime -= integralTime; + + if ((m_direction == Animation::AnimationDirectionAlternate) && (integralTime & 1)) + fractionalTime = 1 - fractionalTime; + + *finalProgress = fractionalTime; + return true; +} + +double AndroidAnimation::applyTimingFunction(float from, float to, double progress, + const TimingFunction* tf) +{ + double fractionalTime = progress; + double offset = from; + double scale = 1.0 / (to - from); + + if (scale != 1 || offset) + fractionalTime = (fractionalTime - offset) * scale; + + const TimingFunction* timingFunction = tf; + + if (!timingFunction) + timingFunction = m_timingFunction.get(); + + if (timingFunction && timingFunction->isCubicBezierTimingFunction()) { + const CubicBezierTimingFunction* bezierFunction = static_cast<const CubicBezierTimingFunction*>(timingFunction); UnitBezier bezier(bezierFunction->x1(), bezierFunction->y1(), bezierFunction->x2(), bezierFunction->y2()); if (m_duration > 0) - progress = bezier.solve(progress, 1.0f / (200.0f * m_duration)); + fractionalTime = bezier.solve(fractionalTime, 1.0f / (200.0f * m_duration)); + } else if (timingFunction && timingFunction->isStepsTimingFunction()) { + const StepsTimingFunction* stepFunction = static_cast<const StepsTimingFunction*>(timingFunction); + if (stepFunction->stepAtStart()) { + fractionalTime = (floor(stepFunction->numberOfSteps() * fractionalTime) + 1) / stepFunction->numberOfSteps(); + if (fractionalTime > 1.0) + fractionalTime = 1.0; + } else { + fractionalTime = floor(stepFunction->numberOfSteps() * fractionalTime) / stepFunction->numberOfSteps(); + } } - - *finalProgress = progress; - return true; + return fractionalTime; } PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create( @@ -150,14 +181,12 @@ PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create( AndroidOpacityAnimation::AndroidOpacityAnimation(const Animation* animation, KeyframeValueList* operations, double beginTime) - : AndroidAnimation(AndroidAnimation::OPACITY, animation, beginTime) - , m_operations(operations) + : AndroidAnimation(AnimatedPropertyOpacity, animation, operations, beginTime) { } AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim) : AndroidAnimation(anim) - , m_operations(anim->m_operations) { } @@ -166,41 +195,45 @@ PassRefPtr<AndroidAnimation> AndroidOpacityAnimation::copy() return adoptRef(new AndroidOpacityAnimation(this)); } -bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) +void AndroidAnimation::pickValues(double progress, int* start, int* end) { - float progress; - if (!checkIterationsAndProgress(time, &progress)) - return false; - - if (progress < 0) // we still want to be evaluated until we get progress > 0 - return true; - - // First, we need to get the from and to values - - FloatAnimationValue* fromValue = 0; - FloatAnimationValue* toValue = 0; - - float distance = 0; + float distance = -1; unsigned int foundAt = 0; for (unsigned int i = 0; i < m_operations->size(); i++) { - FloatAnimationValue* value = (FloatAnimationValue*) m_operations->at(i); - float opacity = (float) value->value(); + const AnimationValue* value = m_operations->at(i); float key = value->keyTime(); float d = progress - key; - XLOG("[%d] Key %.2f, opacity %.4f", i, key, opacity); - if (!fromValue || (d > 0 && d < distance && i + 1 < m_operations->size())) { - fromValue = value; + if (distance == -1 || (d >= 0 && d < distance && i + 1 < m_operations->size())) { distance = d; foundAt = i; } } + *start = foundAt; + if (foundAt + 1 < m_operations->size()) - toValue = (FloatAnimationValue*) m_operations->at(foundAt + 1); + *end = foundAt + 1; else - toValue = fromValue; + *end = foundAt; +} - XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", +bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) +{ + float progress; + if (!checkIterationsAndProgress(time, &progress)) + return false; + + if (progress < 0) // we still want to be evaluated until we get progress > 0 + return true; + + // First, we need to get the from and to values + + int from, to; + pickValues(progress, &from, &to); + FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from); + FloatAnimationValue* toValue = (FloatAnimationValue*) m_operations->at(to); + + XLOG("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", layer->uniqueId(), fromValue, fromValue->keyTime(), toValue, toValue->keyTime(), progress); @@ -208,18 +241,14 @@ bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) // 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; - - float from = (float) fromValue->value(); - float to = (float) toValue->value(); - float value = from + ((to - from) * progress); + const TimingFunction* timingFunction = fromValue->timingFunction(); + progress = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), + progress, timingFunction); + float value = fromValue->value() + ((toValue->value() - fromValue->value()) * progress); layer->setOpacity(value); - XLOG("AndroidOpacityAnimation::evaluate(%p, %p, %L) value=%.6f", this, layer, time, value); + + XLOG("AndroidOpacityAnimation::evaluate(%p, %p, %.2f) value=%.6f", this, layer, time, value); return true; } @@ -234,14 +263,12 @@ PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create( AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation, KeyframeValueList* operations, double beginTime) - : AndroidAnimation(AndroidAnimation::TRANSFORM, animation, beginTime) - , m_operations(operations) + : AndroidAnimation(AnimatedPropertyWebkitTransform, animation, operations, beginTime) { } AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim) : AndroidAnimation(anim) - , m_operations(anim->m_operations) { } @@ -269,28 +296,10 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) // 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 = progress - key; - XLOG("[%d] Key %.2f, %d values", i, key, values->size()); - if (!fromValue || (d > 0 && 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; + int from, to; + pickValues(progress, &from, &to); + TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from); + TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to); XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", layer->uniqueId(), @@ -300,12 +309,12 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) // 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; - + const TimingFunction* timingFunction = fromValue->timingFunction(); + float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(), + progress, timingFunction); + XLOG("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(), + toValue->keyTime()); + progress = p; // 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 |