mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
LibWeb: Implement the animation-composition property
This commit is contained in:
parent
968a8e618c
commit
e502f19fa7
Notes:
github-actions[bot]
2025-09-19 09:11:25 +00:00
Author: https://github.com/tcl3
Commit: e502f19fa7
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6233
Reviewed-by: https://github.com/AtkinsSJ ✅
14 changed files with 222 additions and 7 deletions
|
|
@ -67,6 +67,7 @@
|
|||
"absolute",
|
||||
"accentcolor",
|
||||
"accentcolortext",
|
||||
"accumulate",
|
||||
"active",
|
||||
"activeborder",
|
||||
"activecaption",
|
||||
|
|
@ -424,6 +425,7 @@
|
|||
"repeat",
|
||||
"repeat-x",
|
||||
"repeat-y",
|
||||
"replace",
|
||||
"reverse",
|
||||
"revert",
|
||||
"revert-layer",
|
||||
|
|
|
|||
|
|
@ -209,6 +209,17 @@
|
|||
"animation-fill-mode"
|
||||
]
|
||||
},
|
||||
"animation-composition": {
|
||||
"affects-layout": false,
|
||||
"animation-type": "none",
|
||||
"inherited": false,
|
||||
"initial": "replace",
|
||||
"valid-identifiers": [
|
||||
"replace",
|
||||
"add",
|
||||
"accumulate"
|
||||
]
|
||||
},
|
||||
"animation-delay": {
|
||||
"affects-layout": false,
|
||||
"animation-type": "none",
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,20 @@ static void apply_animation_properties(DOM::Document& document, CascadedProperti
|
|||
if (auto timing_property = cascaded_properties.property(PropertyID::AnimationTimingFunction); timing_property && timing_property->is_easing())
|
||||
timing_function = timing_property->as_easing().function();
|
||||
|
||||
Bindings::CompositeOperation composite_operation { Bindings::CompositeOperation::Replace };
|
||||
if (auto composite_property = cascaded_properties.property(PropertyID::AnimationComposition); composite_property) {
|
||||
switch (composite_property->to_keyword()) {
|
||||
case Keyword::Add:
|
||||
composite_operation = Bindings::CompositeOperation::Add;
|
||||
break;
|
||||
case Keyword::Accumulate:
|
||||
composite_operation = Bindings::CompositeOperation::Accumulate;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto iteration_duration = duration.has_value()
|
||||
? Variant<double, String> { duration.release_value().to_milliseconds() }
|
||||
: "auto"_string;
|
||||
|
|
@ -1252,6 +1266,7 @@ static void apply_animation_properties(DOM::Document& document, CascadedProperti
|
|||
effect.set_timing_function(move(timing_function));
|
||||
effect.set_fill_mode(Animations::css_fill_mode_to_bindings_fill_mode(fill_mode));
|
||||
effect.set_playback_direction(Animations::css_animation_direction_to_bindings_playback_direction(direction));
|
||||
effect.set_composite(composite_operation);
|
||||
|
||||
if (play_state != effect.last_css_animation_play_state()) {
|
||||
if (play_state == CSS::AnimationPlayState::Running && animation.play_state() != Bindings::AnimationPlayState::Running) {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ All properties associated with getComputedStyle(document.body):
|
|||
"align-content",
|
||||
"align-items",
|
||||
"align-self",
|
||||
"animation-composition",
|
||||
"animation-delay",
|
||||
"animation-direction",
|
||||
"animation-duration",
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ All supported properties and their default values exposed from CSSStylePropertie
|
|||
'align-self': 'auto'
|
||||
'all': ''
|
||||
'animation': 'none'
|
||||
'animationComposition': 'replace'
|
||||
'animation-composition': 'replace'
|
||||
'animationDelay': '0s'
|
||||
'animation-delay': '0s'
|
||||
'animationDirection': 'normal'
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ writing-mode: horizontal-tb
|
|||
align-content: normal
|
||||
align-items: normal
|
||||
align-self: auto
|
||||
animation-composition: replace
|
||||
animation-delay: 0s
|
||||
animation-direction: normal
|
||||
animation-duration: 0s
|
||||
|
|
@ -94,7 +95,7 @@ background-position-x: 0%
|
|||
background-position-y: 0%
|
||||
background-repeat: repeat
|
||||
background-size: auto
|
||||
block-size: 1440px
|
||||
block-size: 1455px
|
||||
border-block-end-color: rgb(0, 0, 0)
|
||||
border-block-end-style: none
|
||||
border-block-end-width: 0px
|
||||
|
|
@ -171,7 +172,7 @@ grid-row-start: auto
|
|||
grid-template-areas: none
|
||||
grid-template-columns: none
|
||||
grid-template-rows: none
|
||||
height: 2595px
|
||||
height: 2610px
|
||||
inline-size: 784px
|
||||
inset-block-end: auto
|
||||
inset-block-start: auto
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ Harness status: OK
|
|||
|
||||
Found 8 tests
|
||||
|
||||
4 Pass
|
||||
4 Fail
|
||||
5 Pass
|
||||
3 Fail
|
||||
Fail Setting a null effect on a running animation fires an animationend event
|
||||
Pass Replacing an animation's effect with an effect that targets a different property should update both properties
|
||||
Pass Replacing an animation's effect with a shorter one that should have already finished, the animation finishes immediately
|
||||
Pass A play-pending animation's effect whose effect is replaced still exits the pending state
|
||||
Fail CSS animation events are dispatched at the original element even after setting an effect with a different target element
|
||||
Pass After replacing a finished animation's effect with a longer one it fires an animationstart event
|
||||
Fail Setting animation-composition sets the composite property on the effect
|
||||
Pass Setting animation-composition sets the composite property on the effect
|
||||
Fail Replacing the effect of a CSSAnimation causes subsequent changes to corresponding animation-* properties to be ignored
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 6 tests
|
||||
|
||||
4 Pass
|
||||
2 Fail
|
||||
Pass animation-composition: replace of property filter
|
||||
Fail animation-composition: add of property filter
|
||||
Fail animation-composition: accumulate of property filter
|
||||
Pass animation-composition: replace of property width
|
||||
Pass animation-composition: add of property width
|
||||
Pass animation-composition: accumulate of property width
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 4 tests
|
||||
|
||||
4 Pass
|
||||
Pass e.style['animation-composition'] = "auto" should not set the property value
|
||||
Pass e.style['animation-composition'] = "add replace" should not set the property value
|
||||
Pass e.style['animation-composition'] = "add, initial" should not set the property value
|
||||
Pass e.style['animation-composition'] = "initial, add" should not set the property value
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 4 tests
|
||||
|
||||
3 Pass
|
||||
1 Fail
|
||||
Pass e.style['animation-composition'] = "replace" should set the property value
|
||||
Pass e.style['animation-composition'] = "add" should set the property value
|
||||
Pass e.style['animation-composition'] = "accumulate" should set the property value
|
||||
Fail e.style['animation-composition'] = "replace, add, accumulate" should set the property value
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 260 tests
|
||||
Found 261 tests
|
||||
|
||||
253 Pass
|
||||
254 Pass
|
||||
7 Fail
|
||||
Pass accent-color
|
||||
Pass border-collapse
|
||||
|
|
@ -76,6 +76,7 @@ Pass word-wrap
|
|||
Pass writing-mode
|
||||
Pass align-items
|
||||
Pass align-self
|
||||
Pass animation-composition
|
||||
Pass animation-delay
|
||||
Pass animation-direction
|
||||
Pass animation-duration
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>animation-composition test</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-composition">
|
||||
<script src=../../resources/testharness.js></script>
|
||||
<script src=../../resources/testharnessreport.js></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from {
|
||||
filter: blur(10px);
|
||||
width: 100px;
|
||||
}
|
||||
50% {
|
||||
filter: blur(15px);
|
||||
width: 228px;
|
||||
}
|
||||
to {
|
||||
filter: blur(20px);
|
||||
width: 1337px;
|
||||
}
|
||||
}
|
||||
|
||||
.anim-target {
|
||||
animation: anim 1s;
|
||||
animation-fill-mode: forwards;
|
||||
animation-timing-function: linear;
|
||||
filter: blur(5px);
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.replace {
|
||||
animation-composition: replace;
|
||||
}
|
||||
|
||||
.add {
|
||||
animation-composition: add;
|
||||
}
|
||||
|
||||
.accumulate {
|
||||
animation-composition: accumulate;
|
||||
}
|
||||
</style>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
function run_test_case(element, property, composite_type, timing_value_map) {
|
||||
element.classList.add(composite_type);
|
||||
const anim = element.getAnimations()[0];
|
||||
for (const [time, value] of Object.entries(timing_value_map)) {
|
||||
anim.currentTime = time;
|
||||
const property_value = getComputedStyle(element).getPropertyValue(property);
|
||||
assert_equals(property_value, value, "at time " + time);
|
||||
}
|
||||
element.classList.remove(composite_type);
|
||||
}
|
||||
|
||||
const test_cases = [
|
||||
["filter", {
|
||||
"replace": {
|
||||
0: "blur(10px)",
|
||||
250: "blur(12.5px)",
|
||||
500: "blur(15px)",
|
||||
1000: "blur(20px)"
|
||||
},
|
||||
"add": {
|
||||
0: "blur(5px) blur(10px)",
|
||||
250: "blur(5px) blur(12.5px)",
|
||||
500: "blur(5px) blur(15px)",
|
||||
1000: "blur(5px) blur(20px)"
|
||||
},
|
||||
"accumulate": {
|
||||
0: "blur(15px)",
|
||||
250: "blur(17.5px)",
|
||||
500: "blur(20px)",
|
||||
1000: "blur(25px)"
|
||||
}
|
||||
}],
|
||||
["width", {
|
||||
"replace": {
|
||||
0: "100px",
|
||||
250: "164px",
|
||||
500: "228px",
|
||||
1000: "1337px"
|
||||
},
|
||||
"add": {
|
||||
0: "150px",
|
||||
250: "214px",
|
||||
500: "278px",
|
||||
1000: "1387px"
|
||||
},
|
||||
"accumulate": {
|
||||
0: "150px",
|
||||
250: "214px",
|
||||
500: "278px",
|
||||
1000: "1387px"
|
||||
}
|
||||
}]
|
||||
]
|
||||
|
||||
for (const test_case of test_cases) {
|
||||
const property = test_case[0];
|
||||
const test_data = test_case[1];
|
||||
for (const [composite_type, expected_values] of Object.entries(test_data)) {
|
||||
test(t => {
|
||||
let elem = addDiv(t, {"class": "anim-target"});
|
||||
run_test_case(elem, property, composite_type, expected_values);
|
||||
}, "animation-composition: " + composite_type + " of property " + property);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Animations: parsing animation-composition with invalid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#propdef-animation-composition">
|
||||
<meta name="assert" content="animation-composition supports only the grammar '<single-animation-composition> #'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_invalid_value("animation-composition", "auto");
|
||||
test_invalid_value("animation-composition", "add replace");
|
||||
|
||||
test_invalid_value("animation-composition", "add, initial");
|
||||
test_invalid_value("animation-composition", "initial, add");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Animations: parsing animation-composition with valid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#propdef-animation-composition">
|
||||
<meta name="assert" content="animation-composition supports the full grammar '<single-animation-composition> #'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("animation-composition", "replace");
|
||||
test_valid_value("animation-composition", "add");
|
||||
test_valid_value("animation-composition", "accumulate");
|
||||
test_valid_value("animation-composition", "replace, add, accumulate");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue