From 54beb7433ee7fff89b1bdfae1e69fe6654147304 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 24 Jan 2022 01:56:15 +0100 Subject: LibWeb: Place block-level boxes vertically before formatting them inside Block placement is now divided into a vertical and horizontal step. The vertical step runs before formatting boxes internally. The horizontal step still runs after (since we may need the final width value.) This solves a long-standing architectural problem where IFC didn't know its origin Y position within the BFC root box. This is required for figuring out how to flow around floating objects. (Floating objects are always relative to the BFC root.) --- .../LibWeb/Layout/BlockFormattingContext.cpp | 33 ++++++++++++++-------- .../LibWeb/Layout/BlockFormattingContext.h | 3 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index d17e454598..8b9f36c1d8 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -407,6 +407,9 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer& block_c } compute_width(child_box); + if (is(child_box) || is(child_box)) + place_block_level_element_in_normal_flow_vertically(child_box, block_container); + (void)layout_inside(child_box, layout_mode); compute_height(child_box); @@ -414,7 +417,7 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer& block_c compute_position(child_box); if (is(child_box) || is(child_box)) - place_block_level_element_in_normal_flow(child_box, block_container); + place_block_level_element_in_normal_flow_horizontally(child_box, block_container); // FIXME: This should be factored differently. It's uncool that we mutate the tree *during* layout! // Instead, we should generate the marker box during the tree build. @@ -446,20 +449,13 @@ void BlockFormattingContext::compute_vertical_box_model_metrics(Box& child_box, box_model.padding.bottom = computed_values.padding().bottom.resolved(width_of_containing_block).resolved_or_zero(containing_block).to_px(child_box); } -void BlockFormattingContext::place_block_level_element_in_normal_flow(Box& child_box, BlockContainer const& containing_block) +void BlockFormattingContext::place_block_level_element_in_normal_flow_vertically(Box& child_box, BlockContainer const& containing_block) { auto& box_model = child_box.box_model(); auto const& computed_values = child_box.computed_values(); compute_vertical_box_model_metrics(child_box, containing_block); - float x = 0; - if (containing_block.computed_values().text_align() == CSS::TextAlign::LibwebCenter) { - x = (containing_block.width() / 2) - child_box.width() / 2; - } else { - x = box_model.margin_box().left + box_model.offset.left; - } - float y = box_model.margin_box().top + box_model.offset.top; @@ -514,7 +510,21 @@ void BlockFormattingContext::place_block_level_element_in_normal_flow(Box& child if ((computed_values.clear() == CSS::Clear::Right || computed_values.clear() == CSS::Clear::Both) && !child_box.is_flex_item()) clear_floating_boxes(m_right_floats); - child_box.set_offset(x, y); + child_box.set_offset(child_box.effective_offset().x(), y); +} + +void BlockFormattingContext::place_block_level_element_in_normal_flow_horizontally(Box& child_box, BlockContainer const& containing_block) +{ + auto& box_model = child_box.box_model(); + + float x = 0; + if (containing_block.computed_values().text_align() == CSS::TextAlign::LibwebCenter) { + x = (containing_block.width() / 2) - child_box.width() / 2; + } else { + x = box_model.margin_box().left + box_model.offset.left; + } + + child_box.set_offset(x, child_box.effective_offset().y()); } void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_mode) @@ -559,7 +569,8 @@ void BlockFormattingContext::layout_floating_child(Box& box, BlockContainer cons compute_height(box); // First we place the box normally (to get the right y coordinate.) - place_block_level_element_in_normal_flow(box, containing_block); + place_block_level_element_in_normal_flow_vertically(box, containing_block); + place_block_level_element_in_normal_flow_horizontally(box, containing_block); auto float_box = [&](FloatSide side, FloatSideData& side_data) { auto first_edge = [&](PixelBox const& thing) { return side == FloatSide::Left ? thing.left : thing.right; }; diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h index 763c8cdaa6..403bad5f1a 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -50,7 +50,8 @@ private: void layout_inline_children(BlockContainer&, LayoutMode); void compute_vertical_box_model_metrics(Box& child_box, BlockContainer const& containing_block); - void place_block_level_element_in_normal_flow(Box& child_box, BlockContainer const&); + void place_block_level_element_in_normal_flow_horizontally(Box& child_box, BlockContainer const&); + void place_block_level_element_in_normal_flow_vertically(Box& child_box, BlockContainer const&); void layout_floating_child(Box& child, BlockContainer const& containing_block); -- cgit v1.2.3