From fa0745159a6cc532c565c1cbac91fa036c35f800 Mon Sep 17 00:00:00 2001 From: Matthew Olsson Date: Tue, 5 Mar 2024 19:48:36 -0700 Subject: [PATCH] LibWeb: Don't render elements with invalid interpolated transform values --- ...e-invalid-transform-should-not-render.html | 22 ++++++++++++++++ ...valid-transform-should-not-render-ref.html | 1 + .../Libraries/LibWeb/CSS/StyleComputer.cpp | 25 +++++++++++-------- 3 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 Tests/LibWeb/Ref/css-keyframe-invalid-transform-should-not-render.html create mode 100644 Tests/LibWeb/Ref/reference/css-keyframe-invalid-transform-should-not-render-ref.html diff --git a/Tests/LibWeb/Ref/css-keyframe-invalid-transform-should-not-render.html b/Tests/LibWeb/Ref/css-keyframe-invalid-transform-should-not-render.html new file mode 100644 index 000000000000000..19b1aa37dec7436 --- /dev/null +++ b/Tests/LibWeb/Ref/css-keyframe-invalid-transform-should-not-render.html @@ -0,0 +1,22 @@ + + + +
+ diff --git a/Tests/LibWeb/Ref/reference/css-keyframe-invalid-transform-should-not-render-ref.html b/Tests/LibWeb/Ref/reference/css-keyframe-invalid-transform-should-not-render-ref.html new file mode 100644 index 000000000000000..8b137891791fe96 --- /dev/null +++ b/Tests/LibWeb/Ref/reference/css-keyframe-invalid-transform-should-not-render-ref.html @@ -0,0 +1 @@ + diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index ab6af448fcf0c49..c0288aa1bc2d12f 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1220,7 +1220,7 @@ static NonnullRefPtr interpolate_value(DOM::Element& element, } } -static ValueComparingNonnullRefPtr interpolate_property(DOM::Element& element, PropertyID property_id, StyleValue const& from, StyleValue const& to, float delta) +static ValueComparingRefPtr interpolate_property(DOM::Element& element, PropertyID property_id, StyleValue const& from, StyleValue const& to, float delta) { auto animation_type = animation_type_from_longhand_property(property_id); switch (animation_type) { @@ -1233,13 +1233,11 @@ static ValueComparingNonnullRefPtr interpolate_property(DOM::E if (auto interpolated_transform = interpolate_transform(element, from, to, delta)) return *interpolated_transform; - // FIXME: https://drafts.csswg.org/css-transforms-1/#interpolation-of-transforms - // In some cases, an animation might cause a transformation matrix to be singular or non-invertible. - // For example, an animation in which scale moves from 1 to -1. At the time when the matrix is in - // such a state, the transformed element is not rendered. - - // For now, just fall back to discrete interpolation - return delta >= 0.5f ? to : from; + // https://drafts.csswg.org/css-transforms-1/#interpolation-of-transforms + // In some cases, an animation might cause a transformation matrix to be singular or non-invertible. + // For example, an animation in which scale moves from 1 to -1. At the time when the matrix is in + // such a state, the transformed element is not rendered. + return {}; } if (property_id == PropertyID::BoxShadow) return interpolate_box_shadow(element, from, to, delta); @@ -1335,9 +1333,14 @@ void StyleComputer::collect_animation_into(JS::NonnullGCPtrtarget(), it.key, *start, *end, progress_in_keyframe); - dbgln_if(LIBWEB_CSS_ANIMATION_DEBUG, "Interpolated value for property {} at {}: {} -> {} = {}", string_from_property_id(it.key), progress_in_keyframe, start->to_string(), end->to_string(), next_value->to_string()); - style_properties.set_property(it.key, next_value); + if (auto next_value = interpolate_property(*effect->target(), it.key, *start, *end, progress_in_keyframe)) { + dbgln_if(LIBWEB_CSS_ANIMATION_DEBUG, "Interpolated value for property {} at {}: {} -> {} = {}", string_from_property_id(it.key), progress_in_keyframe, start->to_string(), end->to_string(), next_value->to_string()); + style_properties.set_property(it.key, *next_value); + } else { + // If interpolate_property() fails, the element should not be rendered + dbgln_if(LIBWEB_CSS_ANIMATION_DEBUG, "Interpolated value for property {} at {}: {} -> {} is invalid", string_from_property_id(it.key), progress_in_keyframe, start->to_string(), end->to_string()); + style_properties.set_property(PropertyID::Visibility, IdentifierStyleValue::create(ValueID::Hidden)); + } } }