diff options
author | Andreas Kling <kling@serenityos.org> | 2021-10-06 21:53:25 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-06 21:53:25 +0200 |
commit | f73aa8e2bd06155bb18a6dd3a0f67ebbb3690d1f (patch) | |
tree | 89839a4205fbe781a5a7ee7de53f1272aab9efd8 /Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp | |
parent | a0bea52a5f4146a14badccc6e4d7e13f5da05a21 (diff) | |
download | serenity-f73aa8e2bd06155bb18a6dd3a0f67ebbb3690d1f.zip |
LibWeb: Move line boxes from Layout::Box to BlockContainer
Per the spec, only a BlockContainer" can have line boxes, so let's not
clutter up every Layout::Box with line boxes.
This also allows us to establish an invariant that BFC and IFC always
operate on a Layout::BlockContainer.
Note that if BlockContainer has all block-level children, its line boxes
are not used for anything. They are only used in the all inline-level
children scenario.
Diffstat (limited to 'Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp')
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 1a5c4953cb..6727d9444b 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -17,7 +17,7 @@ namespace Web::Layout { -BlockFormattingContext::BlockFormattingContext(Box& root, FormattingContext* parent) +BlockFormattingContext::BlockFormattingContext(BlockContainer& root, FormattingContext* parent) : FormattingContext(root, parent) { } @@ -46,9 +46,9 @@ void BlockFormattingContext::run(Box& box, LayoutMode layout_mode) compute_width(box); if (box.children_are_inline()) { - layout_inline_children(box, layout_mode); + layout_inline_children(verify_cast<BlockContainer>(box), layout_mode); } else { - layout_block_level_children(box, layout_mode); + layout_block_level_children(verify_cast<BlockContainer>(box), layout_mode); } if (layout_mode == LayoutMode::Default) { @@ -289,7 +289,7 @@ 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) +static float compute_auto_height_for_block_level_element(Box const& box) { Optional<float> top; Optional<float> bottom; @@ -297,12 +297,13 @@ static float compute_auto_height_for_block_level_element(const Box& box) 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()) { + auto& block_container = verify_cast<Layout::BlockContainer>(box); + if (!block_container.line_boxes().is_empty()) { + for (auto& fragment : block_container.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()) { + for (auto& fragment : block_container.line_boxes().last().fragments()) { if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value()) bottom = fragment.offset().y() + fragment.height(); } @@ -415,23 +416,23 @@ void BlockFormattingContext::compute_position(Box& box) } } -void BlockFormattingContext::layout_inline_children(Box& box, LayoutMode layout_mode) +void BlockFormattingContext::layout_inline_children(BlockContainer& block_container, LayoutMode layout_mode) { - InlineFormattingContext context(box, this); - context.run(box, layout_mode); + InlineFormattingContext context(block_container, this); + context.run(block_container, layout_mode); } -void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode layout_mode) +void BlockFormattingContext::layout_block_level_children(BlockContainer& block_container, LayoutMode layout_mode) { float content_height = 0; float content_width = 0; - box.for_each_child_of_type<Box>([&](auto& child_box) { + block_container.for_each_child_of_type<Box>([&](Box& child_box) { if (child_box.is_absolutely_positioned()) return IterationDecision::Continue; if (child_box.is_floating()) { - layout_floating_child(child_box, box); + layout_floating_child(child_box, block_container); return IterationDecision::Continue; } @@ -443,9 +444,9 @@ void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode la compute_position(child_box); if (is<ReplacedBox>(child_box)) - place_block_level_replaced_element_in_normal_flow(child_box, box); + place_block_level_replaced_element_in_normal_flow(child_box, block_container); else if (is<BlockContainer>(child_box)) - place_block_level_non_replaced_element_in_normal_flow(child_box, box); + place_block_level_non_replaced_element_in_normal_flow(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. @@ -458,12 +459,12 @@ void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode la }); if (layout_mode != LayoutMode::Default) { - if (box.computed_values().width().is_undefined() || box.computed_values().width().is_auto()) - box.set_width(content_width); + if (block_container.computed_values().width().is_undefined() || block_container.computed_values().width().is_auto()) + block_container.set_width(content_width); } } -void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(Box& child_box, Box& containing_block) +void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(Box& child_box, BlockContainer const& containing_block) { VERIFY(!containing_block.is_absolutely_positioned()); auto& replaced_element_box_model = child_box.box_model(); @@ -485,7 +486,7 @@ void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(B child_box.set_offset(x, y); } -void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_flow(Box& child_box, Box& containing_block) +void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_flow(Box& child_box, BlockContainer const& containing_block) { auto& box_model = child_box.box_model(); auto& computed_values = child_box.computed_values(); @@ -600,7 +601,7 @@ static Gfx::FloatRect rect_in_coordinate_space(const Box& box, const Box& contex return rect; } -void BlockFormattingContext::layout_floating_child(Box& box, Box& containing_block) +void BlockFormattingContext::layout_floating_child(Box& box, BlockContainer const& containing_block) { VERIFY(box.is_floating()); |