From ccf35a973f0e4e9fb4c0bc7be4e7b0c56b8a71b5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 25 Jul 2023 10:58:11 +0200 Subject: [PATCH] LibWeb: Derive box baseline from last child *with line boxes* Before this change, we always derived a box's baseline from its last child, even if the last child didn't have any line boxes inside. This caused baselines to slip further down vertically than expected. There are more baseline alignment issues to fix, but this one was responsible for a fair chunk of trouble. :^) --- .../inline-block-baseline-1.txt | 22 ++++++++++++++++ .../inline-block-baseline-2.txt | 26 +++++++++++++++++++ .../block-and-inline/margin-collapse-5.txt | 14 +++++----- .../inline-block-baseline-1.html | 16 ++++++++++++ .../inline-block-baseline-2.html | 15 +++++++++++ .../LibWeb/Layout/FormattingContext.cpp | 20 +++++++++++++- .../LibWeb/Layout/FormattingContext.h | 2 ++ 7 files changed, 107 insertions(+), 8 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-1.txt create mode 100644 Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-2.txt create mode 100644 Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-1.html create mode 100644 Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-2.html diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-1.txt b/Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-1.txt new file mode 100644 index 0000000000..ce7e4680cc --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-1.txt @@ -0,0 +1,22 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x600 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x92.9375 children: inline + line 0 width: 307.140625, height: 92.9375, bottom: 92.9375, baseline: 35 + frag 0 from TextNode start: 0, length: 13, rect: [10,31.46875 103.140625x17.46875] + "Hello friends" + frag 1 from BlockContainer start: 0, length: 0, rect: [114.140625,11 202x90.9375] + TextNode <#text> + BlockContainer at (114.140625,11) content-size 202x90.9375 inline-block [BFC] children: not-inline + BlockContainer
at (115.140625,12) content-size 200x17.46875 children: inline + line 0 width: 22.546875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 3, rect: [115.140625,12 22.546875x17.46875] + "1st" + TextNode <#text> + BlockContainer
at (115.140625,31.46875) content-size 200x17.46875 children: inline + line 0 width: 26.28125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 3, rect: [115.140625,31.46875 26.28125x17.46875] + "2nd" + TextNode <#text> + BlockContainer at (115.140625,50.9375) content-size 200x50 children: not-inline + BlockContainer <(anonymous)> at (114.140625,101.9375) content-size 202x0 children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-2.txt b/Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-2.txt new file mode 100644 index 0000000000..d9722abe9c --- /dev/null +++ b/Tests/LibWeb/Layout/expected/block-and-inline/inline-block-baseline-2.txt @@ -0,0 +1,26 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x600 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x60.40625 children: inline + line 0 width: 144.375, height: 60.40625, bottom: 60.40625, baseline: 35 + frag 0 from TextNode start: 0, length: 13, rect: [10,31.46875 103.140625x17.46875] + "Hello friends" + frag 1 from BlockContainer start: 0, length: 0, rect: [114.140625,11 39.234375x58.40625] + TextNode <#text> + BlockContainer at (114.140625,11) content-size 39.234375x58.40625 inline-block [BFC] children: not-inline + BlockContainer
at (115.140625,12) content-size 37.234375x17.46875 children: inline + line 0 width: 22.546875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 3, rect: [115.140625,12 22.546875x17.46875] + "1st" + TextNode <#text> + BlockContainer
at (115.140625,31.46875) content-size 37.234375x17.46875 children: inline + line 0 width: 26.28125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 3, rect: [115.140625,31.46875 26.28125x17.46875] + "2nd" + TextNode <#text> + BlockContainer at (115.140625,50.9375) content-size 37.234375x17.46875 floating [BFC] children: inline + line 0 width: 37.234375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 5, rect: [115.140625,50.9375 37.234375x17.46875] + "float" + TextNode <#text> + BlockContainer <(anonymous)> at (114.140625,49.9375) content-size 39.234375x0 children: inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/margin-collapse-5.txt b/Tests/LibWeb/Layout/expected/block-and-inline/margin-collapse-5.txt index e23782854e..d0e188aade 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/margin-collapse-5.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/margin-collapse-5.txt @@ -1,12 +1,12 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline - BlockContainer at (1,1) content-size 798x135 [BFC] children: inline - line 0 width: 170.96875, height: 135, bottom: 135, baseline: 13.53125 - frag 0 from BlockContainer start: 0, length: 0, rect: [2,15.53125 168.96875x119.46875] - BlockContainer at (2,15.53125) content-size 168.96875x119.46875 inline-block [BFC] children: not-inline - BlockContainer at (3,16.53125) content-size 166.96875x17.46875 children: inline + BlockContainer at (1,1) content-size 798x121.46875 [BFC] children: inline + line 0 width: 170.96875, height: 121.46875, bottom: 121.46875, baseline: 15.53125 + frag 0 from BlockContainer start: 0, length: 0, rect: [2,2 168.96875x119.46875] + BlockContainer at (2,2) content-size 168.96875x119.46875 inline-block [BFC] children: not-inline + BlockContainer at (3,3) content-size 166.96875x17.46875 children: inline line 0 width: 166.96875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 21, rect: [3,16.53125 166.96875x17.46875] + frag 0 from TextNode start: 0, length: 21, rect: [3,3 166.96875x17.46875] "suspiciously tall box" TextNode <#text> - BlockContainer <(anonymous)> at (2,135) content-size 168.96875x0 children: inline + BlockContainer <(anonymous)> at (2,121.46875) content-size 168.96875x0 children: inline TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-1.html b/Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-1.html new file mode 100644 index 0000000000..d91e0117ba --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-1.html @@ -0,0 +1,16 @@ +Hello friends
1st
2nd
diff --git a/Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-2.html b/Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-2.html new file mode 100644 index 0000000000..49a21a02c8 --- /dev/null +++ b/Tests/LibWeb/Layout/input/block-and-inline/inline-block-baseline-2.html @@ -0,0 +1,15 @@ +Hello friends
1st
2nd
float
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 283bd954a4..fce3be6a4e 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -1686,6 +1686,24 @@ CSSPixelRect FormattingContext::absolute_content_rect(Box const& box) const return rect; } +Box const* FormattingContext::box_child_to_derive_baseline_from(Box const& box) const +{ + // To find the baseline of a box, we first look for the last in-flow child with at least one line box. + auto const* last_box_child = box.last_child_of_type(); + for (Node const* child = last_box_child; child; child = child->previous_sibling()) { + if (!child->is_box()) + continue; + auto& child_box = static_cast(*child); + if (child_box.is_out_of_flow(*this)) + continue; + if (m_state.get(child_box).line_boxes.is_empty()) + continue; + return &child_box; + } + // If none of the children has a line box, the baseline is formed by the last in-flow child. + return last_box_child; +} + CSSPixels FormattingContext::box_baseline(Box const& box) const { auto const& box_state = m_state.get(box); @@ -1714,7 +1732,7 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const if (!box_state.line_boxes.is_empty()) return box_state.margin_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline(); if (box.has_children() && !box.children_are_inline()) { - auto const* child_box = box.last_child_of_type(); + auto const* child_box = box_child_to_derive_baseline_from(box); VERIFY(child_box); return box_baseline(*child_box); } diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index 12d626cc3e..d628027921 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h @@ -151,6 +151,8 @@ protected: [[nodiscard]] Optional compute_auto_height_for_absolutely_positioned_element(Box const&, AvailableSpace const&, BeforeOrAfterInsideLayout) const; + [[nodiscard]] Box const* box_child_to_derive_baseline_from(Box const&) const; + Type m_type {}; FormattingContext* m_parent { nullptr };