Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "config.h"
     18 #include "AndroidAnimation.h"
     19 
     20 #if USE(ACCELERATED_COMPOSITING)
     21 
     22 #include "Animation.h"
     23 #include "GraphicsLayerAndroid.h"
     24 
     25 #include "Timer.h"
     26 #include "TimingFunction.h"
     27 #include "UnitBezier.h"
     28 
     29 #include <wtf/CurrentTime.h>
     30 
     31 namespace WebCore {
     32 
     33 static long gDebugAndroidAnimationInstances;
     34 
     35 long AndroidAnimation::instancesCount()
     36 {
     37     return gDebugAndroidAnimationInstances;
     38 }
     39 
     40 AndroidAnimation::AndroidAnimation(const Animation* animation,
     41                                    double beginTime) :
     42     m_beginTime(beginTime),
     43     m_duration(animation->duration()),
     44     m_iterationCount(animation->iterationCount()),
     45     m_currentIteration(0),
     46     m_direction(animation->direction()),
     47     m_timingFunction(animation->timingFunction())
     48 {
     49     if (!static_cast<int>(beginTime)) // time not set
     50         m_beginTime = WTF::currentTime();
     51 
     52     gDebugAndroidAnimationInstances++;
     53 }
     54 
     55 AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) :
     56     m_beginTime(anim->m_beginTime),
     57     m_duration(anim->m_duration),
     58     m_iterationCount(anim->m_iterationCount),
     59     m_currentIteration(0),
     60     m_direction(anim->m_direction),
     61     m_timingFunction(anim->m_timingFunction)
     62 {
     63     gDebugAndroidAnimationInstances++;
     64 }
     65 
     66 AndroidAnimation::~AndroidAnimation()
     67 {
     68     gDebugAndroidAnimationInstances--;
     69 }
     70 
     71 float AndroidAnimation::currentProgress(double time)
     72 {
     73     if (m_beginTime <= 0.000001) // overflow or not correctly set
     74         m_beginTime = time;
     75 
     76     m_elapsedTime = time - m_beginTime;
     77 
     78     if (m_duration <= 0)
     79       m_duration = 0.000001;
     80 
     81     if (m_elapsedTime < 0) // animation not yet started.
     82         return 0;
     83 
     84     return m_elapsedTime / m_duration;
     85 }
     86 
     87 bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgress)
     88 {
     89     float progress = currentProgress(time);
     90 
     91     int currentIteration = static_cast<int>(progress);
     92     if (currentIteration != m_currentIteration)
     93         if (m_direction == Animation::AnimationDirectionAlternate)
     94             swapDirection();
     95 
     96     m_currentIteration = currentIteration;
     97     progress -= m_currentIteration;
     98 
     99     if ((m_currentIteration >= m_iterationCount)
    100           && (m_iterationCount != Animation::IterationCountInfinite))
    101         return false;
    102 
    103     if (m_timingFunction.type() != LinearTimingFunction) {
    104         UnitBezier bezier(m_timingFunction.x1(),
    105                           m_timingFunction.y1(),
    106                           m_timingFunction.x2(),
    107                           m_timingFunction.y2());
    108         if (m_duration > 0)
    109             progress = bezier.solve(progress, 1.0f / (200.0f * m_duration));
    110     }
    111 
    112     *finalProgress = progress;
    113     return true;
    114 }
    115 
    116 PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create(
    117                                                 float fromValue,
    118                                                 float toValue,
    119                                                 const Animation* animation,
    120                                                 double beginTime)
    121 {
    122     return adoptRef(new AndroidOpacityAnimation(fromValue, toValue,
    123                                                 animation, beginTime));
    124 }
    125 
    126 AndroidOpacityAnimation::AndroidOpacityAnimation(float fromValue, float toValue,
    127                                                  const Animation* animation,
    128                                                  double beginTime)
    129     : AndroidAnimation(animation, beginTime),
    130       m_fromValue(fromValue), m_toValue(toValue)
    131 {
    132 }
    133 
    134 AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim)
    135     : AndroidAnimation(anim),
    136     m_fromValue(anim->m_fromValue),
    137     m_toValue(anim->m_toValue)
    138 {
    139 }
    140 
    141 PassRefPtr<AndroidAnimation> AndroidOpacityAnimation::copy()
    142 {
    143     return adoptRef(new AndroidOpacityAnimation(this));
    144 }
    145 
    146 void AndroidOpacityAnimation::swapDirection()
    147 {
    148     float v = m_toValue;
    149     m_toValue = m_fromValue;
    150     m_fromValue = m_toValue;
    151 }
    152 
    153 bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time)
    154 {
    155     float progress;
    156     if (!checkIterationsAndProgress(time, &progress))
    157         return false;
    158 
    159     if (progress < 0) // we still want to be evaluated until we get progress > 0
    160         return true;
    161 
    162     float value = m_fromValue + ((m_toValue - m_fromValue) * progress);
    163     layer->setOpacity(value);
    164     return true;
    165 }
    166 
    167 PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create(
    168                                                      const Animation* animation,
    169                                                      double beginTime)
    170 {
    171     return adoptRef(new AndroidTransformAnimation(animation, beginTime));
    172 }
    173 
    174 AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation,
    175                                                      double beginTime)
    176     : AndroidAnimation(animation, beginTime),
    177     m_doTranslation(false),
    178     m_doScaling(false),
    179     m_doRotation(false)
    180 {
    181 }
    182 
    183 AndroidTransformAnimation::AndroidTransformAnimation(AndroidTransformAnimation* anim)
    184     : AndroidAnimation(anim),
    185     m_doTranslation(anim->m_doTranslation),
    186     m_doScaling(anim->m_doScaling),
    187     m_doRotation(anim->m_doRotation),
    188     m_position(anim->m_position),
    189     m_fromX(anim->m_fromX), m_fromY(anim->m_fromY), m_fromZ(anim->m_fromZ),
    190     m_toX(anim->m_toX), m_toY(anim->m_toY), m_toZ(anim->m_toZ),
    191     m_fromAngle(anim->m_fromAngle), m_toAngle(anim->m_toAngle),
    192     m_fromScaleX(anim->m_fromScaleX), m_fromScaleY(anim->m_fromScaleY), m_fromScaleZ(anim->m_fromScaleZ),
    193     m_toScaleX(anim->m_toScaleX), m_toScaleY(anim->m_toScaleY), m_toScaleZ(anim->m_toScaleZ)
    194 {
    195 }
    196 
    197 PassRefPtr<AndroidAnimation> AndroidTransformAnimation::copy()
    198 {
    199     return adoptRef(new AndroidTransformAnimation(this));
    200 }
    201 
    202 void AndroidTransformAnimation::setRotation(float fA, float tA)
    203 {
    204     m_fromAngle = fA;
    205     m_toAngle = tA;
    206     m_doRotation = true;
    207 }
    208 
    209 void AndroidTransformAnimation::setTranslation(float fX, float fY, float fZ,
    210     float tX, float tY, float tZ)
    211 {
    212     m_fromX = fX;
    213     m_fromY = fY;
    214     m_fromZ = fZ;
    215     m_toX = tX;
    216     m_toY = tY;
    217     m_toZ = tZ;
    218     m_doTranslation = true;
    219 }
    220 
    221 void AndroidTransformAnimation::setScale(float fX, float fY, float fZ,
    222                                          float tX, float tY, float tZ)
    223 {
    224     m_fromScaleX = fX;
    225     m_fromScaleY = fY;
    226     m_fromScaleZ = fZ;
    227     m_toScaleX   = tX;
    228     m_toScaleY   = tY;
    229     m_toScaleZ   = tZ;
    230     m_doScaling = true;
    231 }
    232 
    233 void AndroidTransformAnimation::swapDirection()
    234 {
    235     if (m_doTranslation) {
    236         float tx = m_toX;
    237         m_toX = m_fromX;
    238         m_fromX = tx;
    239         float ty = m_toY;
    240         m_toY = m_fromY;
    241         m_fromY = ty;
    242         float tz = m_toZ;
    243         m_toZ = m_fromZ;
    244         m_fromZ = tz;
    245     }
    246     if (m_doScaling) {
    247         float sx = m_toScaleX;
    248         m_toScaleX = m_fromScaleX;
    249         m_fromScaleX = sx;
    250         float sy = m_toScaleY;
    251         m_toScaleY = m_fromScaleY;
    252         m_fromScaleY = sy;
    253     }
    254     if (m_doRotation) {
    255         float a = m_toAngle;
    256         m_toAngle = m_fromAngle;
    257         m_fromAngle = a;
    258     }
    259 }
    260 
    261 bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time)
    262 {
    263     float progress;
    264     if (!checkIterationsAndProgress(time, &progress))
    265         return false;
    266 
    267     if (progress < 0) // we still want to be evaluated until we get progress > 0
    268         return true;
    269 
    270     float x = m_fromX + (m_toX - m_fromX) * progress;
    271     float y = m_fromY + (m_toY - m_fromY) * progress;
    272     float z = m_fromZ + (m_toZ - m_fromZ) * progress;
    273     float sx = m_fromScaleX + (m_toScaleX - m_fromScaleX) * progress;
    274     float sy = m_fromScaleY + (m_toScaleY - m_fromScaleY) * progress;
    275     float sz = m_fromScaleZ + (m_toScaleZ - m_fromScaleZ) * progress;
    276     float a = m_fromAngle + (m_toAngle - m_fromAngle) * progress;
    277 
    278     if (m_doTranslation)
    279         layer->setTranslation(x, y);
    280 
    281     if (m_doScaling)
    282         layer->setScale(sx, sy);
    283 
    284     if (m_doRotation)
    285         layer->setRotation(a);
    286 
    287     return true;
    288 }
    289 
    290 } // namespace WebCore
    291 
    292 #endif // USE(ACCELERATED_COMPOSITING)
    293