commit 5392eae8d8cd87a49ac5648e2160700e2e778121
parent e70bea9e542268197c1e6dee93c75c4d8f668744
Author: Sam Davis Omekara Jr. <samomekarajr@microsoft.com>
Date: Fri, 7 Nov 2025 08:56:50 +0000
Bug 1998543 [wpt PR 55876] - [Gap-Decorations] Interpolation behavior V2 for gap decorations color, a=testonly
Automatic update from web-platform-tests
[Gap-Decorations] Interpolation behavior V2 for gap decorations color
This CL builds on crrev.com/c/6961880 and introduces the updated
interpolation behavior for `*-rule-color`, as resolved through
discussions with the CSSWG.
You can view the discussion at
https://github.com/w3c/csswg-drafts/issues/12431 and see the updated
specification at
https://drafts.csswg.org/css-gaps-1/#interpolation-behavior
The main updates allow interpolation in more scenarios, including:
- between integer repeaters and non-repeaters
- between lists of different lengths
- between integer repeaters with different repeater and repeated value counts
- between auto repeaters with different repeated value counts.
Most groundwork for this was completed in crrev.com/c/6961880, so this
change adds the color implementation for the new framework and removes
the previous `InterpolableGapDataRepeater` as it is no longer needed.
Additional test cases have been included, and existing tests have been
updated to align with the specification.
Bug: 357648037, 419066541
Change-Id: I61ef162358c61fe6f15aba91da07414d2d1d3c17
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7078855
Reviewed-by: Javier Contreras <javiercon@microsoft.com>
Reviewed-by: Kevin Ellis <kevers@chromium.org>
Commit-Queue: Javier Contreras <javiercon@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1540697}
--
wpt-commits: 923d485bb239ec1d1cfdf1e32e1c9a564b3d0ae6
wpt-pr: 55876
Diffstat:
6 files changed, 131 insertions(+), 75 deletions(-)
diff --git a/testing/web-platform/tests/css/css-gaps/animation/gap-decorations-color-neutral-keyframe-004.html b/testing/web-platform/tests/css/css-gaps/animation/gap-decorations-color-neutral-keyframe-004.html
@@ -2,9 +2,9 @@
<html>
<head>
<meta charset="utf-8">
- <title>gap decorations column-rule-color neutral keyframe</title>
+ <title>gap decorations row-rule-color neutral keyframe</title>
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/#column-row-rule-color">
- <meta name="assert" content="gap decorations column-rule-color value list supports neutral keyframe.">
+ <meta name="assert" content="gap decorations row-rule-color with repeaters supports neutral keyframe.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/interpolation-testcommon.js"></script>
@@ -18,8 +18,8 @@
var animation = target.animate([{}, {rowRuleColor: 'repeat(3, red red) repeat(1, black)'}], 1000);
animation.pause();
animation.currentTime = 500;
- assert_equals(getComputedStyle(target).rowRuleColor, 'repeat(3, rgb(128, 0, 0) rgb(128, 0, 0)) repeat(1, rgb(128, 0, 0))');
- }, 'gap decorations row-rule-color value list supports neutral keyframe.');
+ assert_equals(getComputedStyle(target).rowRuleColor, 'rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0)');
+ }, 'gap decorations row-rule-color with repeaters supports neutral keyframe.');
</script>
</body>
</html>
diff --git a/testing/web-platform/tests/css/css-gaps/animation/gap-decorations-color-neutral-keyframe-005.html b/testing/web-platform/tests/css/css-gaps/animation/gap-decorations-color-neutral-keyframe-005.html
@@ -2,9 +2,9 @@
<html>
<head>
<meta charset="utf-8">
- <title>gap decorations column-rule-color neutral keyframe</title>
+ <title>gap decorations row-rule-color neutral keyframe</title>
<link rel="help" href="https://drafts.csswg.org/css-gaps-1/#column-row-rule-color">
- <meta name="assert" content="gap decorations column-rule-color value list supports neutral keyframe.">
+ <meta name="assert" content="gap decorations row-rule-color with repeaters supports neutral keyframe.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/interpolation-testcommon.js"></script>
@@ -18,8 +18,8 @@
var animation = target.animate([{}, {rowRuleColor: 'repeat(3, red red) black black'}], 1000);
animation.pause();
animation.currentTime = 500;
- assert_equals(getComputedStyle(target).rowRuleColor, 'repeat(3, rgb(128, 0, 0) rgb(128, 0, 0)) rgb(128, 0, 0) rgb(128, 0, 0)');
- }, 'gap decorations row-rule-color value list supports neutral keyframe.');
+ assert_equals(getComputedStyle(target).rowRuleColor, 'rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0) rgb(128, 0, 0)');
+ }, 'gap decorations row-rule-color with repeaters supports neutral keyframe.');
</script>
</body>
</html>
diff --git a/testing/web-platform/tests/css/css-gaps/animation/row-rule-color-interpolation.html b/testing/web-platform/tests/css/css-gaps/animation/row-rule-color-interpolation.html
@@ -95,16 +95,32 @@ test_interpolation({
{at: 1.5, expect: 'blue'}
]);
-// Lists can only be interpolated if they have the same length.
-test_no_interpolation({
+// Lists can be interpolated by expanding to match lengths.
+test_interpolation({
property: 'row-rule-color',
from: neutralKeyframe,
to: 'red blue blue',
-});
-test_no_interpolation({
+}, [
+ {at: -5, expect: 'rgb(255, 255, 0) rgb(255, 255, 0) rgb(255, 255, 0)'},
+ {at: -0.4, expect: 'rgb(255, 255, 0) rgb(255, 255, 0) rgb(255, 255, 0)'},
+ {at: 0, expect: 'rgb(255, 255, 0) rgb(255, 255, 0) rgb(255, 255, 0)'},
+ {at: 0.2, expect: 'rgb(255, 204, 0) rgb(204, 204, 51) rgb(204, 204, 51)'},
+ {at: 0.6, expect: 'rgb(255, 102, 0) rgb(102, 102, 153) rgb(102, 102, 153)'},
+ {at: 1, expect: 'rgb(255, 0, 0) rgb(0, 0, 255) rgb(0, 0, 255)'},
+ {at: 1.5, expect: 'rgb(255, 0, 0) rgb(0, 0, 255) rgb(0, 0, 255)'},
+]);
+test_interpolation({
property: 'row-rule-color',
from: 'red blue green',
to: 'red',
-});
+}, [
+ {at: -5, expect: 'rgb(255, 0, 0) rgb(0, 0, 255) rgb(0, 255, 0)'},
+ {at: -0.4, expect: 'rgb(255, 0, 0) rgb(0, 0, 255) rgb(0, 179, 0)'},
+ {at: 0, expect: 'rgb(255, 0, 0) rgb(0, 0, 255) rgb(0, 128, 0)'},
+ {at: 0.2, expect: 'rgb(255, 0, 0) rgb(51, 0, 204) rgb(51, 102, 0)'},
+ {at: 0.6, expect: 'rgb(255, 0, 0) rgb(153, 0, 102) rgb(153, 51, 0)'},
+ {at: 1, expect: 'rgb(255, 0, 0) rgb(255, 0, 0) rgb(255, 0, 0)'},
+ {at: 1.5, expect: 'rgb(255, 0, 0) rgb(255, 0, 0) rgb(255, 0, 0)'},
+]);
</script>
</body>
diff --git a/testing/web-platform/tests/css/css-gaps/animation/rule-color-interpolation-conversion-001.html b/testing/web-platform/tests/css/css-gaps/animation/rule-color-interpolation-conversion-001.html
@@ -36,12 +36,12 @@
'rgb(128, 0, 128)' // The color at 50% of the animation.
);
- el.style.columnRuleColor = 'repeat(2, red)';
+ el.style.columnRuleColor = 'repeat(auto, red)';
const snapped = getComputedStyle(el).columnRuleColor;
assert_equals(
snapped,
- 'repeat(2, rgb(255, 0, 0))'
+ 'repeat(auto, rgb(255, 0, 0))'
);
});
</script>
diff --git a/testing/web-platform/tests/css/css-gaps/animation/rule-color-interpolation-conversion-002.html b/testing/web-platform/tests/css/css-gaps/animation/rule-color-interpolation-conversion-002.html
@@ -13,7 +13,7 @@
animation: color-anim 2s linear paused;
}
@keyframes color-anim {
- from { column-rule-color: red; }
+ from { column-rule-color: red repeat(auto, red); }
}
</style>
</head>
@@ -25,7 +25,7 @@
const el = document.getElementById('target');
const anim = el.getAnimations()[0];
- assert_equals(getComputedStyle(el).columnRuleColor, 'rgb(255, 0, 0)');
+ assert_equals(getComputedStyle(el).columnRuleColor, 'rgb(255, 0, 0) repeat(auto, rgb(255, 0, 0))');
// Jump to 50% of the animation.
anim.currentTime = anim.effect.getComputedTiming().duration / 2;
@@ -36,12 +36,12 @@
'rgb(0, 0, 255) rgb(0, 0, 255)'
);
- el.style.columnRuleColor = 'blue';
+ el.style.columnRuleColor = 'blue repeat(auto, blue)';
const intermediate = getComputedStyle(el).columnRuleColor;
assert_equals(
intermediate,
- 'rgb(128, 0, 128)' // The color at 50% of the animation.
+ 'rgb(128, 0, 128) repeat(auto, rgb(128, 0, 128))' // The color at 50% of the animation.
);
});
</script>
diff --git a/testing/web-platform/tests/css/css-gaps/animation/rule-color-interpolation-repeaters-001.html b/testing/web-platform/tests/css/css-gaps/animation/rule-color-interpolation-repeaters-001.html
@@ -30,30 +30,32 @@
<body>
<script>
// Valid Interpolations:
+ // Repeaters should expand.
test_interpolation({
property: 'row-rule-color',
from: neutralKeyframe,
to: 'red repeat(2, black black) blue',
}, [
- { at: -0.3, expect: 'black repeat(2, red blue) black' },
- { at: 0, expect: 'black repeat(2, red blue) black' },
- { at: 0.3, expect: 'rgb(77, 0, 0) repeat(2, rgb(179, 0, 0) rgb(0, 0, 179)) rgb(0, 0, 77)' },
- { at: 0.6, expect: 'rgb(153, 0, 0) repeat(2, rgb(102, 0, 0) rgb(0, 0, 102)) rgb(0, 0, 153)' },
- { at: 1, expect: 'rgb(255, 0, 0) repeat(2, rgb(0, 0, 0) rgb(0, 0, 0)) rgb(0, 0, 255)' },
- { at: 1.5, expect: 'rgb(255, 0, 0) repeat(2, rgb(0, 0, 0) rgb(0, 0, 0)) rgb(0, 0, 255)' },
+ { at: -0.3, expect: 'black red blue red blue black' },
+ { at: 0, expect: 'black red blue red blue black' },
+ { at: 0.3, expect: 'rgb(77, 0, 0) rgb(179, 0, 0) rgb(0, 0, 179) rgb(179, 0, 0) rgb(0, 0, 179) rgb(0, 0, 77)' },
+ { at: 0.6, expect: 'rgb(153, 0, 0) rgb(102, 0, 0) rgb(0, 0, 102) rgb(102, 0, 0) rgb(0, 0, 102) rgb(0, 0, 153)' },
+ { at: 1, expect: 'rgb(255, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 255)' },
+ { at: 1.5, expect: 'rgb(255, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 255)' },
]);
test_interpolation({
property: 'column-rule-color',
from: neutralKeyframe,
to: 'repeat(2, red black)',
}, [
- { at: -0.3, expect: 'repeat(2, black red)' },
- { at: 0, expect: 'repeat(2, black red)' },
- { at: 0.3, expect: 'repeat(2, rgb(77, 0, 0) rgb(179, 0, 0))' },
- { at: 0.6, expect: 'repeat(2, rgb(153, 0, 0) rgb(102, 0, 0))' },
- { at: 1, expect: 'repeat(2, red black)' },
- { at: 1.5, expect: 'repeat(2, red black)' },
+ { at: -0.3, expect: 'black red black red' },
+ { at: 0, expect: 'black red black red' },
+ { at: 0.3, expect: 'rgb(77, 0, 0) rgb(179, 0, 0) rgb(77, 0, 0) rgb(179, 0, 0)' },
+ { at: 0.6, expect: 'rgb(153, 0, 0) rgb(102, 0, 0) rgb(153, 0, 0) rgb(102, 0, 0)' },
+ { at: 1, expect: 'red black red black' },
+ { at: 1.5, expect: 'red black red black' },
]);
+ // Auto repeaters don't expand.
test_interpolation({
property: 'column-rule-color',
from: 'repeat(auto, black black)',
@@ -67,55 +69,93 @@
{ at: 1.5, expect: 'repeat(auto, rgb(0, 0, 255) rgb(255, 0, 0)' },
]);
- // // Shouldn't interpolate, length of the list is different:
- test_no_interpolation({
- property: 'row-rule-color',
- from: neutralKeyframe,
- to: 'repeat(2, blue blue) white',
- });
- test_no_interpolation({
- property: 'row-rule-color',
- from: neutralKeyframe,
- to: 'repeat(2, red red) repeat(2, blue blue)',
- });
+ // Auto repeaters should interpolate, we apply
+ // lowest common multiple interpolation to the inner values
+ // of auto repeaters.
+ test_interpolation({
+ property: 'column-rule-color',
+ from: 'repeat(auto, red)',
+ to: 'repeat(auto, blue blue)',
+ }, [
+ { at: -0.3, expect: 'repeat(auto, rgb(255, 0, 0) rgb(255, 0, 0))' },
+ { at: 0, expect: 'repeat(auto, rgb(255, 0, 0) rgb(255, 0, 0))' },
+ { at: 0.3, expect: 'repeat(auto, rgb(179, 0, 77) rgb(179, 0, 77))' },
+ { at: 0.6, expect: 'repeat(auto, rgb(102, 0, 153) rgb(102, 0, 153))' },
+ { at: 1, expect: 'repeat(auto, rgb(0, 0, 255) rgb(0, 0, 255))' },
+ { at: 1.5, expect: 'repeat(auto, rgb(0, 0, 255) rgb(0, 0, 255))' },
+ ]);
- // // Shouldn't interpolate, repeaters are not compatible:
- test_no_interpolation({
- property: 'column-rule-color',
- from: neutralKeyframe,
- to: 'repeat(3, white white)',
- });
- test_no_interpolation({
- property: 'column-rule-color',
- from: neutralKeyframe,
- to: 'repeat(2, yellow orange green)',
- });
- test_no_interpolation({
- property: 'row-rule-color',
- from: neutralKeyframe,
- to: 'black repeat(3, red white) blue',
- });
- test_no_interpolation({
- property: 'row-rule-color',
- from: neutralKeyframe,
- to: 'white repeat(2, blue blue blue) yellow',
- });
- test_no_interpolation({
- property: 'column-rule-color',
- from: 'repeat(auto, red black)',
- to: 'repeat(3, black red)',
- });
+ // Repeaters should expand.
+ test_interpolation({
+ property: 'column-rule-color',
+ from: 'repeat(1, red)',
+ to: 'repeat(2, blue blue)',
+ }, [
+ { at: -0.3, expect: 'rgb(255, 0, 0) rgb(255, 0, 0) rgb(255, 0, 0) rgb(255, 0, 0)' },
+ { at: 0, expect: 'rgb(255, 0, 0) rgb(255, 0, 0) rgb(255, 0, 0) rgb(255, 0, 0)' },
+ { at: 0.3, expect: 'rgb(179, 0, 77) rgb(179, 0, 77) rgb(179, 0, 77) rgb(179, 0, 77)' },
+ { at: 0.6, expect: 'rgb(102, 0, 153) rgb(102, 0, 153) rgb(102, 0, 153) rgb(102, 0, 153)' },
+ { at: 1, expect: 'rgb(0, 0, 255) rgb(0, 0, 255) rgb(0, 0, 255) rgb(0, 0, 255)' },
+ { at: 1.5, expect: 'rgb(0, 0, 255) rgb(0, 0, 255) rgb(0, 0, 255) rgb(0, 0, 255)' },
+ ]);
+
+ // Repeaters should expand and interpolate with non repeaters.
+ test_interpolation({
+ property: 'column-rule-color',
+ from: 'repeat(2, red)',
+ to: 'blue blue',
+ }, [
+ { at: -0.3, expect: 'rgb(255, 0, 0) rgb(255, 0, 0)' },
+ { at: 0, expect: 'rgb(255, 0, 0) rgb(255, 0, 0)' },
+ { at: 0.3, expect: 'rgb(179, 0, 77) rgb(179, 0, 77)' },
+ { at: 0.6, expect: 'rgb(102, 0, 153) rgb(102, 0, 153)' },
+ { at: 1, expect: 'rgb(0, 0, 255) rgb(0, 0, 255)' },
+ { at: 1.5, expect: 'rgb(0, 0, 255) rgb(0, 0, 255)' },
+ ]);
+
+ // Repeaters should expand and interpolate with non repeaters.
+ test_interpolation({
+ property: 'column-rule-color',
+ from: 'repeat(2, red)',
+ to: 'blue',
+ }, [
+ { at: -0.3, expect: 'rgb(255, 0, 0) rgb(255, 0, 0)' },
+ { at: 0, expect: 'rgb(255, 0, 0) rgb(255, 0, 0)' },
+ { at: 0.3, expect: 'rgb(179, 0, 77) rgb(179, 0, 77)' },
+ { at: 0.6, expect: 'rgb(102, 0, 153) rgb(102, 0, 153)' },
+ { at: 1, expect: 'rgb(0, 0, 255) rgb(0, 0, 255)' },
+ { at: 1.5, expect: 'rgb(0, 0, 255) rgb(0, 0, 255)' },
+ ]);
+
+ // When auto repeaters are present, we only interpolate if the length
+ // of the `leading` segments match, and the length of the `trailing`
+ // segments match.
+ test_interpolation({
+ property: 'column-rule-color',
+ from: 'repeat(2, red) repeat(auto, red) red',
+ to: 'blue blue repeat(auto, blue) blue',
+ }, [
+ { at: -0.3, expect: 'rgb(255, 0, 0) rgb(255, 0, 0) repeat(auto, rgb(255, 0, 0)) rgb(255, 0, 0)' },
+ { at: 0, expect: 'rgb(255, 0, 0) rgb(255, 0, 0) repeat(auto, rgb(255, 0, 0)) rgb(255, 0, 0)' },
+ { at: 0.3, expect: 'rgb(179, 0, 77) rgb(179, 0, 77) repeat(auto, rgb(179, 0, 77)) rgb(179, 0, 77)' },
+ { at: 0.6, expect: 'rgb(102, 0, 153) rgb(102, 0, 153) repeat(auto, rgb(102, 0, 153)) rgb(102, 0, 153)' },
+ { at: 1, expect: 'rgb(0, 0, 255) rgb(0, 0, 255) repeat(auto, rgb(0, 0, 255)) rgb(0, 0, 255)' },
+ { at: 1.5, expect: 'rgb(0, 0, 255) rgb(0, 0, 255) repeat(auto, rgb(0, 0, 255)) rgb(0, 0, 255)' },
+ ]);
+
+ // Invalid interpolations:
+ // Shouldn't interpolate, different leading lengths with present auto repeater:
test_no_interpolation({
- property: 'column-rule-color',
- from: 'repeat(auto, black black)',
- to: 'repeat(auto, red white yellow)',
+ property: 'column-rule-color',
+ from: 'red repeat(auto, red)',
+ to: 'blue blue repeat(auto, blue)',
});
- // // Shouldn't interpolate, repeater and a color are not compatible:
+ // Shouldn't interpolate, different trailing lengths with present auto repeater:
test_no_interpolation({
- property: 'column-rule-color',
- from: neutralKeyframe,
- to: 'white',
+ property: 'column-rule-color',
+ from: 'red repeat(auto, red)',
+ to: 'blue repeat(auto, blue) blue',
});
</script>
</body>