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.)
This commit is contained in:
parent
bb6af641d4
commit
54beb7433e
Notes:
sideshowbarker
2024-07-17 20:20:49 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/54beb7433ee
2 changed files with 24 additions and 12 deletions
|
@ -407,6 +407,9 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer& block_c
|
|||
}
|
||||
|
||||
compute_width(child_box);
|
||||
if (is<ReplacedBox>(child_box) || is<BlockContainer>(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<ReplacedBox>(child_box) || is<BlockContainer>(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; };
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue