diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/frame/animation')
13 files changed, 0 insertions, 4350 deletions
diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.cpp deleted file mode 100644 index 5dafb2de2fd..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/AnimationBase.h" - -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/platform/animation/TimingFunction.h" -#include "core/rendering/RenderBox.h" -#include "platform/animation/AnimationUtilities.h" -#include <algorithm> - -using namespace std; - -namespace WebCore { - -AnimationBase::AnimationBase(const CSSAnimationData* transition, RenderObject& renderer, CompositeAnimation* compAnim) - : m_animState(AnimationStateNew) - , m_isAccelerated(false) - , m_transformFunctionListValid(false) - , m_filterFunctionListsMatch(false) - , m_startTime(0) - , m_pauseTime(-1) - , m_requestedStartTime(0) - , m_totalDuration(-1) - , m_nextIterationDuration(-1) - , m_object(&renderer) - , m_animation(const_cast<CSSAnimationData*>(transition)) - , m_compAnim(compAnim) -{ - // Compute the total duration - if (m_animation->iterationCount() > 0) - m_totalDuration = m_animation->duration() * m_animation->iterationCount(); -} - -void AnimationBase::setNeedsStyleRecalc(Node* node) -{ - if (node) - node->setNeedsStyleRecalc(LocalStyleChange); -} - -double AnimationBase::duration() const -{ - return m_animation->duration(); -} - -bool AnimationBase::playStatePlaying() const -{ - return m_animation->playState() == AnimPlayStatePlaying; -} - -void AnimationBase::updateStateMachine(AnimStateInput input, double param) -{ - if (!m_compAnim) - return; - - // If we get AnimationStateInputRestartAnimation then we force a new animation, regardless of state. - if (input == AnimationStateInputMakeNew) { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); - m_animState = AnimationStateNew; - m_startTime = 0; - m_pauseTime = -1; - m_requestedStartTime = 0; - m_nextIterationDuration = -1; - endAnimation(); - return; - } - - if (input == AnimationStateInputRestartAnimation) { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); - m_animState = AnimationStateNew; - m_startTime = 0; - m_pauseTime = -1; - m_requestedStartTime = 0; - m_nextIterationDuration = -1; - endAnimation(); - - if (!paused()) - updateStateMachine(AnimationStateInputStartAnimation, -1); - return; - } - - if (input == AnimationStateInputEndAnimation) { - if (m_animState == AnimationStateStartWaitStyleAvailable) - m_compAnim->animationController()->removeFromAnimationsWaitingForStyle(this); - m_animState = AnimationStateDone; - endAnimation(); - return; - } - - if (input == AnimationStateInputPauseOverride) { - if (m_animState == AnimationStateStartWaitResponse) { - // If we are in AnimationStateStartWaitResponse, the animation will get canceled before - // we get a response, so move to the next state. - endAnimation(); - updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); - } - return; - } - - if (input == AnimationStateInputResumeOverride) { - if (m_animState == AnimationStateLooping || m_animState == AnimationStateEnding) { - // Start the animation - startAnimation(beginAnimationUpdateTime() - m_startTime); - } - return; - } - - // Execute state machine - switch (m_animState) { - case AnimationStateNew: - ASSERT(input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning || input == AnimationStateInputPlayStatePaused); - if (input == AnimationStateInputStartAnimation || input == AnimationStateInputPlayStateRunning) { - m_requestedStartTime = beginAnimationUpdateTime(); - m_animState = AnimationStateStartWaitTimer; - } - break; - case AnimationStateStartWaitTimer: - ASSERT(input == AnimationStateInputStartTimerFired || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputStartTimerFired) { - ASSERT(param >= 0); - // Start timer has fired, tell the animation to start and wait for it to respond with start time - m_animState = AnimationStateStartWaitStyleAvailable; - m_compAnim->animationController()->addToAnimationsWaitingForStyle(this); - - // Trigger a render so we can start the animation - if (m_object) - m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); - } else { - ASSERT(!paused()); - // We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait - m_pauseTime = beginAnimationUpdateTime(); - m_animState = AnimationStatePausedWaitTimer; - } - break; - case AnimationStateStartWaitStyleAvailable: - ASSERT(input == AnimationStateInputStyleAvailable || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputStyleAvailable) { - // Start timer has fired, tell the animation to start and wait for it to respond with start time - m_animState = AnimationStateStartWaitResponse; - - overrideAnimations(); - - // Start the animation - if (overridden()) { - m_animState = AnimationStateStartWaitResponse; - updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); - } else { - double timeOffset = 0; - // If the value for 'animation-delay' is negative then the animation appears to have started in the past. - if (m_animation->delay() < 0) - timeOffset = -m_animation->delay(); - startAnimation(timeOffset); - m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, isAccelerated()); - } - } else { - // We're waiting for the style to be available and we got a pause. Pause and wait - m_pauseTime = beginAnimationUpdateTime(); - m_animState = AnimationStatePausedWaitStyleAvailable; - } - break; - case AnimationStateStartWaitResponse: - ASSERT(input == AnimationStateInputStartTimeSet || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputStartTimeSet) { - ASSERT(param >= 0); - // We have a start time, set it, unless the startTime is already set - if (m_startTime <= 0) { - m_startTime = param; - // If the value for 'animation-delay' is negative then the animation appears to have started in the past. - if (m_animation->delay() < 0) - m_startTime += m_animation->delay(); - } - - // Now that we know the start time, fire the start event. - onAnimationStart(0); // The elapsedTime is 0. - - // Decide whether to go into looping or ending state - goIntoEndingOrLoopingState(); - - // Dispatch updateStyleIfNeeded so we can start the animation - if (m_object) - m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); - } else { - // We are pausing while waiting for a start response. Cancel the animation and wait. When - // we unpause, we will act as though the start timer just fired - m_pauseTime = beginAnimationUpdateTime(); - pauseAnimation(beginAnimationUpdateTime() - m_startTime); - m_animState = AnimationStatePausedWaitResponse; - } - break; - case AnimationStateLooping: - ASSERT(input == AnimationStateInputLoopTimerFired || input == AnimationStateInputPlayStatePaused); - - if (input == AnimationStateInputLoopTimerFired) { - ASSERT(param >= 0); - // Loop timer fired, loop again or end. - onAnimationIteration(param); - - // Decide whether to go into looping or ending state - goIntoEndingOrLoopingState(); - } else { - // We are pausing while running. Cancel the animation and wait - m_pauseTime = beginAnimationUpdateTime(); - pauseAnimation(beginAnimationUpdateTime() - m_startTime); - m_animState = AnimationStatePausedRun; - } - break; - case AnimationStateEnding: -#if !LOG_DISABLED - if (input != AnimationStateInputEndTimerFired && input != AnimationStateInputPlayStatePaused) - WTF_LOG_ERROR("State is AnimationStateEnding, but input is not AnimationStateInputEndTimerFired or AnimationStateInputPlayStatePaused. It is %d.", input); -#endif - if (input == AnimationStateInputEndTimerFired) { - - ASSERT(param >= 0); - // End timer fired, finish up - onAnimationEnd(param); - - m_animState = AnimationStateDone; - - if (m_object) { - if (m_animation->fillsForwards()) - m_animState = AnimationStateFillingForwards; - else - resumeOverriddenAnimations(); - - // Fire off another style change so we can set the final value - m_compAnim->animationController()->addNodeChangeToDispatch(m_object->node()); - } - } else { - // We are pausing while running. Cancel the animation and wait - m_pauseTime = beginAnimationUpdateTime(); - pauseAnimation(beginAnimationUpdateTime() - m_startTime); - m_animState = AnimationStatePausedRun; - } - // |this| may be deleted here - break; - case AnimationStatePausedWaitTimer: - ASSERT(input == AnimationStateInputPlayStateRunning); - ASSERT(paused()); - // Update the times - m_startTime += beginAnimationUpdateTime() - m_pauseTime; - m_pauseTime = -1; - - // we were waiting for the start timer to fire, go back and wait again - m_animState = AnimationStateNew; - updateStateMachine(AnimationStateInputStartAnimation, 0); - break; - case AnimationStatePausedWaitResponse: - case AnimationStatePausedWaitStyleAvailable: - case AnimationStatePausedRun: - // We treat these two cases the same. The only difference is that, when we are in - // AnimationStatePausedWaitResponse, we don't yet have a valid startTime, so we send 0 to startAnimation. - // When the AnimationStateInputStartTimeSet comes in and we were in AnimationStatePausedRun, we will notice - // that we have already set the startTime and will ignore it. - ASSERT(input == AnimationStateInputPlayStateRunning || input == AnimationStateInputStartTimeSet || input == AnimationStateInputStyleAvailable); - ASSERT(paused()); - - if (input == AnimationStateInputPlayStateRunning) { - // Update the times - if (m_animState == AnimationStatePausedRun) - m_startTime += beginAnimationUpdateTime() - m_pauseTime; - else - m_startTime = 0; - m_pauseTime = -1; - - if (m_animState == AnimationStatePausedWaitStyleAvailable) - m_animState = AnimationStateStartWaitStyleAvailable; - else { - // We were either running or waiting for a begin time response from the animation. - // Either way we need to restart the animation (possibly with an offset if we - // had already been running) and wait for it to start. - m_animState = AnimationStateStartWaitResponse; - - // Start the animation - if (overridden()) { - updateStateMachine(AnimationStateInputStartTimeSet, beginAnimationUpdateTime()); - } else { - startAnimation(beginAnimationUpdateTime() - m_startTime); - m_compAnim->animationController()->addToAnimationsWaitingForStartTimeResponse(this, isAccelerated()); - } - } - break; - } - - if (input == AnimationStateInputStartTimeSet) { - ASSERT(m_animState == AnimationStatePausedWaitResponse); - - // We are paused but we got the callback that notifies us that an accelerated animation started. - // We ignore the start time and just move into the paused-run state. - m_animState = AnimationStatePausedRun; - ASSERT(m_startTime == 0); - m_startTime = param; - m_pauseTime += m_startTime; - break; - } - - ASSERT(m_animState == AnimationStatePausedWaitStyleAvailable); - // We are paused but we got the callback that notifies us that style has been updated. - // We move to the AnimationStatePausedWaitResponse state - m_animState = AnimationStatePausedWaitResponse; - overrideAnimations(); - break; - case AnimationStateFillingForwards: - case AnimationStateDone: - // We're done. Stay in this state until we are deleted - break; - } -} - -void AnimationBase::fireAnimationEventsIfNeeded() -{ - if (!m_compAnim) - return; - - // If we are waiting for the delay time to expire and it has, go to the next state - if (m_animState != AnimationStateStartWaitTimer && m_animState != AnimationStateLooping && m_animState != AnimationStateEnding) - return; - - // We have to make sure to keep a ref to the this pointer, because it could get destroyed - // during an animation callback that might get called. Since the owner is a CompositeAnimation - // and it ref counts this object, we will keep a ref to that instead. That way the AnimationBase - // can still access the resources of its CompositeAnimation as needed. - RefPtr<AnimationBase> protector(this); - RefPtr<CompositeAnimation> compProtector(m_compAnim); - - // Check for start timeout - if (m_animState == AnimationStateStartWaitTimer) { - if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay()) - updateStateMachine(AnimationStateInputStartTimerFired, 0); - return; - } - - double elapsedDuration = getElapsedTime(); - - // Check for end timeout - if (m_totalDuration >= 0 && elapsedDuration >= m_totalDuration) { - // We may still be in AnimationStateLooping if we've managed to skip a - // whole iteration, in which case we should jump to the end state. - m_animState = AnimationStateEnding; - - // Fire an end event - updateStateMachine(AnimationStateInputEndTimerFired, m_totalDuration); - } else { - // Check for iteration timeout - if (m_nextIterationDuration < 0) { - // Hasn't been set yet, set it - double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); - m_nextIterationDuration = elapsedDuration + durationLeft; - } - - if (elapsedDuration >= m_nextIterationDuration) { - // Set to the next iteration - double previous = m_nextIterationDuration; - double durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); - m_nextIterationDuration = elapsedDuration + durationLeft; - - // Send the event - updateStateMachine(AnimationStateInputLoopTimerFired, previous); - } - } -} - -void AnimationBase::updatePlayState(EAnimPlayState playState) -{ - if (!m_compAnim) - return; - - // Set the state machine to the desired state. - bool pause = playState == AnimPlayStatePaused; - - if (pause == paused() && !isNew()) - return; - - updateStateMachine(pause ? AnimationStateInputPlayStatePaused : AnimationStateInputPlayStateRunning, -1); -} - -double AnimationBase::timeToNextService() -{ - // Returns the time at which next service is required. -1 means no service is required. 0 means - // service is required now, and > 0 means service is required that many seconds in the future. - if (paused() || isNew() || m_animState == AnimationStateFillingForwards) - return -1; - - if (m_animState == AnimationStateStartWaitTimer) { - double timeFromNow = m_animation->delay() - (beginAnimationUpdateTime() - m_requestedStartTime); - return max(timeFromNow, 0.0); - } - - fireAnimationEventsIfNeeded(); - - // In all other cases, we need service right away. - return 0; -} - -// Compute the fractional time, taking into account direction. -// There is no need to worry about iterations, we assume that we would have -// short circuited above if we were done. - -double AnimationBase::fractionalTime(double scale, double elapsedTime, double offset) const -{ - double fractionalTime = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1; - // FIXME: startTime can be before the current animation "frame" time. This is to sync with the frame time - // concept in AnimationTimeController. So we need to somehow sync the two. Until then, the possible - // error is small and will probably not be noticeable. Until we fix this, remove the assert. - // https://bugs.webkit.org/show_bug.cgi?id=52037 - // ASSERT(fractionalTime >= 0); - if (fractionalTime < 0) - fractionalTime = 0; - - int integralTime = static_cast<int>(fractionalTime); - const int integralIterationCount = static_cast<int>(m_animation->iterationCount()); - const bool iterationCountHasFractional = m_animation->iterationCount() - integralIterationCount; - if (m_animation->iterationCount() != CSSAnimationData::IterationCountInfinite && !iterationCountHasFractional) - integralTime = min(integralTime, integralIterationCount - 1); - - fractionalTime -= integralTime; - - // Thie method can be called with an elapsedTime which very slightly - // exceeds the end of the animation. In this case, clamp the - // fractionalTime. - if (fractionalTime > 1) - fractionalTime = 1; - ASSERT(fractionalTime >= 0 && fractionalTime <= 1); - - if (((m_animation->direction() == CSSAnimationData::AnimationDirectionAlternate) && (integralTime & 1)) - || ((m_animation->direction() == CSSAnimationData::AnimationDirectionAlternateReverse) && !(integralTime & 1)) - || m_animation->direction() == CSSAnimationData::AnimationDirectionReverse) - fractionalTime = 1 - fractionalTime; - - fractionalTime -= offset; - // Note that if fractionalTime == 0 here, scale may be infinity, but in - // this case we don't need to apply scale anyway. - if (scale != 1.0 && fractionalTime) { - ASSERT(scale >= 0 && !std::isinf(scale)); - fractionalTime *= scale; - } - - ASSERT(fractionalTime >= 0 && fractionalTime <= 1); - return fractionalTime; -} - -double AnimationBase::progress(double scale, double offset, const TimingFunction* timingFunction) const -{ - if (preActive()) - return 0; - - double dur = m_animation->duration(); - if (m_animation->iterationCount() > 0) - dur *= m_animation->iterationCount(); - - if (postActive() || !m_animation->duration()) - return 1.0; - - double elapsedTime = getElapsedTime(); - if (m_animation->iterationCount() > 0 && elapsedTime >= dur) { - const int integralIterationCount = static_cast<int>(m_animation->iterationCount()); - const bool iterationCountHasFractional = m_animation->iterationCount() - integralIterationCount; - return (integralIterationCount % 2 || iterationCountHasFractional) ? 1.0 : 0.0; - } - - const double fractionalTime = this->fractionalTime(scale, elapsedTime, offset); - - if (!timingFunction) - timingFunction = m_animation->timingFunction(); - - return timingFunction->evaluate(fractionalTime, accuracyForDuration(m_animation->duration())); -} - -void AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const -{ - if (postActive()) { - time = -1; - isLooping = false; - return; - } - - // Decide when the end or loop event needs to fire - const double elapsedDuration = getElapsedTime(); - double durationLeft = 0; - double nextIterationTime = m_totalDuration; - - if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) { - durationLeft = m_animation->duration() > 0 ? (m_animation->duration() - fmod(elapsedDuration, m_animation->duration())) : 0; - nextIterationTime = elapsedDuration + durationLeft; - } - - if (m_totalDuration < 0 || nextIterationTime < m_totalDuration) { - // We are not at the end yet - ASSERT(m_totalDuration < 0 || nextIterationTime > 0); - isLooping = true; - } else { - // We are at the end - isLooping = false; - } - - time = durationLeft; -} - -void AnimationBase::goIntoEndingOrLoopingState() -{ - double t; - bool isLooping; - getTimeToNextEvent(t, isLooping); - m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding; -} - -void AnimationBase::freezeAtTime(double t) -{ - if (!m_compAnim) - return; - - if (!m_startTime) { - // If we haven't started yet, make it as if we started. - m_animState = AnimationStateStartWaitResponse; - onAnimationStartResponse(beginAnimationUpdateTime()); - } - - ASSERT(m_startTime); // if m_startTime is zero, we haven't started yet, so we'll get a bad pause time. - if (t <= m_animation->delay()) - m_pauseTime = m_startTime; - else - m_pauseTime = m_startTime + t - m_animation->delay(); - - // It is possible that m_isAccelerated is true and m_object->compositingState() is NotComposited, because of style change. - // So, both conditions need to be checked. - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - pauseAnimation(t); -} - -double AnimationBase::beginAnimationUpdateTime() const -{ - if (!m_compAnim) - return 0; - - return m_compAnim->animationController()->beginAnimationUpdateTime(); -} - -double AnimationBase::getElapsedTime() const -{ - ASSERT(!postActive()); - if (paused()) - return m_pauseTime - m_startTime; - if (m_startTime <= 0) - return 0; - - double elapsedTime = beginAnimationUpdateTime() - m_startTime; - // It's possible for the start time to be ahead of the last update time - // if the compositor has just sent notification for the start of an - // accelerated animation. - return max(elapsedTime, 0.0); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.h b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.h deleted file mode 100644 index 6ab1d5801e4..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationBase.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AnimationBase_h -#define AnimationBase_h - -#include "CSSPropertyNames.h" -#include "core/platform/animation/CSSAnimationData.h" -#include "core/rendering/style/RenderStyleConstants.h" -#include "wtf/RefCounted.h" - -namespace WebCore { - -class AnimationBase; -class AnimationController; -class CompositeAnimation; -class Element; -class Node; -class RenderObject; -class RenderStyle; -class TimingFunction; - -class AnimationBase : public RefCounted<AnimationBase> { - friend class CompositeAnimation; - friend class CSSPropertyAnimation; - -public: - AnimationBase(const CSSAnimationData* transition, RenderObject& renderer, CompositeAnimation* compAnim); - virtual ~AnimationBase() { } - - RenderObject* renderer() const { return m_object; } - void clear() - { - endAnimation(); - m_object = 0; - m_compAnim = 0; - } - - double duration() const; - - // Animations and Transitions go through the states below. When entering the STARTED state - // the animation is started. This may or may not require deferred response from the animator. - // If so, we stay in this state until that response is received (and it returns the start time). - // Otherwise, we use the current time as the start time and go immediately to AnimationStateLooping - // or AnimationStateEnding. - enum AnimState { - AnimationStateNew, // animation just created, animation not running yet - AnimationStateStartWaitTimer, // start timer running, waiting for fire - AnimationStateStartWaitStyleAvailable, // waiting for style setup so we can start animations - AnimationStateStartWaitResponse, // animation started, waiting for response - AnimationStateLooping, // response received, animation running, loop timer running, waiting for fire - AnimationStateEnding, // received, animation running, end timer running, waiting for fire - AnimationStatePausedWaitTimer, // in pause mode when animation started - AnimationStatePausedWaitStyleAvailable, // in pause mode when waiting for style setup - AnimationStatePausedWaitResponse, // animation paused when in STARTING state - AnimationStatePausedRun, // animation paused when in LOOPING or ENDING state - AnimationStateDone, // end timer fired, animation finished and removed - AnimationStateFillingForwards // animation has ended and is retaining its final value - }; - - enum AnimStateInput { - AnimationStateInputMakeNew, // reset back to new from any state - AnimationStateInputStartAnimation, // animation requests a start - AnimationStateInputRestartAnimation, // force a restart from any state - AnimationStateInputStartTimerFired, // start timer fired - AnimationStateInputStyleAvailable, // style is setup, ready to start animating - AnimationStateInputStartTimeSet, // m_startTime was set - AnimationStateInputLoopTimerFired, // loop timer fired - AnimationStateInputEndTimerFired, // end timer fired - AnimationStateInputPauseOverride, // pause an animation due to override - AnimationStateInputResumeOverride, // resume an overridden animation - AnimationStateInputPlayStateRunning, // play state paused -> running - AnimationStateInputPlayStatePaused, // play state running -> paused - AnimationStateInputEndAnimation // force an end from any state - }; - - // Called when animation is in AnimationStateNew to start animation - void updateStateMachine(AnimStateInput, double param); - - // Animation has actually started, at passed time - void onAnimationStartResponse(double startTime) - { - updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, startTime); - } - - // Called to change to or from paused state - void updatePlayState(EAnimPlayState); - bool playStatePlaying() const; - - bool waitingToStart() const { return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer; } - bool preActive() const - { - return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer || m_animState == AnimationStateStartWaitStyleAvailable || m_animState == AnimationStateStartWaitResponse; - } - - bool postActive() const { return m_animState == AnimationStateDone; } - bool active() const { return !postActive() && !preActive(); } - bool running() const { return !isNew() && !postActive(); } - bool paused() const { return m_pauseTime >= 0; } - bool isNew() const { return m_animState == AnimationStateNew; } - bool waitingForStartTime() const { return m_animState == AnimationStateStartWaitResponse; } - bool waitingForStyleAvailable() const { return m_animState == AnimationStateStartWaitStyleAvailable; } - - virtual double timeToNextService(); - - double progress(double scale, double offset, const TimingFunction*) const; - - virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* /*currentStyle*/, RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) = 0; - virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0; - - virtual bool shouldFireEvents() const { return false; } - - void fireAnimationEventsIfNeeded(); - - void setAnimation(const CSSAnimationData* anim) { m_animation = const_cast<CSSAnimationData*>(anim); } - - // Return true if this animation is overridden. This will only be the case for - // ImplicitAnimations and is used to determine whether or not we should force - // set the start time. If an animation is overridden, it will probably not get - // back the AnimationStateInputStartTimeSet input. - virtual bool overridden() const { return false; } - - // Does this animation/transition involve the given property? - virtual bool affectsProperty(CSSPropertyID /*property*/) const { return false; } - - bool isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, bool isRunningNow) const - { - if (acceleratedOnly && !m_isAccelerated) - return false; - - if (isRunningNow) - return (!waitingToStart() && !postActive()) && affectsProperty(property); - - return !postActive() && affectsProperty(property); - } - - // FIXME: rename this using the "lists match" terminology. - bool isTransformFunctionListValid() const { return m_transformFunctionListValid; } - bool filterFunctionListsMatch() const { return m_filterFunctionListsMatch; } - - // Freeze the animation; used by DumpRenderTree. - void freezeAtTime(double t); - - double beginAnimationUpdateTime() const; - - double getElapsedTime() const; - - void styleAvailable() - { - ASSERT(waitingForStyleAvailable()); - updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1); - } - - const CSSAnimationData* animation() const { return m_animation.get(); } - -protected: - virtual void overrideAnimations() { } - virtual void resumeOverriddenAnimations() { } - - CompositeAnimation* compositeAnimation() { return m_compAnim; } - - // These are called when the corresponding timer fires so subclasses can do any extra work - virtual void onAnimationStart(double /*elapsedTime*/) { } - virtual void onAnimationIteration(double /*elapsedTime*/) { } - virtual void onAnimationEnd(double /*elapsedTime*/) { } - - // timeOffset is an offset from the current time when the animation should start. Negative values are OK. - virtual void startAnimation(double /*timeOffset*/) { } - // timeOffset is the time at which the animation is being paused. - virtual void pauseAnimation(double /*timeOffset*/) { } - virtual void endAnimation() { } - - void goIntoEndingOrLoopingState(); - - bool isAccelerated() const { return m_isAccelerated; } - - static void setNeedsStyleRecalc(Node*); - - void getTimeToNextEvent(double& time, bool& isLooping) const; - - double fractionalTime(double scale, double elapsedTime, double offset) const; - - AnimState m_animState; - - bool m_isAccelerated; - bool m_transformFunctionListValid; - bool m_filterFunctionListsMatch; - double m_startTime; - double m_pauseTime; - double m_requestedStartTime; - - double m_totalDuration; - double m_nextIterationDuration; - - RenderObject* m_object; - - RefPtr<CSSAnimationData> m_animation; - CompositeAnimation* m_compAnim; -}; - -} // namespace WebCore - -#endif // AnimationBase_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.cpp deleted file mode 100644 index 8521e139a08..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/AnimationController.h" - -#include "core/dom/PseudoElement.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/events/TransitionEvent.h" -#include "core/events/WebKitAnimationEvent.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" -#include "core/page/Page.h" -#include "core/frame/animation/AnimationBase.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/rendering/RenderView.h" -#include "wtf/CurrentTime.h" - -namespace WebCore { - -static const double cBeginAnimationUpdateTimeNotSet = -1; - -AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) - : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired) - , m_updateStyleIfNeededDispatcher(this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired) - , m_frame(frame) - , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet) - , m_animationsWaitingForStyle() - , m_animationsWaitingForStartTimeResponse() - , m_animationsWaitingForAsyncStartNotification() -{ -} - -AnimationControllerPrivate::~AnimationControllerPrivate() -{ -} - -PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimation(RenderObject& renderer) -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(&renderer); - if (!animation) { - animation = CompositeAnimation::create(this); - m_compositeAnimations.set(&renderer, animation); - } - return animation; -} - -bool AnimationControllerPrivate::clear(RenderObject* renderer) -{ - // Return false if we didn't do anything. - PassRefPtr<CompositeAnimation> animation = m_compositeAnimations.take(renderer); - if (!animation) - return false; - animation->clearRenderer(); - return true; -} - -void AnimationControllerPrivate::updateAnimations(double& timeToNextService, double& timeToNextEvent, SetNeedsStyleRecalc callSetNeedsStyleRecalc/* = DoNotCallSetNeedsStyleRecalc*/) -{ - double minTimeToNextService = -1; - double minTimeToNextEvent = -1; - bool updateStyleNeeded = false; - - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - CompositeAnimation* compAnim = it->value.get(); - if (compAnim->hasAnimations()) { - double t = compAnim->timeToNextService(); - if (t != -1 && (t < minTimeToNextService || minTimeToNextService == -1)) - minTimeToNextService = t; - double nextEvent = compAnim->timeToNextEvent(); - if (nextEvent != -1 && (nextEvent < minTimeToNextEvent || minTimeToNextEvent == -1)) - minTimeToNextEvent = nextEvent; - if (callSetNeedsStyleRecalc == CallSetNeedsStyleRecalc) { - if (!t) { - Node* node = it->key->node(); - node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - updateStyleNeeded = true; - } - } else if (!minTimeToNextService && !minTimeToNextEvent) { - // Found the minimum values and do not need to mark for style recalc. - break; - } - } - } - - if (updateStyleNeeded) - m_frame->document()->updateStyleIfNeeded(); - - timeToNextService = minTimeToNextService; - timeToNextEvent = minTimeToNextEvent; -} - -void AnimationControllerPrivate::scheduleServiceForRenderer(RenderObject& renderer) -{ - double timeToNextService = -1; - double timeToNextEvent = -1; - - RefPtr<CompositeAnimation> compAnim = m_compositeAnimations.get(&renderer); - if (compAnim->hasAnimations()) { - timeToNextService = compAnim->timeToNextService(); - timeToNextEvent = compAnim->timeToNextEvent(); - } - - if (timeToNextService >= 0) - scheduleService(timeToNextService, timeToNextEvent); -} - -void AnimationControllerPrivate::scheduleService() -{ - double timeToNextService = -1; - double timeToNextEvent = -1; - updateAnimations(timeToNextService, timeToNextEvent, DoNotCallSetNeedsStyleRecalc); - scheduleService(timeToNextService, timeToNextEvent); -} - -void AnimationControllerPrivate::scheduleService(double timeToNextService, double timeToNextEvent) -{ - if (!m_frame->page()) - return; - - bool visible = m_frame->page()->visibilityState() == WebCore::PageVisibilityStateVisible; - - // This std::max to 1 second limits how often we service animations on background tabs. - // Without this, plus and gmail were recalculating style as every 200ms or even more - // often, burning CPU needlessly for background tabs. - // FIXME: Do we want to fire events at all on background tabs? - if (!visible) - timeToNextService = std::max(timeToNextEvent, 1.0); - - if (visible && !timeToNextService) { - m_frame->document()->view()->scheduleAnimation(); - if (m_animationTimer.isActive()) - m_animationTimer.stop(); - return; - } - - if (timeToNextService < 0) { - if (m_animationTimer.isActive()) - m_animationTimer.stop(); - return; - } - - if (m_animationTimer.isActive() && m_animationTimer.nextFireInterval() <= timeToNextService) - return; - - m_animationTimer.startOneShot(timeToNextService); -} - -void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*) -{ - fireEventsAndUpdateStyle(); -} - -void AnimationControllerPrivate::fireEventsAndUpdateStyle() -{ - // Protect the frame from getting destroyed in the event handler - RefPtr<Frame> protector = m_frame; - - bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_nodeChangesToDispatch.isEmpty(); - - // fire all the events - Vector<EventToDispatch> eventsToDispatch = m_eventsToDispatch; - m_eventsToDispatch.clear(); - Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = eventsToDispatch.end(); - for (Vector<EventToDispatch>::const_iterator it = eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) { - Element* element = it->element.get(); - if (it->eventType == EventTypeNames::transitionend) - element->dispatchEvent(TransitionEvent::create(it->eventType, it->name, it->elapsedTime, PseudoElement::pseudoElementNameForEvents(element->pseudoId()))); - else - element->dispatchEvent(WebKitAnimationEvent::create(it->eventType, it->name, it->elapsedTime)); - } - - // call setChanged on all the elements - Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end(); - for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it) - (*it)->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - - m_nodeChangesToDispatch.clear(); - - if (updateStyle && m_frame) - m_frame->document()->updateStyleIfNeeded(); -} - -void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher() -{ - if (!m_updateStyleIfNeededDispatcher.isActive()) - m_updateStyleIfNeededDispatcher.startOneShot(0); -} - -void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime) -{ - m_eventsToDispatch.grow(m_eventsToDispatch.size()+1); - EventToDispatch& event = m_eventsToDispatch[m_eventsToDispatch.size()-1]; - event.element = element; - event.eventType = eventType; - event.name = name; - event.elapsedTime = elapsedTime; - - startUpdateStyleIfNeededDispatcher(); -} - -void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) -{ - if (!node) - return; - - m_nodeChangesToDispatch.append(node); - startUpdateStyleIfNeededDispatcher(); -} - -void AnimationControllerPrivate::serviceAnimations() -{ - double timeToNextService = -1; - double timeToNextEvent = -1; - updateAnimations(timeToNextService, timeToNextEvent, CallSetNeedsStyleRecalc); - scheduleService(timeToNextService, timeToNextEvent); - - // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before - // the 'end' event fires. - fireEventsAndUpdateStyle(); -} - -void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*) -{ - // Make sure animationUpdateTime is updated, so that it is current even if no - // styleChange has happened (e.g. accelerated animations) - setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); - serviceAnimations(); -} - -bool AnimationControllerPrivate::isRunningAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); - if (!animation) - return false; - - return animation->isAnimatingProperty(property, false, isRunningNow); -} - -bool AnimationControllerPrivate::isRunningAcceleratableAnimationOnRenderer(RenderObject *renderer) const -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); - if (!animation) - return false; - - bool acceleratedOnly = false; - bool isRunningNow = true; - return animation->isAnimatingProperty(CSSPropertyOpacity, acceleratedOnly, isRunningNow) - || animation->isAnimatingProperty(CSSPropertyWebkitTransform, acceleratedOnly, isRunningNow) - || animation->isAnimatingProperty(CSSPropertyWebkitFilter, acceleratedOnly, isRunningNow); -} - -bool AnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); - if (!animation) - return false; - - return animation->isAnimatingProperty(property, true, isRunningNow); -} - -void AnimationControllerPrivate::pauseAnimationsForTesting(double t) -{ - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - it->value->pauseAnimationsForTesting(t); - it->key->node()->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - } -} - -double AnimationControllerPrivate::beginAnimationUpdateTime() -{ - if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet) - m_beginAnimationUpdateTime = currentTime(); - return m_beginAnimationUpdateTime; -} - -void AnimationControllerPrivate::endAnimationUpdate() -{ - styleAvailable(); - if (m_animationsWaitingForAsyncStartNotification.isEmpty()) - startTimeResponse(beginAnimationUpdateTime()); -} - -void AnimationControllerPrivate::receivedStartTimeResponse(double time) -{ - startTimeResponse(time); -} - -PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderObject* renderer) -{ - if (!renderer) - return 0; - - RefPtr<CompositeAnimation> rendererAnimations = m_compositeAnimations.get(renderer); - if (!rendererAnimations) - return renderer->style(); - - RefPtr<RenderStyle> animatingStyle = rendererAnimations->getAnimatedStyle(); - if (!animatingStyle) - animatingStyle = renderer->style(); - - return animatingStyle.release(); -} - -unsigned AnimationControllerPrivate::numberOfActiveAnimations(Document* document) const -{ - unsigned count = 0; - - RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); - for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { - RenderObject* renderer = it->key; - CompositeAnimation* compAnim = it->value.get(); - if (renderer->document() == document) - count += compAnim->numberOfActiveAnimations(); - } - - return count; -} - -void AnimationControllerPrivate::addToAnimationsWaitingForStyle(AnimationBase* animation) -{ - // Make sure this animation is not in the start time waiters - m_animationsWaitingForStartTimeResponse.remove(animation); - m_animationsWaitingForAsyncStartNotification.remove(animation); - - m_animationsWaitingForStyle.add(animation); -} - -void AnimationControllerPrivate::removeFromAnimationsWaitingForStyle(AnimationBase* animationToRemove) -{ - m_animationsWaitingForStyle.remove(animationToRemove); -} - -void AnimationControllerPrivate::styleAvailable() -{ - // Go through list of waiters and send them on their way - WaitingAnimationsSet::const_iterator it = m_animationsWaitingForStyle.begin(); - WaitingAnimationsSet::const_iterator end = m_animationsWaitingForStyle.end(); - for (; it != end; ++it) - (*it)->styleAvailable(); - - m_animationsWaitingForStyle.clear(); -} - -void AnimationControllerPrivate::addToAnimationsWaitingForStartTimeResponse(AnimationBase* animation, bool willGetResponse) -{ - // If willGetResponse is true, it means this animation is actually waiting for a response - // (which will come in as a call to notifyAnimationStarted()). - // In that case we don't need to add it to this list. We just set a waitingForAResponse flag - // which says we are waiting for the response. If willGetResponse is false, this animation - // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for - // another animation to which it will sync. - // - // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is - // true. If so, we just return and will do our work when the first notifyXXXStarted() call - // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will - // do our work right away. In both cases we call the onAnimationStartResponse() method - // on each animation. In the first case we send in the time we got from notifyXXXStarted(). - // In the second case, we just pass in the beginAnimationUpdateTime(). - // - // This will synchronize all software and accelerated animations started in the same - // updateStyleIfNeeded cycle. - // - - if (willGetResponse) - m_animationsWaitingForAsyncStartNotification.add(animation); - - m_animationsWaitingForStartTimeResponse.add(animation); -} - -void AnimationControllerPrivate::removeFromAnimationsWaitingForStartTimeResponse(AnimationBase* animationToRemove) -{ - m_animationsWaitingForStartTimeResponse.remove(animationToRemove); - m_animationsWaitingForAsyncStartNotification.remove(animationToRemove); -} - -void AnimationControllerPrivate::startTimeResponse(double time) -{ - // Go through list of waiters and send them on their way - - WaitingAnimationsSet::const_iterator it = m_animationsWaitingForStartTimeResponse.begin(); - WaitingAnimationsSet::const_iterator end = m_animationsWaitingForStartTimeResponse.end(); - for (; it != end; ++it) - (*it)->onAnimationStartResponse(time); - - m_animationsWaitingForStartTimeResponse.clear(); - m_animationsWaitingForAsyncStartNotification.clear(); -} - -void AnimationControllerPrivate::animationWillBeRemoved(AnimationBase* animation) -{ - removeFromAnimationsWaitingForStyle(animation); - removeFromAnimationsWaitingForStartTimeResponse(animation); -} - -AnimationController::AnimationController(Frame* frame) - : m_data(adoptPtr(new AnimationControllerPrivate(frame))) - , m_beginAnimationUpdateCount(0) -{ -} - -AnimationController::~AnimationController() -{ -} - -void AnimationController::cancelAnimations(RenderObject* renderer) -{ - if (!m_data->hasAnimations()) - return; - - if (m_data->clear(renderer)) { - if (Node* node = renderer->node()) - node->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer); - } -} - -PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject& renderer, RenderStyle& newStyle) -{ - RenderStyle* oldStyle = renderer.style(); - - if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle.animations() && !newStyle.transitions())) - return PassRefPtr<RenderStyle>(newStyle); - - // Don't run transitions when printing. - if (renderer.view()->document().printing()) - return PassRefPtr<RenderStyle>(newStyle); - - // Fetch our current set of implicit animations from a hashtable. We then compare them - // against the animations in the style and make sure we're in sync. If destination values - // have changed, we reset the animation. We then do a blend to get new values and we return - // a new style. - - // We don't support anonymous pseudo elements like :first-line or :first-letter. - ASSERT(renderer.node()); - - RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer); - RefPtr<RenderStyle> blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle); - - if (renderer.parent() || newStyle.animations() || (oldStyle && oldStyle->animations())) { - m_data->scheduleServiceForRenderer(renderer); - } - - if (blendedStyle != &newStyle) { - // If the animations/transitions change opacity or transform, we need to update - // the style to impose the stacking rules. Note that this is also - // done in StyleResolver::adjustRenderStyle(). - if (blendedStyle->hasAutoZIndex() && (blendedStyle->opacity() < 1.0f || blendedStyle->hasTransform())) - blendedStyle->setZIndex(0); - } - return blendedStyle.release(); -} - -PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderObject* renderer) -{ - return m_data->getAnimatedStyleForRenderer(renderer); -} - -void AnimationController::notifyAnimationStarted(RenderObject*, double startTime) -{ - m_data->receivedStartTimeResponse(startTime); -} - -void AnimationController::pauseAnimationsForTesting(double t) -{ - m_data->pauseAnimationsForTesting(t); -} - -unsigned AnimationController::numberOfActiveAnimations(Document* document) const -{ - return m_data->numberOfActiveAnimations(document); -} - -bool AnimationController::isRunningAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - return m_data->isRunningAnimationOnRenderer(renderer, property, isRunningNow); -} - -bool AnimationController::isRunningAcceleratableAnimationOnRenderer(RenderObject* renderer) const -{ - return m_data->isRunningAcceleratableAnimationOnRenderer(renderer); -} - -bool AnimationController::isRunningAcceleratedAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const -{ - return m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, isRunningNow); -} - -void AnimationController::serviceAnimations() -{ - m_data->serviceAnimations(); -} - -void AnimationController::beginAnimationUpdate() -{ - if (!m_beginAnimationUpdateCount) - m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); - ++m_beginAnimationUpdateCount; -} - -void AnimationController::endAnimationUpdate() -{ - ASSERT(m_beginAnimationUpdateCount > 0); - --m_beginAnimationUpdateCount; - if (!m_beginAnimationUpdateCount) - m_data->endAnimationUpdate(); -} - -bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property) -{ - return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.h b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.h deleted file mode 100644 index 01cf32699ba..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationController.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AnimationController_h -#define AnimationController_h - -#include "CSSPropertyNames.h" -#include "wtf/Forward.h" -#include "wtf/OwnPtr.h" - -namespace WebCore { - -class AnimationBase; -class AnimationControllerPrivate; -class Document; -class Element; -class Frame; -class Node; -class RenderObject; -class RenderStyle; - -class AnimationController { -public: - AnimationController(Frame*); - ~AnimationController(); - - void cancelAnimations(RenderObject*); - PassRefPtr<RenderStyle> updateAnimations(RenderObject&, RenderStyle& newStyle); - PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderObject*); - - // This is called when an accelerated animation or transition has actually started to animate. - void notifyAnimationStarted(RenderObject*, double startTime); - - void pauseAnimationsForTesting(double t); - unsigned numberOfActiveAnimations(Document*) const; // To be used only for testing - - bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const; - bool isRunningAcceleratableAnimationOnRenderer(RenderObject*) const; - bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const; - - void serviceAnimations(); - - void beginAnimationUpdate(); - void endAnimationUpdate(); - - static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID); - -private: - OwnPtr<AnimationControllerPrivate> m_data; - int m_beginAnimationUpdateCount; -}; - -class AnimationUpdateBlock { -public: - explicit AnimationUpdateBlock(AnimationController* animationController) - : m_animationController(animationController) - { - if (m_animationController) - m_animationController->beginAnimationUpdate(); - } - - explicit AnimationUpdateBlock(AnimationController& animationController) - : m_animationController(&animationController) - { - m_animationController->beginAnimationUpdate(); - } - - ~AnimationUpdateBlock() - { - if (m_animationController) - m_animationController->endAnimationUpdate(); - } - - AnimationController* m_animationController; -}; - -} // namespace WebCore - -#endif // AnimationController_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationControllerPrivate.h b/chromium/third_party/WebKit/Source/core/frame/animation/AnimationControllerPrivate.h deleted file mode 100644 index 671ec89b573..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/AnimationControllerPrivate.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef AnimationControllerPrivate_h -#define AnimationControllerPrivate_h - -#include "CSSPropertyNames.h" -#include "platform/Timer.h" -#include "wtf/HashMap.h" -#include "wtf/HashSet.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefPtr.h" -#include "wtf/Vector.h" -#include "wtf/text/AtomicString.h" -#include "wtf/text/WTFString.h" - -namespace WebCore { - -class AnimationBase; -class CompositeAnimation; -class Document; -class Element; -class Frame; -class Node; -class RenderObject; -class RenderStyle; - -enum SetNeedsStyleRecalc { - DoNotCallSetNeedsStyleRecalc = 0, - CallSetNeedsStyleRecalc = 1 -}; - -class AnimationControllerPrivate { - WTF_MAKE_NONCOPYABLE(AnimationControllerPrivate); WTF_MAKE_FAST_ALLOCATED; -public: - AnimationControllerPrivate(Frame*); - ~AnimationControllerPrivate(); - - void updateAnimations(double& timeToNextService, double& timeToNextEvent, SetNeedsStyleRecalc callSetNeedsStyleRecalc = DoNotCallSetNeedsStyleRecalc); - void scheduleService(); - - PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject&); - bool clear(RenderObject*); - - void updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*); - void startUpdateStyleIfNeededDispatcher(); - void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime); - void addNodeChangeToDispatch(PassRefPtr<Node>); - - bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); } - - void serviceAnimations(); - - bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const; - bool isRunningAcceleratableAnimationOnRenderer(RenderObject*) const; - bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow) const; - - void pauseAnimationsForTesting(double t); - unsigned numberOfActiveAnimations(Document*) const; - - PassRefPtr<RenderStyle> getAnimatedStyleForRenderer(RenderObject* renderer); - - double beginAnimationUpdateTime(); - void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; } - void endAnimationUpdate(); - void receivedStartTimeResponse(double); - - void addToAnimationsWaitingForStyle(AnimationBase*); - void removeFromAnimationsWaitingForStyle(AnimationBase*); - - void addToAnimationsWaitingForStartTimeResponse(AnimationBase*, bool willGetResponse); - void removeFromAnimationsWaitingForStartTimeResponse(AnimationBase*); - - void animationWillBeRemoved(AnimationBase*); - - void scheduleServiceForRenderer(RenderObject&); - -private: - void animationTimerFired(Timer<AnimationControllerPrivate>*); - - void scheduleService(double timeToNextService, double timeToNextEvent); - - void styleAvailable(); - void fireEventsAndUpdateStyle(); - void startTimeResponse(double t); - - typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap; - - RenderObjectAnimationMap m_compositeAnimations; - Timer<AnimationControllerPrivate> m_animationTimer; - Timer<AnimationControllerPrivate> m_updateStyleIfNeededDispatcher; - Frame* m_frame; - - class EventToDispatch { - public: - RefPtr<Element> element; - AtomicString eventType; - String name; - double elapsedTime; - }; - - Vector<EventToDispatch> m_eventsToDispatch; - Vector<RefPtr<Node> > m_nodeChangesToDispatch; - - double m_beginAnimationUpdateTime; - - typedef HashSet<RefPtr<AnimationBase> > WaitingAnimationsSet; - WaitingAnimationsSet m_animationsWaitingForStyle; - WaitingAnimationsSet m_animationsWaitingForStartTimeResponse; - WaitingAnimationsSet m_animationsWaitingForAsyncStartNotification; -}; - -} // namespace WebCore - -#endif // AnimationControllerPrivate_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.cpp deleted file mode 100644 index 4d07ebf1e86..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/CSSPropertyAnimation.h" - -#include <algorithm> -#include "StylePropertyShorthand.h" -#include "core/animation/css/CSSAnimations.h" -#include "core/css/CSSCrossfadeValue.h" -#include "core/css/CSSImageValue.h" -#include "core/css/CSSPrimitiveValue.h" -#include "core/fetch/ImageResource.h" -#include "core/frame/animation/AnimationBase.h" -#include "core/rendering/ClipPathOperation.h" -#include "core/rendering/RenderBox.h" -#include "core/rendering/style/RenderStyle.h" -#include "core/rendering/style/ShadowList.h" -#include "core/rendering/style/StyleFetchedImage.h" -#include "core/rendering/style/StyleGeneratedImage.h" -#include "platform/FloatConversion.h" -#include "wtf/Noncopyable.h" - -namespace WebCore { - -template <typename T> -static inline T blendFunc(const AnimationBase*, T from, T to, double progress) -{ - return blend(from, to, progress); -} - -static inline float blendFunc(const AnimationBase*, float from, float to, double progress) -{ - return narrowPrecisionToFloat(from + (to - from) * progress); -} - -static inline Color blendFunc(const AnimationBase*, const Color& from, const Color& to, double progress) -{ - return blend(from, to, progress); -} - -static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress) -{ - return to.blend(from, progress, ValueRangeAll); -} - -static inline BorderImageLength blendFunc(const AnimationBase* anim, const BorderImageLength& from, const BorderImageLength& to, double progress) -{ - if (from.isNumber() && to.isNumber()) - return BorderImageLength(blendFunc(anim, from.number(), to.number(), progress)); - - if (from.isLength() && to.isLength()) - return BorderImageLength(blendFunc(anim, from.length(), to.length(), progress)); - - // FIXME: Converting numbers to lengths using the computed border - // width would make it possible to interpolate between numbers and - // lengths. - // https://code.google.com/p/chromium/issues/detail?id=316164 - return to; -} - -static inline BorderImageLengthBox blendFunc(const AnimationBase* anim, const BorderImageLengthBox& from, - const BorderImageLengthBox& to, double progress) -{ - return BorderImageLengthBox(blendFunc(anim, from.top(), to.top(), progress), - blendFunc(anim, from.right(), to.right(), progress), - blendFunc(anim, from.bottom(), to.bottom(), progress), - blendFunc(anim, from.left(), to.left(), progress)); -} - -static inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress) -{ - return LengthSize(blendFunc(anim, from.width(), to.width(), progress), - blendFunc(anim, from.height(), to.height(), progress)); -} - -static inline LengthPoint blendFunc(const AnimationBase* anim, const LengthPoint& from, const LengthPoint& to, double progress) -{ - return LengthPoint(blendFunc(anim, from.x(), to.x(), progress), blendFunc(anim, from.y(), to.y(), progress)); -} - -static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress) -{ - if (anim->isTransformFunctionListValid()) - return to.blendByMatchingOperations(from, progress); - return to.blendByUsingMatrixInterpolation(from, progress); -} - -static inline PassRefPtr<ClipPathOperation> blendFunc(const AnimationBase*, ClipPathOperation* from, ClipPathOperation* to, double progress) -{ - // Other clip-path operations than BasicShapes can not be animated. - if (!from || !to || from->type() != ClipPathOperation::SHAPE || to->type() != ClipPathOperation::SHAPE) - return to; - - const BasicShape* fromShape = toShapeClipPathOperation(from)->basicShape(); - const BasicShape* toShape = toShapeClipPathOperation(to)->basicShape(); - - if (!fromShape->canBlend(toShape)) - return to; - - return ShapeClipPathOperation::create(toShape->blend(fromShape, progress)); -} - -static inline PassRefPtr<ShapeValue> blendFunc(const AnimationBase*, ShapeValue* from, ShapeValue* to, double progress) -{ - // FIXME Bug 102723: Shape-inside should be able to animate a value of 'outside-shape' when shape-outside is set to a BasicShape - if (!from || !to || from->type() != ShapeValue::Shape || to->type() != ShapeValue::Shape) - return to; - - const BasicShape* fromShape = from->shape(); - const BasicShape* toShape = to->shape(); - - if (!fromShape->canBlend(toShape)) - return to; - - return ShapeValue::createShapeValue(toShape->blend(fromShape, progress)); -} - -static inline FilterOperations blendFunc(const AnimationBase* anim, const FilterOperations& from, const FilterOperations& to, double progress) -{ - FilterOperations result; - - // If we have a filter function list, use that to do a per-function animation. - if (anim->filterFunctionListsMatch()) { - size_t fromSize = from.operations().size(); - size_t toSize = to.operations().size(); - size_t size = max(fromSize, toSize); - for (size_t i = 0; i < size; i++) { - const FilterOperation* fromOp = (i < fromSize) ? from.operations()[i].get() : 0; - const FilterOperation* toOp = (i < toSize) ? to.operations()[i].get() : 0; - RefPtr<FilterOperation> blendedOp = FilterOperation::blend(fromOp, toOp, progress); - if (blendedOp) - result.operations().append(blendedOp); - else - ASSERT_NOT_REACHED(); - } - } else { - // If the filter function lists don't match, we could try to cross-fade, but don't yet have a way to represent that in CSS. - // For now we'll just fail to animate. - result = to; - } - - return result; -} - -static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, EVisibility to, double progress) -{ - // Any non-zero result means we consider the object to be visible. Only at 0 do we consider the object to be - // invisible. The invisible value we use (HIDDEN vs. COLLAPSE) depends on the specified from/to values. - double fromVal = from == VISIBLE ? 1. : 0.; - double toVal = to == VISIBLE ? 1. : 0.; - if (fromVal == toVal) - return to; - double result = blendFunc(anim, fromVal, toVal, progress); - return result > 0. ? VISIBLE : (to != VISIBLE ? to : from); -} - -static inline LengthBox blendFunc(const AnimationBase* anim, const LengthBox& from, const LengthBox& to, double progress) -{ - // Length types have to match to animate - if (from.top().type() != to.top().type() - || from.right().type() != to.right().type() - || from.bottom().type() != to.bottom().type() - || from.left().type() != to.left().type()) - return to; - - LengthBox result(blendFunc(anim, from.top(), to.top(), progress), - blendFunc(anim, from.right(), to.right(), progress), - blendFunc(anim, from.bottom(), to.bottom(), progress), - blendFunc(anim, from.left(), to.left(), progress)); - return result; -} - -static inline SVGLength blendFunc(const AnimationBase*, const SVGLength& from, const SVGLength& to, double progress) -{ - return to.blend(from, narrowPrecisionToFloat(progress)); -} - -static inline Vector<SVGLength> blendFunc(const AnimationBase*, const Vector<SVGLength>& from, const Vector<SVGLength>& to, double progress) -{ - size_t fromLength = from.size(); - size_t toLength = to.size(); - if (!fromLength) - return !progress ? from : to; - if (!toLength) - return progress == 1 ? from : to; - - size_t resultLength = fromLength; - if (fromLength != toLength) { - if (!(fromLength % toLength)) - resultLength = fromLength; - else if (!(toLength % fromLength)) - resultLength = toLength; - else - resultLength = fromLength * toLength; - } - Vector<SVGLength> result(resultLength); - for (size_t i = 0; i < resultLength; ++i) - result[i] = to[i % toLength].blend(from[i % fromLength], narrowPrecisionToFloat(progress)); - return result; -} - -static inline PassRefPtr<StyleImage> crossfadeBlend(const AnimationBase*, StyleFetchedImage* fromStyleImage, StyleFetchedImage* toStyleImage, double progress) -{ - // If progress is at one of the extremes, we want getComputedStyle to show the image, - // not a completed cross-fade, so we hand back one of the existing images. - if (!progress) - return fromStyleImage; - if (progress == 1) - return toStyleImage; - - ImageResource* fromImageResource = static_cast<ImageResource*>(fromStyleImage->data()); - ImageResource* toImageResource = static_cast<ImageResource*>(toStyleImage->data()); - - RefPtr<CSSImageValue> fromImageValue = CSSImageValue::create(fromImageResource->url(), fromStyleImage); - RefPtr<CSSImageValue> toImageValue = CSSImageValue::create(toImageResource->url(), toStyleImage); - RefPtr<CSSCrossfadeValue> crossfadeValue = CSSCrossfadeValue::create(fromImageValue, toImageValue); - - crossfadeValue->setPercentage(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER)); - - return StyleGeneratedImage::create(crossfadeValue.get()); -} - -static inline PassRefPtr<StyleImage> blendFunc(const AnimationBase* anim, StyleImage* from, StyleImage* to, double progress) -{ - if (!from || !to) - return to; - - if (from->isImageResource() && to->isImageResource()) - return crossfadeBlend(anim, toStyleFetchedImage(from), toStyleFetchedImage(to), progress); - - // FIXME: Support transitioning generated images as well. (gradients, etc.) - - return to; -} - -class AnimationPropertyWrapperBase { - WTF_MAKE_NONCOPYABLE(AnimationPropertyWrapperBase); - WTF_MAKE_FAST_ALLOCATED; -public: - AnimationPropertyWrapperBase(CSSPropertyID prop) - : m_prop(prop) - { - } - - virtual ~AnimationPropertyWrapperBase() { } - - virtual bool isShorthandWrapper() const { return false; } - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0; - virtual void blend(const AnimationBase*, RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0; - - CSSPropertyID property() const { return m_prop; } - - virtual bool animationIsAccelerated() const { return false; } - -private: - CSSPropertyID m_prop; -}; - -static int gPropertyWrapperMap[numCSSProperties]; -static const int cInvalidPropertyWrapperIndex = -1; -static Vector<AnimationPropertyWrapperBase*>* gPropertyWrappers = 0; - -static void addPropertyWrapper(CSSPropertyID propertyID, AnimationPropertyWrapperBase* wrapper) -{ - int propIndex = propertyID - firstCSSProperty; - - ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex); - - unsigned wrapperIndex = gPropertyWrappers->size(); - gPropertyWrappers->append(wrapper); - gPropertyWrapperMap[propIndex] = wrapperIndex; -} - -static AnimationPropertyWrapperBase* wrapperForProperty(CSSPropertyID propertyID) -{ - int propIndex = propertyID - firstCSSProperty; - if (propIndex >= 0 && propIndex < numCSSProperties) { - int wrapperIndex = gPropertyWrapperMap[propIndex]; - if (wrapperIndex >= 0) - return (*gPropertyWrappers)[wrapperIndex]; - } - return 0; -} - -template <typename T> -class PropertyWrapperGetter : public AnimationPropertyWrapperBase { -public: - PropertyWrapperGetter(CSSPropertyID prop, T (RenderStyle::*getter)() const) - : AnimationPropertyWrapperBase(prop) - , m_getter(getter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if ((!a && !b) || a == b) - return true; - if (!a || !b) - return false; - return (a->*m_getter)() == (b->*m_getter)(); - } - -protected: - T (RenderStyle::*m_getter)() const; -}; - -template <typename T> -class PropertyWrapper : public PropertyWrapperGetter<T> { -public: - PropertyWrapper(CSSPropertyID prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T)) - : PropertyWrapperGetter<T>(prop, getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), progress)); - } - -protected: - void (RenderStyle::*m_setter)(T); -}; - -class NonNegativeLengthWrapper : public PropertyWrapper<Length> { -public: - NonNegativeLengthWrapper(CSSPropertyID prop, Length (RenderStyle::*getter)() const, void (RenderStyle::*setter)(Length)) - : PropertyWrapper<Length>(prop, getter, setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - Length from = (a->*PropertyWrapperGetter<Length>::m_getter)(); - Length to = (b->*PropertyWrapperGetter<Length>::m_getter)(); - (dst->*PropertyWrapper<Length>::m_setter)(to.blend(from, progress, ValueRangeNonNegative)); - } -}; - -template <typename T> -class RefCountedPropertyWrapper : public PropertyWrapperGetter<T*> { -public: - RefCountedPropertyWrapper(CSSPropertyID prop, T* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<T>)) - : PropertyWrapperGetter<T*>(prop, getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T*>::m_getter)(), (b->*PropertyWrapperGetter<T*>::m_getter)(), progress)); - } - -protected: - void (RenderStyle::*m_setter)(PassRefPtr<T>); -}; - - -class PropertyWrapperClipPath : public RefCountedPropertyWrapper<ClipPathOperation> { -public: - PropertyWrapperClipPath(CSSPropertyID prop, ClipPathOperation* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ClipPathOperation>)) - : RefCountedPropertyWrapper<ClipPathOperation>(prop, getter, setter) - { - } -}; - -class PropertyWrapperShape : public RefCountedPropertyWrapper<ShapeValue> { -public: - PropertyWrapperShape(CSSPropertyID prop, ShapeValue* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShapeValue>)) - : RefCountedPropertyWrapper<ShapeValue>(prop, getter, setter) - { - } -}; - -class StyleImagePropertyWrapper : public RefCountedPropertyWrapper<StyleImage> { -public: - StyleImagePropertyWrapper(CSSPropertyID prop, StyleImage* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<StyleImage>)) - : RefCountedPropertyWrapper<StyleImage>(prop, getter, setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if (a == b) - return true; - if (!a || !b) - return false; - - StyleImage* imageA = (a->*m_getter)(); - StyleImage* imageB = (b->*m_getter)(); - return StyleImage::imagesEquivalent(imageA, imageB); - } -}; - -class PropertyWrapperColor : public PropertyWrapperGetter<Color> { -public: - PropertyWrapperColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) - : PropertyWrapperGetter<Color>(prop, getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<Color>::m_getter)(), (b->*PropertyWrapperGetter<Color>::m_getter)(), progress)); - } - -protected: - void (RenderStyle::*m_setter)(const Color&); -}; - -class PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> { -public: - PropertyWrapperAcceleratedOpacity() - : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity) - { - } - - virtual bool animationIsAccelerated() const { return true; } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - float fromOpacity = a->opacity(); - - // This makes sure we put the object being animated into a RenderLayer during the animation - dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress)); - } -}; - -class PropertyWrapperAcceleratedTransform : public PropertyWrapper<const TransformOperations&> { -public: - PropertyWrapperAcceleratedTransform() - : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform) - { - } - - virtual bool animationIsAccelerated() const { return true; } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress)); - } -}; - -class PropertyWrapperAcceleratedFilter : public PropertyWrapper<const FilterOperations&> { -public: - PropertyWrapperAcceleratedFilter() - : PropertyWrapper<const FilterOperations&>(CSSPropertyWebkitFilter, &RenderStyle::filter, &RenderStyle::setFilter) - { - } - - virtual bool animationIsAccelerated() const { return true; } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - dst->setFilter(blendFunc(anim, a->filter(), b->filter(), progress)); - } -}; - -class PropertyWrapperShadow : public AnimationPropertyWrapperBase { -public: - PropertyWrapperShadow(CSSPropertyID prop, ShadowList* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShadowList>)) - : AnimationPropertyWrapperBase(prop) - , m_getter(getter) - , m_setter(setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - const ShadowList* shadowA = (a->*m_getter)(); - const ShadowList* shadowB = (b->*m_getter)(); - if (shadowA == shadowB) - return true; - if (shadowA && shadowB) - return *shadowA == *shadowB; - return false; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - (dst->*m_setter)(ShadowList::blend((a->*m_getter)(), (b->*m_getter)(), progress)); - } - - ShadowList* (RenderStyle::*m_getter)() const; - void (RenderStyle::*m_setter)(PassRefPtr<ShadowList>); -}; - -class PropertyWrapperMaybeInvalidColor : public AnimationPropertyWrapperBase { -public: - PropertyWrapperMaybeInvalidColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_getter(getter) - , m_setter(setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return true; - - if (!fromColor.isValid()) - fromColor = a->color(); - if (!toColor.isValid()) - toColor = b->color(); - - return fromColor == toColor; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return; - - if (!fromColor.isValid()) - fromColor = a->color(); - if (!toColor.isValid()) - toColor = b->color(); - (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress)); - } - -private: - Color (RenderStyle::*m_getter)() const; - void (RenderStyle::*m_setter)(const Color&); -}; - - -enum MaybeInvalidColorTag { MaybeInvalidColor }; -class PropertyWrapperVisitedAffectedColor : public AnimationPropertyWrapperBase { -public: - PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), - Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_wrapper(adoptPtr(new PropertyWrapperColor(prop, getter, setter))) - , m_visitedWrapper(adoptPtr(new PropertyWrapperColor(prop, visitedGetter, visitedSetter))) - { - } - PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, MaybeInvalidColorTag, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), - Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_wrapper(adoptPtr(new PropertyWrapperMaybeInvalidColor(prop, getter, setter))) - , m_visitedWrapper(adoptPtr(new PropertyWrapperMaybeInvalidColor(prop, visitedGetter, visitedSetter))) - { - } - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - return m_wrapper->equals(a, b) && m_visitedWrapper->equals(a, b); - } - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - m_wrapper->blend(anim, dst, a, b, progress); - m_visitedWrapper->blend(anim, dst, a, b, progress); - } - -private: - OwnPtr<AnimationPropertyWrapperBase> m_wrapper; - OwnPtr<AnimationPropertyWrapperBase> m_visitedWrapper; -}; - -// Wrapper base class for an animatable property in a FillLayer -class FillLayerAnimationPropertyWrapperBase { -public: - FillLayerAnimationPropertyWrapperBase() - { - } - - virtual ~FillLayerAnimationPropertyWrapperBase() { } - - virtual bool equals(const FillLayer*, const FillLayer*) const = 0; - virtual void blend(const AnimationBase*, FillLayer*, const FillLayer*, const FillLayer*, double) const = 0; -}; - -template <typename T> -class FillLayerPropertyWrapperGetter : public FillLayerAnimationPropertyWrapperBase { - WTF_MAKE_NONCOPYABLE(FillLayerPropertyWrapperGetter); -public: - FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const) - : m_getter(getter) - { - } - - virtual bool equals(const FillLayer* a, const FillLayer* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if ((!a && !b) || a == b) - return true; - if (!a || !b) - return false; - return (a->*m_getter)() == (b->*m_getter)(); - } - -protected: - T (FillLayer::*m_getter)() const; -}; - -template <typename T> -class FillLayerPropertyWrapper : public FillLayerPropertyWrapperGetter<T> { -public: - FillLayerPropertyWrapper(T (FillLayer::*getter)() const, void (FillLayer::*setter)(T)) - : FillLayerPropertyWrapperGetter<T>(getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T>::m_getter)(), progress)); - } - -protected: - void (FillLayer::*m_setter)(T); -}; - -template <typename T> -class FillLayerRefCountedPropertyWrapper : public FillLayerPropertyWrapperGetter<T*> { -public: - FillLayerRefCountedPropertyWrapper(T* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<T>)) - : FillLayerPropertyWrapperGetter<T*>(getter) - , m_setter(setter) - { - } - - virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const - { - (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), progress)); - } - -protected: - void (FillLayer::*m_setter)(PassRefPtr<T>); -}; - -class FillLayerStyleImagePropertyWrapper : public FillLayerRefCountedPropertyWrapper<StyleImage> { -public: - FillLayerStyleImagePropertyWrapper(StyleImage* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<StyleImage>)) - : FillLayerRefCountedPropertyWrapper<StyleImage>(getter, setter) - { - } - - virtual bool equals(const FillLayer* a, const FillLayer* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if (a == b) - return true; - if (!a || !b) - return false; - - StyleImage* imageA = (a->*m_getter)(); - StyleImage* imageB = (b->*m_getter)(); - return StyleImage::imagesEquivalent(imageA, imageB); - } -}; - - -class FillLayersPropertyWrapper : public AnimationPropertyWrapperBase { -public: - typedef const FillLayer* (RenderStyle::*LayersGetter)() const; - typedef FillLayer* (RenderStyle::*LayersAccessor)(); - - FillLayersPropertyWrapper(CSSPropertyID prop, LayersGetter getter, LayersAccessor accessor) - : AnimationPropertyWrapperBase(prop) - , m_layersGetter(getter) - , m_layersAccessor(accessor) - { - switch (prop) { - case CSSPropertyBackgroundPositionX: - case CSSPropertyWebkitMaskPositionX: - m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::xPosition, &FillLayer::setXPosition); - break; - case CSSPropertyBackgroundPositionY: - case CSSPropertyWebkitMaskPositionY: - m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::yPosition, &FillLayer::setYPosition); - break; - case CSSPropertyBackgroundSize: - case CSSPropertyWebkitBackgroundSize: - case CSSPropertyWebkitMaskSize: - m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<LengthSize>(&FillLayer::sizeLength, &FillLayer::setSizeLength); - break; - case CSSPropertyBackgroundImage: - m_fillLayerPropertyWrapper = new FillLayerStyleImagePropertyWrapper(&FillLayer::image, &FillLayer::setImage); - break; - default: - break; - } - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - const FillLayer* fromLayer = (a->*m_layersGetter)(); - const FillLayer* toLayer = (b->*m_layersGetter)(); - - while (fromLayer && toLayer) { - if (!m_fillLayerPropertyWrapper->equals(fromLayer, toLayer)) - return false; - - fromLayer = fromLayer->next(); - toLayer = toLayer->next(); - } - - return true; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - const FillLayer* aLayer = (a->*m_layersGetter)(); - const FillLayer* bLayer = (b->*m_layersGetter)(); - FillLayer* dstLayer = (dst->*m_layersAccessor)(); - - while (aLayer && bLayer && dstLayer) { - m_fillLayerPropertyWrapper->blend(anim, dstLayer, aLayer, bLayer, progress); - aLayer = aLayer->next(); - bLayer = bLayer->next(); - dstLayer = dstLayer->next(); - } - } - -private: - FillLayerAnimationPropertyWrapperBase* m_fillLayerPropertyWrapper; - - LayersGetter m_layersGetter; - LayersAccessor m_layersAccessor; -}; - -class ShorthandPropertyWrapper : public AnimationPropertyWrapperBase { -public: - ShorthandPropertyWrapper(CSSPropertyID property, const StylePropertyShorthand& shorthand) - : AnimationPropertyWrapperBase(property) - { - for (unsigned i = 0; i < shorthand.length(); ++i) { - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(shorthand.properties()[i]); - if (wrapper) - m_propertyWrappers.append(wrapper); - } - } - - virtual bool isShorthandWrapper() const { return true; } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); - for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) { - if (!(*it)->equals(a, b)) - return false; - } - return true; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); - for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) - (*it)->blend(anim, dst, a, b, progress); - } - - const Vector<AnimationPropertyWrapperBase*> propertyWrappers() const { return m_propertyWrappers; } - -private: - Vector<AnimationPropertyWrapperBase*> m_propertyWrappers; -}; - -class PropertyWrapperFlex : public AnimationPropertyWrapperBase { -public: - PropertyWrapperFlex() - : AnimationPropertyWrapperBase(CSSPropertyFlex) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - // If the style pointers are the same, don't bother doing the test. - // If either is null, return false. If both are null, return true. - if ((!a && !b) || a == b) - return true; - if (!a || !b) - return false; - - return a->flexBasis() == b->flexBasis() && a->flexGrow() == b->flexGrow() && a->flexShrink() == b->flexShrink(); - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - dst->setFlexBasis(blendFunc(anim, a->flexBasis(), b->flexBasis(), progress)); - dst->setFlexGrow(blendFunc(anim, a->flexGrow(), b->flexGrow(), progress)); - dst->setFlexShrink(blendFunc(anim, a->flexShrink(), b->flexShrink(), progress)); - } -}; - -class PropertyWrapperSVGPaint : public AnimationPropertyWrapperBase { -public: - PropertyWrapperSVGPaint(CSSPropertyID prop, const SVGPaint::SVGPaintType& (RenderStyle::*paintTypeGetter)() const, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) - : AnimationPropertyWrapperBase(prop) - , m_paintTypeGetter(paintTypeGetter) - , m_getter(getter) - , m_setter(setter) - { - } - - virtual bool equals(const RenderStyle* a, const RenderStyle* b) const - { - if ((a->*m_paintTypeGetter)() != (b->*m_paintTypeGetter)()) - return false; - - // We only support animations between SVGPaints that are pure Color values. - // For everything else we must return true for this method, otherwise - // we will try to animate between values forever. - if ((a->*m_paintTypeGetter)() == SVGPaint::SVG_PAINTTYPE_RGBCOLOR) { - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return true; - - if (!fromColor.isValid()) - fromColor = Color(); - if (!toColor.isValid()) - toColor = Color(); - - return fromColor == toColor; - } - return true; - } - - virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const - { - if ((a->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR - || (b->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR) - return; - - Color fromColor = (a->*m_getter)(); - Color toColor = (b->*m_getter)(); - - if (!fromColor.isValid() && !toColor.isValid()) - return; - - if (!fromColor.isValid()) - fromColor = Color(); - if (!toColor.isValid()) - toColor = Color(); - (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress)); - } - -private: - const SVGPaint::SVGPaintType& (RenderStyle::*m_paintTypeGetter)() const; - Color (RenderStyle::*m_getter)() const; - void (RenderStyle::*m_setter)(const Color&); -}; - -static void addShorthandProperties() -{ - static const CSSPropertyID animatableShorthandProperties[] = { - CSSPropertyBackground, // for background-color, background-position, background-image - CSSPropertyBackgroundPosition, - CSSPropertyFont, // for font-size, font-weight - CSSPropertyWebkitMask, // for mask-position - CSSPropertyWebkitMaskPosition, - CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft, - CSSPropertyBorderColor, - CSSPropertyBorderRadius, - CSSPropertyBorderWidth, - CSSPropertyBorder, - CSSPropertyBorderImage, - CSSPropertyBorderSpacing, - CSSPropertyListStyle, // for list-style-image - CSSPropertyMargin, - CSSPropertyOutline, - CSSPropertyPadding, - CSSPropertyWebkitTextStroke, - CSSPropertyWebkitColumnRule, - CSSPropertyWebkitBorderRadius, - CSSPropertyWebkitTransformOrigin - }; - - for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableShorthandProperties); ++i) { - CSSPropertyID propertyID = animatableShorthandProperties[i]; - StylePropertyShorthand shorthand = shorthandForProperty(propertyID); - if (shorthand.length() > 0) - addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, shorthand)); - } -} - -void CSSPropertyAnimation::ensurePropertyMap() -{ - // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed? - if (gPropertyWrappers) - return; - - gPropertyWrappers = new Vector<AnimationPropertyWrapperBase*>(); - - // build the list of property wrappers to do the comparisons and blends - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom)); - - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth)); - - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight)); - - if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) - gPropertyWrappers->append(new PropertyWrapperFlex()); - - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth)); - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth)); - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth)); - gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor, &RenderStyle::visitedLinkColor, &RenderStyle::setVisitedLinkColor)); - - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor, &RenderStyle::visitedLinkBackgroundColor, &RenderStyle::setVisitedLinkBackgroundColor)); - - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundImage, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyListStyleImage, &RenderStyle::listStyleImage, &RenderStyle::setListStyleImage)); - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskImage, &RenderStyle::maskImage, &RenderStyle::setMaskImage)); - - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource)); - gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyBorderImageSlice, &RenderStyle::borderImageSlices, &RenderStyle::setBorderImageSlices)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageWidth, &RenderStyle::borderImageWidth, &RenderStyle::setBorderImageWidth)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageOutset, &RenderStyle::borderImageOutset, &RenderStyle::setBorderImageOutset)); - - gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource)); - gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyWebkitMaskBoxImageSlice, &RenderStyle::maskBoxImageSlices, &RenderStyle::setMaskBoxImageSlices)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageWidth, &RenderStyle::maskBoxImageWidth, &RenderStyle::setMaskBoxImageWidth)); - gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageOutset, &RenderStyle::maskBoxImageOutset, &RenderStyle::setMaskBoxImageOutset)); - - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); - - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionX, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); - gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskSize, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); - - gPropertyWrappers->append(new PropertyWrapper<LengthPoint>(CSSPropertyObjectPosition, &RenderStyle::objectPosition, &RenderStyle::setObjectPosition)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFontSize, - // Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size - // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same). - // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to - // enable text zoom rather than Text Autosizing? See http://crbug.com/227545. - &RenderStyle::specifiedFontSize, - &RenderStyle::setFontSize)); - gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap)); - gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing)); - gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyOrphans, &RenderStyle::orphans, &RenderStyle::setOrphans)); - gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWidows, &RenderStyle::widows, &RenderStyle::setWidows)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight)); - gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset)); - gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius)); - gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius)); - gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoomWithoutReturnValue)); - - gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip)); - - gPropertyWrappers->append(new PropertyWrapperAcceleratedOpacity()); - gPropertyWrappers->append(new PropertyWrapperAcceleratedTransform()); - gPropertyWrappers->append(new PropertyWrapperAcceleratedFilter()); - - gPropertyWrappers->append(new PropertyWrapperClipPath(CSSPropertyWebkitClipPath, &RenderStyle::clipPath, &RenderStyle::setClipPath)); - - gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeInside, &RenderStyle::shapeInside, &RenderStyle::setShapeInside)); - gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeOutside, &RenderStyle::shapeOutside, &RenderStyle::setShapeOutside)); - gPropertyWrappers->append(new NonNegativeLengthWrapper(CSSPropertyShapeMargin, &RenderStyle::shapeMargin, &RenderStyle::setShapeMargin)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyShapeImageThreshold, &RenderStyle::shapeImageThreshold, &RenderStyle::setShapeImageThreshold)); - - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitColumnRuleColor, MaybeInvalidColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::visitedLinkColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitTextStrokeColor, MaybeInvalidColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor, &RenderStyle::visitedLinkTextStrokeColor, &RenderStyle::setVisitedLinkTextStrokeColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderLeftColor, MaybeInvalidColor, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor, &RenderStyle::visitedLinkBorderLeftColor, &RenderStyle::setVisitedLinkBorderLeftColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderRightColor, MaybeInvalidColor, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor, &RenderStyle::visitedLinkBorderRightColor, &RenderStyle::setVisitedLinkBorderRightColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderTopColor, MaybeInvalidColor, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor, &RenderStyle::visitedLinkBorderTopColor, &RenderStyle::setVisitedLinkBorderTopColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderBottomColor, MaybeInvalidColor, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor, &RenderStyle::visitedLinkBorderBottomColor, &RenderStyle::setVisitedLinkBorderBottomColor)); - gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyOutlineColor, MaybeInvalidColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor, &RenderStyle::visitedLinkOutlineColor, &RenderStyle::setVisitedLinkOutlineColor)); - - gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); - gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); - gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow)); - - gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyFill, &RenderStyle::fillPaintType, &RenderStyle::fillPaintColor, &RenderStyle::setFillPaintColor)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFillOpacity, &RenderStyle::fillOpacity, &RenderStyle::setFillOpacity)); - - gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyStroke, &RenderStyle::strokePaintType, &RenderStyle::strokePaintColor, &RenderStyle::setStrokePaintColor)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity)); - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth)); - gPropertyWrappers->append(new PropertyWrapper< Vector<SVGLength> >(CSSPropertyStrokeDasharray, &RenderStyle::strokeDashArray, &RenderStyle::setStrokeDashArray)); - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeMiterlimit, &RenderStyle::strokeMiterLimit, &RenderStyle::setStrokeMiterLimit)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity)); - gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyFloodColor, &RenderStyle::floodColor, &RenderStyle::setFloodColor)); - - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStopOpacity, &RenderStyle::stopOpacity, &RenderStyle::setStopOpacity)); - gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyStopColor, &RenderStyle::stopColor, &RenderStyle::setStopColor)); - - gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyLightingColor, &RenderStyle::lightingColor, &RenderStyle::setLightingColor)); - - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyBaselineShift, &RenderStyle::baselineShiftValue, &RenderStyle::setBaselineShiftValue)); - gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyKerning, &RenderStyle::kerning, &RenderStyle::setKerning)); - - if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()) { - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexGrow, &RenderStyle::flexGrow, &RenderStyle::setFlexGrow)); - gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexShrink, &RenderStyle::flexShrink, &RenderStyle::setFlexShrink)); - gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyFlexBasis, &RenderStyle::flexBasis, &RenderStyle::setFlexBasis)); - } - - // TODO: - // - // CSSPropertyVerticalAlign - // - // Compound properties that have components that should be animatable: - // - // CSSPropertyWebkitColumns - // CSSPropertyWebkitBoxReflect - - // Make sure unused slots have a value - for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i) - gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex; - - // First we put the non-shorthand property wrappers into the map, so the shorthand-building - // code can find them. - size_t n = gPropertyWrappers->size(); - for (unsigned int i = 0; i < n; ++i) { - CSSPropertyID property = (*gPropertyWrappers)[i]->property(); - ASSERT_WITH_MESSAGE(RuntimeEnabledFeatures::webAnimationsCSSEnabled() || CSSAnimations::isAnimatableProperty(property), "%s is not whitelisted for animation", getPropertyNameString(property).utf8().data()); - ASSERT(property - firstCSSProperty < numCSSProperties); - gPropertyWrapperMap[property - firstCSSProperty] = i; - } - - // Now add the shorthand wrappers. - addShorthandProperties(); -} - -// Returns true if we need to start animation timers -bool CSSPropertyAnimation::blendProperties(const AnimationBase* anim, CSSPropertyID prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) -{ - ASSERT(prop != CSSPropertyInvalid); - - ensurePropertyMap(); - - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); - if (wrapper) { - wrapper->blend(anim, dst, a, b, progress); - return !wrapper->animationIsAccelerated() || !anim->isAccelerated(); - } - - return false; -} - -bool CSSPropertyAnimation::animationOfPropertyIsAccelerated(CSSPropertyID prop) -{ - ensurePropertyMap(); - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); - return wrapper ? wrapper->animationIsAccelerated() : false; -} - -bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID prop, const RenderStyle* a, const RenderStyle* b) -{ - ensurePropertyMap(); - - AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); - if (wrapper) - return wrapper->equals(a, b); - return true; -} - -CSSPropertyID CSSPropertyAnimation::getPropertyAtIndex(int i, bool& isShorthand) -{ - ensurePropertyMap(); - - if (i < 0 || i >= getNumProperties()) - return CSSPropertyInvalid; - - AnimationPropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; - isShorthand = wrapper->isShorthandWrapper(); - return wrapper->property(); -} - -int CSSPropertyAnimation::getNumProperties() -{ - ensurePropertyMap(); - - return gPropertyWrappers->size(); -} - -} diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.h deleted file mode 100644 index 6ffd75c1a83..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CSSPropertyAnimation.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CSSPropertyAnimation_h -#define CSSPropertyAnimation_h - -#include "CSSPropertyNames.h" - -namespace WebCore { - -class AnimationBase; -class RenderStyle; - -class CSSPropertyAnimation { -public: - static bool animationOfPropertyIsAccelerated(CSSPropertyID); - static bool propertiesEqual(CSSPropertyID, const RenderStyle* a, const RenderStyle* b); - static CSSPropertyID getPropertyAtIndex(int, bool& isShorthand); - static int getNumProperties(); - - // Return true if we need to start software animation timers - static bool blendProperties(const AnimationBase*, CSSPropertyID, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress); -private: - static void ensurePropertyMap(); -}; - -} // namespace WebCore - -#endif // CSSPropertyAnimation_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.cpp deleted file mode 100644 index f20f6856683..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.cpp +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/CompositeAnimation.h" - -#include "CSSPropertyNames.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/rendering/style/RenderStyle.h" - -namespace WebCore { - -CompositeAnimation::~CompositeAnimation() -{ - // Toss the refs to all animations, but make sure we remove them from - // any waiting lists first. - - clearRenderer(); - m_transitions.clear(); - m_keyframeAnimations.clear(); -} - -void CompositeAnimation::clearRenderer() -{ - if (!m_transitions.isEmpty()) { - // Clear the renderers from all running animations, in case we are in the middle of - // an animation callback (see https://bugs.webkit.org/show_bug.cgi?id=22052) - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->value.get(); - animationController()->animationWillBeRemoved(transition); - transition->clear(); - } - } - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->value.get(); - animationController()->animationWillBeRemoved(anim); - anim->clear(); - } - } -} - -void CompositeAnimation::updateTransitions(RenderObject& renderer, RenderStyle* currentStyle, RenderStyle& targetStyle) -{ - // If currentStyle is null or there are no old or new transitions, just skip it - if (!currentStyle || (!targetStyle.transitions() && m_transitions.isEmpty())) - return; - - // Mark all existing transitions as no longer active. We will mark the still active ones - // in the next loop and then toss the ones that didn't get marked. - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) - it->value->setActive(false); - - RefPtr<RenderStyle> modifiedCurrentStyle; - - // Check to see if we need to update the active transitions - if (targetStyle.transitions()) { - for (size_t i = 0; i < targetStyle.transitions()->size(); ++i) { - const CSSAnimationData* anim = targetStyle.transitions()->animation(i); - bool isActiveTransition = anim->duration() || anim->delay() > 0; - - CSSAnimationData::AnimationMode mode = anim->animationMode(); - if (mode == CSSAnimationData::AnimateNone) - continue; - - CSSPropertyID prop = anim->property(); - - bool all = mode == CSSAnimationData::AnimateAll; - - // Handle both the 'all' and single property cases. For the single prop case, we make only one pass - // through the loop. - for (int propertyIndex = 0; propertyIndex < CSSPropertyAnimation::getNumProperties(); ++propertyIndex) { - if (all) { - // Get the next property which is not a shorthand. - bool isShorthand; - prop = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand); - if (isShorthand) - continue; - } - - // ImplicitAnimations are always hashed by actual properties, never animateAll. - ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties)); - - // If there is a running animation for this property, the transition is overridden - // and we have to use the unanimatedStyle from the animation. We do the test - // against the unanimated style here, but we "override" the transition later. - RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop); - RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle; - - // See if there is a current transition for this prop - ImplicitAnimation* implAnim = m_transitions.get(prop); - bool equal = true; - - if (implAnim) { - // If we are post active don't bother setting the active flag. This will cause - // this animation to get removed at the end of this function. - if (!implAnim->postActive()) - implAnim->setActive(true); - - // This might be a transition that is just finishing. That would be the case - // if it were postActive. But we still need to check for equality because - // it could be just finishing AND changing to a new goal state. - // - // This implAnim might also not be an already running transition. It might be - // newly added to the list in a previous iteration. This would happen if - // you have both an explicit transition-property and 'all' in the same - // list. In this case, the latter one overrides the earlier one, so we - // behave as though this is a running animation being replaced. - if (!implAnim->isTargetPropertyEqual(prop, &targetStyle)) { - // For accelerated animations we need to return a new RenderStyle with the _current_ value - // of the property, so that restarted transitions use the correct starting point. - if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(prop) && implAnim->isAccelerated()) { - if (!modifiedCurrentStyle) - modifiedCurrentStyle = RenderStyle::clone(currentStyle); - - implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get()); - } - animationController()->animationWillBeRemoved(implAnim); - m_transitions.remove(prop); - equal = false; - } - } else { - // We need to start a transition if it is active and the properties don't match - equal = !isActiveTransition || CSSPropertyAnimation::propertiesEqual(prop, fromStyle, &targetStyle); - } - - // We can be in this loop with an inactive transition (!isActiveTransition). We need - // to do that to check to see if we are canceling a transition. But we don't want to - // start one of the inactive transitions. So short circuit that here. (See - // <https://bugs.webkit.org/show_bug.cgi?id=24787> - if (!equal && isActiveTransition) { - // Add the new transition - m_transitions.set(prop, ImplicitAnimation::create(const_cast<CSSAnimationData*>(anim), prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle)); - } - - // We only need one pass for the single prop case - if (!all) - break; - } - } - } - - // Make a list of transitions to be removed - Vector<int> toBeRemoved; - end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (!anim->active()) { - animationController()->animationWillBeRemoved(anim); - toBeRemoved.append(anim->animatingProperty()); - } - } - - // Now remove the transitions from the list - for (size_t j = 0; j < toBeRemoved.size(); ++j) - m_transitions.remove(toBeRemoved[j]); -} - -void CompositeAnimation::updateKeyframeAnimations(RenderObject& renderer, RenderStyle* currentStyle, RenderStyle& targetStyle) -{ - // Nothing to do if we don't have any animations, and didn't have any before - if (m_keyframeAnimations.isEmpty() && !targetStyle.hasAnimations()) - return; - - AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); - - if (currentStyle && currentStyle->hasAnimations() && targetStyle.hasAnimations() && *(currentStyle->animations()) == *(targetStyle.animations())) { - // The current and target animations are the same so we just need to toss any - // animation which is finished (postActive). - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { - if (it->value->postActive()) - it->value->setIndex(-1); - } - } else { - // Mark all existing animations as no longer active. - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) - it->value->setIndex(-1); - - // Toss the animation order map. - m_keyframeAnimationOrderList.clear(); - - DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::ConstructFromLiteral)); - - // Now mark any still active animations as active and add any new animations. - if (targetStyle.animations()) { - int numAnims = targetStyle.animations()->size(); - for (int i = 0; i < numAnims; ++i) { - const CSSAnimationData* anim = targetStyle.animations()->animation(i); - if (!anim->isValidAnimation()) - continue; - - // See if there is a current animation for this name. - AtomicString name(anim->name()); - RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(name); - if (keyframeAnim) { - // If this animation is postActive, skip it so it gets removed at the end of this function. - if (keyframeAnim->postActive()) - continue; - - // This one is still active. - - // Animations match, but play states may differ. Update if needed. - keyframeAnim->updatePlayState(anim->playState()); - - // Set the saved animation to this new one, just in case the play state has changed. - keyframeAnim->setAnimation(anim); - keyframeAnim->setIndex(i); - } else if ((anim->duration() || anim->delay()) && anim->iterationCount() && name != none) { - keyframeAnim = KeyframeAnimation::create(const_cast<CSSAnimationData*>(anim), renderer, i, this, targetStyle); - m_keyframeAnimations.set(name, keyframeAnim); - } - - // Add this to the animation order map. - if (keyframeAnim) - m_keyframeAnimationOrderList.append(name); - } - } - } - - // Make a list of animations to be removed. - Vector<AtomicString> animsToBeRemoved; - kfend = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { - KeyframeAnimation* keyframeAnim = it->value.get(); - if (keyframeAnim->index() < 0) { - animsToBeRemoved.append(keyframeAnim->name()); - animationController()->animationWillBeRemoved(keyframeAnim); - keyframeAnim->clear(); - } - } - - // Now remove the animations from the list, and keep stale keys out of the order list. - if (animsToBeRemoved.size()) { - for (size_t j = 0; j < animsToBeRemoved.size(); ++j) { - ASSERT(m_keyframeAnimations.contains(animsToBeRemoved[j])); - m_keyframeAnimations.remove(animsToBeRemoved[j]); - } - Vector<AtomicString> newOrderList; - for (size_t j = 0; j < m_keyframeAnimationOrderList.size(); ++j) { - AtomicString key = m_keyframeAnimationOrderList[j]; - if (m_keyframeAnimations.contains(key)) - newOrderList.append(key); - } - m_keyframeAnimationOrderList.swap(newOrderList); - } -} - -PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject& renderer, RenderStyle* currentStyle, RenderStyle& targetStyle) -{ - RefPtr<RenderStyle> resultStyle; - - // We don't do any transitions if we don't have a currentStyle (on startup). - updateTransitions(renderer, currentStyle, targetStyle); - updateKeyframeAnimations(renderer, currentStyle, targetStyle); - - if (currentStyle) { - // Now that we have transition objects ready, let them know about the new goal state. We want them - // to fill in a RenderStyle*& only if needed. - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - if (ImplicitAnimation* anim = it->value.get()) - anim->animate(this, &renderer, currentStyle, &targetStyle, resultStyle); - } - } - } - - // Now that we have animation objects ready, let them know about the new goal state. We want them - // to fill in a RenderStyle*& only if needed. - for (Vector<AtomicString>::const_iterator it = m_keyframeAnimationOrderList.begin(); it != m_keyframeAnimationOrderList.end(); ++it) { - RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(*it); - ASSERT(keyframeAnim); - keyframeAnim->animate(this, &renderer, currentStyle, &targetStyle, resultStyle); - } - - return resultStyle ? resultStyle.release() : PassRefPtr<RenderStyle>(targetStyle); -} - -PassRefPtr<RenderStyle> CompositeAnimation::getAnimatedStyle() const -{ - RefPtr<RenderStyle> resultStyle; - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - if (ImplicitAnimation* implicitAnimation = it->value.get()) - implicitAnimation->getAnimatedStyle(resultStyle); - } - - for (Vector<AtomicString>::const_iterator it = m_keyframeAnimationOrderList.begin(); it != m_keyframeAnimationOrderList.end(); ++it) { - RefPtr<KeyframeAnimation> keyframeAnimation = m_keyframeAnimations.get(*it); - ASSERT(keyframeAnimation); - keyframeAnimation->getAnimatedStyle(resultStyle); - } - - return resultStyle; -} - -double CompositeAnimation::timeToNextService() const -{ - // Returns the time at which next service is required. -1 means no service is required. 0 means - // service is required now, and > 0 means service is required that many seconds in the future. - double minT = -1; - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->value.get(); - double t = transition ? transition->timeToNextService() : -1; - if (t < minT || minT == -1) - minT = t; - if (minT == 0) - return 0; - } - } - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* animation = it->value.get(); - double t = animation ? animation->timeToNextService() : -1; - if (t < minT || minT == -1) - minT = t; - if (minT == 0) - return 0; - } - } - - return minT; -} - -double CompositeAnimation::timeToNextEvent() const -{ - // Returns the time at which next service to trigger events is required. -1 means no service is required. 0 means - // service is required now, and > 0 means service is required that many seconds in the future. - double minT = -1; - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* transition = it->value.get(); - double t = -1; - bool isLooping; - if (transition) - transition->getTimeToNextEvent(t, isLooping); - if (t < minT || minT == -1) - minT = t; - if (!minT) - return 0; - } - } - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* animation = it->value.get(); - double t = -1; - bool isLooping; - if (animation) - animation->getTimeToNextEvent(t, isLooping); - if (t < minT || minT == -1) - minT = t; - if (!minT) - return 0; - } - } - - return minT; -} - -PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(CSSPropertyID property) const -{ - RefPtr<KeyframeAnimation> retval; - - // We want to send back the last animation with the property if there are multiples. - // So we need to iterate through all animations - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - RefPtr<KeyframeAnimation> anim = it->value; - if (anim->hasAnimationForProperty(property)) - retval = anim; - } - } - - return retval; -} - -void CompositeAnimation::overrideImplicitAnimations(CSSPropertyID property) -{ - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - if (!m_transitions.isEmpty()) { - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim && anim->animatingProperty() == property) - anim->setOverridden(true); - } - } -} - -void CompositeAnimation::resumeOverriddenImplicitAnimations(CSSPropertyID property) -{ - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim && anim->animatingProperty() == property) - anim->setOverridden(false); - } - } -} - -bool CompositeAnimation::isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, bool isRunningNow) const -{ - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->value.get(); - if (anim && anim->isAnimatingProperty(property, acceleratedOnly, isRunningNow)) - return true; - } - } - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim && anim->isAnimatingProperty(property, acceleratedOnly, isRunningNow)) - return true; - } - } - return false; -} - -void CompositeAnimation::pauseAnimationsForTesting(double t) -{ - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - RefPtr<KeyframeAnimation> keyframeAnim = it->value; - if (!keyframeAnim || !keyframeAnim->running()) - continue; - - double count = keyframeAnim->m_animation->iterationCount(); - if ((t >= 0.0) && ((count == CSSAnimationData::IterationCountInfinite) || (t <= count * keyframeAnim->duration()))) - keyframeAnim->freezeAtTime(t); - } - - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - RefPtr<ImplicitAnimation> implAnim = it->value; - - if (!implAnim->running()) - continue; - - if ((t >= 0.0) && (t <= implAnim->duration())) - implAnim->freezeAtTime(t); - } -} - -unsigned CompositeAnimation::numberOfActiveAnimations() const -{ - unsigned count = 0; - - if (!m_keyframeAnimations.isEmpty()) { - AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); - for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { - KeyframeAnimation* anim = it->value.get(); - if (anim->running()) - ++count; - } - } - - if (!m_transitions.isEmpty()) { - CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); - for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { - ImplicitAnimation* anim = it->value.get(); - if (anim->running()) - ++count; - } - } - - return count; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.h deleted file mode 100644 index ee0bd467288..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/CompositeAnimation.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CompositeAnimation_h -#define CompositeAnimation_h - -#include "core/frame/animation/ImplicitAnimation.h" -#include "core/frame/animation/KeyframeAnimation.h" -#include "wtf/HashMap.h" - -namespace WebCore { - -class AnimationControllerPrivate; -class AnimationController; -class RenderObject; -class RenderStyle; - -// A CompositeAnimation represents a collection of animations that are running -// on a single RenderObject, such as a number of properties transitioning at once. -class CompositeAnimation : public RefCounted<CompositeAnimation> { -public: - static PassRefPtr<CompositeAnimation> create(AnimationControllerPrivate* animationController) - { - return adoptRef(new CompositeAnimation(animationController)); - }; - - ~CompositeAnimation(); - - void clearRenderer(); - - PassRefPtr<RenderStyle> animate(RenderObject&, RenderStyle* currentStyle, RenderStyle& targetStyle); - PassRefPtr<RenderStyle> getAnimatedStyle() const; - - double timeToNextService() const; - double timeToNextEvent() const; - - AnimationControllerPrivate* animationController() const { return m_animationController; } - - bool hasAnimations() const { return !m_transitions.isEmpty() || !m_keyframeAnimations.isEmpty(); } - - bool isAnimatingProperty(CSSPropertyID, bool acceleratedOnly, bool isRunningNow) const; - - PassRefPtr<KeyframeAnimation> getAnimationForProperty(CSSPropertyID) const; - - void overrideImplicitAnimations(CSSPropertyID); - void resumeOverriddenImplicitAnimations(CSSPropertyID); - - void pauseAnimationsForTesting(double t); - unsigned numberOfActiveAnimations() const; - -private: - CompositeAnimation(AnimationControllerPrivate* animationController) - : m_animationController(animationController) - { - } - - void updateTransitions(RenderObject&, RenderStyle* currentStyle, RenderStyle& targetStyle); - void updateKeyframeAnimations(RenderObject&, RenderStyle* currentStyle, RenderStyle& targetStyle); - - typedef HashMap<int, RefPtr<ImplicitAnimation> > CSSPropertyTransitionsMap; - typedef HashMap<AtomicString, RefPtr<KeyframeAnimation> > AnimationNameMap; - - AnimationControllerPrivate* m_animationController; - CSSPropertyTransitionsMap m_transitions; - AnimationNameMap m_keyframeAnimations; - Vector<AtomicString> m_keyframeAnimationOrderList; -}; - -} // namespace WebCore - -#endif // CompositeAnimation_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.cpp deleted file mode 100644 index 2cf82b64b2b..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/UseCounter.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/frame/animation/ImplicitAnimation.h" -#include "core/frame/animation/KeyframeAnimation.h" -#include "core/rendering/RenderBoxModelObject.h" -#include "public/platform/Platform.h" - -namespace WebCore { - -ImplicitAnimation::ImplicitAnimation(const CSSAnimationData* transition, CSSPropertyID animatingProperty, RenderObject& renderer, CompositeAnimation* compAnim, RenderStyle* fromStyle) - : AnimationBase(transition, renderer, compAnim) - , m_transitionProperty(transition->property()) - , m_animatingProperty(animatingProperty) - , m_overridden(false) - , m_active(true) - , m_fromStyle(fromStyle) -{ - ASSERT(animatingProperty != CSSPropertyInvalid); - blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(m_animatingProperty)); -} - -ImplicitAnimation::~ImplicitAnimation() -{ - // // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. - if (!postActive()) - endAnimation(); -} - -bool ImplicitAnimation::shouldSendEventForListener(Document::ListenerType inListenerType) const -{ - return m_object->document().hasListenerType(inListenerType); -} - -void ImplicitAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) -{ - // If we get this far and the animation is done, it means we are cleaning up a just finished animation. - // So just return. Everything is already all cleaned up. - if (postActive()) - return; - - // Reset to start the transition if we are new - if (isNew()) - reset(targetStyle); - - // Run a cycle of animation. - // We know we will need a new render style, so make one if needed - if (!animatedStyle) - animatedStyle = RenderStyle::clone(targetStyle); - - bool needsAnim = CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); - // FIXME: we also need to detect cases where we have to software animate for other reasons, - // such as a child using inheriting the transform. https://bugs.webkit.org/show_bug.cgi?id=23902 - if (!needsAnim) - // If we are running an accelerated animation, set a flag in the style which causes the style - // to compare as different to any other style. This ensures that changes to the property - // that is animating are correctly detected during the animation (e.g. when a transition - // gets interrupted). - animatedStyle->setIsRunningAcceleratedAnimation(); - - // Fire the start timeout if needed - fireAnimationEventsIfNeeded(); -} - -void ImplicitAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle) -{ - if (!animatedStyle) - animatedStyle = RenderStyle::clone(m_toStyle.get()); - - CSSPropertyAnimation::blendProperties(this, m_animatingProperty, animatedStyle.get(), m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); -} - -void ImplicitAnimation::startAnimation(double timeOffset) -{ - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking) - m_isAccelerated = toRenderBoxModelObject(m_object)->startTransition(timeOffset, m_animatingProperty, m_fromStyle.get(), m_toStyle.get()); -} - -void ImplicitAnimation::pauseAnimation(double timeOffset) -{ - if (!m_object) - return; - - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->transitionPaused(timeOffset, m_animatingProperty); - - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); -} - -void ImplicitAnimation::endAnimation() -{ - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->transitionFinished(m_animatingProperty); - m_isAccelerated = false; -} - -void ImplicitAnimation::onAnimationEnd(double elapsedTime) -{ - // If we have a keyframe animation on this property, this transition is being overridden. The keyframe - // animation keeps an unanimated style in case a transition starts while the keyframe animation is - // running. But now that the transition has completed, we need to update this style with its new - // destination. If we didn't, the next time through we would think a transition had started - // (comparing the old unanimated style with the new final style of the transition). - RefPtr<KeyframeAnimation> keyframeAnim = m_compAnim->getAnimationForProperty(m_animatingProperty); - if (keyframeAnim) - keyframeAnim->setUnanimatedStyle(m_toStyle); - - sendTransitionEvent(EventTypeNames::transitionend, elapsedTime); - endAnimation(); -} - -bool ImplicitAnimation::sendTransitionEvent(const AtomicString& eventType, double elapsedTime) -{ - if (eventType == EventTypeNames::transitionend) { - Document::ListenerType listenerType = Document::TRANSITIONEND_LISTENER; - - if (shouldSendEventForListener(listenerType)) { - String propertyName = getPropertyNameString(m_animatingProperty); - - // Dispatch the event - RefPtr<Element> element = 0; - if (m_object->node() && m_object->node()->isElementNode()) - element = toElement(m_object->node()); - - if (!element) - return false; - - // Schedule event handling - m_compAnim->animationController()->addEventToDispatch(element, eventType, propertyName, elapsedTime); - - // Restore the original (unanimated) style - if (eventType == EventTypeNames::transitionend && element->renderer()) - setNeedsStyleRecalc(element.get()); - - return true; // Did dispatch an event - } - } - - return false; // Didn't dispatch an event -} - -void ImplicitAnimation::reset(RenderStyle* to) -{ - ASSERT(to); - ASSERT(m_fromStyle); - - m_toStyle = to; - - // Restart the transition - if (m_fromStyle && m_toStyle) - updateStateMachine(AnimationStateInputRestartAnimation, -1); - - // set the transform animation list - validateTransformFunctionList(); - checkForMatchingFilterFunctionLists(); -} - -void ImplicitAnimation::setOverridden(bool b) -{ - if (b == m_overridden) - return; - - m_overridden = b; - updateStateMachine(m_overridden ? AnimationStateInputPauseOverride : AnimationStateInputResumeOverride, -1); -} - -bool ImplicitAnimation::affectsProperty(CSSPropertyID property) const -{ - return (m_animatingProperty == property); -} - -bool ImplicitAnimation::isTargetPropertyEqual(CSSPropertyID prop, const RenderStyle* targetStyle) -{ - // We can get here for a transition that has not started yet. This would make m_toStyle unset and null. - // So we check that here (see <https://bugs.webkit.org/show_bug.cgi?id=26706>) - if (!m_toStyle) - return false; - return CSSPropertyAnimation::propertiesEqual(prop, m_toStyle.get(), targetStyle); -} - -void ImplicitAnimation::blendPropertyValueInStyle(CSSPropertyID prop, RenderStyle* currentStyle) -{ - // We should never add a transition with a 0 duration and delay. But if we ever did - // it would have a null toStyle. So just in case, let's check that here. (See - // <https://bugs.webkit.org/show_bug.cgi?id=24787> - if (!m_toStyle) - return; - - CSSPropertyAnimation::blendProperties(this, prop, currentStyle, m_fromStyle.get(), m_toStyle.get(), progress(1, 0, 0)); -} - -void ImplicitAnimation::validateTransformFunctionList() -{ - m_transformFunctionListValid = false; - - if (!m_fromStyle || !m_toStyle) - return; - - const TransformOperations* val = &m_fromStyle->transform(); - const TransformOperations* toVal = &m_toStyle->transform(); - - if (val->operations().isEmpty()) - val = toVal; - - if (val->operations().isEmpty()) - return; - - // An emtpy transform list matches anything. - if (val != toVal && !toVal->operations().isEmpty() && !val->operationsMatch(*toVal)) - return; - - // Transform lists match. - m_transformFunctionListValid = true; -} - -void ImplicitAnimation::checkForMatchingFilterFunctionLists() -{ - m_filterFunctionListsMatch = false; - - if (!m_fromStyle || !m_toStyle) - return; - - const FilterOperations* val = &m_fromStyle->filter(); - const FilterOperations* toVal = &m_toStyle->filter(); - - if (!val->canInterpolateWith(*toVal)) - return; - - // Filter lists match. - m_filterFunctionListsMatch = true; -} - -double ImplicitAnimation::timeToNextService() -{ - double t = AnimationBase::timeToNextService(); - if (t != 0 || preActive()) - return t; - - // A return value of 0 means we need service. But if this is an accelerated animation we - // only need service at the end of the transition. - if (CSSPropertyAnimation::animationOfPropertyIsAccelerated(m_animatingProperty) && isAccelerated()) { - bool isLooping; - getTimeToNextEvent(t, isLooping); - } - - return t; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.h deleted file mode 100644 index c531b36a81d..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/ImplicitAnimation.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ImplicitAnimation_h -#define ImplicitAnimation_h - -#include "CSSPropertyNames.h" -#include "core/dom/Document.h" -#include "core/frame/animation/AnimationBase.h" - -namespace WebCore { - -// An ImplicitAnimation tracks the state of a transition of a specific CSS property -// for a single RenderObject. -class ImplicitAnimation : public AnimationBase { -public: - static PassRefPtr<ImplicitAnimation> create(const CSSAnimationData* animation, CSSPropertyID animatingProperty, RenderObject& renderer, CompositeAnimation* compositeAnimation, RenderStyle* fromStyle) - { - return adoptRef(new ImplicitAnimation(animation, animatingProperty, renderer, compositeAnimation, fromStyle)); - }; - - CSSPropertyID transitionProperty() const { return m_transitionProperty; } - CSSPropertyID animatingProperty() const { return m_animatingProperty; } - - virtual void onAnimationEnd(double elapsedTime); - virtual void startAnimation(double timeOffset); - virtual void pauseAnimation(double /*timeOffset*/); - virtual void endAnimation(); - - virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle); - virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle); - virtual void reset(RenderStyle* to); - - void setOverridden(bool); - virtual bool overridden() const { return m_overridden; } - - virtual bool affectsProperty(CSSPropertyID) const; - - bool hasStyle() const { return m_fromStyle && m_toStyle; } - - bool isTargetPropertyEqual(CSSPropertyID, const RenderStyle*); - - void blendPropertyValueInStyle(CSSPropertyID, RenderStyle*); - - virtual double timeToNextService(); - - bool active() const { return m_active; } - void setActive(bool b) { m_active = b; } - -protected: - bool shouldSendEventForListener(Document::ListenerType) const; - bool sendTransitionEvent(const AtomicString&, double elapsedTime); - - void validateTransformFunctionList(); - void checkForMatchingFilterFunctionLists(); - -private: - ImplicitAnimation(const CSSAnimationData*, CSSPropertyID, RenderObject&, CompositeAnimation*, RenderStyle*); - virtual ~ImplicitAnimation(); - - CSSPropertyID m_transitionProperty; // Transition property as specified in the RenderStyle. - CSSPropertyID m_animatingProperty; // Specific property for this ImplicitAnimation - bool m_overridden; // true when there is a keyframe animation that overrides the transitioning property - bool m_active; // used for culling the list of transitions - - // The two styles that we are blending. - RefPtr<RenderStyle> m_fromStyle; - RefPtr<RenderStyle> m_toStyle; -}; - -} // namespace WebCore - -#endif // ImplicitAnimation_h diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.cpp b/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.cpp deleted file mode 100644 index 948ca03ce42..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (C) 2007, 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/frame/animation/KeyframeAnimation.h" - -#include "CSSPropertyNames.h" -#include "core/css/resolver/StyleResolver.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/UseCounter.h" -#include "core/frame/animation/AnimationControllerPrivate.h" -#include "core/frame/animation/CSSPropertyAnimation.h" -#include "core/frame/animation/CompositeAnimation.h" -#include "core/rendering/RenderBoxModelObject.h" -#include "core/rendering/style/RenderStyle.h" -#include "public/platform/Platform.h" - -using namespace std; - -namespace WebCore { - -KeyframeAnimation::KeyframeAnimation(const CSSAnimationData* animation, RenderObject& renderer, int index, CompositeAnimation* compAnim, RenderStyle& unanimatedStyle) - : AnimationBase(animation, renderer, compAnim) - , m_keyframes(renderer, animation->name()) - , m_index(index) - , m_startEventDispatched(false) - , m_unanimatedStyle(unanimatedStyle) -{ - // Get the keyframe RenderStyles - if (m_object && m_object->node() && m_object->node()->isElementNode()) - m_object->document().ensureStyleResolver().keyframeStylesForAnimation(toElement(m_object->node()), unanimatedStyle, m_keyframes); - - // Update the m_transformFunctionListValid flag based on whether the function lists in the keyframes match. - validateTransformFunctionList(); - checkForMatchingFilterFunctionLists(); - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) - blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(*it)); -} - -KeyframeAnimation::~KeyframeAnimation() -{ - // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed. - if (!postActive()) - endAnimation(); -} - -void KeyframeAnimation::fetchIntervalEndpointsForProperty(CSSPropertyID property, const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const -{ - // Find the first key - double elapsedTime = getElapsedTime(); - if (m_animation->duration() && m_animation->iterationCount() != CSSAnimationData::IterationCountInfinite) - elapsedTime = min(elapsedTime, m_animation->duration() * m_animation->iterationCount()); - - const double fractionalTime = this->fractionalTime(1, elapsedTime, 0); - - size_t numKeyframes = m_keyframes.size(); - if (!numKeyframes) - return; - - ASSERT(!m_keyframes[0].key()); - ASSERT(m_keyframes[m_keyframes.size() - 1].key() == 1); - - size_t currentIndex = 0; - size_t firstIndex = 0; - size_t lastIndex = numKeyframes - 1; - size_t distance = numKeyframes; - - // Find keyframe that is closest to elapsed time. - while (distance > 1) { - currentIndex = (lastIndex + firstIndex) >> 1; - double key = m_keyframes[currentIndex].key(); - distance = lastIndex - currentIndex; - - if (key < fractionalTime) { - if (distance < 2) - currentIndex++; - firstIndex = currentIndex; - } else { - lastIndex = currentIndex; - } - } - - int prevIndex = -1; - int nextIndex = -1; - - // Iterate forward to find next keyframe that is used to animate CSS property. - for (size_t i = currentIndex; i < numKeyframes; ++i) { - const KeyframeValue& keyFrame = m_keyframes[i]; - if (keyFrame.key() > fractionalTime && keyFrame.containsProperty(property)) { - nextIndex = i; - break; - } - } - - // Iterate backward to find previous keyframe. - for (int i = currentIndex; i >= 0; --i) { - const KeyframeValue& keyFrame = m_keyframes[i]; - if (keyFrame.key() <= fractionalTime && keyFrame.containsProperty(property)) { - prevIndex = i; - break; - } - } - - double scale = 1; - double offset = 0; - - if (prevIndex == -1) - prevIndex = 0; - - if (nextIndex == -1) - nextIndex = numKeyframes - 1; - - const KeyframeValue& prevKeyframe = m_keyframes[prevIndex]; - const KeyframeValue& nextKeyframe = m_keyframes[nextIndex]; - - fromStyle = prevKeyframe.style(); - toStyle = nextKeyframe.style(); - - offset = prevKeyframe.key(); - scale = 1.0 / (nextKeyframe.key() - prevKeyframe.key()); - // A scale of infinity is handled in AnimationBase::fractionalTime(). - ASSERT(scale >= 0 && (!std::isinf(scale) || prevIndex == nextIndex)); - - prog = progress(scale, offset, KeyframeValue::timingFunction(*prevKeyframe.style())); -} - -void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) -{ - // Fire the start timeout if needed - fireAnimationEventsIfNeeded(); - - // If we have not yet started, we will not have a valid start time, so just start the animation if needed. - if (isNew() && m_animation->playState() == AnimPlayStatePlaying) - updateStateMachine(AnimationStateInputStartAnimation, -1); - - // If we get this far and the animation is done, it means we are cleaning up a just finished animation. - // If so, we need to send back the targetStyle. - if (postActive()) { - if (!animatedStyle) - animatedStyle = const_cast<RenderStyle*>(targetStyle); - return; - } - - // If we are waiting for the start timer, we don't want to change the style yet. - // Special case 1 - if the delay time is 0, then we do want to set the first frame of the - // animation right away. This avoids a flash when the animation starts. - // Special case 2 - if there is a backwards fill mode, then we want to continue - // through to the style blend so that we get the fromStyle. - if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards()) - return; - - // If we have no keyframes, don't animate. - if (!m_keyframes.size()) { - updateStateMachine(AnimationStateInputEndAnimation, -1); - return; - } - - // Run a cycle of animation. - // We know we will need a new render style, so make one if needed. - if (!animatedStyle) - animatedStyle = RenderStyle::clone(targetStyle); - - // FIXME: we need to be more efficient about determining which keyframes we are animating between. - // We should cache the last pair or something. - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - // Get the from/to styles and progress between - const RenderStyle* fromStyle = 0; - const RenderStyle* toStyle = 0; - double progress = 0.0; - fetchIntervalEndpointsForProperty(*it, fromStyle, toStyle, progress); - - bool needsAnim = CSSPropertyAnimation::blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); - if (!needsAnim) - // If we are running an accelerated animation, set a flag in the style - // to indicate it. This can be used to make sure we get an updated - // style for hit testing, etc. - animatedStyle->setIsRunningAcceleratedAnimation(); - } -} - -void KeyframeAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle) -{ - // If we're in the delay phase and we're not backwards filling, tell the caller - // to use the current style. - if (waitingToStart() && m_animation->delay() > 0 && !m_animation->fillsBackwards()) - return; - - if (!m_keyframes.size()) - return; - - if (!animatedStyle) - animatedStyle = RenderStyle::clone(m_object->style()); - - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - // Get the from/to styles and progress between - const RenderStyle* fromStyle = 0; - const RenderStyle* toStyle = 0; - double progress = 0.0; - fetchIntervalEndpointsForProperty(*it, fromStyle, toStyle, progress); - - CSSPropertyAnimation::blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); - } -} - -bool KeyframeAnimation::hasAnimationForProperty(CSSPropertyID property) const -{ - return m_keyframes.containsProperty(property); -} - -void KeyframeAnimation::startAnimation(double timeOffset) -{ - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking) - m_isAccelerated = toRenderBoxModelObject(m_object)->startAnimation(timeOffset, m_animation.get(), m_keyframes); -} - -void KeyframeAnimation::pauseAnimation(double timeOffset) -{ - if (!m_object) - return; - - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->animationPaused(timeOffset, m_keyframes.animationName()); - - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); -} - -void KeyframeAnimation::endAnimation() -{ - if (!m_object) - return; - - if (m_object && m_object->compositingState() == PaintsIntoOwnBacking && isAccelerated()) - toRenderBoxModelObject(m_object)->animationFinished(m_keyframes.animationName()); - m_isAccelerated = false; - - // Restore the original (unanimated) style - if (!paused()) - setNeedsStyleRecalc(m_object->node()); -} - -bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const -{ - return m_object->document().hasListenerType(listenerType); -} - -void KeyframeAnimation::onAnimationStart(double elapsedTime) -{ - sendAnimationEvent(EventTypeNames::animationstart, elapsedTime); -} - -void KeyframeAnimation::onAnimationIteration(double elapsedTime) -{ - sendAnimationEvent(EventTypeNames::animationiteration, elapsedTime); -} - -void KeyframeAnimation::onAnimationEnd(double elapsedTime) -{ - sendAnimationEvent(EventTypeNames::animationend, elapsedTime); - // End the animation if we don't fill forwards. Forward filling - // animations are ended properly in the class destructor. - if (!m_animation->fillsForwards()) - endAnimation(); -} - -bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double elapsedTime) -{ - Document::ListenerType listenerType; - if (eventType == EventTypeNames::animationiteration) - listenerType = Document::ANIMATIONITERATION_LISTENER; - else if (eventType == EventTypeNames::animationend) - listenerType = Document::ANIMATIONEND_LISTENER; - else { - ASSERT(eventType == EventTypeNames::animationstart); - if (m_startEventDispatched) - return false; - m_startEventDispatched = true; - listenerType = Document::ANIMATIONSTART_LISTENER; - } - - if (shouldSendEventForListener(listenerType)) { - // Dispatch the event - RefPtr<Element> element; - if (m_object->node() && m_object->node()->isElementNode()) - element = toElement(m_object->node()); - - if (!element) - return false; - - // Schedule event handling - m_compAnim->animationController()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); - - // Restore the original (unanimated) style - if (eventType == EventTypeNames::animationend && element->renderer()) - setNeedsStyleRecalc(element.get()); - - return true; // Did dispatch an event - } - - return false; // Did not dispatch an event -} - -void KeyframeAnimation::overrideAnimations() -{ - // This will override implicit animations that match the properties in the keyframe animation - HashSet<CSSPropertyID>::const_iterator end = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != end; ++it) - compositeAnimation()->overrideImplicitAnimations(*it); -} - -void KeyframeAnimation::resumeOverriddenAnimations() -{ - // This will resume overridden implicit animations - HashSet<CSSPropertyID>::const_iterator end = m_keyframes.endProperties(); - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != end; ++it) - compositeAnimation()->resumeOverriddenImplicitAnimations(*it); -} - -bool KeyframeAnimation::affectsProperty(CSSPropertyID property) const -{ - return m_keyframes.containsProperty(property); -} - -void KeyframeAnimation::validateTransformFunctionList() -{ - m_transformFunctionListValid = false; - - if (m_keyframes.size() < 2 || !m_keyframes.containsProperty(CSSPropertyWebkitTransform)) - return; - - // Empty transforms match anything, so find the first non-empty entry as the reference - size_t numKeyframes = m_keyframes.size(); - size_t firstNonEmptyTransformKeyframeIndex = numKeyframes; - - for (size_t i = 0; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - if (currentKeyframe.style()->transform().operations().size()) { - firstNonEmptyTransformKeyframeIndex = i; - break; - } - } - - if (firstNonEmptyTransformKeyframeIndex == numKeyframes) - return; - - const TransformOperations* firstVal = &m_keyframes[firstNonEmptyTransformKeyframeIndex].style()->transform(); - - // See if the keyframes are valid - for (size_t i = firstNonEmptyTransformKeyframeIndex + 1; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - const TransformOperations* val = ¤tKeyframe.style()->transform(); - - // An emtpy transform list matches anything. - if (val->operations().isEmpty()) - continue; - - if (!firstVal->operationsMatch(*val)) - return; - } - - // Keyframes are valid - m_transformFunctionListValid = true; -} - -void KeyframeAnimation::checkForMatchingFilterFunctionLists() -{ - m_filterFunctionListsMatch = false; - - if (m_keyframes.size() < 2 || !m_keyframes.containsProperty(CSSPropertyWebkitFilter)) - return; - - // Empty filters match anything, so find the first non-empty entry as the reference - size_t numKeyframes = m_keyframes.size(); - size_t firstNonEmptyFilterKeyframeIndex = numKeyframes; - - for (size_t i = 0; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - if (currentKeyframe.style()->filter().operations().size()) { - firstNonEmptyFilterKeyframeIndex = i; - break; - } - } - - if (firstNonEmptyFilterKeyframeIndex == numKeyframes) - return; - - const FilterOperations* firstVal = &m_keyframes[firstNonEmptyFilterKeyframeIndex].style()->filter(); - - for (size_t i = firstNonEmptyFilterKeyframeIndex + 1; i < numKeyframes; ++i) { - const KeyframeValue& currentKeyframe = m_keyframes[i]; - const FilterOperations* val = ¤tKeyframe.style()->filter(); - - if (!firstVal->canInterpolateWith(*val)) - return; - } - - m_filterFunctionListsMatch = true; -} - -double KeyframeAnimation::timeToNextService() -{ - double t = AnimationBase::timeToNextService(); - if (t != 0 || preActive()) - return t; - - // A return value of 0 means we need service. But if we only have accelerated animations we - // only need service at the end of the transition - HashSet<CSSPropertyID>::const_iterator endProperties = m_keyframes.endProperties(); - bool acceleratedPropertiesOnly = true; - - for (HashSet<CSSPropertyID>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - if (!CSSPropertyAnimation::animationOfPropertyIsAccelerated(*it) || !isAccelerated()) { - acceleratedPropertiesOnly = false; - break; - } - } - - if (acceleratedPropertiesOnly) { - bool isLooping; - getTimeToNextEvent(t, isLooping); - } - - return t; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.h b/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.h deleted file mode 100644 index 93334d93c62..00000000000 --- a/chromium/third_party/WebKit/Source/core/frame/animation/KeyframeAnimation.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyframeAnimation_h -#define KeyframeAnimation_h - -#include "core/dom/Document.h" -#include "core/frame/animation/AnimationBase.h" -#include "core/rendering/style/KeyframeList.h" - -namespace WebCore { - -class RenderStyle; - -// A KeyframeAnimation tracks the state of an explicit animation -// for a single RenderObject. -class KeyframeAnimation : public AnimationBase { -public: - static PassRefPtr<KeyframeAnimation> create(const CSSAnimationData* animation, RenderObject& renderer, int index, CompositeAnimation* compositeAnimation, RenderStyle& unanimatedStyle) - { - return adoptRef(new KeyframeAnimation(animation, renderer, index, compositeAnimation, unanimatedStyle)); - }; - - virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle); - virtual void getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle); - - const AtomicString& name() const { return m_keyframes.animationName(); } - int index() const { return m_index; } - void setIndex(int i) { m_index = i; } - - bool hasAnimationForProperty(CSSPropertyID) const; - - void setUnanimatedStyle(PassRefPtr<RenderStyle> style) { m_unanimatedStyle = style; } - RenderStyle* unanimatedStyle() const { return m_unanimatedStyle.get(); } - - virtual double timeToNextService(); - -protected: - virtual void onAnimationStart(double elapsedTime); - virtual void onAnimationIteration(double elapsedTime); - virtual void onAnimationEnd(double elapsedTime); - virtual void startAnimation(double timeOffset); - virtual void pauseAnimation(double timeOffset); - virtual void endAnimation(); - - virtual void overrideAnimations(); - virtual void resumeOverriddenAnimations(); - - bool shouldSendEventForListener(Document::ListenerType inListenerType) const; - bool sendAnimationEvent(const AtomicString&, double elapsedTime); - - virtual bool affectsProperty(CSSPropertyID) const; - - void validateTransformFunctionList(); - void checkForMatchingFilterFunctionLists(); - -private: - KeyframeAnimation(const CSSAnimationData*, RenderObject&, int index, CompositeAnimation*, RenderStyle& unanimatedStyle); - virtual ~KeyframeAnimation(); - - // Get the styles for the given property surrounding the current animation time and the progress between them. - void fetchIntervalEndpointsForProperty(CSSPropertyID, const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& progress) const; - - // The keyframes that we are blending. - KeyframeList m_keyframes; - - // The order in which this animation appears in the animation-name style. - int m_index; - bool m_startEventDispatched; - - // The style just before we started animation - RefPtr<RenderStyle> m_unanimatedStyle; -}; - -} // namespace WebCore - -#endif // KeyframeAnimation_h |