summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
Diffstat (limited to 'Libraries')
-rw-r--r--Libraries/LibWeb/DOM/Document.cpp2
-rw-r--r--Libraries/LibWeb/Layout/BlockBox.cpp8
-rw-r--r--Libraries/LibWeb/Layout/BlockFormattingContext.cpp165
-rw-r--r--Libraries/LibWeb/Layout/BlockFormattingContext.h18
-rw-r--r--Libraries/LibWeb/Layout/BreakNode.cpp4
-rw-r--r--Libraries/LibWeb/Layout/FormattingContext.cpp11
-rw-r--r--Libraries/LibWeb/Layout/FormattingContext.h4
-rw-r--r--Libraries/LibWeb/Layout/InlineFormattingContext.cpp50
-rw-r--r--Libraries/LibWeb/Layout/InlineFormattingContext.h6
-rw-r--r--Libraries/LibWeb/Layout/Node.h1
-rw-r--r--Libraries/LibWeb/Layout/ReplacedBox.cpp2
-rw-r--r--Libraries/LibWeb/Layout/TableFormattingContext.cpp18
-rw-r--r--Libraries/LibWeb/Layout/TableFormattingContext.h2
-rw-r--r--Libraries/LibWeb/Layout/TextNode.cpp3
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();