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 31namespace WebCore { 32 33static long gDebugAndroidAnimationInstances; 34 35long AndroidAnimation::instancesCount() 36{ 37 return gDebugAndroidAnimationInstances; 38} 39 40AndroidAnimation::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 55AndroidAnimation::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 66AndroidAnimation::~AndroidAnimation() 67{ 68 gDebugAndroidAnimationInstances--; 69} 70 71float 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 87bool 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 116PassRefPtr<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 126AndroidOpacityAnimation::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 134AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim) 135 : AndroidAnimation(anim), 136 m_fromValue(anim->m_fromValue), 137 m_toValue(anim->m_toValue) 138{ 139} 140 141PassRefPtr<AndroidAnimation> AndroidOpacityAnimation::copy() 142{ 143 return adoptRef(new AndroidOpacityAnimation(this)); 144} 145 146void AndroidOpacityAnimation::swapDirection() 147{ 148 float v = m_toValue; 149 m_toValue = m_fromValue; 150 m_fromValue = m_toValue; 151} 152 153bool 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 167PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create( 168 const Animation* animation, 169 double beginTime) 170{ 171 return adoptRef(new AndroidTransformAnimation(animation, beginTime)); 172} 173 174AndroidTransformAnimation::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 183AndroidTransformAnimation::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 197PassRefPtr<AndroidAnimation> AndroidTransformAnimation::copy() 198{ 199 return adoptRef(new AndroidTransformAnimation(this)); 200} 201 202void AndroidTransformAnimation::setRotation(float fA, float tA) 203{ 204 m_fromAngle = fA; 205 m_toAngle = tA; 206 m_doRotation = true; 207} 208 209void 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 221void 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 233void 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 261bool 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