Chromium Code Reviews| Index: Source/core/animation/css/CSSAnimations.cpp |
| diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp |
| index 7ca241a49405e2f544fe2611b1400edd229aeb11..6fe14b7081543bc02fa388adfa2c14e1c365fd54 100644 |
| --- a/Source/core/animation/css/CSSAnimations.cpp |
| +++ b/Source/core/animation/css/CSSAnimations.cpp |
| @@ -36,9 +36,9 @@ |
| #include "core/animation/AnimationPlayer.h" |
| #include "core/animation/AnimationTimeline.h" |
| #include "core/animation/CompositorAnimations.h" |
| +#include "core/animation/DeferredLegacyStyleInterpolation.h" |
| #include "core/animation/Interpolation.h" |
| #include "core/animation/KeyframeEffectModel.h" |
| -#include "core/animation/LegacyStyleInterpolation.h" |
| #include "core/animation/css/CSSAnimatableValueFactory.h" |
| #include "core/animation/css/CSSPropertyEquality.h" |
| #include "core/css/CSSKeyframeRule.h" |
| @@ -85,15 +85,15 @@ CSSPropertyID propertyForAnimation(CSSPropertyID property) |
| return property; |
| } |
| -static void resolveKeyframes(StyleResolver* resolver, const Element* animatingElement, Element& element, const LayoutStyle& style, LayoutStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction, |
| - AnimatableValueKeyframeVector& keyframes) |
| +static PassRefPtrWillBeRawPtr<StringKeyframeEffectModel> createKeyframeEffect(StyleResolver* resolver, const Element* animatingElement, Element& element, const LayoutStyle& style, LayoutStyle* parentStyle, |
| + const AtomicString& name, TimingFunction* defaultTimingFunction) |
| { |
| // When the animating element is null, use its parent for scoping purposes. |
| const Element* elementForScoping = animatingElement ? animatingElement : &element; |
| const StyleRuleKeyframes* keyframesRule = resolver->findKeyframesRule(elementForScoping, name); |
| - if (!keyframesRule) |
| - return; |
| + ASSERT(keyframesRule); |
| + StringKeyframeVector keyframes; |
| const WillBeHeapVector<RefPtrWillBeMember<StyleRuleKeyframe>>& styleKeyframes = keyframesRule->keyframes(); |
| // Construct and populate the style for each keyframe |
| @@ -101,7 +101,7 @@ static void resolveKeyframes(StyleResolver* resolver, const Element* animatingEl |
| for (size_t i = 0; i < styleKeyframes.size(); ++i) { |
| const StyleRuleKeyframe* styleKeyframe = styleKeyframes[i].get(); |
| RefPtr<LayoutStyle> keyframeStyle = resolver->styleForKeyframe(element, style, parentStyle, styleKeyframe, name); |
| - RefPtrWillBeRawPtr<AnimatableValueKeyframe> keyframe = AnimatableValueKeyframe::create(); |
| + RefPtrWillBeRawPtr<StringKeyframe> keyframe = StringKeyframe::create(); |
| const Vector<double>& offsets = styleKeyframe->keys(); |
| ASSERT(!offsets.isEmpty()); |
| keyframe->setOffset(offsets[0]); |
| @@ -123,13 +123,13 @@ static void resolveKeyframes(StyleResolver* resolver, const Element* animatingEl |
| } |
| keyframe->setEasing(timingFunction.release()); |
| } else if (CSSPropertyMetadata::isAnimatableProperty(property)) { |
| - keyframe->setPropertyValue(property, CSSAnimatableValueFactory::create(property, *keyframeStyle).get()); |
| + keyframe->setPropertyValue(property, properties.propertyAt(j).value()); |
| } |
| } |
| keyframes.append(keyframe); |
| // The last keyframe specified at a given offset is used. |
| for (size_t j = 1; j < offsets.size(); ++j) { |
| - keyframes.append(toAnimatableValueKeyframe(keyframe->cloneWithOffset(offsets[j]).get())); |
| + keyframes.append(toStringKeyframe(keyframe->cloneWithOffset(offsets[j]).get())); |
| } |
| } |
| @@ -154,16 +154,16 @@ static void resolveKeyframes(StyleResolver* resolver, const Element* animatingEl |
| keyframes.shrink(targetIndex + 1); |
| // Add 0% and 100% keyframes if absent. |
| - RefPtrWillBeRawPtr<AnimatableValueKeyframe> startKeyframe = keyframes.isEmpty() ? nullptr : keyframes[0]; |
| + RefPtrWillBeRawPtr<StringKeyframe> startKeyframe = keyframes.isEmpty() ? nullptr : keyframes[0]; |
| if (!startKeyframe || keyframes[0]->offset() != 0) { |
| - startKeyframe = AnimatableValueKeyframe::create(); |
| + startKeyframe = StringKeyframe::create(); |
| startKeyframe->setOffset(0); |
| startKeyframe->setEasing(defaultTimingFunction); |
| keyframes.prepend(startKeyframe); |
| } |
| - RefPtrWillBeRawPtr<AnimatableValueKeyframe> endKeyframe = keyframes[keyframes.size() - 1]; |
| + RefPtrWillBeRawPtr<StringKeyframe> endKeyframe = keyframes[keyframes.size() - 1]; |
| if (endKeyframe->offset() != 1) { |
| - endKeyframe = AnimatableValueKeyframe::create(); |
| + endKeyframe = StringKeyframe::create(); |
| endKeyframe->setOffset(1); |
| endKeyframe->setEasing(defaultTimingFunction); |
| keyframes.append(endKeyframe); |
| @@ -172,7 +172,7 @@ static void resolveKeyframes(StyleResolver* resolver, const Element* animatingEl |
| ASSERT(!keyframes.first()->offset()); |
| ASSERT(keyframes.last()->offset() == 1); |
| - // Snapshot current property values for 0% and 100% if missing. |
| + // FIXME: This is only used for use counting neutral keyframes running on the compositor. |
| PropertySet allProperties; |
| for (const auto& keyframe : keyframes) { |
| for (CSSPropertyID property : keyframe->properties()) |
| @@ -188,19 +188,33 @@ static void resolveKeyframes(StyleResolver* resolver, const Element* animatingEl |
| bool endNeedsValue = missingEndValues && !endKeyframeProperties.contains(property); |
| if (!startNeedsValue && !endNeedsValue) |
| continue; |
| - RefPtrWillBeRawPtr<AnimatableValue> snapshotValue = CSSAnimatableValueFactory::create(property, style); |
| - if (startNeedsValue) |
| - startKeyframe->setPropertyValue(property, snapshotValue.get()); |
| - if (endNeedsValue) |
| - endKeyframe->setPropertyValue(property, snapshotValue.get()); |
| - if (property == CSSPropertyOpacity || property == CSSPropertyTransform) |
| + if (CompositorAnimations::isCompositableProperty(property)) |
| UseCounter::count(elementForScoping->document(), UseCounter::SyntheticKeyframesInCompositedCSSAnimation); |
| } |
| } |
| - ASSERT(startKeyframe->properties().size() == allProperties.size()); |
| - ASSERT(endKeyframe->properties().size() == allProperties.size()); |
| + |
| + RefPtrWillBeRawPtr<StringKeyframeEffectModel> effect = StringKeyframeEffectModel::create(keyframes, &keyframes[0]->easing()); |
| + effect->snapshotCompositableProperties(animatingElement, style); // FIXME: Remove this once CompositorAnimations no longer depends on AnimatableValues |
| + effect->forceConversionsToAnimatableValues(&element); // FIXME: Remove this once LegacyStyleInterpolation is removed from StringKeyframe |
| + return effect; |
| } |
| +CSSAnimationUpdate::UpdatedAnimationStyle::CompositableStyleSnapshot snapshotCompositableProperties(LayoutObject* renderer, const LayoutStyle& newStyle, const AnimationEffect* effect) |
| +{ |
| + CSSAnimationUpdate::UpdatedAnimationStyle::CompositableStyleSnapshot snapshot; |
| + if (!renderer) |
| + return snapshot; |
| + |
| + const LayoutStyle& oldStyle = *renderer->style(); |
|
Timothy Loh
2015/02/11 03:54:36
renderer->styleRef()
|
| + if (!CSSPropertyEquality::propertiesEqual(CSSPropertyOpacity, oldStyle, newStyle) && effect->affects(CSSPropertyOpacity)) |
| + snapshot.opacity = CSSAnimatableValueFactory::create(CSSPropertyOpacity, newStyle); |
| + if (!CSSPropertyEquality::propertiesEqual(CSSPropertyTransform, oldStyle, newStyle) && effect->affects(CSSPropertyTransform)) |
| + snapshot.transform = CSSAnimatableValueFactory::create(CSSPropertyTransform, newStyle); |
| + if (!CSSPropertyEquality::propertiesEqual(CSSPropertyWebkitFilter, oldStyle, newStyle) && effect->affects(CSSPropertyWebkitFilter)) |
| + snapshot.webkitFilter = CSSAnimatableValueFactory::create(CSSPropertyWebkitFilter, newStyle); |
| + |
| + return snapshot; |
| +} |
| } // namespace |
| CSSAnimations::CSSAnimations() |
| @@ -239,10 +253,12 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
| { |
| const ActiveAnimations* activeAnimations = animatingElement ? animatingElement->activeAnimations() : nullptr; |
| + bool isAnimationStyleChange = activeAnimations && activeAnimations->isAnimationStyleChange(); |
| + |
| #if !ENABLE(ASSERT) |
| // If we're in an animation style change, no animations can have started, been cancelled or changed play state. |
| // When ASSERT is enabled, we verify this optimization. |
| - if (activeAnimations && activeAnimations->isAnimationStyleChange()) |
| + if (isAnimationStyleChange) |
| return; |
| #endif |
| @@ -281,17 +297,22 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
| const RunningAnimation* runningAnimation = existing->value.get(); |
| AnimationPlayer* player = runningAnimation->player.get(); |
| - ASSERT(keyframesRule); |
| if (keyframesRule != runningAnimation->styleRule || keyframesRule->version() != runningAnimation->styleRuleVersion || runningAnimation->specifiedTiming != specifiedTiming) { |
| - AnimatableValueKeyframeVector resolvedKeyframes; |
| - resolveKeyframes(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); |
| - |
| - update->updateAnimation(animationName, player, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), |
| + ASSERT(!isAnimationStyleChange); |
| + update->updateAnimation(animationName, player, InertAnimation::create( |
| + createKeyframeEffect(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get()), |
| timing, isPaused, player->currentTimeInternal()), specifiedTiming, keyframesRule); |
| + } else if (!isAnimationStyleChange && player->source() && player->source()->isAnimation()) { |
| + AnimationEffect* effect = toAnimation(player->source())->effect(); |
| + if (effect && effect->isKeyframeEffectModel()) { |
| + KeyframeEffectModelBase* keyframeEffect = toKeyframeEffectModelBase(effect); |
| + if (keyframeEffect->hasSyntheticKeyframes()) |
| + update->updateAnimationStyle(player, keyframeEffect, snapshotCompositableProperties(animatingElement->renderer(), style, effect)); |
| + } |
| } |
| if (isPaused != player->paused()) { |
| - ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()); |
| + ASSERT(!isAnimationStyleChange); |
| update->toggleAnimationPaused(animationName); |
| } |
| @@ -299,18 +320,16 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
| } |
| } |
| - AnimatableValueKeyframeVector resolvedKeyframes; |
| - resolveKeyframes(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); |
| - if (!resolvedKeyframes.isEmpty()) { |
| - ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()); |
| - update->startAnimation(animationName, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0), specifiedTiming, keyframesRule); |
| - } |
| + ASSERT(!isAnimationStyleChange); |
| + update->startAnimation(animationName, InertAnimation::create( |
| + createKeyframeEffect(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get()), |
| + timing, isPaused, 0), specifiedTiming, keyframesRule); |
| } |
| } |
| ASSERT(inactive.isEmpty() || cssAnimations); |
| for (const AtomicString& animationName : inactive) { |
| - ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()); |
| + ASSERT(!isAnimationStyleChange); |
| update->cancelAnimation(animationName, *cssAnimations->m_animations.get(animationName)->player); |
| } |
| } |
| @@ -356,6 +375,21 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
| m_animations.find(entry.name)->value->update(entry); |
| } |
| + for (const auto& styleUpdate : update->animationsWithStyleUpdates()) { |
| + styleUpdate.effect->forEachInterpolation([](Interpolation& interpolation) { |
| + if (interpolation.isStyleInterpolation() && toStyleInterpolation(interpolation).isDeferredLegacyStyleInterpolation()) |
| + toDeferredLegacyStyleInterpolation(toStyleInterpolation(interpolation)).underlyingStyleChanged(); |
| + }); |
| + |
| + if (styleUpdate.snapshot.opacity || styleUpdate.snapshot.transform || styleUpdate.snapshot.webkitFilter) { |
| + styleUpdate.effect->updateNeutralKeyframeAnimatableValues(CSSPropertyOpacity, styleUpdate.snapshot.opacity); |
| + styleUpdate.effect->updateNeutralKeyframeAnimatableValues(CSSPropertyTransform, styleUpdate.snapshot.transform); |
| + styleUpdate.effect->updateNeutralKeyframeAnimatableValues(CSSPropertyWebkitFilter, styleUpdate.snapshot.webkitFilter); |
| + styleUpdate.player->setOutdated(); |
| + styleUpdate.player->setCompositorPending(true); |
| + } |
| + } |
| + |
| for (const auto& entry : update->newAnimations()) { |
| const InertAnimation* inertAnimation = entry.animation.get(); |
| OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillBeNoop(new AnimationEventDelegate(element, entry.name)); |