mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +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: https://github.com/LadybirdBrowser/ladybird/commit/e5441669776 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);
|
||||
if (shorthand_id == CSS::PropertyID::AnimationName)
|
||||
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 {
|
||||
style.set_property(shorthand_id, shorthand_value, StyleProperties::Inherited::No, important);
|
||||
if (shorthand_id == CSS::PropertyID::AnimationName)
|
||||
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());
|
||||
}
|
||||
|
||||
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://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
|
||||
|
@ -2110,6 +2194,9 @@ RefPtr<StyleProperties> StyleComputer::compute_style_impl(DOM::Element& element,
|
|||
// 8. Let the element adjust computed 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,14 +40,15 @@ namespace Web::CSS {
|
|||
NonnullRefPtr<StyleProperties::Data> StyleProperties::Data::clone() const
|
||||
{
|
||||
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_animated_property_values = m_animated_property_values;
|
||||
clone->m_property_important = m_property_important;
|
||||
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_line_height = m_line_height;
|
||||
clone->m_animation_name_source = m_animation_name_source;
|
||||
clone->m_math_depth = m_math_depth;
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,9 @@ private:
|
|||
|
||||
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_transition_property_source;
|
||||
|
||||
Array<RefPtr<CSSStyleValue const>, number_of_properties> m_property_values;
|
||||
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; }
|
||||
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;
|
||||
LengthPercentage length_percentage_or_fallback(CSS::PropertyID, LengthPercentage const& fallback) const;
|
||||
Optional<LengthPercentage> length_percentage(CSS::PropertyID) const;
|
||||
|
|
Loading…
Add table
Reference in a new issue