summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-02-12 19:54:09 +0100
committerAndreas Kling <kling@serenityos.org>2022-02-12 22:30:50 +0100
commit0532d7d2556ad5007c06a26c66e2e5d94a8fe13a (patch)
treef25d1b9a4c15494362920cf723e6c88578ba4404 /Userland/Libraries/LibWeb
parent2f3af7126174623cd986d1a8b1485ccb7b464f52 (diff)
downloadserenity-0532d7d2556ad5007c06a26c66e2e5d94a8fe13a.zip
LibWeb: Stop sizing the context root box in formatting contexts
Until now, some formatting contexts (BFC in particular) have been assigning size to the root box. This is really the responsibility of the parent formatting context, so let's stop doing it. To keep position:absolute working, parent formatting contexts now notify child contexts when the child's root box has been sized. (Note that the important thing here is for the child root to have its final used height before it's able to place bottom-relative boxes.) This breaks flexbox layout in some ways, but we'll have to address those by improving the spec compliance of FFC.)
Diffstat (limited to 'Userland/Libraries/LibWeb')
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp57
-rw-r--r--Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h7
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.cpp5
-rw-r--r--Userland/Libraries/LibWeb/Layout/FormattingContext.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp5
5 files changed, 47 insertions, 29 deletions
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
index edf3427e88..b84e1ef4b8 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
@@ -32,38 +32,25 @@ bool BlockFormattingContext::is_initial() const
return is<InitialContainingBlock>(root());
}
-void BlockFormattingContext::run(Box& box, LayoutMode layout_mode)
+void BlockFormattingContext::run(Box&, LayoutMode layout_mode)
{
if (is_initial()) {
layout_initial_containing_block(layout_mode);
return;
}
- // 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(box);
-
- if (box.children_are_inline()) {
- layout_inline_children(verify_cast<BlockContainer>(box), layout_mode);
- } else {
- layout_block_level_children(verify_cast<BlockContainer>(box), layout_mode);
- }
-
- if (layout_mode == LayoutMode::Default) {
- compute_height(box);
+ if (root().children_are_inline())
+ layout_inline_children(root(), layout_mode);
+ else
+ layout_block_level_children(root(), layout_mode);
+}
- box.for_each_child_of_type<Box>([&](auto& child_box) {
- if (child_box.is_absolutely_positioned()) {
- layout_absolutely_positioned_element(child_box);
- }
- return IterationDecision::Continue;
- });
- }
+void BlockFormattingContext::parent_context_did_dimension_child_root_box()
+{
+ for (auto& box : m_absolutely_positioned_boxes)
+ layout_absolutely_positioned_element(box);
- apply_transformations_to_children(box);
+ apply_transformations_to_children(root());
}
void BlockFormattingContext::apply_transformations_to_children(Box& box)
@@ -384,18 +371,24 @@ void BlockFormattingContext::compute_position(Box& box)
void BlockFormattingContext::layout_inline_children(BlockContainer& block_container, LayoutMode layout_mode)
{
+ VERIFY(block_container.children_are_inline());
+
InlineFormattingContext context(block_container, *this);
context.run(block_container, layout_mode);
}
void BlockFormattingContext::layout_block_level_children(BlockContainer& block_container, LayoutMode layout_mode)
{
+ VERIFY(!block_container.children_are_inline());
+
float content_height = 0;
float content_width = 0;
block_container.for_each_child_of_type<Box>([&](Box& child_box) {
- if (child_box.is_absolutely_positioned())
+ if (child_box.is_absolutely_positioned()) {
+ m_absolutely_positioned_boxes.append(child_box);
return IterationDecision::Continue;
+ }
// NOTE: ListItemMarkerBoxes are placed by their corresponding ListItemBox.
if (is<ListItemMarkerBox>(child_box))
@@ -410,7 +403,15 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer& block_c
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);
+ OwnPtr<FormattingContext> independent_formatting_context;
+ if (child_box.can_have_children()) {
+ independent_formatting_context = create_independent_formatting_context_if_needed(child_box);
+ if (independent_formatting_context)
+ independent_formatting_context->run(child_box, layout_mode);
+ else
+ layout_block_level_children(verify_cast<BlockContainer>(child_box), layout_mode);
+ }
+
compute_height(child_box);
if (child_box.computed_values().position() == CSS::Position::Relative)
@@ -426,6 +427,10 @@ void BlockFormattingContext::layout_block_level_children(BlockContainer& block_c
content_height = max(content_height, child_box.effective_offset().y() + child_box.content_height() + child_box.box_model().margin_box().bottom);
content_width = max(content_width, child_box.content_width());
+
+ if (independent_formatting_context)
+ independent_formatting_context->parent_context_did_dimension_child_root_box();
+
return IterationDecision::Continue;
});
diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
index 403bad5f1a..fffb595003 100644
--- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.h
@@ -33,8 +33,11 @@ public:
BlockContainer& root() { return static_cast<BlockContainer&>(context_box()); }
BlockContainer const& root() const { return static_cast<BlockContainer const&>(context_box()); }
-protected:
+ virtual void parent_context_did_dimension_child_root_box() override;
+
static void compute_height(Box&);
+
+protected:
void compute_position(Box&);
private:
@@ -69,6 +72,8 @@ private:
FloatSideData m_left_floats;
FloatSideData m_right_floats;
+
+ Vector<Box&> m_absolutely_positioned_boxes;
};
}
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
index 3f9b6670b8..7077952ddc 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp
@@ -616,7 +616,7 @@ void FormattingContext::layout_absolutely_positioned_element(Box& box)
auto specified_width = box.computed_values().width().resolved(box, width_of_containing_block).resolved_or_auto(box);
compute_width_for_absolutely_positioned_element(box);
- (void)layout_inside(box, LayoutMode::Default);
+ auto independent_formatting_context = layout_inside(box, LayoutMode::Default);
compute_height_for_absolutely_positioned_element(box);
box_model.margin.left = box.computed_values().margin().left.resolved(box, width_of_containing_block).resolved_or_auto(box).to_px(box);
@@ -676,6 +676,9 @@ void FormattingContext::layout_absolutely_positioned_element(Box& box)
}
box.set_offset(used_offset);
+
+ if (independent_formatting_context)
+ independent_formatting_context->parent_context_did_dimension_child_root_box();
}
void FormattingContext::compute_height_for_absolutely_positioned_replaced_element(ReplacedBox& box)
diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.h b/Userland/Libraries/LibWeb/Layout/FormattingContext.h
index 2ff1e452ed..48f3216cba 100644
--- a/Userland/Libraries/LibWeb/Layout/FormattingContext.h
+++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.h
@@ -43,6 +43,8 @@ public:
OwnPtr<FormattingContext> create_independent_formatting_context_if_needed(Box& child_box);
+ virtual void parent_context_did_dimension_child_root_box() { }
+
protected:
FormattingContext(Type, Box&, FormattingContext* parent = nullptr);
diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
index 420e408318..43bc2abe11 100644
--- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
+++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
@@ -141,14 +141,17 @@ void InlineFormattingContext::dimension_box_on_line(Box& box, LayoutMode layout_
auto container_width = CSS::Length::make_px(containing_block().content_width());
inline_block.set_content_width(inline_block.computed_values().width().resolved(box, container_width).resolved_or_zero(inline_block).to_px(inline_block));
}
- (void)layout_inside(inline_block, layout_mode);
+ auto independent_formatting_context = layout_inside(inline_block, layout_mode);
if (inline_block.computed_values().height().is_length() && inline_block.computed_values().height().length().is_undefined_or_auto()) {
// FIXME: (10.6.6) If 'height' is 'auto', the height depends on the element's descendants per 10.6.7.
+ BlockFormattingContext::compute_height(inline_block);
} else {
auto container_height = CSS::Length::make_px(containing_block().content_height());
inline_block.set_content_height(inline_block.computed_values().height().resolved(box, container_height).resolved_or_zero(inline_block).to_px(inline_block));
}
+
+ independent_formatting_context->parent_context_did_dimension_child_root_box();
return;
}