| Index: Source/core/animation/css/CSSAnimations.cpp
|
| diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp
|
| index 7c1dbcc1d3f59b59f1f5f6b1d4322ea1240fe2c2..a75e00d0eb316e0a22e5377fa65ebdcf2de26057 100644
|
| --- a/Source/core/animation/css/CSSAnimations.cpp
|
| +++ b/Source/core/animation/css/CSSAnimations.cpp
|
| @@ -73,7 +73,7 @@ bool isLaterPhase(TimedItem::Phase target, TimedItem::Phase reference)
|
| }
|
|
|
| static void resolveKeyframes(StyleResolver* resolver, Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction,
|
| - WillBeHeapVector<KeyframeEffectModel::KeyframeVector>& resolvedKeyframes)
|
| + KeyframeEffectModel::KeyframeVector& keyframes)
|
| {
|
| // When the element is null, use its parent for scoping purposes.
|
| const Element* elementForScoping = element ? element : &parentElement;
|
| @@ -87,7 +87,6 @@ static void resolveKeyframes(StyleResolver* resolver, Element* element, const El
|
|
|
| // Construct and populate the style for each keyframe
|
| PropertySet specifiedProperties;
|
| - KeyframeEffectModel::KeyframeVector keyframes;
|
| for (size_t i = 0; i < styleKeyframes.size(); ++i) {
|
| const StyleKeyframe* styleKeyframe = styleKeyframes[i].get();
|
| // It's OK to pass a null element here.
|
| @@ -176,65 +175,6 @@ static void resolveKeyframes(StyleResolver* resolver, Element* element, const El
|
| }
|
| ASSERT(startKeyframe->properties().size() == allProperties.size());
|
| ASSERT(endKeyframe->properties().size() == allProperties.size());
|
| -
|
| - // Determine how many keyframes specify each property. Note that this must
|
| - // be done after we've filled in end keyframes.
|
| - typedef HashCountedSet<CSSPropertyID> PropertyCountedSet;
|
| - PropertyCountedSet propertyCounts;
|
| - for (size_t i = 0; i < numKeyframes; ++i) {
|
| - const PropertySet& properties = keyframes[i]->properties();
|
| - for (PropertySet::const_iterator iter = properties.begin(); iter != properties.end(); ++iter)
|
| - propertyCounts.add(*iter);
|
| - }
|
| -
|
| - // Split keyframes into groups, where each group contains only keyframes
|
| - // which specify all properties used in that group. Each group is animated
|
| - // in a separate animation, to allow per-keyframe timing functions to be
|
| - // applied correctly.
|
| - for (PropertyCountedSet::const_iterator iter = propertyCounts.begin(); iter != propertyCounts.end(); ++iter) {
|
| - const CSSPropertyID property = iter->key;
|
| - const size_t count = iter->value;
|
| - ASSERT(count <= numKeyframes);
|
| - if (count == numKeyframes)
|
| - continue;
|
| - KeyframeEffectModel::KeyframeVector splitOutKeyframes;
|
| - for (size_t i = 0; i < numKeyframes; i++) {
|
| - Keyframe* keyframe = keyframes[i].get();
|
| - if (!keyframe->properties().contains(property)) {
|
| - ASSERT(i && i != numKeyframes - 1);
|
| - continue;
|
| - }
|
| - RefPtrWillBeRawPtr<Keyframe> clonedKeyframe = Keyframe::create();
|
| - clonedKeyframe->setOffset(keyframe->offset());
|
| - clonedKeyframe->setEasing(keyframe->easing());
|
| - clonedKeyframe->setComposite(keyframe->composite());
|
| - clonedKeyframe->setPropertyValue(property, keyframe->propertyValue(property));
|
| - splitOutKeyframes.append(clonedKeyframe);
|
| - // Note that it's OK if this keyframe ends up having no
|
| - // properties. This can only happen when none of the properties
|
| - // are specified in all keyframes, in which case we won't animate
|
| - // anything with these keyframes.
|
| - keyframe->clearPropertyValue(property);
|
| - }
|
| - ASSERT(!splitOutKeyframes.first()->offset());
|
| - ASSERT(splitOutKeyframes.last()->offset() == 1);
|
| -#ifndef NDEBUG
|
| - for (size_t j = 0; j < splitOutKeyframes.size(); ++j)
|
| - ASSERT(splitOutKeyframes[j]->properties().size() == 1);
|
| -#endif
|
| - resolvedKeyframes.append(splitOutKeyframes);
|
| - }
|
| -
|
| - unsigned numPropertiesSpecifiedInAllKeyframes = keyframes.first()->properties().size();
|
| -#ifndef NDEBUG
|
| - for (size_t i = 1; i < numKeyframes; ++i)
|
| - ASSERT(keyframes[i]->properties().size() == numPropertiesSpecifiedInAllKeyframes);
|
| -#endif
|
| -
|
| - // If the animation specifies any keyframes, we always provide at least one
|
| - // vector of resolved keyframes, even if no properties are animated.
|
| - if (numPropertiesSpecifiedInAllKeyframes || resolvedKeyframes.isEmpty())
|
| - resolvedKeyframes.append(keyframes);
|
| }
|
|
|
| // Returns the default timing function.
|
| @@ -295,6 +235,7 @@ const PassRefPtr<TimingFunction> timingFromAnimationData(const CSSAnimationData*
|
| ASSERT(!timing.iterationStart);
|
| ASSERT(timing.playbackRate == 1);
|
| ASSERT(!std::isinf(timing.iterationDuration));
|
| + ASSERT(timing.timingFunction == LinearTimingFunction::preset());
|
|
|
| isPaused = animationData->isPlayStateSet() && animationData->playState() == AnimPlayStatePaused;
|
| return animationData->isTimingFunctionSet() ? animationData->timingFunction() : CSSAnimationData::initialAnimationTimingFunction();
|
| @@ -363,14 +304,8 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element
|
| AnimationMap::const_iterator existing(cssAnimations->m_animations.find(animationName));
|
| if (existing != cssAnimations->m_animations.end()) {
|
| inactive.remove(animationName);
|
| - const HashSet<RefPtr<AnimationPlayer> >& players = existing->value;
|
| - ASSERT(!players.isEmpty());
|
| - bool isFirstAnimationPlayerPaused = (*players.begin())->paused();
|
| -#ifndef NDEBUG
|
| - for (HashSet<RefPtr<AnimationPlayer> >::const_iterator iter = players.begin(); iter != players.end(); ++iter)
|
| - ASSERT((*iter)->paused() == isFirstAnimationPlayerPaused);
|
| -#endif
|
| - if ((animationData->playState() == AnimPlayStatePaused) != isFirstAnimationPlayerPaused) {
|
| + AnimationPlayer* player = existing->value.get();
|
| + if ((animationData->playState() == AnimPlayStatePaused) != player->paused()) {
|
| ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
|
| update->toggleAnimationPaused(animationName);
|
| }
|
| @@ -380,19 +315,12 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element
|
|
|
| Timing timing;
|
| bool isPaused;
|
| - RefPtr<TimingFunction> defaultTimingFunction = timingFromAnimationData(animationData, timing, isPaused);
|
| - WillBeHeapVector<KeyframeEffectModel::KeyframeVector> resolvedKeyframes;
|
| - resolveKeyframes(resolver, element, parentElement, style, parentStyle, animationName, defaultTimingFunction.get(), resolvedKeyframes);
|
| + RefPtr<TimingFunction> keyframeTimingFunction = timingFromAnimationData(animationData, timing, isPaused);
|
| + KeyframeEffectModel::KeyframeVector resolvedKeyframes;
|
| + resolveKeyframes(resolver, element, parentElement, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes);
|
| if (!resolvedKeyframes.isEmpty()) {
|
| - HashSet<RefPtr<InertAnimation> > animations;
|
| - for (size_t j = 0; j < resolvedKeyframes.size(); ++j) {
|
| - ASSERT(!resolvedKeyframes[j].isEmpty());
|
| - timing.timingFunction = LinearTimingFunction::preset();
|
| - // FIXME: crbug.com/268791 - Keyframes are already normalized, perhaps there should be a flag on KeyframeEffectModel to skip normalization.
|
| - animations.add(InertAnimation::create(KeyframeEffectModel::create(resolvedKeyframes[j]), timing, isPaused));
|
| - }
|
| ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
|
| - update->startAnimation(animationName, animations);
|
| + update->startAnimation(animationName, InertAnimation::create(KeyframeEffectModel::create(resolvedKeyframes), timing, isPaused));
|
| }
|
| }
|
| }
|
| @@ -400,7 +328,7 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element
|
| ASSERT(inactive.isEmpty() || cssAnimations);
|
| for (HashSet<AtomicString>::const_iterator iter = inactive.begin(); iter != inactive.end(); ++iter) {
|
| ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange());
|
| - update->cancelAnimation(*iter, cssAnimations->m_animations.get(*iter));
|
| + update->cancelAnimation(*iter, *cssAnimations->m_animations.get(*iter));
|
| }
|
| }
|
|
|
| @@ -421,41 +349,27 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element)
|
| DisableCompositingQueryAsserts disabler;
|
|
|
| for (Vector<AtomicString>::const_iterator iter = update->cancelledAnimationNames().begin(); iter != update->cancelledAnimationNames().end(); ++iter) {
|
| - const HashSet<RefPtr<AnimationPlayer> >& players = m_animations.take(*iter);
|
| - for (HashSet<RefPtr<AnimationPlayer> >::const_iterator iter = players.begin(); iter != players.end(); ++iter)
|
| - (*iter)->cancel();
|
| + m_animations.take(*iter)->cancel();
|
| }
|
|
|
| for (Vector<AtomicString>::const_iterator iter = update->animationsWithPauseToggled().begin(); iter != update->animationsWithPauseToggled().end(); ++iter) {
|
| - const HashSet<RefPtr<AnimationPlayer> >& players = m_animations.get(*iter);
|
| - ASSERT(!players.isEmpty());
|
| - bool isFirstAnimationPlayerPaused = (*players.begin())->paused();
|
| - for (HashSet<RefPtr<AnimationPlayer> >::const_iterator iter = players.begin(); iter != players.end(); ++iter) {
|
| - AnimationPlayer* player = iter->get();
|
| - ASSERT(player->paused() == isFirstAnimationPlayerPaused);
|
| - if (isFirstAnimationPlayerPaused)
|
| - player->unpause();
|
| - else
|
| - player->pause();
|
| - }
|
| + AnimationPlayer* player = m_animations.get(*iter);
|
| + if (player->paused())
|
| + player->unpause();
|
| + else
|
| + player->pause();
|
| }
|
|
|
| for (Vector<CSSAnimationUpdate::NewAnimation>::const_iterator iter = update->newAnimations().begin(); iter != update->newAnimations().end(); ++iter) {
|
| + const InertAnimation* inertAnimation = iter->animation.get();
|
| OwnPtr<AnimationEventDelegate> eventDelegate = adoptPtr(new AnimationEventDelegate(element, iter->name));
|
| - HashSet<RefPtr<AnimationPlayer> > players;
|
| - for (HashSet<RefPtr<InertAnimation> >::const_iterator animationsIter = iter->animations.begin(); animationsIter != iter->animations.end(); ++animationsIter) {
|
| - const InertAnimation* inertAnimation = animationsIter->get();
|
| - // The event delegate is set on the the first animation only. We
|
| - // rely on the behavior of OwnPtr::release() to achieve this.
|
| - RefPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release());
|
| - AnimationPlayer* player = element->document().timeline().createAnimationPlayer(animation.get());
|
| - if (inertAnimation->paused())
|
| - player->pause();
|
| - element->document().cssPendingAnimations().add(player);
|
| - player->update();
|
| - players.add(player);
|
| - }
|
| - m_animations.set(iter->name, players);
|
| + RefPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release());
|
| + RefPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(animation.get());
|
| + if (inertAnimation->paused())
|
| + player->pause();
|
| + element->document().cssPendingAnimations().add(player.get());
|
| + player->update();
|
| + m_animations.set(iter->name, player.get());
|
| }
|
|
|
| // Transitions that are run on the compositor only update main-thread state
|
| @@ -638,11 +552,8 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const
|
|
|
| void CSSAnimations::cancel()
|
| {
|
| - for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animations.end(); ++iter) {
|
| - const HashSet<RefPtr<AnimationPlayer> >& players = iter->value;
|
| - for (HashSet<RefPtr<AnimationPlayer> >::const_iterator animationsIter = players.begin(); animationsIter != players.end(); ++animationsIter)
|
| - (*animationsIter)->cancel();
|
| - }
|
| + for (AnimationMap::iterator iter = m_animations.begin(); iter != m_animations.end(); ++iter)
|
| + iter->value->cancel();
|
|
|
| for (TransitionMap::iterator iter = m_transitions.begin(); iter != m_transitions.end(); ++iter)
|
| iter->value.transition->player()->cancel();
|
| @@ -665,9 +576,7 @@ void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* u
|
|
|
| Vector<InertAnimation*> newAnimations;
|
| for (size_t i = 0; i < update->newAnimations().size(); ++i) {
|
| - HashSet<RefPtr<InertAnimation> > animations = update->newAnimations()[i].animations;
|
| - for (HashSet<RefPtr<InertAnimation> >::const_iterator animationsIter = animations.begin(); animationsIter != animations.end(); ++animationsIter)
|
| - newAnimations.append(animationsIter->get());
|
| + newAnimations.append(update->newAnimations()[i].animation.get());
|
| }
|
| WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, &newAnimations, &update->cancelledAnimationAnimationPlayers(), Animation::DefaultPriority));
|
| update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations);
|
|
|