From 174c94047933cd11763231fd3250d04c5ca33340 Mon Sep 17 00:00:00 2001 From: Egor Ananyin Date: Thu, 22 Apr 2021 10:59:04 +0300 Subject: LibWeb: Fix height computation (again) :^) Height computation algorithm is actually different for absolutely positioned boxes and block formatting contexts (where it doesn't include floats) Fixes #6408 --- .../LibWeb/Layout/BlockFormattingContext.cpp | 43 ++++++++++++++++++++++ .../Libraries/LibWeb/Layout/FormattingContext.cpp | 2 +- .../Libraries/LibWeb/Layout/FormattingContext.h | 1 - 3 files changed, 44 insertions(+), 2 deletions(-) (limited to 'Userland/Libraries/LibWeb') diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 30f3f9f1b5..cca7a854c1 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -247,6 +247,49 @@ void BlockFormattingContext::compute_width_for_block_level_replaced_element_in_n box.set_width(compute_width_for_replaced_element(box)); } +static float compute_auto_height_for_block_level_element(const Box& box) +{ + Optional top; + Optional bottom; + + if (box.children_are_inline()) { + // If it only has inline-level children, the height is the distance between + // the top of the topmost line box and the bottom of the bottommost line box. + if (!box.line_boxes().is_empty()) { + for (auto& fragment : box.line_boxes().first().fragments()) { + if (!top.has_value() || fragment.offset().y() < top.value()) + top = fragment.offset().y(); + } + for (auto& fragment : box.line_boxes().last().fragments()) { + if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value()) + bottom = fragment.offset().y() + fragment.height(); + } + } + } else { + // If it has block-level children, the height is the distance between + // the top margin-edge of the topmost block-level child box + // and the bottom margin-edge of the bottommost block-level child box. + box.for_each_child_of_type([&](Layout::Box& child_box) { + if (child_box.is_absolutely_positioned()) + return IterationDecision::Continue; + if ((box.computed_values().overflow_y() == CSS::Overflow::Visible) && child_box.is_floating()) + return IterationDecision::Continue; + + float child_box_top = child_box.effective_offset().y() - child_box.box_model().margin_box().top; + float child_box_bottom = child_box.effective_offset().y() + child_box.height() + child_box.box_model().margin_box().bottom; + + if (!top.has_value() || child_box_top < top.value()) + top = child_box_top; + + if (!bottom.has_value() || child_box_bottom > bottom.value()) + bottom = child_box_bottom; + + return IterationDecision::Continue; + }); + } + return bottom.value_or(0) - top.value_or(0); +} + void BlockFormattingContext::compute_height(Box& box) { auto& computed_values = box.computed_values(); diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index dfeeaa3f93..412ad77b59 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -160,7 +160,7 @@ static Gfx::FloatSize solve_replaced_size_constraint(float w, float h, const Rep return { w, h }; } -float FormattingContext::compute_auto_height_for_block_level_element(const Box& box) +static float compute_auto_height_for_block_level_element(const Box& box) { Optional top; Optional bottom; diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index e49c1cf06e..e67799000f 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h @@ -38,7 +38,6 @@ protected: float preferred_minimum_width { 0 }; }; - static float compute_auto_height_for_block_level_element(const Box& box); static float tentative_width_for_replaced_element(const ReplacedBox&, const CSS::Length& width); static float tentative_height_for_replaced_element(const ReplacedBox&, const CSS::Length& width); -- cgit v1.2.3