From b918ce4022cc2c9f33a7fc639dd5c7baf54d2997 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 3 Jul 2023 10:29:30 +0200 Subject: [PATCH] LibWeb: Make Layout::TextNode::text_for_rendering() lazily computed As it turns out, Layout::TreeBuilder never managed to wrap text within table boxes in anonymous wrapper boxes, since it relied on checking text_for_rendering(), and that was never initialized during that early stage of tree building. This patch fixes the issue by making text_for_rendering() compute the (potentially collapsed) text lazily when called. Note that the test included with this patch is still totally wrong, but that is now a TFC problem rather than a TreeBuilder problem. :^) --- .../table/table-header-and-footer-groups.txt | 18 +++++++++++++ .../table/table-header-and-footer-groups.html | 24 +++++++++++++++++ .../LibWeb/Layout/InlineLevelIterator.cpp | 3 --- Userland/Libraries/LibWeb/Layout/TextNode.cpp | 27 +++++++++++++++++-- Userland/Libraries/LibWeb/Layout/TextNode.h | 4 +-- 5 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/table/table-header-and-footer-groups.txt create mode 100644 Tests/LibWeb/Layout/input/table/table-header-and-footer-groups.html diff --git a/Tests/LibWeb/Layout/expected/table/table-header-and-footer-groups.txt b/Tests/LibWeb/Layout/expected/table/table-header-and-footer-groups.txt new file mode 100644 index 0000000000..a51f328ae7 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/table/table-header-and-footer-groups.txt @@ -0,0 +1,18 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x216 [BFC] children: not-inline + TableWrapper <(anonymous)> at (9,9) content-size 300x200 [BFC] children: not-inline + Box at (10,10) content-size 298x198 table-box [TFC] children: not-inline + Box at (10,10) content-size 298x0 table-footer-group children: inline + Box <(anonymous)> at (10,10) content-size 298x0 table-row children: inline + BlockContainer <(anonymous)> at (10,10) content-size 298x0 table-cell [BFC] children: inline + line 0 width: 56.109375, height: 0, bottom: 0, baseline: 4.796875 + frag 0 from TextNode start: 0, length: 6, rect: [10,10 56.109375x0] + "bottom" + TextNode <#text> + Box at (10,10) content-size 298x0 table-header-group children: inline + Box <(anonymous)> at (10,10) content-size 298x0 table-row children: inline + BlockContainer <(anonymous)> at (10,10) content-size 298x0 table-cell [BFC] children: inline + line 0 width: 26.640625, height: 0, bottom: 0, baseline: 4.796875 + frag 0 from TextNode start: 0, length: 3, rect: [10,10 26.640625x0] + "top" + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/table/table-header-and-footer-groups.html b/Tests/LibWeb/Layout/input/table/table-header-and-footer-groups.html new file mode 100644 index 0000000000..f59e18269a --- /dev/null +++ b/Tests/LibWeb/Layout/input/table/table-header-and-footer-groups.html @@ -0,0 +1,24 @@ +
bottom
top
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp b/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp index 34c2e9015d..3e85cb5d9d 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp @@ -258,9 +258,6 @@ void InlineLevelIterator::enter_text_node(Layout::TextNode const& text_node) if (text_node.dom_node().is_editable() && !text_node.dom_node().is_uninteresting_whitespace_node()) do_collapse = false; - // FIXME: The const_cast here is gross. - const_cast(text_node).compute_text_for_rendering(do_collapse); - m_text_node_context = TextNodeContext { .do_collapse = do_collapse, .do_wrap_lines = do_wrap_lines, diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.cpp b/Userland/Libraries/LibWeb/Layout/TextNode.cpp index 67ccb5d15f..d191072ad1 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Userland/Libraries/LibWeb/Layout/TextNode.cpp @@ -41,9 +41,32 @@ static ErrorOr apply_text_transform(DeprecatedString const& st return string; } -// NOTE: This collapses whitespace into a single ASCII space if collapse is true. -void TextNode::compute_text_for_rendering(bool collapse) +DeprecatedString const& TextNode::text_for_rendering() const { + if (m_text_for_rendering.is_null()) + const_cast(this)->compute_text_for_rendering(); + return m_text_for_rendering; +} + +// NOTE: This collapses whitespace into a single ASCII space if the CSS white-space property tells us to. +void TextNode::compute_text_for_rendering() +{ + bool collapse = [](CSS::WhiteSpace white_space) { + switch (white_space) { + case CSS::WhiteSpace::Normal: + case CSS::WhiteSpace::Nowrap: + case CSS::WhiteSpace::PreLine: + return true; + case CSS::WhiteSpace::Pre: + case CSS::WhiteSpace::PreWrap: + return false; + } + VERIFY_NOT_REACHED(); + }(computed_values().white_space()); + + if (dom_node().is_editable() && !dom_node().is_uninteresting_whitespace_node()) + collapse = false; + auto data = apply_text_transform(dom_node().data(), computed_values().text_transform()).release_value_but_fixme_should_propagate_errors(); if (dom_node().is_password_input()) { diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.h b/Userland/Libraries/LibWeb/Layout/TextNode.h index cc72d91bab..0201973272 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.h +++ b/Userland/Libraries/LibWeb/Layout/TextNode.h @@ -23,7 +23,7 @@ public: const DOM::Text& dom_node() const { return static_cast(*Node::dom_node()); } - DeprecatedString const& text_for_rendering() const { return m_text_for_rendering; } + DeprecatedString const& text_for_rendering() const; struct Chunk { Utf8View view; @@ -48,7 +48,7 @@ public: Utf8View::Iterator m_iterator; }; - void compute_text_for_rendering(bool collapse); + void compute_text_for_rendering(); virtual JS::GCPtr create_paintable() const override;