mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 17:49:40 +00:00
LibWeb: Parse transition values and cache them on Animatable elements
Co-authored-by: Matthew Olsson <matthewcolsson@gmail.com>
This commit is contained in:
parent
392510c631
commit
e544166977
Notes:
github-actions[bot]
2024-09-22 04:42:52 +00:00
Author: https://github.com/AtkinsSJ
Commit: e544166977
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1442
3 changed files with 96 additions and 4 deletions
|
@ -904,11 +904,15 @@ void StyleComputer::set_property_expanding_shorthands(StyleProperties& style, CS
|
||||||
style.set_property(shorthand_id, *property_in_previous_cascade_origin, StyleProperties::Inherited::No, important);
|
style.set_property(shorthand_id, *property_in_previous_cascade_origin, StyleProperties::Inherited::No, important);
|
||||||
if (shorthand_id == CSS::PropertyID::AnimationName)
|
if (shorthand_id == CSS::PropertyID::AnimationName)
|
||||||
style.set_animation_name_source(style_for_revert.animation_name_source());
|
style.set_animation_name_source(style_for_revert.animation_name_source());
|
||||||
|
if (shorthand_id == CSS::PropertyID::TransitionProperty)
|
||||||
|
style.set_transition_property_source(style_for_revert.transition_property_source());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
style.set_property(shorthand_id, shorthand_value, StyleProperties::Inherited::No, important);
|
style.set_property(shorthand_id, shorthand_value, StyleProperties::Inherited::No, important);
|
||||||
if (shorthand_id == CSS::PropertyID::AnimationName)
|
if (shorthand_id == CSS::PropertyID::AnimationName)
|
||||||
style.set_animation_name_source(declaration);
|
style.set_animation_name_source(declaration);
|
||||||
|
if (shorthand_id == CSS::PropertyID::TransitionProperty)
|
||||||
|
style.set_transition_property_source(declaration);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1210,6 +1214,86 @@ static void apply_dimension_attribute(StyleProperties& style, DOM::Element const
|
||||||
style.set_property(property_id, parsed_value.release_nonnull());
|
style.set_property(property_id, parsed_value.release_nonnull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void compute_transitioned_properties(StyleProperties const& style, DOM::Element& element, Optional<Selector::PseudoElement::Type> pseudo_element)
|
||||||
|
{
|
||||||
|
// FIXME: Implement transitioning for pseudo-elements
|
||||||
|
(void)pseudo_element;
|
||||||
|
|
||||||
|
if (auto const source_declaration = style.transition_property_source(); source_declaration && element.computed_css_values()) {
|
||||||
|
if (source_declaration != element.cached_transition_property_source()) {
|
||||||
|
// Reparse this transition property
|
||||||
|
element.clear_transitions();
|
||||||
|
element.set_cached_transition_property_source(*source_declaration);
|
||||||
|
|
||||||
|
auto transition_properties_value = style.property(PropertyID::TransitionProperty);
|
||||||
|
auto transition_properties = transition_properties_value->is_value_list()
|
||||||
|
? transition_properties_value->as_value_list().values()
|
||||||
|
: StyleValueVector { transition_properties_value };
|
||||||
|
|
||||||
|
auto normalize_transition_length_list = [&](PropertyID property, auto make_default_value) {
|
||||||
|
auto style_value = style.maybe_null_property(property);
|
||||||
|
StyleValueVector list;
|
||||||
|
|
||||||
|
if (!style_value || !style_value->is_value_list() || style_value->as_value_list().size() == 0) {
|
||||||
|
auto default_value = make_default_value();
|
||||||
|
for (size_t i = 0; i < transition_properties.size(); i++)
|
||||||
|
list.append(default_value);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const& value_list = style_value->as_value_list();
|
||||||
|
for (size_t i = 0; i < transition_properties.size(); i++)
|
||||||
|
list.append(value_list.value_at(i, true));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto delays = normalize_transition_length_list(
|
||||||
|
PropertyID::TransitionDelay,
|
||||||
|
[] { return TimeStyleValue::create(Time::make_seconds(0.0)); });
|
||||||
|
auto durations = normalize_transition_length_list(
|
||||||
|
PropertyID::TransitionDuration,
|
||||||
|
[] { return TimeStyleValue::create(Time::make_seconds(0.0)); });
|
||||||
|
auto timing_functions = normalize_transition_length_list(
|
||||||
|
PropertyID::TransitionTimingFunction,
|
||||||
|
[] { return EasingStyleValue::create(EasingStyleValue::CubicBezier::ease()); });
|
||||||
|
|
||||||
|
Vector<Vector<PropertyID>> properties;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < transition_properties.size(); i++) {
|
||||||
|
auto property_value = transition_properties[i];
|
||||||
|
Vector<PropertyID> properties_for_this_transition;
|
||||||
|
|
||||||
|
if (property_value->is_keyword()) {
|
||||||
|
auto keyword = property_value->as_keyword().keyword();
|
||||||
|
if (keyword == Keyword::None)
|
||||||
|
continue;
|
||||||
|
if (keyword == Keyword::All) {
|
||||||
|
for (auto prop = first_property_id; prop != last_property_id; prop = static_cast<PropertyID>(to_underlying(prop) + 1))
|
||||||
|
properties_for_this_transition.append(prop);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto maybe_property = property_id_from_string(property_value->as_custom_ident().custom_ident());
|
||||||
|
if (!maybe_property.has_value())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto transition_property = maybe_property.release_value();
|
||||||
|
if (property_is_shorthand(transition_property)) {
|
||||||
|
for (auto const& prop : longhands_for_shorthand(transition_property))
|
||||||
|
properties_for_this_transition.append(prop);
|
||||||
|
} else {
|
||||||
|
properties_for_this_transition.append(transition_property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.append(move(properties_for_this_transition));
|
||||||
|
}
|
||||||
|
|
||||||
|
element.add_transitioned_properties(move(properties), move(delays), move(durations), move(timing_functions));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://www.w3.org/TR/css-cascade/#cascading
|
// https://www.w3.org/TR/css-cascade/#cascading
|
||||||
// https://drafts.csswg.org/css-cascade-5/#layering
|
// https://drafts.csswg.org/css-cascade-5/#layering
|
||||||
void StyleComputer::compute_cascaded_values(StyleProperties& style, DOM::Element& element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, bool& did_match_any_pseudo_element_rules, ComputeStyleMode mode) const
|
void StyleComputer::compute_cascaded_values(StyleProperties& style, DOM::Element& element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, bool& did_match_any_pseudo_element_rules, ComputeStyleMode mode) const
|
||||||
|
@ -2110,6 +2194,9 @@ RefPtr<StyleProperties> StyleComputer::compute_style_impl(DOM::Element& element,
|
||||||
// 8. Let the element adjust computed style
|
// 8. Let the element adjust computed style
|
||||||
element.adjust_computed_style(style);
|
element.adjust_computed_style(style);
|
||||||
|
|
||||||
|
// 9. Transition declarations [css-transitions-1]
|
||||||
|
// Theoretically this should be part of the cascade, but it works with computed values, which we don't have until now.
|
||||||
|
compute_transitioned_properties(style, element, pseudo_element);
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,15 @@ namespace Web::CSS {
|
||||||
NonnullRefPtr<StyleProperties::Data> StyleProperties::Data::clone() const
|
NonnullRefPtr<StyleProperties::Data> StyleProperties::Data::clone() const
|
||||||
{
|
{
|
||||||
auto clone = adopt_ref(*new StyleProperties::Data);
|
auto clone = adopt_ref(*new StyleProperties::Data);
|
||||||
|
clone->m_animation_name_source = m_animation_name_source;
|
||||||
|
clone->m_transition_property_source = m_transition_property_source;
|
||||||
clone->m_property_values = m_property_values;
|
clone->m_property_values = m_property_values;
|
||||||
clone->m_animated_property_values = m_animated_property_values;
|
|
||||||
clone->m_property_important = m_property_important;
|
clone->m_property_important = m_property_important;
|
||||||
clone->m_property_inherited = m_property_inherited;
|
clone->m_property_inherited = m_property_inherited;
|
||||||
|
clone->m_animated_property_values = m_animated_property_values;
|
||||||
|
clone->m_math_depth = m_math_depth;
|
||||||
clone->m_font_list = m_font_list;
|
clone->m_font_list = m_font_list;
|
||||||
clone->m_line_height = m_line_height;
|
clone->m_line_height = m_line_height;
|
||||||
clone->m_animation_name_source = m_animation_name_source;
|
|
||||||
clone->m_math_depth = m_math_depth;
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,9 @@ private:
|
||||||
|
|
||||||
NonnullRefPtr<Data> clone() const;
|
NonnullRefPtr<Data> clone() const;
|
||||||
|
|
||||||
// FIXME: This needs protection from GC!
|
// FIXME: These need protection from GC!
|
||||||
JS::GCPtr<CSS::CSSStyleDeclaration const> m_animation_name_source;
|
JS::GCPtr<CSS::CSSStyleDeclaration const> m_animation_name_source;
|
||||||
|
JS::GCPtr<CSS::CSSStyleDeclaration const> m_transition_property_source;
|
||||||
|
|
||||||
Array<RefPtr<CSSStyleValue const>, number_of_properties> m_property_values;
|
Array<RefPtr<CSSStyleValue const>, number_of_properties> m_property_values;
|
||||||
Array<u8, ceil_div(number_of_properties, 8uz)> m_property_important {};
|
Array<u8, ceil_div(number_of_properties, 8uz)> m_property_important {};
|
||||||
|
@ -85,6 +86,9 @@ public:
|
||||||
JS::GCPtr<CSS::CSSStyleDeclaration const> animation_name_source() const { return m_data->m_animation_name_source; }
|
JS::GCPtr<CSS::CSSStyleDeclaration const> animation_name_source() const { return m_data->m_animation_name_source; }
|
||||||
void set_animation_name_source(JS::GCPtr<CSS::CSSStyleDeclaration const> declaration) { m_data->m_animation_name_source = declaration; }
|
void set_animation_name_source(JS::GCPtr<CSS::CSSStyleDeclaration const> declaration) { m_data->m_animation_name_source = declaration; }
|
||||||
|
|
||||||
|
JS::GCPtr<CSS::CSSStyleDeclaration const> transition_property_source() const { return m_data->m_transition_property_source; }
|
||||||
|
void set_transition_property_source(JS::GCPtr<CSS::CSSStyleDeclaration const> declaration) { m_data->m_transition_property_source = declaration; }
|
||||||
|
|
||||||
CSS::Size size_value(CSS::PropertyID) const;
|
CSS::Size size_value(CSS::PropertyID) const;
|
||||||
LengthPercentage length_percentage_or_fallback(CSS::PropertyID, LengthPercentage const& fallback) const;
|
LengthPercentage length_percentage_or_fallback(CSS::PropertyID, LengthPercentage const& fallback) const;
|
||||||
Optional<LengthPercentage> length_percentage(CSS::PropertyID) const;
|
Optional<LengthPercentage> length_percentage(CSS::PropertyID) const;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue