Changeset 287827 in webkit


Ignore:
Timestamp:
Jan 9, 2022 1:19:45 PM (6 months ago)
Author:
graouts@webkit.org
Message:

Implicit keyframe for a CSS Animation should always use the underlying style
https://bugs.webkit.org/show_bug.cgi?id=235014

Reviewed by Antti Koivisto.

LayoutTests/imported/w3c:

Add a new WPT which changes the underlying style for a property that is being
animated with an @keyframes rule that doesn't explicitly specify this value
on all keyframes.

  • web-platform-tests/css/css-animations/animation-change-underlying-value-changed-in-flight-expected.txt: Added.
  • web-platform-tests/css/css-animations/animation-change-underlying-value-changed-in-flight.html: Added.

Source/WebCore:

When resolving keyframes for a CSS Animation in Style::Resolver::keyframeStylesForAnimation(),
we would fill implicit keyframes based on the style at the time the animation was created.
However, the underlying style may change at any point while the CSS Animation is in flight,
so we should not be filling those values.

The code that actually resolves animated styles already knows how to handle this case, which
we already supported correctly for JS-originated animations. The only thing we need to do is
to ensure we fill implicit keyframes when calling getKeyframes().

This surfaced an issue with KeyframeList::copyKeyframes() where we only copied the styles
from one set of keyframes to another, but not the timing function, which would cause a
getKeyframes() test to regress. We should also make sure to copy the composite operation
for when we support the animation-composition property (see bug 232086).

Test: imported/w3c/web-platform-tests/css/css-animations/animation-change-underlying-value-changed-in-flight.html

  • animation/KeyframeEffect.cpp:

(WebCore::KeyframeEffect::getKeyframes):

  • rendering/style/KeyframeList.cpp:

(WebCore::KeyframeList::copyKeyframes):

  • style/StyleResolver.cpp:

