diff options
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibWeb/DOM/Document.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BlockBox.cpp | 8 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BlockFormattingContext.cpp | 165 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BlockFormattingContext.h | 18 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BreakNode.cpp | 4 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/FormattingContext.cpp | 11 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/FormattingContext.h | 4 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/InlineFormattingContext.cpp | 50 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/InlineFormattingContext.h | 6 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Node.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/ReplacedBox.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/TableFormattingContext.cpp | 18 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/TableFormattingContext.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/TextNode.cpp | 3 |
14 files changed, 138 insertions, 156 deletions
diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index c57d7e06c7..7ef3a418e0 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -353,7 +353,7 @@ void Document::layout() } Layout::BlockFormattingContext root_formatting_context(*m_layout_root, nullptr); - root_formatting_context.run(Layout::LayoutMode::Default); + root_formatting_context.run(*m_layout_root, Layout::LayoutMode::Default); m_layout_root->set_needs_display(); diff --git a/Libraries/LibWeb/Layout/BlockBox.cpp b/Libraries/LibWeb/Layout/BlockBox.cpp index dc4855975d..39b95277b0 100644 --- a/Libraries/LibWeb/Layout/BlockBox.cpp +++ b/Libraries/LibWeb/Layout/BlockBox.cpp @@ -110,13 +110,13 @@ HitTestResult BlockBox::hit_test(const Gfx::IntPoint& position, HitTestType type void BlockBox::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode) { - auto& container = context.context_box(); - auto* line_box = &container.ensure_last_line_box(); + auto& containing_block = context.containing_block(); + auto* line_box = &containing_block.ensure_last_line_box(); - float available_width = context.available_width_at_line(container.line_boxes().size() - 1); + float available_width = context.available_width_at_line(containing_block.line_boxes().size() - 1); if (layout_mode != LayoutMode::OnlyRequiredLineBreaks && line_box->width() > 0 && line_box->width() + width() > available_width) { - line_box = &container.add_line_box(); + line_box = &containing_block.add_line_box(); } line_box->add_fragment(*this, 0, 0, width(), height()); } diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 0369775c46..858e9d431b 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -51,34 +51,30 @@ bool BlockFormattingContext::is_initial() const return context_box().is_initial_containing_block(); } -void BlockFormattingContext::run(LayoutMode layout_mode) +void BlockFormattingContext::run(Box& box, LayoutMode layout_mode) { if (is_initial()) { layout_initial_containing_block(layout_mode); return; } - // FIXME: BFC currently computes the width+height of the context box. + // FIXME: BFC currently computes the width+height of the target box. // This is necessary to be able to place absolutely positioned descendants. // The same work is also done by the parent BFC for each of its blocks.. if (layout_mode == LayoutMode::Default) - compute_width(context_box()); + compute_width(box); - layout_floating_children(); + layout_floating_children(box); - if (context_box().children_are_inline()) { - layout_inline_children(layout_mode); + if (box.children_are_inline()) { + layout_inline_children(box, layout_mode); } else { - layout_block_level_children(layout_mode); + layout_block_level_children(box, layout_mode); } if (layout_mode == LayoutMode::Default) - compute_height(context_box()); - - // No need to layout absolute positioned boxes during shrink-to-fit layouts. - if (layout_mode == LayoutMode::Default) - layout_absolutely_positioned_descendants(); + compute_height(box); } void BlockFormattingContext::compute_width(Box& box) @@ -411,7 +407,7 @@ void BlockFormattingContext::compute_height(Box& box) } auto& style = box.style(); - auto& containing_block = context_box(); + auto& containing_block = *box.containing_block(); CSS::Length specified_height; @@ -438,80 +434,83 @@ void BlockFormattingContext::compute_height(Box& box) } } -void BlockFormattingContext::layout_inline_children(LayoutMode layout_mode) +void BlockFormattingContext::layout_inline_children(Box& box, LayoutMode layout_mode) { - InlineFormattingContext context(context_box(), this); - context.run(layout_mode); + InlineFormattingContext context(box, this); + context.run(box, layout_mode); } -void BlockFormattingContext::layout_block_level_children(LayoutMode layout_mode) +void BlockFormattingContext::layout_block_level_children(Box& box, LayoutMode layout_mode) { float content_height = 0; float content_width = 0; - context_box().for_each_in_subtree_of_type<Box>([&](auto& box) { - if (box.is_absolutely_positioned() || box.is_floating() || box.containing_block() != &context_box()) + box.for_each_child_of_type<Box>([&](auto& child_box) { + if (child_box.is_absolutely_positioned()) { + layout_absolutely_positioned_child(child_box); + return IterationDecision::Continue; + } + + if (child_box.is_floating()) return IterationDecision::Continue; - compute_width(box); - layout_inside(box, layout_mode); - compute_height(box); + compute_width(child_box); + layout_inside(child_box, layout_mode); + compute_height(child_box); - if (box.is_replaced()) - place_block_level_replaced_element_in_normal_flow(box); - else if (box.is_block()) - place_block_level_non_replaced_element_in_normal_flow(box); + if (child_box.is_replaced()) + place_block_level_replaced_element_in_normal_flow(child_box, box); + else if (child_box.is_block()) + place_block_level_non_replaced_element_in_normal_flow(child_box, box); else - dbgln("FIXME: Layout::BlockBox::layout_contained_boxes doesn't know how to place a {}", box.class_name()); + dbgln("FIXME: BlockFormattingContext::layout_block_level_children() doesn't know how to place a {}", child_box.class_name()); // 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. - if (is<ListItemBox>(box)) - downcast<ListItemBox>(box).layout_marker(); + if (is<ListItemBox>(child_box)) + downcast<ListItemBox>(child_box).layout_marker(); - content_height = max(content_height, box.effective_offset().y() + box.height() + box.box_model().margin_box(box).bottom); - content_width = max(content_width, downcast<Box>(box).width()); + content_height = max(content_height, child_box.effective_offset().y() + child_box.height() + child_box.box_model().margin_box(child_box).bottom); + content_width = max(content_width, downcast<Box>(child_box).width()); return IterationDecision::Continue; }); if (layout_mode != LayoutMode::Default) { - if (context_box().style().width().is_undefined() || context_box().style().width().is_auto()) - context_box().set_width(content_width); + if (box.style().width().is_undefined() || box.style().width().is_auto()) + box.set_width(content_width); } - // FIXME: It's not right to always shrink-wrap the context box to the content here. - context_box().set_height(content_height); + // FIXME: It's not right to always shrink-wrap the box to the content here. + box.set_height(content_height); } -void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(Box& box) +void BlockFormattingContext::place_block_level_replaced_element_in_normal_flow(Box& child_box, Box& containing_block) { - auto& containing_block = context_box(); ASSERT(!containing_block.is_absolutely_positioned()); - auto& replaced_element_box_model = box.box_model(); + auto& replaced_element_box_model = child_box.box_model(); - replaced_element_box_model.margin.top = box.style().margin().top.resolved_or_zero(context_box(), containing_block.width()); - replaced_element_box_model.margin.bottom = box.style().margin().bottom.resolved_or_zero(context_box(), containing_block.width()); - replaced_element_box_model.border.top = CSS::Length::make_px(box.style().border_top().width); - replaced_element_box_model.border.bottom = CSS::Length::make_px(box.style().border_bottom().width); - replaced_element_box_model.padding.top = box.style().padding().top.resolved_or_zero(context_box(), containing_block.width()); - replaced_element_box_model.padding.bottom = box.style().padding().bottom.resolved_or_zero(context_box(), containing_block.width()); + replaced_element_box_model.margin.top = child_box.style().margin().top.resolved_or_zero(containing_block, containing_block.width()); + replaced_element_box_model.margin.bottom = child_box.style().margin().bottom.resolved_or_zero(containing_block, containing_block.width()); + replaced_element_box_model.border.top = CSS::Length::make_px(child_box.style().border_top().width); + replaced_element_box_model.border.bottom = CSS::Length::make_px(child_box.style().border_bottom().width); + replaced_element_box_model.padding.top = child_box.style().padding().top.resolved_or_zero(containing_block, containing_block.width()); + replaced_element_box_model.padding.bottom = child_box.style().padding().bottom.resolved_or_zero(containing_block, containing_block.width()); - float x = replaced_element_box_model.margin.left.to_px(box) - + replaced_element_box_model.border.left.to_px(box) - + replaced_element_box_model.padding.left.to_px(box) - + replaced_element_box_model.offset.left.to_px(box); + float x = replaced_element_box_model.margin.left.to_px(child_box) + + replaced_element_box_model.border.left.to_px(child_box) + + replaced_element_box_model.padding.left.to_px(child_box) + + replaced_element_box_model.offset.left.to_px(child_box); - float y = replaced_element_box_model.margin_box(box).top + context_box().box_model().offset.top.to_px(box); + float y = replaced_element_box_model.margin_box(child_box).top + containing_block.box_model().offset.top.to_px(child_box); - box.set_offset(x, y); + child_box.set_offset(x, y); } -void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_flow(Box& box) +void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_flow(Box& child_box, Box& containing_block) { auto zero_value = CSS::Length::make_px(0); - auto& containing_block = context_box(); - auto& box_model = box.box_model(); - auto& style = box.style(); + auto& box_model = child_box.box_model(); + auto& style = child_box.style(); box_model.margin.top = style.margin().top.resolved(zero_value, containing_block, containing_block.width()); box_model.margin.bottom = style.margin().bottom.resolved(zero_value, containing_block, containing_block.width()); @@ -520,22 +519,22 @@ void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_fl box_model.padding.top = style.padding().top.resolved(zero_value, containing_block, containing_block.width()); box_model.padding.bottom = style.padding().bottom.resolved(zero_value, containing_block, containing_block.width()); - float x = box_model.margin.left.to_px(box) - + box_model.border.left.to_px(box) - + box_model.padding.left.to_px(box) - + box_model.offset.left.to_px(box); + float x = box_model.margin.left.to_px(child_box) + + box_model.border.left.to_px(child_box) + + box_model.padding.left.to_px(child_box) + + box_model.offset.left.to_px(child_box); if (containing_block.style().text_align() == CSS::TextAlign::VendorSpecificCenter) { - x = (containing_block.width() / 2) - box.width() / 2; + x = (containing_block.width() / 2) - child_box.width() / 2; } - float y = box_model.margin_box(box).top - + box_model.offset.top.to_px(box); + float y = box_model.margin_box(child_box).top + + box_model.offset.top.to_px(child_box); // NOTE: Empty (0-height) preceding siblings have their margins collapsed with *their* preceding sibling, etc. float collapsed_bottom_margin_of_preceding_siblings = 0; - auto* relevant_sibling = box.previous_sibling_of_type<Layout::BlockBox>(); + auto* relevant_sibling = child_box.previous_sibling_of_type<Layout::BlockBox>(); while (relevant_sibling != nullptr) { if (!relevant_sibling->is_absolutely_positioned() && !relevant_sibling->is_floating()) { collapsed_bottom_margin_of_preceding_siblings = max(collapsed_bottom_margin_of_preceding_siblings, relevant_sibling->box_model().margin.bottom.to_px(*relevant_sibling)); @@ -551,7 +550,7 @@ void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_fl + relevant_sibling->box_model().border_box(*relevant_sibling).bottom; // Collapse top margin with bottom margin of preceding siblings if needed - float my_margin_top = box_model.margin.top.to_px(box); + float my_margin_top = box_model.margin.top.to_px(child_box); if (my_margin_top < 0 || collapsed_bottom_margin_of_preceding_siblings < 0) { // Negative margins present. @@ -565,7 +564,7 @@ void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_fl } } - if (box.style().clear() == CSS::Clear::Left || box.style().clear() == CSS::Clear::Both) { + if (child_box.style().clear() == CSS::Clear::Left || child_box.style().clear() == CSS::Clear::Both) { if (!m_left_floating_boxes.is_empty()) { float clearance_y = 0; for (auto* floating_box : m_left_floating_boxes) { @@ -576,7 +575,7 @@ void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_fl } } - if (box.style().clear() == CSS::Clear::Right || box.style().clear() == CSS::Clear::Both) { + if (child_box.style().clear() == CSS::Clear::Right || child_box.style().clear() == CSS::Clear::Both) { if (!m_right_floating_boxes.is_empty()) { float clearance_y = 0; for (auto* floating_box : m_right_floating_boxes) { @@ -587,7 +586,7 @@ void BlockFormattingContext::place_block_level_non_replaced_element_in_normal_fl } } - box.set_offset(x, y); + child_box.set_offset(x, y); } void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_mode) @@ -599,9 +598,9 @@ void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_m icb.set_width(viewport_rect.width()); - layout_floating_children(); + layout_floating_children(context_box()); - layout_block_level_children(layout_mode); + layout_block_level_children(context_box(), layout_mode); ASSERT(!icb.children_are_inline()); @@ -613,10 +612,6 @@ void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_m }); icb.set_height(lowest_bottom); - // No need to layout absolute positioned boxes during shrink-to-fit layouts. - if (layout_mode == LayoutMode::Default) - layout_absolutely_positioned_descendants(); - // FIXME: This is a total hack. Make sure any GUI::Widgets are moved into place after layout. // We should stop embedding GUI::Widgets entirely, since that won't work out-of-process. icb.for_each_in_subtree_of_type<Layout::WidgetBox>([&](auto& widget) { @@ -625,26 +620,16 @@ void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_m }); } -void BlockFormattingContext::layout_absolutely_positioned_descendants() -{ - context_box().for_each_in_subtree_of_type<Box>([&](auto& box) { - if (box.is_absolutely_positioned() && box.containing_block() == &context_box()) { - layout_absolutely_positioned_descendant(box); - } - return IterationDecision::Continue; - }); -} - -void BlockFormattingContext::layout_floating_children() +void BlockFormattingContext::layout_floating_children(Box& box) { - context_box().for_each_child_of_type<Box>([&](auto& box) { - if (box.is_floating()) - layout_floating_child(box); + box.for_each_child_of_type<Box>([&](auto& child_box) { + if (child_box.is_floating()) + layout_floating_child(child_box, box); return IterationDecision::Continue; }); } -void BlockFormattingContext::layout_floating_child(Box& box) +void BlockFormattingContext::layout_floating_child(Box& box, Box& containing_block) { ASSERT(box.is_floating()); @@ -653,7 +638,7 @@ void BlockFormattingContext::layout_floating_child(Box& box) compute_height(box); // First we place the box normally (to get the right y coordinate.) - place_block_level_non_replaced_element_in_normal_flow(box); + place_block_level_non_replaced_element_in_normal_flow(box, containing_block); // Then we float it to the left or right. @@ -671,7 +656,7 @@ void BlockFormattingContext::layout_floating_child(Box& box) auto& previous_floating_box = *m_right_floating_boxes.last(); x = previous_floating_box.effective_offset().x() - box.width(); } else { - x = context_box().width() - box.width(); + x = containing_block.width() - box.width(); } m_right_floating_boxes.append(&box); } @@ -679,7 +664,7 @@ void BlockFormattingContext::layout_floating_child(Box& box) box.set_offset(x, y); } -void BlockFormattingContext::layout_absolutely_positioned_descendant(Box& box) +void BlockFormattingContext::layout_absolutely_positioned_child(Box& box) { auto& containing_block = context_box(); auto& box_model = box.box_model(); diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Libraries/LibWeb/Layout/BlockFormattingContext.h index d20a1c7514..21e4a57794 100644 --- a/Libraries/LibWeb/Layout/BlockFormattingContext.h +++ b/Libraries/LibWeb/Layout/BlockFormattingContext.h @@ -37,7 +37,7 @@ public: explicit BlockFormattingContext(Box&, FormattingContext* parent); ~BlockFormattingContext(); - virtual void run(LayoutMode) override; + virtual void run(Box&, LayoutMode) override; bool is_initial() const; @@ -55,16 +55,16 @@ private: void compute_width_for_floating_box(Box&); void layout_initial_containing_block(LayoutMode); - void layout_block_level_children(LayoutMode); - void layout_inline_children(LayoutMode); - void layout_absolutely_positioned_descendants(); - void layout_floating_children(); - void place_block_level_replaced_element_in_normal_flow(Box&); - void place_block_level_non_replaced_element_in_normal_flow(Box&); + void layout_block_level_children(Box&, LayoutMode); + void layout_inline_children(Box&, LayoutMode); + void layout_floating_children(Box&); - void layout_absolutely_positioned_descendant(Box&); - void layout_floating_child(Box&); + void place_block_level_replaced_element_in_normal_flow(Box& child, Box& container); + void place_block_level_non_replaced_element_in_normal_flow(Box& child, Box& container); + + void layout_absolutely_positioned_child(Box&); + void layout_floating_child(Box&, Box& containing_block); Vector<Box*> m_left_floating_boxes; Vector<Box*> m_right_floating_boxes; diff --git a/Libraries/LibWeb/Layout/BreakNode.cpp b/Libraries/LibWeb/Layout/BreakNode.cpp index a16633e71a..9951ae4fe0 100644 --- a/Libraries/LibWeb/Layout/BreakNode.cpp +++ b/Libraries/LibWeb/Layout/BreakNode.cpp @@ -40,9 +40,9 @@ BreakNode::~BreakNode() { } -void BreakNode::split_into_lines(InlineFormattingContext& block, LayoutMode) +void BreakNode::split_into_lines(InlineFormattingContext& context, LayoutMode) { - block.context_box().add_line_box(); + context.containing_block().add_line_box(); } } diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp index 5d81536260..44d1e4bcfb 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -71,22 +71,19 @@ void FormattingContext::layout_inside(Box& box, LayoutMode layout_mode) { if (creates_block_formatting_context(box)) { BlockFormattingContext context(box, this); - context.run(layout_mode); + context.run(box, layout_mode); return; } if (box.is_table()) { TableFormattingContext context(box, this); - context.run(layout_mode); + context.run(box, layout_mode); } else if (box.children_are_inline()) { InlineFormattingContext context(box, this); - context.run(layout_mode); + context.run(box, layout_mode); } else { // FIXME: This needs refactoring! ASSERT(is_block_formatting_context()); - auto& old_box = context_box(); - set_context_box(box); - run(layout_mode); - set_context_box(old_box); + run(box, layout_mode); } } diff --git a/Libraries/LibWeb/Layout/FormattingContext.h b/Libraries/LibWeb/Layout/FormattingContext.h index b505702d67..c1a305ed43 100644 --- a/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Libraries/LibWeb/Layout/FormattingContext.h @@ -32,7 +32,7 @@ namespace Web::Layout { class FormattingContext { public: - virtual void run(LayoutMode) = 0; + virtual void run(Box&, LayoutMode) = 0; Box& context_box() { return *m_context_box; } const Box& context_box() const { return *m_context_box; } @@ -48,8 +48,6 @@ protected: FormattingContext(Box&, FormattingContext* parent = nullptr); virtual ~FormattingContext(); - void set_context_box(Box& box) { m_context_box = &box; } - void layout_inside(Box&, LayoutMode); struct ShrinkToFitResult { diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index ac914a2314..eb3a01240e 100644 --- a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -55,7 +55,7 @@ static AvailableSpaceForLineInfo available_space_for_line(const InlineFormatting AvailableSpaceForLineInfo info; // FIXME: This is a total hack guess since we don't actually know the final y position of lines here! - float line_height = context.context_box().specified_style().line_height(context.context_box()); + float line_height = context.containing_block().specified_style().line_height(context.containing_block()); float y = (line_index * line_height); auto& bfc = static_cast<const BlockFormattingContext&>(*context.parent()); @@ -69,7 +69,7 @@ static AvailableSpaceForLineInfo available_space_for_line(const InlineFormatting } } - info.right = context.context_box().width(); + info.right = context.containing_block().width(); for (ssize_t i = bfc.right_floating_boxes().size() - 1; i >= 0; --i) { auto& floating_box = *bfc.right_floating_boxes().at(i); @@ -89,13 +89,11 @@ float InlineFormattingContext::available_width_at_line(size_t line_index) const return info.right - info.left; } -void InlineFormattingContext::run(LayoutMode layout_mode) +void InlineFormattingContext::run(Box&, LayoutMode layout_mode) { - auto& containing_block = downcast<BlockBox>(context_box()); - - ASSERT(containing_block.children_are_inline()); - containing_block.line_boxes().clear(); - containing_block.for_each_child([&](auto& child) { + ASSERT(containing_block().children_are_inline()); + containing_block().line_boxes().clear(); + containing_block().for_each_child([&](auto& child) { ASSERT(child.is_inline()); if (child.is_absolutely_positioned()) return; @@ -103,21 +101,21 @@ void InlineFormattingContext::run(LayoutMode layout_mode) child.split_into_lines(*this, layout_mode); }); - for (auto& line_box : containing_block.line_boxes()) { + for (auto& line_box : containing_block().line_boxes()) { line_box.trim_trailing_whitespace(); } // If there's an empty line box at the bottom, just remove it instead of giving it height. - if (!containing_block.line_boxes().is_empty() && containing_block.line_boxes().last().fragments().is_empty()) - containing_block.line_boxes().take_last(); + if (!containing_block().line_boxes().is_empty() && containing_block().line_boxes().last().fragments().is_empty()) + containing_block().line_boxes().take_last(); - auto text_align = containing_block.style().text_align(); - float min_line_height = containing_block.specified_style().line_height(containing_block); + auto text_align = containing_block().style().text_align(); + float min_line_height = containing_block().specified_style().line_height(containing_block()); float content_height = 0; float max_linebox_width = 0; - for (size_t line_index = 0; line_index < containing_block.line_boxes().size(); ++line_index) { - auto& line_box = containing_block.line_boxes()[line_index]; + for (size_t line_index = 0; line_index < containing_block().line_boxes().size(); ++line_index) { + auto& line_box = containing_block().line_boxes()[line_index]; float max_height = min_line_height; for (auto& fragment : line_box.fragments()) { max_height = max(max_height, fragment.height()); @@ -125,7 +123,7 @@ void InlineFormattingContext::run(LayoutMode layout_mode) float x_offset = available_space_for_line(*this, line_index).left; - float excess_horizontal_space = (float)containing_block.width() - line_box.width(); + float excess_horizontal_space = (float)containing_block().width() - line_box.width(); switch (text_align) { case CSS::TextAlign::Center: @@ -195,16 +193,14 @@ void InlineFormattingContext::run(LayoutMode layout_mode) } if (layout_mode != LayoutMode::Default) { - containing_block.set_width(max_linebox_width); + containing_block().set_width(max_linebox_width); } - containing_block.set_height(content_height); + containing_block().set_height(content_height); } void InlineFormattingContext::dimension_box_on_line(Box& box, LayoutMode layout_mode) { - auto& containing_block = downcast<BlockBox>(context_box()); - if (box.is_replaced()) { auto& replaced = const_cast<ReplacedBox&>(downcast<ReplacedBox>(box)); replaced.set_width(replaced.calculate_width()); @@ -218,15 +214,15 @@ void InlineFormattingContext::dimension_box_on_line(Box& box, LayoutMode layout_ if (inline_block.style().width().is_undefined_or_auto()) { auto result = calculate_shrink_to_fit_widths(inline_block); - auto margin_left = inline_block.style().margin().left.resolved(CSS::Length::make_px(0), containing_block, containing_block.width()).to_px(inline_block); + auto margin_left = inline_block.style().margin().left.resolved(CSS::Length::make_px(0), containing_block(), containing_block().width()).to_px(inline_block); auto border_left_width = inline_block.style().border_left().width; - auto padding_left = inline_block.style().padding().left.resolved(CSS::Length::make_px(0), containing_block, containing_block.width()).to_px(inline_block); + auto padding_left = inline_block.style().padding().left.resolved(CSS::Length::make_px(0), containing_block(), containing_block().width()).to_px(inline_block); - auto margin_right = inline_block.style().margin().right.resolved(CSS::Length::make_px(0), containing_block, containing_block.width()).to_px(inline_block); + auto margin_right = inline_block.style().margin().right.resolved(CSS::Length::make_px(0), containing_block(), containing_block().width()).to_px(inline_block); auto border_right_width = inline_block.style().border_right().width; - auto padding_right = inline_block.style().padding().right.resolved(CSS::Length::make_px(0), containing_block, containing_block.width()).to_px(inline_block); + auto padding_right = inline_block.style().padding().right.resolved(CSS::Length::make_px(0), containing_block(), containing_block().width()).to_px(inline_block); - auto available_width = containing_block.width() + auto available_width = containing_block().width() - margin_left - border_left_width - padding_left @@ -237,7 +233,7 @@ void InlineFormattingContext::dimension_box_on_line(Box& box, LayoutMode layout_ auto width = min(max(result.preferred_minimum_width, available_width), result.preferred_width); inline_block.set_width(width); } else { - inline_block.set_width(inline_block.style().width().resolved(CSS::Length::make_px(0), containing_block, containing_block.width()).to_px(inline_block)); + inline_block.set_width(inline_block.style().width().resolved(CSS::Length::make_px(0), containing_block(), containing_block().width()).to_px(inline_block)); } layout_inside(inline_block, layout_mode); @@ -245,7 +241,7 @@ void InlineFormattingContext::dimension_box_on_line(Box& box, LayoutMode layout_ if (inline_block.style().height().is_undefined_or_auto()) { // FIXME: (10.6.6) If 'height' is 'auto', the height depends on the element's descendants per 10.6.7. } else { - inline_block.set_height(inline_block.style().height().resolved(CSS::Length::make_px(0), containing_block, containing_block.height()).to_px(inline_block)); + inline_block.set_height(inline_block.style().height().resolved(CSS::Length::make_px(0), containing_block(), containing_block().height()).to_px(inline_block)); } return; } diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.h b/Libraries/LibWeb/Layout/InlineFormattingContext.h index a96f0c9901..8b7d44d267 100644 --- a/Libraries/LibWeb/Layout/InlineFormattingContext.h +++ b/Libraries/LibWeb/Layout/InlineFormattingContext.h @@ -26,6 +26,7 @@ #pragma once +#include <AK/Types.h> #include <LibWeb/Forward.h> #include <LibWeb/Layout/FormattingContext.h> @@ -36,7 +37,10 @@ public: InlineFormattingContext(Box& containing_block, FormattingContext* parent); ~InlineFormattingContext(); - virtual void run(LayoutMode) override; + Box& containing_block() { return context_box(); } + const Box& containing_block() const { return context_box(); } + + virtual void run(Box&, LayoutMode) override; float available_width_at_line(size_t line_index) const; diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h index 3a7f702e0b..ce5c7da605 100644 --- a/Libraries/LibWeb/Layout/Node.h +++ b/Libraries/LibWeb/Layout/Node.h @@ -137,6 +137,7 @@ public: bool is_fixed_position() const; const BlockBox* containing_block() const; + BlockBox* containing_block() { return const_cast<BlockBox*>(const_cast<const Node*>(this)->containing_block()); } bool can_contain_boxes_with_position_absolute() const; diff --git a/Libraries/LibWeb/Layout/ReplacedBox.cpp b/Libraries/LibWeb/Layout/ReplacedBox.cpp index a8b40f039f..9373ea5ffd 100644 --- a/Libraries/LibWeb/Layout/ReplacedBox.cpp +++ b/Libraries/LibWeb/Layout/ReplacedBox.cpp @@ -120,7 +120,7 @@ float ReplacedBox::calculate_height() const void ReplacedBox::split_into_lines(InlineFormattingContext& context, LayoutMode) { - auto& containing_block = context.context_box(); + auto& containing_block = context.containing_block(); // FIXME: This feels out of place. It would be nice if someone at a higher level // made sure we had usable geometry by the time we start splitting. diff --git a/Libraries/LibWeb/Layout/TableFormattingContext.cpp b/Libraries/LibWeb/Layout/TableFormattingContext.cpp index 988b859488..665706ab0f 100644 --- a/Libraries/LibWeb/Layout/TableFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/TableFormattingContext.cpp @@ -47,37 +47,37 @@ TableFormattingContext::~TableFormattingContext() { } -void TableFormattingContext::run(LayoutMode) +void TableFormattingContext::run(Box& box, LayoutMode) { - compute_width(context_box()); + compute_width(box); float total_content_height = 0; - context_box().for_each_child_of_type<TableRowGroupBox>([&](auto& box) { - compute_width(box); - auto column_count = box.column_count(); + box.for_each_child_of_type<TableRowGroupBox>([&](auto& row_group_box) { + compute_width(row_group_box); + auto column_count = row_group_box.column_count(); Vector<float> column_widths; column_widths.resize(column_count); - box.template for_each_child_of_type<TableRowBox>([&](auto& row) { + row_group_box.template for_each_child_of_type<TableRowBox>([&](auto& row) { calculate_column_widths(row, column_widths); }); float content_height = 0; - box.template for_each_child_of_type<TableRowBox>([&](auto& row) { + row_group_box.template for_each_child_of_type<TableRowBox>([&](auto& row) { row.set_offset(0, content_height); layout_row(row, column_widths); content_height += row.height(); }); - box.set_height(content_height); + row_group_box.set_height(content_height); total_content_height += content_height; }); // FIXME: This is a total hack, we should respect the 'height' property. - context_box().set_height(total_content_height); + box.set_height(total_content_height); } void TableFormattingContext::calculate_column_widths(Box& row, Vector<float>& column_widths) diff --git a/Libraries/LibWeb/Layout/TableFormattingContext.h b/Libraries/LibWeb/Layout/TableFormattingContext.h index 5419b437a9..7bb973a5d2 100644 --- a/Libraries/LibWeb/Layout/TableFormattingContext.h +++ b/Libraries/LibWeb/Layout/TableFormattingContext.h @@ -36,7 +36,7 @@ public: explicit TableFormattingContext(Box&, FormattingContext* parent); ~TableFormattingContext(); - virtual void run(LayoutMode) override; + virtual void run(Box&, LayoutMode) override; private: void calculate_column_widths(Box& row, Vector<float>& column_widths); diff --git a/Libraries/LibWeb/Layout/TextNode.cpp b/Libraries/LibWeb/Layout/TextNode.cpp index 5438054e9d..a4f59874a4 100644 --- a/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Libraries/LibWeb/Layout/TextNode.cpp @@ -192,7 +192,8 @@ void TextNode::for_each_chunk(Callback callback, LayoutMode layout_mode, bool do void TextNode::split_into_lines_by_rules(InlineFormattingContext& context, LayoutMode layout_mode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks) { - auto& containing_block = context.context_box(); + auto& containing_block = context.containing_block(); + auto& font = specified_style().font(); float space_width = font.glyph_width(' ') + font.glyph_spacing(); |