diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 8104f483aee..f2fc87698fe 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -81,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -180,8 +181,6 @@ OwnFontFaceKey::operator FontFaceKey() const && slope == other.slope; } -static DOM::Element const* element_to_inherit_style_from(DOM::Element const*, Optional); - StyleComputer::StyleComputer(DOM::Document& document) : m_document(document) , m_default_font_metrics(16, Platform::FontPlugin::the().default_font(16)->pixel_metrics()) @@ -1665,21 +1664,9 @@ GC::Ref StyleComputer::compute_cascaded_values(DOM::Element& return cascaded_properties; } -DOM::Element const* element_to_inherit_style_from(DOM::Element const* element, Optional pseudo_element) -{ - // Pseudo-elements treat their originating element as their parent. - DOM::Element const* parent_element = nullptr; - if (pseudo_element.has_value()) { - parent_element = element; - } else if (element) { - parent_element = element->parent_or_shadow_host_element(); - } - return parent_element; -} - NonnullRefPtr StyleComputer::get_inherit_value(CSS::PropertyID property_id, DOM::Element const* element, Optional pseudo_element) { - auto* parent_element = element_to_inherit_style_from(element, pseudo_element); + auto parent_element = element ? element->element_to_inherit_style_from(pseudo_element) : nullptr; if (!parent_element || !parent_element->computed_properties()) return property_initial_value(property_id); @@ -1751,7 +1738,7 @@ void StyleComputer::compute_defaulted_values(ComputedProperties& style, DOM::Ele if (element && element->local_name() == HTML::TagNames::th && style.property(PropertyID::TextAlign).to_keyword() == Keyword::LibwebInheritOrCenter) { auto const* parent_element = element; - while ((parent_element = element_to_inherit_style_from(parent_element, {}))) { + while ((parent_element = parent_element->element_to_inherit_style_from({}))) { auto parent_computed = parent_element->computed_properties(); auto parent_cascaded = parent_element->cascaded_properties({}); if (!parent_computed || !parent_cascaded) @@ -1911,7 +1898,7 @@ CSSPixelFraction StyleComputer::absolute_size_mapping(Keyword keyword) RefPtr StyleComputer::compute_font_for_style_values(DOM::Element const* element, Optional pseudo_element, StyleValue const& font_family, StyleValue const& font_size, StyleValue const& font_style, StyleValue const& font_weight, StyleValue const& font_stretch, int math_depth) const { - auto* parent_element = element_to_inherit_style_from(element, pseudo_element); + auto parent_element = element ? element->element_to_inherit_style_from(pseudo_element) : nullptr; auto width = font_stretch.to_font_width(); auto weight = font_weight.to_font_weight(); @@ -2180,7 +2167,7 @@ LogicalAliasMappingContext StyleComputer::compute_logical_alias_mapping_context( { auto normalize_value = [&](auto property_id, auto value) { if (!value || value->is_inherit() || value->is_unset()) { - if (auto const* inheritance_parent = element_to_inherit_style_from(&element, pseudo_element)) { + if (auto const inheritance_parent = element.element_to_inherit_style_from(pseudo_element)) { value = inheritance_parent->computed_properties()->property(property_id); } else { value = property_initial_value(property_id); @@ -2297,14 +2284,7 @@ static void compute_text_align(ComputedProperties& style, DOM::Element const& el // value of start or end is interpreted against the parent’s direction value and results in a computed value of // either left or right. Computes to start when specified on the root element. if (style.property(PropertyID::TextAlign).to_keyword() == Keyword::MatchParent) { - - // If it's a pseudo-element, then the "parent" is the originating element instead. - auto const* parent = [&]() -> DOM::Element const* { - if (pseudo_element.has_value()) - return &element; - return element.parent_element(); - }(); - + auto const parent = element.element_to_inherit_style_from(pseudo_element); if (parent) { auto const& parent_text_align = parent->computed_properties()->property(PropertyID::TextAlign); auto const& parent_direction = parent->computed_properties()->direction(); @@ -2355,7 +2335,7 @@ static BoxTypeTransformation required_box_type_transformation(ComputedProperties // FIXME: Containment in a ruby container inlinifies the box’s display type, as described in [CSS-RUBY-1]. // NOTE: If we're computing style for a pseudo-element, the effective parent will be the originating element itself, not its parent. - auto parent = pseudo_element.has_value() ? GC::Ptr { &element } : element.parent_element(); + auto parent = element.element_to_inherit_style_from(pseudo_element); // A parent with a grid or flex display value blockifies the box’s display type. [CSS-GRID-1] [CSS-FLEXBOX-1] if (parent && parent->computed_properties()) { @@ -2597,10 +2577,10 @@ RefPtr StyleComputer::recascade_font_size_if_needed( // Reconstruct the line of ancestor elements we need to inherit style from, and then do the cascade again // but only for the font-size property. - Vector ancestors; + Vector ancestors; if (pseudo_element.has_value()) ancestors.append(element); - for (auto ancestor = element.parent_element(); ancestor; ancestor = ancestor->parent_element()) + for (auto ancestor = element.element_to_inherit_style_from(pseudo_element); ancestor; ancestor = ancestor->element_to_inherit_style_from({})) ancestors.append(*ancestor); NonnullRefPtr new_font_size = CSS::LengthStyleValue::create(CSS::Length::make_px(default_monospace_font_size_in_px)); @@ -2664,7 +2644,7 @@ GC::Ref StyleComputer::compute_properties(DOM::Element& elem // FIXME: Logical properties should inherit from their parent's equivalent unmapped logical property. if ((!value && is_inherited_property(property_id)) || (value && value->is_inherit())) { - if (auto inheritance_parent = element_to_inherit_style_from(&element, pseudo_element)) { + if (auto const inheritance_parent = element.element_to_inherit_style_from(pseudo_element)) { value = inheritance_parent->computed_properties()->property(property_id); inherited = ComputedProperties::Inherited::Yes; } else { @@ -3183,9 +3163,9 @@ NonnullRefPtr StyleComputer::compute_value_of_custom_property( // Unset is the same as inherit for inherited properties, and by default all custom properties are inherited. // FIXME: Support non-inherited registered custom properties. if (value->is_inherit() || value->is_unset()) { - if (!abstract_element.parent_element()) + if (!abstract_element.element_to_inherit_style_from()) return document.custom_property_initial_value(name); - auto inherited_value = DOM::AbstractElement { const_cast(*abstract_element.parent_element()) }.get_custom_property(name); + auto inherited_value = DOM::AbstractElement { const_cast(*abstract_element.element_to_inherit_style_from()) }.get_custom_property(name); if (!inherited_value) return document.custom_property_initial_value(name); return inherited_value.release_nonnull(); @@ -3235,9 +3215,9 @@ void StyleComputer::compute_math_depth(ComputedProperties& style, DOM::Element c compute_defaulted_property_value(style, element, CSS::PropertyID::MathStyle, pseudo_element); auto inherited_math_depth = [&]() { - if (!element || !element->parent_element()) + if (!element || !element->element_to_inherit_style_from(pseudo_element)) return InitialValues::math_depth(); - return element->parent_element()->computed_properties()->math_depth(); + return element->element_to_inherit_style_from(pseudo_element)->computed_properties()->math_depth(); }; auto const& value = style.property(CSS::PropertyID::MathDepth); diff --git a/Libraries/LibWeb/DOM/AbstractElement.cpp b/Libraries/LibWeb/DOM/AbstractElement.cpp index d8e65118817..f07fb274c70 100644 --- a/Libraries/LibWeb/DOM/AbstractElement.cpp +++ b/Libraries/LibWeb/DOM/AbstractElement.cpp @@ -40,6 +40,11 @@ GC::Ptr AbstractElement::parent_element() const return m_element->parent_element(); } +GC::Ptr AbstractElement::element_to_inherit_style_from() const +{ + return m_element->element_to_inherit_style_from(m_pseudo_element); +} + Optional AbstractElement::walk_layout_tree(WalkMethod walk_method) { GC::Ptr node = layout_node(); diff --git a/Libraries/LibWeb/DOM/AbstractElement.h b/Libraries/LibWeb/DOM/AbstractElement.h index fdec63a4bf2..af44dab2579 100644 --- a/Libraries/LibWeb/DOM/AbstractElement.h +++ b/Libraries/LibWeb/DOM/AbstractElement.h @@ -27,6 +27,7 @@ public: GC::Ptr layout_node() const { return const_cast(this)->layout_node(); } GC::Ptr parent_element() const; + GC::Ptr element_to_inherit_style_from() const; Optional previous_in_tree_order() { return walk_layout_tree(WalkMethod::Previous); } Optional previous_sibling_in_tree_order() { return walk_layout_tree(WalkMethod::PreviousSibling); } bool is_before(AbstractElement const&) const; diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 866eeac76c2..396378bbf35 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -4131,4 +4131,17 @@ GC::Ref Element::computed_style_map() return *m_computed_style_map_cache; } +// The element to inherit style from. +// If a pseudo-element is specified, this will return the element itself. +// Otherwise, if this element is slotted somewhere, it will return the slot's element to inherit style from. +// Otherwise, it will return the parent or shadow host element of this element. +GC::Ptr Element::element_to_inherit_style_from(Optional pseudo_element) const +{ + if (pseudo_element.has_value()) + return this; + while (auto const slot = assigned_slot_internal()) + return slot->element_to_inherit_style_from({}); + return parent_or_shadow_host_element(); +} + } diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h index 548f1003a9c..323571c4101 100644 --- a/Libraries/LibWeb/DOM/Element.h +++ b/Libraries/LibWeb/DOM/Element.h @@ -233,6 +233,8 @@ public: WebIDL::ExceptionOr> parse_fragment(StringView markup); + [[nodiscard]] GC::Ptr element_to_inherit_style_from(Optional) const; + WebIDL::ExceptionOr inner_html() const; WebIDL::ExceptionOr set_inner_html(StringView); diff --git a/Tests/LibWeb/Layout/expected/slot-style-inheritance.txt b/Tests/LibWeb/Layout/expected/slot-style-inheritance.txt new file mode 100644 index 00000000000..1dbe7afa7f5 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/slot-style-inheritance.txt @@ -0,0 +1,20 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x54 [BFC] children: not-inline + BlockContainer at (8,8) content-size 784x38 children: not-inline + Box
at (13,13) content-size 774x28 flex-container(row) [FFC] children: not-inline + BlockContainer at (13,13) content-size 52.5625x28 flex-item [BFC] children: not-inline + BlockContainer
at (18,18) content-size 42.5625x18 children: inline + frag 0 from TextNode start: 0, length: 5, rect: [18,18 42.5625x18] baseline: 13.796875 + "story" + TextNode <#text> + +ViewportPaintable (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x54] + PaintableWithLines (BlockContainer) [8,8 784x38] + PaintableBox (Box
) [8,8 784x38] + PaintableWithLines (BlockContainer) [13,13 52.5625x28] + PaintableWithLines (BlockContainer
) [13,13 52.5625x28] + TextPaintable (TextNode<#text>) + +SC for Viewport<#document> [0,0 800x600] [children: 1] (z-index: auto) + SC for BlockContainer [0,0 800x54] [children: 0] (z-index: auto) diff --git a/Tests/LibWeb/Layout/input/slot-style-inheritance.html b/Tests/LibWeb/Layout/input/slot-style-inheritance.html new file mode 100644 index 00000000000..4fb8eda40a9 --- /dev/null +++ b/Tests/LibWeb/Layout/input/slot-style-inheritance.html @@ -0,0 +1,9 @@ +
story