(WebCore::Style::Resolver::keyframeStylesForAnimation):

Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r287826 r287827  
     12022-01-09  Antoine Quint  <graouts@webkit.org>
     2
     3        Implicit keyframe for a CSS Animation should always use the underlying style
     4        https://bugs.webkit.org/show_bug.cgi?id=235014
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Add a new WPT which changes the underlying style for a property that is being
     9        animated with an @keyframes rule that doesn't explicitly specify this value
     10        on all keyframes.
     11
     12        * web-platform-tests/css/css-animations/animation-change-underlying-value-changed-in-flight-expected.txt: Added.
     13        * web-platform-tests/css/css-animations/animation-change-underlying-value-changed-in-flight.html: Added.
     14
    1152022-01-09  Antoine Quint  <graouts@webkit.org>
    216
  • trunk/Source/WebCore/ChangeLog

    r287826 r287827  
     12022-01-09  Antoine Quint  <graouts@webkit.org>
     2
     3        Implicit keyframe for a CSS Animation should always use the underlying style
     4        https://bugs.webkit.org/show_bug.cgi?id=235014
     5
     6        Reviewed by Antti Koivisto.
     7
     8        When resolving keyframes for a CSS Animation in Style::Resolver::keyframeStylesForAnimation(),
     9        we would fill implicit keyframes based on the style at the time the animation was created.
     10        However, the underlying style may change at any point while the CSS Animation is in flight,
     11        so we should not be filling those values.
     12
     13        The code that actually resolves animated styles already knows how to handle this case, which
     14        we already supported correctly for JS-originated animations. The only thing we need to do is
     15        to ensure we fill implicit keyframes when calling getKeyframes().
     16
     17        This surfaced an issue with KeyframeList::copyKeyframes() where we only copied the styles
     18        from one set of keyframes to another, but not the timing function, which would cause a
     19        getKeyframes() test to regress. We should also make sure to copy the composite operation
     20        for when we support the animation-composition property (see bug 232086).
     21
     22        Test: imported/w3c/web-platform-tests/css/css-animations/animation-change-underlying-value-changed-in-flight.html
     23
     24        * animation/KeyframeEffect.cpp:
     25        (WebCore::KeyframeEffect::getKeyframes):
     26        * rendering/style/KeyframeList.cpp:
     27        (WebCore::KeyframeList::copyKeyframes):
     28        * style/StyleResolver.cpp:
     29        (WebCore::Style::Resolver::keyframeStylesForAnimation):
     30
    1312022-01-09  Antoine Quint  <graouts@webkit.org>
    232
  • trunk/Source/WebCore/animation/KeyframeEffect.cpp

    r287826 r287827  
    640640        auto computedStyleExtractor = ComputedStyleExtractor(target, false, m_pseudoId);
    641641
     642        KeyframeList computedKeyframes(m_blendingKeyframes.animationName());
     643        computedKeyframes.copyKeyframes(m_blendingKeyframes);
     644        computedKeyframes.fillImplicitKeyframes(*m_target, m_target->styleResolver(), lastStyleChangeEventStyle, nullptr);
     645
    642646        auto keyframeRules = [&]() -> const Vector<Ref<StyleRuleKeyframe>> {
    643647            if (!is<CSSAnimation>(animation()))
     
    649653                return { };
    650654
    651             return styleScope->resolver().keyframeRulesForName(m_blendingKeyframes.animationName());
     655            return styleScope->resolver().keyframeRulesForName(computedKeyframes.animationName());
    652656        }();
    653657
     
    663667
    664668        // We need to establish which properties are implicit for 0% and 100%.
    665         HashSet<CSSPropertyID> zeroKeyframeProperties = m_blendingKeyframes.properties();
    666         HashSet<CSSPropertyID> oneKeyframeProperties = m_blendingKeyframes.properties();
     669        HashSet<CSSPropertyID> zeroKeyframeProperties = computedKeyframes.properties();
     670        HashSet<CSSPropertyID> oneKeyframeProperties = computedKeyframes.properties();
    667671        zeroKeyframeProperties.remove(CSSPropertyCustom);
    668672        oneKeyframeProperties.remove(CSSPropertyCustom);
    669         for (size_t i = 0; i < m_blendingKeyframes.size(); ++i) {
    670             auto& keyframe = m_blendingKeyframes[i];
     673        for (size_t i = 0; i < computedKeyframes.size(); ++i) {
     674            auto& keyframe = computedKeyframes[i];
    671675            if (!keyframe.key()) {
    672676                for (auto cssPropertyId : keyframe.properties())
     
    678682        }
    679683
    680         for (size_t i = 0; i < m_blendingKeyframes.size(); ++i) {
     684        for (size_t i = 0; i < computedKeyframes.size(); ++i) {
    681685            // 1. Initialize a dictionary object, output keyframe, using the following definition:
    682686            //
     
    688692            // };
    689693
    690             auto& keyframe = m_blendingKeyframes[i];
     694            auto& keyframe = computedKeyframes[i];
    691695
    692696            // 2. Set offset, computedOffset, easing members of output keyframe to the respective values keyframe offset, computed keyframe offset,
     
    696700            computedKeyframe.computedOffset = keyframe.key();
    697701            // For CSS transitions, all keyframes should return "linear" since the effect's global timing function applies.
    698             computedKeyframe.easing = is<CSSTransition>(animation()) ? "linear" : timingFunctionForKeyframeAtIndex(i)->cssText();
     702            computedKeyframe.easing = is<CSSTransition>(animation()) ? "linear" : timingFunctionForBlendingKeyframe(keyframe)->cssText();
    699703
    700704            auto outputKeyframe = convertDictionaryToJS(lexicalGlobalObject, *jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject), computedKeyframe);
  • trunk/Source/WebCore/rendering/style/KeyframeList.cpp

    r287517 r287827  
    8989        for (auto propertyId : keyframe.properties())
    9090            keyframeValue.addProperty(propertyId);
     91        keyframeValue.setTimingFunction(keyframe.timingFunction());
     92        keyframeValue.setCompositeOperation(keyframe.compositeOperation());
    9193        insert(WTFMove(keyframeValue));
    9294    }
  • trunk/Source/WebCore/style/StyleResolver.cpp

    r287820 r287827  
    400400        }
    401401    }
    402 
    403     list.fillImplicitKeyframes(element, *this, elementStyle, context.parentStyle);
    404402}
    405403
Note: See TracChangeset for help on using the changeset viewer.