From dabbade05ce2ba959abf1e9dea22810f9e5b1918 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 17 Oct 2021 18:24:07 +0200 Subject: [PATCH] LibWeb: Factor out creation of independent formatting contexts This patch breaks FormattingContext::layout_inside() into two functions, one that creates an independent formatting context (if needed), and another that calls the former and then performs the inside layout within the appropriate context. The main goal here was to make layout_inside() return the independent formatting context if one was created. This will allow us to defer certain operations in child contexts until the parent context has finished formatting the child root box. --- .../LibWeb/Layout/FormattingContext.cpp | 61 ++++++++++--------- .../LibWeb/Layout/FormattingContext.h | 7 ++- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index d65bd03556..05b438af5f 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -75,47 +75,48 @@ bool FormattingContext::creates_block_formatting_context(const Box& box) return false; } -void FormattingContext::layout_inside(Box& child_box, LayoutMode layout_mode) +OwnPtr FormattingContext::create_independent_formatting_context_if_needed(Box& child_box) { if (!child_box.can_have_children()) - return; - - if (is(child_box)) { - SVGFormattingContext context(child_box, this); - context.run(child_box, layout_mode); - return; - } + return {}; auto child_display = child_box.computed_values().display(); - if (child_display.is_flex_inside()) { - FlexFormattingContext context(child_box, this); - context.run(child_box, layout_mode); - return; - } + if (is(child_box)) + return make(child_box, this); - if (creates_block_formatting_context(child_box)) { - BlockFormattingContext context(verify_cast(child_box), this); - context.run(child_box, layout_mode); - return; - } + if (child_display.is_flex_inside()) + return make(child_box, this); - if (child_display.is_table_inside()) { - TableFormattingContext context(verify_cast(child_box), this); - context.run(child_box, layout_mode); - return; - } + if (creates_block_formatting_context(child_box)) + return make(verify_cast(child_box), this); + + if (child_display.is_table_inside()) + return make(verify_cast(child_box), this); VERIFY(is_block_formatting_context()); + if (child_box.children_are_inline()) + return make(verify_cast(child_box), this); - if (child_box.children_are_inline()) { - InlineFormattingContext context(verify_cast(child_box), this); - context.run(child_box, layout_mode); - return; - } - + // The child box is a block container that doesn't create its own BFC. + // It will be formatted by this BFC. VERIFY(child_display.is_flow_inside()); - run(child_box, layout_mode); + VERIFY(child_box.is_block_container()); + return {}; +} + +OwnPtr FormattingContext::layout_inside(Box& child_box, LayoutMode layout_mode) +{ + if (!child_box.can_have_children()) + return {}; + + auto independent_formatting_context = create_independent_formatting_context_if_needed(child_box); + if (independent_formatting_context) + independent_formatting_context->run(child_box, layout_mode); + else + run(child_box, layout_mode); + + return independent_formatting_context; } static float greatest_child_width(Box const& box) diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h index e652a302cb..de0208a74e 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h @@ -12,6 +12,8 @@ namespace Web::Layout { class FormattingContext { public: + virtual ~FormattingContext(); + enum class Type { Block, Inline, @@ -38,11 +40,12 @@ public: static float compute_width_for_replaced_element(const ReplacedBox&); static float compute_height_for_replaced_element(const ReplacedBox&); + OwnPtr create_independent_formatting_context_if_needed(Box& child_box); + protected: FormattingContext(Type, Box&, FormattingContext* parent = nullptr); - virtual ~FormattingContext(); - void layout_inside(Box&, LayoutMode); + OwnPtr layout_inside(Box&, LayoutMode); struct ShrinkToFitResult { float preferred_width { 0 };