/*
 * Copyright (C) Canon Inc. 2016
 * Copyright (C) 2017 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
 * 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 "AnimationTimeline.h"

#include "Animation.h"
#include "AnimationEffect.h"
#include "AnimationList.h"
#include "CSSAnimation.h"
#include "CSSPropertyAnimation.h"
#include "CSSTransition.h"
#include "DocumentTimeline.h"
#include "Element.h"
#include "KeyframeEffect.h"
#include "RenderStyle.h"
#include "RenderView.h"
#include "StylePropertyShorthand.h"
#include "StyleResolver.h"
#include "WebAnimationUtilities.h"
#include <wtf/text/TextStream.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

AnimationTimeline::AnimationTimeline()
{
}

AnimationTimeline::~AnimationTimeline()
{
}

void AnimationTimeline::forgetAnimation(WebAnimation* animation)
{
    m_allAnimations.removeFirst(animation);
}

void AnimationTimeline::animationTimingDidChange(WebAnimation& animation)
{
    if (m_animations.add(&animation)) {
        animation.setGlobalPosition(m_allAnimations.size());
        m_allAnimations.append(makeWeakPtr(&animation));
        auto* timeline = animation.timeline();
        if (timeline && timeline != this)
            timeline->removeAnimation(animation);
    }
}

void AnimationTimeline::removeAnimation(WebAnimation& animation)
{
    ASSERT(!animation.timeline() || animation.timeline() == this);
    m_animations.remove(&animation);
    if (is<KeyframeEffect>(animation.effect())) {
        if (auto* target = downcast<KeyframeEffect>(animation.effect())->target())
            animationWasRemovedFromElement(animation, *target);
    }
}

Optional<double> AnimationTimeline::bindingsCurrentTime()
{
    auto time = currentTime();
    if (!time)
        return WTF::nullopt;
    return secondsToWebAnimationsAPITime(*time);
}

void AnimationTimeline::animationWasAddedToElement(WebAnimation& animation, Element& element)
{
    [&] () -> ElementToAnimationsMap& {
        if (is<CSSTransition>(animation) && downcast<CSSTransition>(animation).owningElement())
            return m_elementToCSSTransitionsMap;
        if (is<CSSAnimation>(animation) && downcast<CSSAnimation>(animation).owningElement())
            return m_elementToCSSAnimationsMap;
        return m_elementToAnimationsMap;
    }().ensure(&element, [] {
        return ListHashSet<RefPtr<WebAnimation>> { };
    }).iterator->value.add(&animation);
}

static inline bool removeCSSTransitionFromMap(CSSTransition& transition, Element& element, HashMap<Element*, AnimationTimeline::PropertyToTransitionMap>& map)
{
    auto iterator = map.find(&element);
    if (iterator == map.end())
        return false;

    auto& cssTransitionsByProperty = iterator->value;

    auto transitionIterator = cssTransitionsByProperty.find(transition.property());
    if (transitionIterator == cssTransitionsByProperty.end() || transitionIterator->value != &transition)
        return false;

    cssTransitionsByProperty.remove(transitionIterator);

    if (cssTransitionsByProperty.isEmpty())
        map.remove(&element);
    return true;
}

static inline void removeAnimationFromMapForElement(WebAnimation& animation, AnimationTimeline::ElementToAnimationsMap& map, Element& element)
{
    auto iterator = map.find(&element);
    if (iterator == map.end())
        return;

    auto& animations = iterator->value;
    animations.remove(&animation);
    if (!animations.size())
        map.remove(iterator);
}

void AnimationTimeline::animationWasRemovedFromElement(WebAnimation& animation, Element& element)
{
    removeAnimationFromMapForElement(animation, m_elementToCSSTransitionsMap, element);
    removeAnimationFromMapForElement(animation, m_elementToCSSAnimationsMap, element);
    removeAnimationFromMapForElement(animation, m_elementToAnimationsMap, element);

    // Now, if we're dealing with a declarative animation, we remove it from either the m_elementToCSSAnimationByName
    // or the m_elementToRunningCSSTransitionByCSSPropertyID map, whichever is relevant to this type of animation.
    if (is<DeclarativeAnimation>(animation))
        removeDeclarativeAnimationFromListsForOwningElement(animation, element);
}

void AnimationTimeline::removeDeclarativeAnimationFromListsForOwningElement(WebAnimation& animation, Element& element)
{
    ASSERT(is<DeclarativeAnimation>(animation));

    if (is<CSSAnimation>(animation)) {
        auto iterator = m_elementToCSSAnimationByName.find(&element);
        if (iterator != m_elementToCSSAnimationByName.end()) {
            auto& cssAnimationsByName = iterator->value;
            auto& name = downcast<CSSAnimation>(animation).animationName();
            cssAnimationsByName.remove(name);
            if (cssAnimationsByName.isEmpty())
                m_elementToCSSAnimationByName.remove(&element);
        }
    } else if (is<CSSTransition>(animation)) {
        auto& transition = downcast<CSSTransition>(animation);
        if (!removeCSSTransitionFromMap(transition, element, m_elementToRunningCSSTransitionByCSSPropertyID))
            removeCSSTransitionFromMap(transition, element, m_elementToCompletedCSSTransitionByCSSPropertyID);
    }
}

Vector<RefPtr<WebAnimation>> AnimationTimeline::animationsForElement(Element& element, Ordering ordering) const
{
    Vector<RefPtr<WebAnimation>> animations;
    if (m_elementToCSSTransitionsMap.contains(&element)) {
        const auto& cssTransitions = m_elementToCSSTransitionsMap.get(&element);
        if (ordering == Ordering::Sorted) {
            auto sortedCSSTransitions = copyToVector(cssTransitions);
            std::sort(sortedCSSTransitions.begin(), sortedCSSTransitions.end(), [](auto& lhs, auto& rhs) {
                // Sort transitions first by their generation time, and then by transition-property.
                // https://drafts.csswg.org/css-transitions-2/#animation-composite-order
                auto* lhsTransition = downcast<CSSTransition>(lhs.get());
                auto* rhsTransition = downcast<CSSTransition>(rhs.get());
                if (lhsTransition->generationTime() != rhsTransition->generationTime())
                    return lhsTransition->generationTime() < rhsTransition->generationTime();
                return lhsTransition->transitionProperty().utf8() < rhsTransition->transitionProperty().utf8();
            });
            animations.appendVector(sortedCSSTransitions);
        } else
            animations.appendRange(cssTransitions.begin(), cssTransitions.end());
    }
    if (m_elementToCSSAnimationsMap.contains(&element)) {
        const auto& cssAnimations = m_elementToCSSAnimationsMap.get(&element);
        animations.appendRange(cssAnimations.begin(), cssAnimations.end());
    }
    if (m_elementToAnimationsMap.contains(&element)) {
        const auto& webAnimations = m_elementToAnimationsMap.get(&element);
        if (ordering == Ordering::Sorted) {
            auto sortedWebAnimations = copyToVector(webAnimations);
            std::sort(sortedWebAnimations.begin(), sortedWebAnimations.end(), [](auto& lha, auto& rha) {
                return lha->globalPosition() < rha->globalPosition();
            });
            animations.appendVector(sortedWebAnimations);
        } else
            animations.appendRange(webAnimations.begin(), webAnimations.end());
    }
    return animations;
}

void AnimationTimeline::elementWasRemoved(Element& element)
{
    for (auto& cssTransition : m_elementToCSSTransitionsMap.get(&element))
        cssTransition->cancel(WebAnimation::Silently::Yes);
    for (auto& cssAnimation : m_elementToCSSAnimationsMap.get(&element))
        cssAnimation->cancel(WebAnimation::Silently::Yes);
}

void AnimationTimeline::removeAnimationsForElement(Element& element)
{
    for (auto& animation : animationsForElement(element))
        animation->remove();
}

void AnimationTimeline::cancelDeclarativeAnimationsForElement(Element& element)
{
    for (auto& cssTransition : m_elementToCSSTransitionsMap.get(&element))
        cssTransition->cancel();
    for (auto& cssAnimation : m_elementToCSSAnimationsMap.get(&element))
        cssAnimation->cancel();
}

static bool shouldConsiderAnimation(Element& element, const Animation& animation)
{
    if (!animation.isValidAnimation())
        return false;

    static NeverDestroyed<const String> animationNameNone(MAKE_STATIC_STRING_IMPL("none"));

    auto& name = animation.name();
    if (name == animationNameNone || name.isEmpty())
        return false;

    if (auto* styleScope = Style::Scope::forOrdinal(element, animation.nameStyleScopeOrdinal()))
        return styleScope->resolver().isAnimationNameValid(name);

    return false;
}

void AnimationTimeline::updateCSSAnimationsForElement(Element& element, const RenderStyle* currentStyle, const RenderStyle& afterChangeStyle)
{
    // In case this element is newly getting a "display: none" we need to cancel all of its animations and disregard new ones.
    if (currentStyle && currentStyle->hasAnimations() && currentStyle->display() != DisplayType::None && afterChangeStyle.display() == DisplayType::None) {
        if (m_elementToCSSAnimationByName.contains(&element)) {
            for (const auto& cssAnimationsByNameMapItem : m_elementToCSSAnimationByName.take(&element))
                cancelDeclarativeAnimation(*cssAnimationsByNameMapItem.value);
        }
        return;
    }

    if (currentStyle && currentStyle->hasAnimations() && afterChangeStyle.hasAnimations() && *(currentStyle->animations()) == *(afterChangeStyle.animations()))
        return;

    // First, compile the list of animation names that were applied to this element up to this point.
    HashSet<String> namesOfPreviousAnimations;
    if (currentStyle && currentStyle->hasAnimations()) {
        auto* previousAnimations = currentStyle->animations();
        for (size_t i = 0; i < previousAnimations->size(); ++i) {
            auto& previousAnimation = previousAnimations->animation(i);
            if (shouldConsiderAnimation(element, previousAnimation))
                namesOfPreviousAnimations.add(previousAnimation.name());
        }
    }

    // Create or get the CSSAnimations by animation name map for this element.
    auto& cssAnimationsByName = m_elementToCSSAnimationByName.ensure(&element, [] {
        return HashMap<String, RefPtr<CSSAnimation>> { };
    }).iterator->value;

    if (auto* currentAnimations = afterChangeStyle.animations()) {
        for (size_t i = 0; i < currentAnimations->size(); ++i) {
            auto& currentAnimation = currentAnimations->animation(i);
            auto& name = currentAnimation.name();
            if (namesOfPreviousAnimations.contains(name)) {
                // We've found the name of this animation in our list of previous animations, this means we've already
                // created a CSSAnimation object for it and need to ensure that this CSSAnimation is backed by the current
                // animation object for this animation name.
                if (auto cssAnimation = cssAnimationsByName.get(name))
                    cssAnimation->setBackingAnimation(currentAnimation);
            } else if (shouldConsiderAnimation(element, currentAnimation)) {
                // Otherwise we are dealing with a new animation name and must create a CSSAnimation for it.
                cssAnimationsByName.set(name, CSSAnimation::create(element, currentAnimation, currentStyle, afterChangeStyle));
            }
            // Remove the name of this animation from our list since it's now known to be current.
            namesOfPreviousAnimations.remove(name);
        }
    }

    // The animations names left in namesOfPreviousAnimations are now known to no longer apply so we need to
    // remove the CSSAnimation object created for them.
    for (const auto& nameOfAnimationToRemove : namesOfPreviousAnimations) {
        if (auto animation = cssAnimationsByName.take(nameOfAnimationToRemove))
            cancelDeclarativeAnimation(*animation);
    }
}

RefPtr<WebAnimation> AnimationTimeline::cssAnimationForElementAndProperty(Element& element, CSSPropertyID property)
{
    RefPtr<WebAnimation> matchingAnimation;
    for (const auto& animation : m_elementToCSSAnimationsMap.get(&element)) {
        auto* effect = animation->effect();
        if (is<KeyframeEffect>(effect) && downcast<KeyframeEffect>(effect)->animatedProperties().contains(property))
            matchingAnimation = animation;
    }
    return matchingAnimation;
}

static bool propertyInStyleMatchesValueForTransitionInMap(CSSPropertyID property, const RenderStyle& style, AnimationTimeline::PropertyToTransitionMap& transitions)
{
    if (auto* transition = transitions.get(property)) {
        if (CSSPropertyAnimation::propertiesEqual(property, &style, &transition->targetStyle()))
            return true;
    }
    return false;
}

static double transitionCombinedDuration(const Animation* transition)
{
    return std::max(0.0, transition->duration()) + transition->delay();
}

static bool transitionMatchesProperty(const Animation& transition, CSSPropertyID property)
{
    auto mode = transition.animationMode();
    if (mode == Animation::AnimateNone || mode == Animation::AnimateUnknownProperty)
        return false;
    if (mode == Animation::AnimateSingleProperty) {
        auto transitionProperty = transition.property();
        if (transitionProperty != property) {
            auto shorthand = shorthandForProperty(transitionProperty);
            for (size_t i = 0; i < shorthand.length(); ++i) {
                if (shorthand.properties()[i] == property)
                    return true;
            }
            return false;
        }
    }
    return true;
}

AnimationTimeline::PropertyToTransitionMap& AnimationTimeline::ensureRunningTransitionsByProperty(Element& element)
{
    return m_elementToRunningCSSTransitionByCSSPropertyID.ensure(&element, [] {
        return PropertyToTransitionMap { };
    }).iterator->value;
}

void AnimationTimeline::updateCSSTransitionsForElement(Element& element, const RenderStyle& currentStyle, const RenderStyle& afterChangeStyle)
{
    // In case this element is newly getting a "display: none" we need to cancel all of its transitions and disregard new ones.
    if (currentStyle.hasTransitions() && currentStyle.display() != DisplayType::None && afterChangeStyle.display() == DisplayType::None) {
        if (m_elementToRunningCSSTransitionByCSSPropertyID.contains(&element)) {
            for (const auto& cssTransitionsByCSSPropertyIDMapItem : m_elementToRunningCSSTransitionByCSSPropertyID.take(&element))
                cancelDeclarativeAnimation(*cssTransitionsByCSSPropertyIDMapItem.value);
        }
        return;
    }

    // Section 3 "Starting of transitions" from the CSS Transitions Level 1 specification.
    // https://drafts.csswg.org/css-transitions-1/#starting

    auto& runningTransitionsByProperty = ensureRunningTransitionsByProperty(element);

    auto& completedTransitionsByProperty = m_elementToCompletedCSSTransitionByCSSPropertyID.ensure(&element, [] {
        return PropertyToTransitionMap { };
    }).iterator->value;

    auto generationTime = MonotonicTime::now();

    auto numberOfProperties = CSSPropertyAnimation::getNumProperties();
    for (int propertyIndex = 0; propertyIndex < numberOfProperties; ++propertyIndex) {
        Optional<bool> isShorthand;
        auto property = CSSPropertyAnimation::getPropertyAtIndex(propertyIndex, isShorthand);
        if (isShorthand && *isShorthand)
            continue;

        const Animation* matchingBackingAnimation = nullptr;
        if (auto* transitions = afterChangeStyle.transitions()) {
            for (size_t i = 0; i < transitions->size(); ++i) {
                auto& backingAnimation = transitions->animation(i);
                if (transitionMatchesProperty(backingAnimation, property))
                    matchingBackingAnimation = &backingAnimation;
            }
        }

        // https://drafts.csswg.org/css-transitions-1/#before-change-style
        // Define the before-change style as the computed values of all properties on the element as of the previous style change event, except with
        // any styles derived from declarative animations such as CSS Transitions, CSS Animations, and SMIL Animations updated to the current time.
        auto existingAnimation = cssAnimationForElementAndProperty(element, property);
        const auto& beforeChangeStyle = existingAnimation ? downcast<CSSAnimation>(existingAnimation.get())->unanimatedStyle() : currentStyle;

        if (!runningTransitionsByProperty.contains(property)
            && !CSSPropertyAnimation::propertiesEqual(property, &beforeChangeStyle, &afterChangeStyle)
            && CSSPropertyAnimation::canPropertyBeInterpolated(property, &beforeChangeStyle, &afterChangeStyle)
            && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, completedTransitionsByProperty)
            && matchingBackingAnimation && transitionCombinedDuration(matchingBackingAnimation) > 0) {
            // 1. If all of the following are true:
            //   - the element does not have a running transition for the property,
            //   - the before-change style is different from and can be interpolated with the after-change style for that property,
            //   - the element does not have a completed transition for the property or the end value of the completed transition is different from the after-change style for the property,
            //   - there is a matching transition-property value, and
            //   - the combined duration is greater than 0s,

            // then implementations must remove the completed transition (if present) from the set of completed transitions
            completedTransitionsByProperty.remove(property);

            // and start a transition whose:
            //   - start time is the time of the style change event plus the matching transition delay,
            //   - end time is the start time plus the matching transition duration,
            //   - start value is the value of the transitioning property in the before-change style,
            //   - end value is the value of the transitioning property in the after-change style,
            //   - reversing-adjusted start value is the same as the start value, and
            //   - reversing shortening factor is 1.
            auto delay = Seconds(matchingBackingAnimation->delay());
            auto duration = Seconds(matchingBackingAnimation->duration());
            auto& reversingAdjustedStartStyle = beforeChangeStyle;
            auto reversingShorteningFactor = 1;
            runningTransitionsByProperty.set(property, CSSTransition::create(element, property, generationTime, *matchingBackingAnimation, &beforeChangeStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
        } else if (completedTransitionsByProperty.contains(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, completedTransitionsByProperty)) {
            // 2. Otherwise, if the element has a completed transition for the property and the end value of the completed transition is different from
            //    the after-change style for the property, then implementations must remove the completed transition from the set of completed transitions.
            completedTransitionsByProperty.remove(property);
        }

        bool hasRunningTransition = runningTransitionsByProperty.contains(property);
        if ((hasRunningTransition || completedTransitionsByProperty.contains(property)) && !matchingBackingAnimation) {
            // 3. If the element has a running transition or completed transition for the property, and there is not a matching transition-property
            //    value, then implementations must cancel the running transition or remove the completed transition from the set of completed transitions.
            if (hasRunningTransition)
                runningTransitionsByProperty.take(property)->cancel();
            else
                completedTransitionsByProperty.remove(property);
        }

        if (matchingBackingAnimation && runningTransitionsByProperty.contains(property) && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, runningTransitionsByProperty)) {
            auto previouslyRunningTransition = runningTransitionsByProperty.take(property);
            auto& previouslyRunningTransitionCurrentStyle = previouslyRunningTransition->currentStyle();
            // 4. If the element has a running transition for the property, there is a matching transition-property value, and the end value of the running
            //    transition is not equal to the value of the property in the after-change style, then:
            if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle) || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &currentStyle, &afterChangeStyle)) {
                // 1. If the current value of the property in the running transition is equal to the value of the property in the after-change style,
                //    or if these two values cannot be interpolated, then implementations must cancel the running transition.
                cancelDeclarativeAnimation(*previouslyRunningTransition);
            } else if (transitionCombinedDuration(matchingBackingAnimation) <= 0.0 || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle)) {
                // 2. Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the running transition
                //    cannot be interpolated with the value of the property in the after-change style, then implementations must cancel the running transition.
                cancelDeclarativeAnimation(*previouslyRunningTransition);
            } else if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransition->reversingAdjustedStartStyle(), &afterChangeStyle)) {
                // 3. Otherwise, if the reversing-adjusted start value of the running transition is the same as the value of the property in the after-change
                //    style (see the section on reversing of transitions for why these case exists), implementations must cancel the running transition
                cancelDeclarativeAnimation(*previouslyRunningTransition);

                // and start a new transition whose:
                //   - reversing-adjusted start value is the end value of the running transition,
                //   - reversing shortening factor is the absolute value, clamped to the range [0, 1], of the sum of:
                //       1. the output of the timing function of the old transition at the time of the style change event, times the reversing shortening factor of the old transition
                //       2. 1 minus the reversing shortening factor of the old transition.
                //   - start time is the time of the style change event plus:
                //       1. if the matching transition delay is nonnegative, the matching transition delay, or
                //       2. if the matching transition delay is negative, the product of the new transition’s reversing shortening factor and the matching transition delay,
                //   - end time is the start time plus the product of the matching transition duration and the new transition’s reversing shortening factor,
                //   - start value is the current value of the property in the running transition,
                //   - end value is the value of the property in the after-change style
                auto& reversingAdjustedStartStyle = previouslyRunningTransition->targetStyle();
                double transformedProgress = 1;
                if (auto* effect = previouslyRunningTransition->effect()) {
                    if (auto computedTimingProgress = effect->getComputedTiming().progress)
                        transformedProgress = *computedTimingProgress;
                }
                auto reversingShorteningFactor = std::max(std::min(((transformedProgress * previouslyRunningTransition->reversingShorteningFactor()) + (1 - previouslyRunningTransition->reversingShorteningFactor())), 1.0), 0.0);
                auto delay = matchingBackingAnimation->delay() < 0 ? Seconds(matchingBackingAnimation->delay()) * reversingShorteningFactor : Seconds(matchingBackingAnimation->delay());
                auto duration = Seconds(matchingBackingAnimation->duration()) * reversingShorteningFactor;

                ensureRunningTransitionsByProperty(element).set(property, CSSTransition::create(element, property, generationTime, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
            } else {
                // 4. Otherwise, implementations must cancel the running transition
                cancelDeclarativeAnimation(*previouslyRunningTransition);

                // and start a new transition whose:
                //   - start time is the time of the style change event plus the matching transition delay,
                //   - end time is the start time plus the matching transition duration,
                //   - start value is the current value of the property in the running transition,
                //   - end value is the value of the property in the after-change style,
                //   - reversing-adjusted start value is the same as the start value, and
                //   - reversing shortening factor is 1.
                auto delay = Seconds(matchingBackingAnimation->delay());
                auto duration = Seconds(matchingBackingAnimation->duration());
                auto& reversingAdjustedStartStyle = currentStyle;
                auto reversingShorteningFactor = 1;
                ensureRunningTransitionsByProperty(element).set(property, CSSTransition::create(element, property, generationTime, *matchingBackingAnimation, &previouslyRunningTransitionCurrentStyle, afterChangeStyle, delay, duration, reversingAdjustedStartStyle, reversingShorteningFactor));
            }
        }
    }
}

void AnimationTimeline::cancelDeclarativeAnimation(DeclarativeAnimation& animation)
{
    animation.cancelFromStyle();
    removeAnimation(animation);
    m_allAnimations.removeFirst(&animation);
}

} // namespace WebCore
