From a52d346839b8e2c5c94a21379cfb8750ce6f1666 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 22 Sep 2022 16:46:48 +0200 Subject: [PATCH] LibWeb: Take coordinate spaces into account when clearing past floats We were forgetting to convert to and from BFC root relative coordinates when calculating how much clearance was needed to get past floats. This fixes the last remaining issue on Acid1, which is now perfect. :^) --- .../LibWeb/Layout/BlockFormattingContext.cpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index bf01a9d93c..1223aae905 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -504,12 +504,25 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically auto clear_floating_boxes = [&](FloatSideData& float_side) { if (!float_side.current_boxes.is_empty()) { - float clearance_y = 0; + // NOTE: Floating boxes are globally relevant within this BFC, *but* their offset coordinates + // are relative to their containing block. + // This means that we have to first convert to a root-space Y coordinate before clearing, + // and then convert back to a local Y coordinate when assigning the cleared offset to + // the `child_box` layout state. + + // First, find the lowest margin box edge on this float side and calculate the Y offset just below it. + float clearance_y_in_root = 0; for (auto const& floating_box : float_side.current_boxes) { - auto const& floating_box_state = m_state.get(floating_box.box); - clearance_y = max(clearance_y, floating_box_state.offset.y() + floating_box_state.border_box_height()); + auto floating_box_rect_in_root = margin_box_rect_in_ancestor_coordinate_space(floating_box.box, root(), m_state); + clearance_y_in_root = max(clearance_y_in_root, floating_box_rect_in_root.bottom() + 1); } - y = max(y, clearance_y); + + // Then, convert the clearance Y to a coordinate relative to the containing block of `child_box`. + float clearance_y_in_containing_block = clearance_y_in_root; + for (auto* containing_block = child_box.containing_block(); containing_block && containing_block != &root(); containing_block = containing_block->containing_block()) + clearance_y_in_containing_block -= m_state.get(*containing_block).offset.y(); + + y = max(y, clearance_y_in_containing_block); float_side.clear(); } };