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. Ref<AnimationBase> protect(*this); Ref<CompositeAnimation> protectCompositeAnimation(*m_compAnim); // Check for start timeout if (m_animState == AnimationStateStartWaitTimer) { if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay()) updateStateMachine(AnimationStateInputStartTimerFired, 0); return; } double elapsedDuration = beginAnimationUpdateTime() - m_startTime; // FIXME: we need to ensure that elapsedDuration is never < 0. If it is, this suggests that // we had a recalcStyle() outside of beginAnimationUpdate()/endAnimationUpdate(). // Also check in getTimeToNextEvent(). elapsedDuration = max(elapsedDuration, 0.0); // 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. LOG(Animations, "%p AnimationState %s -> Ending", this, nameForState(m_animState)); 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::fireAnimationEventsIfNeeded() { if (!m_compositeAnimation) return; // If we are waiting for the delay time to expire and it has, go to the next state if (m_animationState != AnimationState::StartWaitTimer && m_animationState != AnimationState::Looping && m_animationState != AnimationState::Ending) 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. Ref<AnimationBase> protect(*this); Ref<CompositeAnimation> protectCompositeAnimation(*m_compositeAnimation); // Check for start timeout if (m_animationState == AnimationState::StartWaitTimer) { #if ENABLE(CSS_ANIMATIONS_LEVEL_2) if (m_animation->trigger() && m_animation->trigger()->isScrollAnimationTrigger()) { if (m_object) { float offset = m_compositeAnimation->animationController().scrollPosition(); ScrollAnimationTrigger& scrollTrigger = downcast<ScrollAnimationTrigger>(*m_animation->trigger().get()); if (offset > scrollTrigger.startValue().value()) updateStateMachine(AnimationStateInput::StartTimerFired, 0); } return; } #endif if (beginAnimationUpdateTime() - m_requestedStartTime >= m_animation->delay()) updateStateMachine(AnimationStateInput::StartTimerFired, 0); return; } double elapsedDuration = beginAnimationUpdateTime() - m_startTime; #if ENABLE(CSS_ANIMATIONS_LEVEL_2) // If we are a triggered animation that depends on scroll, our elapsed // time is determined by the scroll position. if (m_animation->trigger() && m_animation->trigger()->isScrollAnimationTrigger()) elapsedDuration = getElapsedTime(); #endif // FIXME: we need to ensure that elapsedDuration is never < 0. If it is, this suggests that // we had a recalcStyle() outside of beginAnimationUpdate()/endAnimationUpdate(). // Also check in getTimeToNextEvent(). elapsedDuration = std::max(elapsedDuration, 0.0); // Check for end timeout if (m_totalDuration >= 0 && elapsedDuration >= m_totalDuration) { // We may still be in AnimationState::Looping if we've managed to skip a // whole iteration, in which case we should jump to the end state. LOG(Animations, "%p AnimationState %s -> Ending", this, nameForState(m_animationState)); m_animationState = AnimationState::Ending; // Fire an end event updateStateMachine(AnimationStateInput::EndTimerFired, 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(AnimationStateInput::LoopTimerFired, previous); } } }