void CompositeAnimationPrivate::cleanupFinishedAnimations(RenderObject* renderer) { if (isSuspended()) return; // Make a list of transitions to be deleted Vector<int> finishedTransitions; CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end(); for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) { ImplicitAnimation* anim = it->second.get(); if (!anim) continue; if (anim->postActive()) finishedTransitions.append(anim->animatingProperty()); } // Delete them size_t finishedTransitionCount = finishedTransitions.size(); for (size_t i = 0; i < finishedTransitionCount; ++i) m_transitions.remove(finishedTransitions[i]); // Make a list of animations to be deleted Vector<AtomicStringImpl*> finishedAnimations; AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) { KeyframeAnimation* anim = it->second.get(); if (!anim) continue; if (anim->postActive()) finishedAnimations.append(anim->name().impl()); } // Delete them size_t finishedAnimationCount = finishedAnimations.size(); for (size_t i = 0; i < finishedAnimationCount; ++i) m_keyframeAnimations.remove(finishedAnimations[i]); }
void CompositeAnimation::cleanupFinishedAnimations(RenderObject* renderer) { if (suspended()) return; // Make a list of transitions to be deleted Vector<int> finishedTransitions; CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { ImplicitAnimation* anim = it->second; if (!anim) continue; if (anim->postActive() && !anim->waitingForEndEvent()) finishedTransitions.append(anim->animatingProperty()); } // Delete them for (Vector<int>::iterator it = finishedTransitions.begin(); it != finishedTransitions.end(); ++it) { ImplicitAnimation* anim = m_transitions.get(*it); if (anim) { anim->reset(renderer); delete anim; } m_transitions.remove(*it); } // Make a list of animations to be deleted Vector<AtomicStringImpl*> finishedAnimations; AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end(); for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) { KeyframeAnimation* anim = it->second; if (!anim) continue; if (anim->postActive() && !anim->waitingForEndEvent()) finishedAnimations.append(anim->name().impl()); } // delete them for (Vector<AtomicStringImpl*>::iterator it = finishedAnimations.begin(); it != finishedAnimations.end(); ++it) { KeyframeAnimation* kfanim = m_keyframeAnimations.get(*it); if (kfanim) { kfanim->reset(renderer); delete kfanim; } m_keyframeAnimations.remove(*it); } }
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->second->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 Animation* anim = targetStyle->transitions()->animation(i); bool isActiveTransition = anim->duration() || anim->delay() > 0; int prop = anim->property(); if (prop == cAnimateNone) continue; bool all = prop == cAnimateAll; // 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 < AnimationBase::getNumProperties(); ++propertyIndex) { if (all) { // Get the next property which is not a shorthand. bool isShorthand; prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand); if (isShorthand) continue; } // ImplicitAnimations are always hashed by actual properties, never cAnimateAll 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).get(); 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)) { #if USE(ACCELERATED_COMPOSITING) // 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 (AnimationBase::animationOfPropertyIsAccelerated(prop) && !implAnim->isFallbackAnimating()) { if (!modifiedCurrentStyle) modifiedCurrentStyle = RenderStyle::clone(currentStyle); implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get()); } #endif 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 || AnimationBase::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<Animation*>(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->second.get(); if (!anim->active()) 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::updateTransitions(RenderElement* 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. for (auto& transition : m_transitions.values()) transition->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) { Animation& animation = targetStyle->transitions()->animation(i); bool isActiveTransition = !m_suspended && (animation.duration() || animation.delay() > 0); Animation::AnimationMode mode = animation.animationMode(); if (mode == Animation::AnimateNone) continue; CSSPropertyID prop = animation.property(); bool all = mode == Animation::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()); } LOG(Animations, "Removing existing ImplicitAnimation %p for property %s", implAnim, getPropertyName(prop)); 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 RefPtr<ImplicitAnimation> implicitAnimation = ImplicitAnimation::create(animation, prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle); LOG(Animations, "Created ImplicitAnimation %p for property %s duration %.2f delay %.2f", implicitAnimation.get(), getPropertyName(prop), animation.duration(), animation.delay()); m_transitions.set(prop, implicitAnimation.release()); } // We only need one pass for the single prop case if (!all) break; } } } // Make a list of transitions to be removed Vector<int> toBeRemoved; for (auto& transition : m_transitions.values()) { if (!transition->active()) { animationController().animationWillBeRemoved(transition.get()); toBeRemoved.append(transition->animatingProperty()); LOG(Animations, "Removing ImplicitAnimation %p for property %s", transition.get(), getPropertyName(transition->animatingProperty())); } } // Now remove the transitions from the list for (auto propertyToRemove : toBeRemoved) m_transitions.remove(propertyToRemove); }