From 9330bf4b72f36376b4e8244382bd78e64a355e45 Mon Sep 17 00:00:00 2001 From: Callum Law Date: Wed, 20 Aug 2025 23:30:31 +1200 Subject: [PATCH] LibWeb: Propagate animated values in `recompute_inherited_style` As `recompute_inherited_style` works in-place rather than building ComputedProperties from scratch we need to keep track of which animated properties are inherited to know whether we should remove them when we have no more inherited value. --- Libraries/LibWeb/CSS/ComputedProperties.cpp | 23 +++++++++++++++- Libraries/LibWeb/CSS/ComputedProperties.h | 6 ++++- Libraries/LibWeb/CSS/StyleComputer.cpp | 8 +++--- Libraries/LibWeb/DOM/Element.cpp | 11 ++++++++ ...te-inherited-style-animated-properties.txt | 1 + ...e-inherited-style-animated-properties.html | 26 +++++++++++++++++++ 6 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/css/recompute-inherited-style-animated-properties.txt create mode 100644 Tests/LibWeb/Text/input/css/recompute-inherited-style-animated-properties.html diff --git a/Libraries/LibWeb/CSS/ComputedProperties.cpp b/Libraries/LibWeb/CSS/ComputedProperties.cpp index 4de39b32d75..0bf65957cd1 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.cpp +++ b/Libraries/LibWeb/CSS/ComputedProperties.cpp @@ -76,6 +76,12 @@ bool ComputedProperties::is_property_inherited(PropertyID property_id) const return m_property_inherited[n / 8] & (1 << (n % 8)); } +bool ComputedProperties::is_animated_property_inherited(PropertyID property_id) const +{ + size_t n = to_underlying(property_id); + return m_animated_property_inherited[n / 8] & (1 << (n % 8)); +} + void ComputedProperties::set_property_inherited(PropertyID property_id, Inherited inherited) { size_t n = to_underlying(property_id); @@ -85,6 +91,15 @@ void ComputedProperties::set_property_inherited(PropertyID property_id, Inherite m_property_inherited[n / 8] &= ~(1 << (n % 8)); } +void ComputedProperties::set_animated_property_inherited(PropertyID property_id, Inherited inherited) +{ + size_t n = to_underlying(property_id); + if (inherited == Inherited::Yes) + m_animated_property_inherited[n / 8] |= (1 << (n % 8)); + else + m_animated_property_inherited[n / 8] &= ~(1 << (n % 8)); +} + void ComputedProperties::set_property(PropertyID id, NonnullRefPtr value, Inherited inherited, Important important) { m_property_values[to_underlying(id)] = move(value); @@ -99,9 +114,15 @@ void ComputedProperties::revert_property(PropertyID id, ComputedProperties const set_property_inherited(id, style_for_revert.is_property_inherited(id) ? Inherited::Yes : Inherited::No); } -void ComputedProperties::set_animated_property(PropertyID id, NonnullRefPtr value) +void ComputedProperties::set_animated_property(PropertyID id, NonnullRefPtr value, Inherited inherited) { m_animated_property_values.set(id, move(value)); + set_animated_property_inherited(id, inherited); +} + +void ComputedProperties::remove_animated_property(PropertyID id) +{ + m_animated_property_values.remove(id); } void ComputedProperties::reset_animated_properties(Badge) diff --git a/Libraries/LibWeb/CSS/ComputedProperties.h b/Libraries/LibWeb/CSS/ComputedProperties.h index 196143cfef9..73d4130434f 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.h +++ b/Libraries/LibWeb/CSS/ComputedProperties.h @@ -53,11 +53,14 @@ public: bool is_property_important(PropertyID property_id) const; bool is_property_inherited(PropertyID property_id) const; + bool is_animated_property_inherited(PropertyID property_id) const; void set_property_important(PropertyID, Important); void set_property_inherited(PropertyID, Inherited); + void set_animated_property_inherited(PropertyID, Inherited); void set_property(PropertyID, NonnullRefPtr value, Inherited = Inherited::No, Important = Important::No); - void set_animated_property(PropertyID, NonnullRefPtr value); + void set_animated_property(PropertyID, NonnullRefPtr value, Inherited = Inherited::No); + void remove_animated_property(PropertyID); enum class WithAnimationsApplied { No, Yes, @@ -270,6 +273,7 @@ private: Array, number_of_properties> m_property_values; Array m_property_important {}; Array m_property_inherited {}; + Array m_animated_property_inherited {}; HashMap> m_animated_property_values; diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 773729bbba3..750110b744d 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1701,7 +1701,7 @@ void StyleComputer::compute_defaulted_property_value(ComputedProperties& style, if (!value_slot) { if (is_inherited_property(property_id)) { if (auto animated_inherit_value = get_animated_inherit_value(property_id, element, pseudo_element); animated_inherit_value.has_value()) - style.set_animated_property(property_id, animated_inherit_value.value()); + style.set_animated_property(property_id, animated_inherit_value.value(), ComputedProperties::Inherited::Yes); style.set_property( property_id, get_inherit_value(property_id, element, pseudo_element), @@ -1720,7 +1720,7 @@ void StyleComputer::compute_defaulted_property_value(ComputedProperties& style, if (value_slot->is_inherit()) { if (auto animated_inherit_value = get_animated_inherit_value(property_id, element, pseudo_element); animated_inherit_value.has_value()) - style.set_animated_property(property_id, animated_inherit_value.value()); + style.set_animated_property(property_id, animated_inherit_value.value(), ComputedProperties::Inherited::Yes); value_slot = get_inherit_value(property_id, element, pseudo_element); style.set_property_inherited(property_id, ComputedProperties::Inherited::Yes); return; @@ -1732,7 +1732,7 @@ void StyleComputer::compute_defaulted_property_value(ComputedProperties& style, if (is_inherited_property(property_id)) { // then if it is an inherited property, this is treated as inherit, if (auto animated_inherit_value = get_animated_inherit_value(property_id, element, pseudo_element); animated_inherit_value.has_value()) - style.set_animated_property(property_id, animated_inherit_value.value()); + style.set_animated_property(property_id, animated_inherit_value.value(), ComputedProperties::Inherited::Yes); value_slot = get_inherit_value(property_id, element, pseudo_element); style.set_property_inherited(property_id, ComputedProperties::Inherited::Yes); } else { @@ -2693,7 +2693,7 @@ GC::Ref StyleComputer::compute_properties(DOM::Element& elem computed_style->set_property(property_id, value.release_nonnull(), inherited); if (animated_value.has_value()) - computed_style->set_animated_property(property_id, animated_value.value()); + computed_style->set_animated_property(property_id, animated_value.value(), inherited); if (property_id == PropertyID::AnimationName) { computed_style->set_animation_name_source(cascaded_properties.property_source(property_id)); diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 2f6bf43ed1c..9462d4fcb78 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -817,6 +817,17 @@ CSS::RequiredInvalidationAfterStyleChange Element::recompute_inherited_style() } if (!computed_properties->is_property_inherited(property_id)) continue; + + RefPtr old_animated_value = computed_properties->animated_property_values().get(property_id).value_or({}); + RefPtr new_animated_value = CSS::StyleComputer::get_animated_inherit_value(property_id, this).map([&](auto& value) { return value.ptr(); }).value_or({}); + + if (new_animated_value) + computed_properties->set_animated_property(property_id, new_animated_value.release_nonnull(), CSS::ComputedProperties::Inherited::Yes); + else if (old_animated_value && computed_properties->is_animated_property_inherited(property_id)) + computed_properties->remove_animated_property(property_id); + + invalidation |= CSS::compute_property_invalidation(property_id, old_animated_value, new_animated_value); + RefPtr new_value = CSS::StyleComputer::get_inherit_value(property_id, this); computed_properties->set_property(property_id, *new_value, CSS::ComputedProperties::Inherited::Yes); invalidation |= CSS::compute_property_invalidation(property_id, old_value, new_value); diff --git a/Tests/LibWeb/Text/expected/css/recompute-inherited-style-animated-properties.txt b/Tests/LibWeb/Text/expected/css/recompute-inherited-style-animated-properties.txt new file mode 100644 index 00000000000..d70568e7568 --- /dev/null +++ b/Tests/LibWeb/Text/expected/css/recompute-inherited-style-animated-properties.txt @@ -0,0 +1 @@ +rgb(128, 0, 128) diff --git a/Tests/LibWeb/Text/input/css/recompute-inherited-style-animated-properties.html b/Tests/LibWeb/Text/input/css/recompute-inherited-style-animated-properties.html new file mode 100644 index 00000000000..6af8bb86cc5 --- /dev/null +++ b/Tests/LibWeb/Text/input/css/recompute-inherited-style-animated-properties.html @@ -0,0 +1,26 @@ + + + +
+ + +