Title: [288571] trunk
Revision
288571
Author
grao...@webkit.org
Date
2022-01-25 11:41:29 -0800 (Tue, 25 Jan 2022)

Log Message

Deduplication for @keyframes rules should account for animation-composition
https://bugs.webkit.org/show_bug.cgi?id=235596

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

Import test recently added in WPT via https://github.com/web-platform-tests/wpt/pull/32495.
We pass them all with the source change.

* web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt:
* web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html:

Source/WebCore:

The CSS Animations Level 2 spec recently changed to account for animation-composition
when deduplicating @keyframes rules (see https://github.com/w3c/csswg-drafts/pull/6974).

* animation/CompositeOperation.h:
* style/StyleResolver.cpp:
(WebCore::Style::Resolver::keyframeRulesForName const):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (288570 => 288571)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-25 19:38:36 UTC (rev 288570)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-01-25 19:41:29 UTC (rev 288571)
@@ -1,3 +1,16 @@
+2022-01-25  Antoine Quint  <grao...@webkit.org>
+
+        Deduplication for @keyframes rules should account for animation-composition
+        https://bugs.webkit.org/show_bug.cgi?id=235596
+
+        Reviewed by Dean Jackson.
+
+        Import test recently added in WPT via https://github.com/web-platform-tests/wpt/pull/32495.
+        We pass them all with the source change.
+
+        * web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt:
+        * web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html:
+
 2022-01-25  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         REGRESSION(r281419): iCloud.com Notes web app fonts render incorrectly

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt (288570 => 288571)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt	2022-01-25 19:38:36 UTC (rev 288570)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative-expected.txt	2022-01-25 19:41:29 UTC (rev 288571)
@@ -17,6 +17,8 @@
 PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time, and all with the same easing function
 PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different easing functions
 PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different but equivalent easing functions
+PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different composite operations
+PASS KeyframeEffect.getKeyframes() returns expected frames for an animation with multiple keyframes for the same time and with different easing functions and composite operations
 PASS KeyframeEffect.getKeyframes() returns expected frames for overlapping keyframes
 PASS KeyframeEffect.getKeyframes() returns expected values for animations with filter properties and missing keyframes
 PASS KeyframeEffect.getKeyframes() returns expected values for animation with drop-shadow of filter property

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html (288570 => 288571)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html	2022-01-25 19:38:36 UTC (rev 288570)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html	2022-01-25 19:41:29 UTC (rev 288571)
@@ -125,6 +125,28 @@
   to   { margin-top: 20px; margin-right: 20px; margin-bottom: 20px; }
 }
 
+@keyframes anim-merge-offset-and-composite {
+  from { color: rgb(0, 0, 0); animation-composition: add; }
+  to   { color: rgb(255, 255, 255); }
+  from { margin-top: 8px; animation-composition: accumulate; }
+  to   { margin-top: 16px; }
+  from { font-size: 16px; animation-composition: add; }
+  to   { font-size: 32px; }
+  from { padding-left: 2px; animation-composition: accumulate; }
+  to   { padding-left: 4px; }
+}
+
+@keyframes anim-merge-offset-easing-and-composite {
+  from { color: rgb(0, 0, 0); animation-composition: add; }
+  to   { color: rgb(255, 255, 255); }
+  from { margin-top: 8px; animation-composition: accumulate; }
+  to   { margin-top: 16px; }
+  from { font-size: 16px; animation-composition: add; animation-timing-function: linear; }
+  to   { font-size: 32px; }
+  from { padding-left: 2px; animation-composition: accumulate; }
+  to   { padding-left: 4px; }
+}
+
 @keyframes anim-overriding {
   from          { padding-top: 50px }
   50%, from     { padding-top: 30px } /* wins: 0% */
@@ -530,6 +552,48 @@
 
 test(t => {
   const div = addDiv(t);
+  div.style.animation = 'anim-merge-offset-and-composite 100s';
+
+  const frames = getKeyframes(div);
+
+  const expected = [
+    { offset: 0, computedOffset: 0, easing: "ease", composite: "add",
+      color: "rgb(0, 0, 0)", fontSize: "16px" },
+    { offset: 0, computedOffset: 0, easing: "ease", composite: "accumulate",
+      marginTop: "8px", paddingLeft: "2px" },
+    { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
+      color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
+      paddingLeft: "4px" },
+  ];
+  assert_frame_lists_equal(frames, expected);
+}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
+   'animation with multiple keyframes for the same time and with ' +
+   'different composite operations');
+
+test(t => {
+  const div = addDiv(t);
+  div.style.animation = 'anim-merge-offset-easing-and-composite 100s';
+
+  const frames = getKeyframes(div);
+
+  const expected = [
+    { offset: 0, computedOffset: 0, easing: "ease", composite: "add",
+      color: "rgb(0, 0, 0)" },
+    { offset: 0, computedOffset: 0, easing: "ease", composite: "accumulate",
+      marginTop: "8px", paddingLeft: "2px" },
+    { offset: 0, computedOffset: 0, easing: "linear", composite: "add",
+      fontSize: "16px" },
+    { offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
+      color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
+      paddingLeft: "4px" },
+  ];
+  assert_frame_lists_equal(frames, expected);
+}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
+   'animation with multiple keyframes for the same time and with ' +
+   'different easing functions and composite operations');
+
+test(t => {
+  const div = addDiv(t);
   div.style.animation = 'anim-overriding 100s';
 
   const frames = getKeyframes(div);

Modified: trunk/Source/WebCore/ChangeLog (288570 => 288571)


--- trunk/Source/WebCore/ChangeLog	2022-01-25 19:38:36 UTC (rev 288570)
+++ trunk/Source/WebCore/ChangeLog	2022-01-25 19:41:29 UTC (rev 288571)
@@ -1,3 +1,17 @@
+2022-01-25  Antoine Quint  <grao...@webkit.org>
+
+        Deduplication for @keyframes rules should account for animation-composition
+        https://bugs.webkit.org/show_bug.cgi?id=235596
+
+        Reviewed by Dean Jackson.
+
+        The CSS Animations Level 2 spec recently changed to account for animation-composition
+        when deduplicating @keyframes rules (see https://github.com/w3c/csswg-drafts/pull/6974).
+
+        * animation/CompositeOperation.h:
+        * style/StyleResolver.cpp:
+        (WebCore::Style::Resolver::keyframeRulesForName const):
+
 2022-01-25  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         REGRESSION(r281419): iCloud.com Notes web app fonts render incorrectly

Modified: trunk/Source/WebCore/animation/CompositeOperation.h (288570 => 288571)


--- trunk/Source/WebCore/animation/CompositeOperation.h	2022-01-25 19:38:36 UTC (rev 288570)
+++ trunk/Source/WebCore/animation/CompositeOperation.h	2022-01-25 19:41:29 UTC (rev 288571)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include <optional>
+#include <wtf/HashTraits.h>
 
 namespace WebCore {
 
@@ -36,3 +37,7 @@
 std::optional<CompositeOperation> toCompositeOperation(const CSSValue&);
 
 } // namespace WebCore
+
+namespace WTF {
+template<> struct DefaultHash<WebCore::CompositeOperation> : IntHash<WebCore::CompositeOperation> { };
+} // namespace WTF

Modified: trunk/Source/WebCore/style/StyleResolver.cpp (288570 => 288571)


--- trunk/Source/WebCore/style/StyleResolver.cpp	2022-01-25 19:38:36 UTC (rev 288570)
+++ trunk/Source/WebCore/style/StyleResolver.cpp	2022-01-25 19:41:29 UTC (rev 288571)
@@ -320,6 +320,14 @@
     if (it == m_keyframesRuleMap.end())
         return { };
 
+    auto compositeOperationForKeyframe = [](Ref<StyleRuleKeyframe> keyframe) -> CompositeOperation {
+        if (auto compositeOperationCSSValue = keyframe->properties().getPropertyCSSValue(CSSPropertyAnimationComposition)) {
+            if (auto compositeOperation = toCompositeOperation(*compositeOperationCSSValue))
+                return *compositeOperation;
+        }
+        return Animation::initialCompositeOperation();
+    };
+
     auto timingFunctionForKeyframe = [](Ref<StyleRuleKeyframe> keyframe) -> RefPtr<const TimingFunction> {
         if (auto timingFunctionCSSValue = keyframe->properties().getPropertyCSSValue(CSSPropertyAnimationTimingFunction)) {
             if (auto timingFunction = TimingFunction::createFromCSSValue(*timingFunctionCSSValue))
@@ -342,13 +350,14 @@
     auto* keyframesRule = it->value.get();
     auto* keyframes = &keyframesRule->keyframes();
 
-    using KeyframeUniqueKey = std::pair<double, RefPtr<const TimingFunction>>;
+    using KeyframeUniqueKey = std::tuple<double, RefPtr<const TimingFunction>, CompositeOperation>;
     auto hasDuplicateKeys = [&]() -> bool {
         HashSet<KeyframeUniqueKey> uniqueKeyframeKeys;
         for (auto& keyframe : *keyframes) {
+            auto compositeOperation = compositeOperationForKeyframe(keyframe);
             auto timingFunction = uniqueTimingFunctionForKeyframe(keyframe);
             for (auto key : keyframe->keys()) {
-                if (!uniqueKeyframeKeys.add({ key, timingFunction }))
+                if (!uniqueKeyframeKeys.add({ key, timingFunction, compositeOperation }))
                     return true;
             }
         }
@@ -360,19 +369,21 @@
 
     // FIXME: If HashMaps could have Ref<> as value types, we wouldn't need
     // to copy the HashMap into a Vector.
+    // Merge keyframes with a similar offset and timing function.
     Vector<Ref<StyleRuleKeyframe>> deduplicatedKeyframes;
-    // Merge keyframes with a similar offset and timing function.
     HashMap<KeyframeUniqueKey, RefPtr<StyleRuleKeyframe>> keyframesMap;
     for (auto& originalKeyframe : *keyframes) {
+        auto compositeOperation = compositeOperationForKeyframe(originalKeyframe);
         auto timingFunction = uniqueTimingFunctionForKeyframe(originalKeyframe);
         for (auto key : originalKeyframe->keys()) {
-            if (auto keyframe = keyframesMap.get({ key, timingFunction }))
+            KeyframeUniqueKey uniqueKey { key, timingFunction, compositeOperation };
+            if (auto keyframe = keyframesMap.get(uniqueKey))
                 keyframe->mutableProperties().mergeAndOverrideOnConflict(originalKeyframe->properties());
             else {
                 auto styleRuleKeyframe = StyleRuleKeyframe::create(MutableStyleProperties::create());
                 styleRuleKeyframe.ptr()->setKey(key);
                 styleRuleKeyframe.ptr()->mutableProperties().mergeAndOverrideOnConflict(originalKeyframe->properties());
-                keyframesMap.set({ key, timingFunction }, styleRuleKeyframe.ptr());
+                keyframesMap.set(uniqueKey, styleRuleKeyframe.ptr());
                 deduplicatedKeyframes.append(styleRuleKeyframe);
             }
         }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to