diff options
Diffstat (limited to 'WebCore/platform/graphics/android/AndroidAnimation.cpp')
-rw-r--r-- | WebCore/platform/graphics/android/AndroidAnimation.cpp | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp new file mode 100644 index 0000000..9cdb0c7 --- /dev/null +++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config.h" +#include "AndroidAnimation.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "Animation.h" +#include "GraphicsLayerAndroid.h" + +#include "Timer.h" +#include "TimingFunction.h" +#include "UnitBezier.h" + +#include <wtf/CurrentTime.h> + +namespace WebCore { + +void AndroidTransformAnimationValue::apply() +{ + if (m_doTranslation) + m_layer->setTranslation(m_translation); + + if (m_doScaling) + m_layer->setScale(m_scale); + + if (m_doRotation) + m_layer->setRotation(m_rotation); +} + +void AndroidAnimationTimer::fired() +{ + if (!m_notificationSent) { + m_notificationSent = true; + if (m_layer && m_layer->client()) + m_layer->client()->notifyAnimationStarted(m_layer, WTF::currentTime()); + } +} + +static long gDebugAndroidAnimationInstances; + +long AndroidAnimation::instancesCount() +{ + return gDebugAndroidAnimationInstances; +} + +AndroidAnimation::AndroidAnimation(LayerAndroid* contentLayer, + const Animation* animation, + double beginTime) : + m_contentLayer(contentLayer), + m_beginTime(beginTime), + m_duration(animation->duration()), + m_iterationCount(animation->iterationCount()), + m_currentIteration(0), + m_direction(animation->direction()), + m_timingFunction(animation->timingFunction()) +{ + if (!static_cast<int>(beginTime)) // time not set + m_beginTime = WTF::currentTime(); + + gDebugAndroidAnimationInstances++; +} + +AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) : + m_contentLayer(anim->m_contentLayer), + 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) +{ + gDebugAndroidAnimationInstances++; +} + +AndroidAnimation::~AndroidAnimation() +{ + gDebugAndroidAnimationInstances--; +} + +float AndroidAnimation::currentProgress(double time) +{ + if (m_beginTime <= 0.000001) // overflow or not correctly set + m_beginTime = time; + + m_elapsedTime = time - m_beginTime; + + if (m_duration <= 0) + m_duration = 0.000001; + + if (m_elapsedTime < 0) // animation not yet started. + return 0; + + return m_elapsedTime / m_duration; +} + +bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress) +{ + float progress = currentProgress(time); + + int currentIteration = static_cast<int>(progress); + if (currentIteration != m_currentIteration) + if (m_direction == Animation::AnimationDirectionAlternate) + swapDirection(); + + m_currentIteration = currentIteration; + progress -= m_currentIteration; + + if ((m_currentIteration >= m_iterationCount) + && (m_iterationCount != Animation::IterationCountInfinite)) + return false; + + if (m_timingFunction.type() != LinearTimingFunction) { + UnitBezier bezier(m_timingFunction.x1(), + m_timingFunction.y1(), + m_timingFunction.x2(), + m_timingFunction.y2()); + if (m_duration > 0) + progress = bezier.solve(progress, 1.0f / (200.0f * m_duration)); + } + + *finalProgress = progress; + return true; +} + +PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create(LayerAndroid* contentLayer, + float fromValue, float toValue, + const Animation* animation, double beginTime) +{ + return adoptRef(new AndroidOpacityAnimation(contentLayer, + fromValue, toValue, animation, beginTime)); +} + +AndroidOpacityAnimation::AndroidOpacityAnimation(LayerAndroid* contentLayer, + float fromValue, float toValue, + const Animation* animation, + double beginTime) + : AndroidAnimation(contentLayer, 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* AndroidOpacityAnimation::copy() +{ + return new AndroidOpacityAnimation(this); +} + +void AndroidOpacityAnimation::swapDirection() +{ + float v = m_toValue; + m_toValue = m_fromValue; + m_fromValue = m_toValue; +} + +bool AndroidOpacityAnimation::evaluate(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; + + float value = m_fromValue + ((m_toValue - m_fromValue) * progress); + m_result = AndroidOpacityAnimationValue::create(m_contentLayer.get(), value); + return true; +} + +PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create(LayerAndroid* contentLayer, + const Animation* animation, double beginTime) +{ + return adoptRef(new AndroidTransformAnimation(contentLayer, animation, beginTime)); +} + +AndroidTransformAnimation::AndroidTransformAnimation(LayerAndroid* contentLayer, + const Animation* animation, + double beginTime) + : AndroidAnimation(contentLayer, animation, beginTime), + m_doTranslation(false), + m_doScaling(false), + m_doRotation(false) +{ +} + +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* AndroidTransformAnimation::copy() +{ + return 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(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; + + 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; + + FloatPoint translation(x, y); + FloatPoint3D scale(sx, sy, sz); + m_result = AndroidTransformAnimationValue::create(m_contentLayer.get(), + translation, scale, a); + m_result->setDoTranslation(m_doTranslation); + m_result->setDoScaling(m_doScaling); + m_result->setDoRotation(m_doRotation); + return true; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) |