From 510dfbb7e651902300ca1893f37d39a129bce2da Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 3 Jul 2023 12:49:13 +0200 Subject: [PATCH] LibWeb: Update anonymous wrappers when applying style changes Anonymous wrapper boxes inherit style from their layout tree parent, and since style data is per-layout-node, we have to manually sync them from parent to anonymous children when something changes. This is not very elegant or efficient, so I've left a FIXME about solving it in a nicer way. This fixes horizontal dog alignment on https://waffles.dog/ :^) --- ...ppers-continue-to-inherit-style-after-change.txt | 13 +++++++++++++ ...pers-continue-to-inherit-style-after-change.html | 8 ++++++++ Userland/Libraries/LibWeb/CSS/ComputedValues.h | 5 +++++ Userland/Libraries/LibWeb/Layout/Node.cpp | 10 ++++++++++ 4 files changed, 36 insertions(+) create mode 100644 Tests/LibWeb/Layout/expected/anonymous-wrappers-continue-to-inherit-style-after-change.txt create mode 100644 Tests/LibWeb/Layout/input/anonymous-wrappers-continue-to-inherit-style-after-change.html diff --git a/Tests/LibWeb/Layout/expected/anonymous-wrappers-continue-to-inherit-style-after-change.txt b/Tests/LibWeb/Layout/expected/anonymous-wrappers-continue-to-inherit-style-after-change.txt new file mode 100644 index 0000000000..b88ff48875 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/anonymous-wrappers-continue-to-inherit-style-after-change.txt @@ -0,0 +1,13 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x89.846250 [BFC] children: not-inline + BlockContainer at (8,21.440000) content-size 784x73.846250 children: not-inline + BlockContainer

at (8,21.440000) content-size 784x34.9375 children: inline + line 0 width: 105.53125, height: 34.9375, bottom: 34.9375, baseline: 27.0625 + frag 0 from TextNode start: 0, length: 6, rect: [8,21.440000 105.53125x34.9375] + "header" + TextNode <#text> + BlockContainer <(anonymous)> at (8,77.817501) content-size 784x17.46875 children: inline + line 0 width: 212.125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 24, rect: [8,77.817501 212.125x17.46875] + "anonymously wrapped text" + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/anonymous-wrappers-continue-to-inherit-style-after-change.html b/Tests/LibWeb/Layout/input/anonymous-wrappers-continue-to-inherit-style-after-change.html new file mode 100644 index 0000000000..8803f32489 --- /dev/null +++ b/Tests/LibWeb/Layout/input/anonymous-wrappers-continue-to-inherit-style-after-change.html @@ -0,0 +1,8 @@ +

header

anonymously wrapped text \ No newline at end of file diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index c3b1f25a79..44bf9e45c9 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -431,6 +431,11 @@ class ImmutableComputedValues final : public ComputedValues { class MutableComputedValues final : public ComputedValues { public: + void inherit_from(ComputedValues const& other) + { + m_inherited = static_cast(other).m_inherited; + } + void set_aspect_ratio(AspectRatio aspect_ratio) { m_noninherited.aspect_ratio = aspect_ratio; } void set_font_size(float font_size) { m_inherited.font_size = font_size; } void set_font_weight(int font_weight) { m_inherited.font_weight = font_weight; } diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 65e5d684e2..5cdc175233 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -739,6 +739,16 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) auto& wrapper_computed_values = static_cast(parent())->m_computed_values; transfer_table_box_computed_values_to_wrapper_computed_values(wrapper_computed_values); } + + // Update any anonymous children that inherit from this node. + // FIXME: This is pretty hackish. It would be nicer if they shared the inherited style + // data structure somehow, so this wasn't necessary. + for_each_child([&](auto& child) { + if (child.is_anonymous()) { + auto& child_computed_values = static_cast(static_cast(const_cast(child.computed_values()))); + child_computed_values.inherit_from(computed_values); + } + }); } bool Node::is_root_element() const