summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb/Layout
diff options
context:
space:
mode:
Diffstat (limited to 'Libraries/LibWeb/Layout')
-rw-r--r--Libraries/LibWeb/Layout/BlockBox.cpp9
-rw-r--r--Libraries/LibWeb/Layout/BlockBox.h2
-rw-r--r--Libraries/LibWeb/Layout/BlockFormattingContext.cpp46
-rw-r--r--Libraries/LibWeb/Layout/BlockFormattingContext.h11
-rw-r--r--Libraries/LibWeb/Layout/BreakNode.cpp5
-rw-r--r--Libraries/LibWeb/Layout/BreakNode.h2
-rw-r--r--Libraries/LibWeb/Layout/FormattingContext.cpp40
-rw-r--r--Libraries/LibWeb/Layout/FormattingContext.h12
-rw-r--r--Libraries/LibWeb/Layout/InlineFormattingContext.cpp52
-rw-r--r--Libraries/LibWeb/Layout/InlineFormattingContext.h2
-rw-r--r--Libraries/LibWeb/Layout/InlineNode.cpp7
-rw-r--r--Libraries/LibWeb/Layout/InlineNode.h2
-rw-r--r--Libraries/LibWeb/Layout/Node.cpp15
-rw-r--r--Libraries/LibWeb/Layout/Node.h2
-rw-r--r--Libraries/LibWeb/Layout/ReplacedBox.cpp11
-rw-r--r--Libraries/LibWeb/Layout/ReplacedBox.h2
-rw-r--r--Libraries/LibWeb/Layout/TextNode.cpp26
-rw-r--r--Libraries/LibWeb/Layout/TextNode.h4
18 files changed, 209 insertions, 41 deletions
diff --git a/Libraries/LibWeb/Layout/BlockBox.cpp b/Libraries/LibWeb/Layout/BlockBox.cpp
index 2fbebba10a..ed10978314 100644
--- a/Libraries/LibWeb/Layout/BlockBox.cpp
+++ b/Libraries/LibWeb/Layout/BlockBox.cpp
@@ -30,6 +30,7 @@
#include <LibWeb/Dump.h>
#include <LibWeb/Layout/BlockBox.h>
#include <LibWeb/Layout/InitialContainingBlockBox.h>
+#include <LibWeb/Layout/InlineFormattingContext.h>
#include <LibWeb/Layout/InlineNode.h>
#include <LibWeb/Layout/ReplacedBox.h>
#include <LibWeb/Layout/TextNode.h>
@@ -107,10 +108,14 @@ HitTestResult BlockBox::hit_test(const Gfx::IntPoint& position, HitTestType type
return { absolute_rect().contains(position.x(), position.y()) ? this : nullptr };
}
-void BlockBox::split_into_lines(BlockBox& container, LayoutMode layout_mode)
+void BlockBox::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
{
+ auto& container = context.context_box();
auto* line_box = &container.ensure_last_line_box();
- if (layout_mode != LayoutMode::OnlyRequiredLineBreaks && line_box->width() > 0 && line_box->width() + width() > container.width()) {
+
+ float available_width = context.available_width_at_line(container.line_boxes().size());
+
+ if (layout_mode != LayoutMode::OnlyRequiredLineBreaks && line_box->width() > 0 && line_box->width() + width() > available_width) {
line_box = &container.add_line_box();
}
line_box->add_fragment(*this, 0, 0, width(), height());
diff --git a/Libraries/LibWeb/Layout/BlockBox.h b/Libraries/LibWeb/Layout/BlockBox.h
index 8d1b43d3a8..83929ac14e 100644
--- a/Libraries/LibWeb/Layout/BlockBox.h
+++ b/Libraries/LibWeb/Layout/BlockBox.h
@@ -52,7 +52,7 @@ public:
template<typename Callback>
void for_each_fragment(Callback) const;
- virtual void split_into_lines(BlockBox& container, LayoutMode) override;
+ virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
private:
virtual bool is_block() const override { return true; }
diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
index 4b888bdd7d..e6e1421743 100644
--- a/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
+++ b/Libraries/LibWeb/Layout/BlockFormattingContext.cpp
@@ -65,6 +65,8 @@ void BlockFormattingContext::run(LayoutMode layout_mode)
if (layout_mode == LayoutMode::Default)
compute_width(context_box());
+ layout_floating_descendants();
+
if (context_box().children_are_inline()) {
layout_inline_children(layout_mode);
} else {
@@ -403,7 +405,7 @@ void BlockFormattingContext::layout_block_level_children(LayoutMode layout_mode)
float content_width = 0;
context_box().for_each_in_subtree_of_type<Box>([&](auto& box) {
- if (box.is_absolutely_positioned() || box.containing_block() != &context_box())
+ if (box.is_absolutely_positioned() || box.is_floating() || box.containing_block() != &context_box())
return IterationDecision::Continue;
compute_width(box);
@@ -530,6 +532,8 @@ void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_m
icb.set_width(viewport_rect.width());
+ layout_floating_descendants();
+
layout_block_level_children(layout_mode);
ASSERT(!icb.children_are_inline());
@@ -564,6 +568,46 @@ void BlockFormattingContext::layout_absolutely_positioned_descendants()
});
}
+void BlockFormattingContext::layout_floating_descendants()
+{
+ context_box().for_each_in_subtree_of_type<Box>([&](auto& box) {
+ if (box.is_floating() && box.containing_block() == &context_box()) {
+ layout_floating_descendant(box);
+ }
+ return IterationDecision::Continue;
+ });
+}
+
+void BlockFormattingContext::layout_floating_descendant(Box& box)
+{
+ ASSERT(box.is_floating());
+ auto& containing_block = context_box();
+
+ compute_width(box);
+ layout_inside(box, LayoutMode::Default);
+ compute_height(box);
+
+ if (box.style().float_() == CSS::Float::Left) {
+ float x = 0;
+ if (!m_left_floating_boxes.is_empty()) {
+ auto& previous_floating_box = *m_left_floating_boxes.last();
+ x = previous_floating_box.effective_offset().x() + previous_floating_box.width();
+ }
+ box.set_offset(x, 0);
+ m_left_floating_boxes.append(&box);
+ } else if (box.style().float_() == CSS::Float::Right) {
+ float x = 0;
+ if (!m_right_floating_boxes.is_empty()) {
+ auto& previous_floating_box = *m_right_floating_boxes.last();
+ x = previous_floating_box.effective_offset().x() - box.width();
+ } else {
+ x = containing_block.width() - box.width();
+ }
+ box.set_offset(x, 0);
+ m_right_floating_boxes.append(&box);
+ }
+}
+
void BlockFormattingContext::layout_absolutely_positioned_descendant(Box& box)
{
auto& containing_block = context_box();
diff --git a/Libraries/LibWeb/Layout/BlockFormattingContext.h b/Libraries/LibWeb/Layout/BlockFormattingContext.h
index dbbbbe5caf..dd30469935 100644
--- a/Libraries/LibWeb/Layout/BlockFormattingContext.h
+++ b/Libraries/LibWeb/Layout/BlockFormattingContext.h
@@ -26,6 +26,7 @@
#pragma once
+#include <AK/Vector.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Layout/FormattingContext.h>
@@ -40,22 +41,32 @@ public:
bool is_initial() const;
+ const Vector<Box*>& left_floating_boxes() const { return m_left_floating_boxes; }
+ const Vector<Box*>& right_floating_boxes() const { return m_right_floating_boxes; }
+
protected:
void compute_width(Box&);
void compute_height(Box&);
private:
+ virtual bool is_block_formatting_context() const final { return true; }
+
void compute_width_for_absolutely_positioned_block(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_descendants();
void place_block_level_replaced_element_in_normal_flow(Box&);
void place_block_level_non_replaced_element_in_normal_flow(Box&);
void layout_absolutely_positioned_descendant(Box&);
+ void layout_floating_descendant(Box&);
+
+ 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 0a230a9873..a16633e71a 100644
--- a/Libraries/LibWeb/Layout/BreakNode.cpp
+++ b/Libraries/LibWeb/Layout/BreakNode.cpp
@@ -26,6 +26,7 @@
#include <LibWeb/Layout/BlockBox.h>
#include <LibWeb/Layout/BreakNode.h>
+#include <LibWeb/Layout/InlineFormattingContext.h>
namespace Web::Layout {
@@ -39,9 +40,9 @@ BreakNode::~BreakNode()
{
}
-void BreakNode::split_into_lines(BlockBox& block, LayoutMode)
+void BreakNode::split_into_lines(InlineFormattingContext& block, LayoutMode)
{
- block.add_line_box();
+ block.context_box().add_line_box();
}
}
diff --git a/Libraries/LibWeb/Layout/BreakNode.h b/Libraries/LibWeb/Layout/BreakNode.h
index 07ecb6926f..2bc15fc529 100644
--- a/Libraries/LibWeb/Layout/BreakNode.h
+++ b/Libraries/LibWeb/Layout/BreakNode.h
@@ -41,7 +41,7 @@ public:
private:
virtual bool is_break() const override { return true; }
virtual const char* class_name() const override { return "BreakNode"; }
- virtual void split_into_lines(BlockBox&, LayoutMode) override;
+ virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
};
}
diff --git a/Libraries/LibWeb/Layout/FormattingContext.cpp b/Libraries/LibWeb/Layout/FormattingContext.cpp
index 670191f41f..5d81536260 100644
--- a/Libraries/LibWeb/Layout/FormattingContext.cpp
+++ b/Libraries/LibWeb/Layout/FormattingContext.cpp
@@ -24,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <LibWeb/Dump.h>
#include <LibWeb/Layout/BlockFormattingContext.h>
#include <LibWeb/Layout/Box.h>
#include <LibWeb/Layout/FormattingContext.h>
@@ -34,7 +35,7 @@ namespace Web::Layout {
FormattingContext::FormattingContext(Box& context_box, FormattingContext* parent)
: m_parent(parent)
- , m_context_box(context_box)
+ , m_context_box(&context_box)
{
}
@@ -42,8 +43,37 @@ FormattingContext::~FormattingContext()
{
}
+bool FormattingContext::creates_block_formatting_context(const Box& box)
+{
+ if (box.is_root_element())
+ return true;
+ if (box.is_floating())
+ return true;
+ if (box.is_absolutely_positioned())
+ return true;
+ if (box.is_inline_block())
+ return true;
+ if (box.is_table_cell())
+ return true;
+ // FIXME: table-caption
+ // FIXME: anonymous table cells
+ // FIXME: Block elements where overflow has a value other than visible and clip.
+ // FIXME: display: flow-root
+ // FIXME: Elements with contain: layout, content, or paint.
+ // FIXME: flex
+ // FIXME: grid
+ // FIXME: multicol
+ // FIXME: column-span: all
+ return false;
+}
+
void FormattingContext::layout_inside(Box& box, LayoutMode layout_mode)
{
+ if (creates_block_formatting_context(box)) {
+ BlockFormattingContext context(box, this);
+ context.run(layout_mode);
+ return;
+ }
if (box.is_table()) {
TableFormattingContext context(box, this);
context.run(layout_mode);
@@ -51,8 +81,12 @@ void FormattingContext::layout_inside(Box& box, LayoutMode layout_mode)
InlineFormattingContext context(box, this);
context.run(layout_mode);
} else {
- BlockFormattingContext context(box, this);
- context.run(layout_mode);
+ // 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);
}
}
diff --git a/Libraries/LibWeb/Layout/FormattingContext.h b/Libraries/LibWeb/Layout/FormattingContext.h
index c8f7487dc2..b505702d67 100644
--- a/Libraries/LibWeb/Layout/FormattingContext.h
+++ b/Libraries/LibWeb/Layout/FormattingContext.h
@@ -34,16 +34,22 @@ class FormattingContext {
public:
virtual void run(LayoutMode) = 0;
- Box& context_box() { return m_context_box; }
- const Box& context_box() const { return m_context_box; }
+ Box& context_box() { return *m_context_box; }
+ const Box& context_box() const { return *m_context_box; }
FormattingContext* parent() { return m_parent; }
const FormattingContext* parent() const { return m_parent; }
+ virtual bool is_block_formatting_context() const { return false; }
+
+ static bool creates_block_formatting_context(const Box&);
+
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 {
@@ -54,7 +60,7 @@ protected:
ShrinkToFitResult calculate_shrink_to_fit_widths(Box&);
FormattingContext* m_parent { nullptr };
- Box& m_context_box;
+ Box* m_context_box { nullptr };
};
}
diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
index 105dffa119..270a80a97d 100644
--- a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
+++ b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp
@@ -45,6 +45,50 @@ InlineFormattingContext::~InlineFormattingContext()
{
}
+struct AvailableSpaceForLineInfo {
+ float left { 0 };
+ float right { 0 };
+};
+
+static AvailableSpaceForLineInfo available_space_for_line(const InlineFormattingContext& context, size_t line_index)
+{
+ 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 y = (line_index * line_height) + line_height / 2;
+
+ auto& bfc = static_cast<const BlockFormattingContext&>(*context.parent());
+
+ for (ssize_t i = bfc.left_floating_boxes().size() - 1; i >= 0; --i) {
+ auto& floating_box = *bfc.left_floating_boxes().at(i);
+ Gfx::FloatRect rect { floating_box.effective_offset(), floating_box.size() };
+ if (rect.contains_vertically(y)) {
+ info.left = rect.right() + 1;
+ break;
+ }
+ }
+
+ info.right = context.context_box().width();
+
+ for (ssize_t i = bfc.right_floating_boxes().size() - 1; i >= 0; --i) {
+ auto& floating_box = *bfc.right_floating_boxes().at(i);
+ Gfx::FloatRect rect { floating_box.effective_offset(), floating_box.size() };
+ if (rect.contains_vertically(y)) {
+ info.right = rect.left() - 1;
+ break;
+ }
+ }
+
+ return info;
+}
+
+float InlineFormattingContext::available_width_at_line(size_t line_index) const
+{
+ auto info = available_space_for_line(*this, line_index);
+ return info.right - info.left;
+}
+
void InlineFormattingContext::run(LayoutMode layout_mode)
{
auto& containing_block = downcast<BlockBox>(context_box());
@@ -56,7 +100,7 @@ void InlineFormattingContext::run(LayoutMode layout_mode)
if (child.is_absolutely_positioned())
return;
- child.split_into_lines(containing_block, layout_mode);
+ child.split_into_lines(*this, layout_mode);
});
for (auto& line_box : containing_block.line_boxes()) {
@@ -73,13 +117,15 @@ void InlineFormattingContext::run(LayoutMode layout_mode)
float content_height = 0;
float max_linebox_width = 0;
- for (auto& line_box : containing_block.line_boxes()) {
+ 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());
}
- float x_offset = 0;
+ float x_offset = available_space_for_line(*this, line_index).left;
+
float excess_horizontal_space = (float)containing_block.width() - line_box.width();
switch (text_align) {
diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.h b/Libraries/LibWeb/Layout/InlineFormattingContext.h
index 2cc6c5f88f..a96f0c9901 100644
--- a/Libraries/LibWeb/Layout/InlineFormattingContext.h
+++ b/Libraries/LibWeb/Layout/InlineFormattingContext.h
@@ -38,6 +38,8 @@ public:
virtual void run(LayoutMode) override;
+ float available_width_at_line(size_t line_index) const;
+
private:
void dimension_box_on_line(Box&, LayoutMode);
};
diff --git a/Libraries/LibWeb/Layout/InlineNode.cpp b/Libraries/LibWeb/Layout/InlineNode.cpp
index b34237f400..4a69afe6ff 100644
--- a/Libraries/LibWeb/Layout/InlineNode.cpp
+++ b/Libraries/LibWeb/Layout/InlineNode.cpp
@@ -27,6 +27,7 @@
#include <LibGfx/Painter.h>
#include <LibWeb/DOM/Element.h>
#include <LibWeb/Layout/BlockBox.h>
+#include <LibWeb/Layout/InlineFormattingContext.h>
#include <LibWeb/Layout/InlineNode.h>
namespace Web::Layout {
@@ -41,14 +42,16 @@ InlineNode::~InlineNode()
{
}
-void InlineNode::split_into_lines(BlockBox& containing_block, LayoutMode layout_mode)
+void InlineNode::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
{
+ auto& containing_block = context.context_box();
+
if (!style().padding().left.is_undefined_or_auto()) {
float padding_left = style().padding().left.resolved(CSS::Length::make_px(0), *this, containing_block.width()).to_px(*this);
containing_block.ensure_last_line_box().add_fragment(*this, 0, 0, padding_left, 0, LineBoxFragment::Type::Leading);
}
- NodeWithStyleAndBoxModelMetrics::split_into_lines(containing_block, layout_mode);
+ NodeWithStyleAndBoxModelMetrics::split_into_lines(context, layout_mode);
if (!style().padding().right.is_undefined_or_auto()) {
float padding_right = style().padding().right.resolved(CSS::Length::make_px(0), *this, containing_block.width()).to_px(*this);
diff --git a/Libraries/LibWeb/Layout/InlineNode.h b/Libraries/LibWeb/Layout/InlineNode.h
index a140339599..9725651b2e 100644
--- a/Libraries/LibWeb/Layout/InlineNode.h
+++ b/Libraries/LibWeb/Layout/InlineNode.h
@@ -38,7 +38,7 @@ public:
virtual void paint_fragment(PaintContext&, const LineBoxFragment&, PaintPhase) const override;
- virtual void split_into_lines(BlockBox& containing_block, LayoutMode) override;
+ virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
private:
virtual bool is_inline_node() const final { return true; }
diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp
index a7eafcef39..b2c79b922c 100644
--- a/Libraries/LibWeb/Layout/Node.cpp
+++ b/Libraries/LibWeb/Layout/Node.cpp
@@ -30,6 +30,7 @@
#include <LibWeb/Dump.h>
#include <LibWeb/HTML/HTMLHtmlElement.h>
#include <LibWeb/Layout/BlockBox.h>
+#include <LibWeb/Layout/FormattingContext.h>
#include <LibWeb/Layout/InitialContainingBlockBox.h>
#include <LibWeb/Layout/Node.h>
#include <LibWeb/Layout/ReplacedBox.h>
@@ -65,6 +66,13 @@ const BlockBox* Node::containing_block() const
return downcast<BlockBox>(ancestor);
};
+ auto nearest_block_ancestor_that_creates_a_block_formatting_context = [this] {
+ auto* ancestor = parent();
+ while (ancestor && (!is<Box>(*ancestor) || !FormattingContext::creates_block_formatting_context(downcast<Box>(*ancestor))))
+ ancestor = ancestor->parent();
+ return downcast<BlockBox>(ancestor);
+ };
+
if (is_text())
return nearest_block_ancestor();
@@ -82,6 +90,9 @@ const BlockBox* Node::containing_block() const
if (position == CSS::Position::Fixed)
return &root();
+ if (is_floating())
+ return nearest_block_ancestor_that_creates_a_block_formatting_context();
+
return nearest_block_ancestor();
}
@@ -140,10 +151,10 @@ InitialContainingBlockBox& Node::root()
return *document().layout_node();
}
-void Node::split_into_lines(BlockBox& container, LayoutMode layout_mode)
+void Node::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
{
for_each_child([&](auto& child) {
- child.split_into_lines(container, layout_mode);
+ child.split_into_lines(context, layout_mode);
});
}
diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h
index 90121e7621..3a7f702e0b 100644
--- a/Libraries/LibWeb/Layout/Node.h
+++ b/Libraries/LibWeb/Layout/Node.h
@@ -150,7 +150,7 @@ public:
void removed_from(Node&) { }
void children_changed() { }
- virtual void split_into_lines(BlockBox& container, LayoutMode);
+ virtual void split_into_lines(InlineFormattingContext&, LayoutMode);
bool is_visible() const { return m_visible; }
void set_visible(bool visible) { m_visible = visible; }
diff --git a/Libraries/LibWeb/Layout/ReplacedBox.cpp b/Libraries/LibWeb/Layout/ReplacedBox.cpp
index 340d96462c..be2b4d77ec 100644
--- a/Libraries/LibWeb/Layout/ReplacedBox.cpp
+++ b/Libraries/LibWeb/Layout/ReplacedBox.cpp
@@ -25,6 +25,7 @@
*/
#include <LibWeb/DOM/Element.h>
+#include <LibWeb/Layout/InlineFormattingContext.h>
#include <LibWeb/Layout/BlockBox.h>
#include <LibWeb/Layout/ReplacedBox.h>
@@ -117,17 +118,19 @@ float ReplacedBox::calculate_height() const
return used_height;
}
-void ReplacedBox::split_into_lines(Layout::BlockBox& container, LayoutMode)
+void ReplacedBox::split_into_lines(InlineFormattingContext& context, LayoutMode)
{
+ auto& containing_block = context.context_box();
+
// 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.
prepare_for_replaced_layout();
auto width = calculate_width();
auto height = calculate_height();
- auto* line_box = &container.ensure_last_line_box();
- if (line_box->width() > 0 && line_box->width() + width > container.width())
- line_box = &container.add_line_box();
+ auto* line_box = &containing_block.ensure_last_line_box();
+ if (line_box->width() > 0 && line_box->width() + width > context.available_width_at_line(containing_block.line_boxes().size()))
+ line_box = &containing_block.add_line_box();
line_box->add_fragment(*this, 0, 0, width, height);
}
diff --git a/Libraries/LibWeb/Layout/ReplacedBox.h b/Libraries/LibWeb/Layout/ReplacedBox.h
index 1a9ded51af..081bfd8348 100644
--- a/Libraries/LibWeb/Layout/ReplacedBox.h
+++ b/Libraries/LibWeb/Layout/ReplacedBox.h
@@ -65,7 +65,7 @@ public:
virtual bool can_have_children() const override { return false; }
protected:
- virtual void split_into_lines(Layout::BlockBox& container, LayoutMode) override;
+ virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
private:
virtual const char* class_name() const override { return "ReplacedBox"; }
diff --git a/Libraries/LibWeb/Layout/TextNode.cpp b/Libraries/LibWeb/Layout/TextNode.cpp
index 3846627fa0..0433167093 100644
--- a/Libraries/LibWeb/Layout/TextNode.cpp
+++ b/Libraries/LibWeb/Layout/TextNode.cpp
@@ -31,6 +31,7 @@
#include <LibGfx/Font.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/Layout/BlockBox.h>
+#include <LibWeb/Layout/InlineFormattingContext.h>
#include <LibWeb/Layout/TextNode.h>
#include <LibWeb/Page/Frame.h>
#include <ctype.h>
@@ -189,14 +190,15 @@ void TextNode::for_each_chunk(Callback callback, LayoutMode layout_mode, bool do
commit_chunk(view.end(), false, true);
}
-void TextNode::split_into_lines_by_rules(BlockBox& container, LayoutMode layout_mode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks)
+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& font = specified_style().font();
float space_width = font.glyph_width(' ') + font.glyph_spacing();
- auto& line_boxes = container.line_boxes();
- container.ensure_last_line_box();
- float available_width = container.width() - line_boxes.last().width();
+ auto& line_boxes = containing_block.line_boxes();
+ containing_block.ensure_last_line_box();
+ float available_width = context.available_width_at_line(line_boxes.size()) - line_boxes.last().width();
// Collapse whitespace into single spaces
if (do_collapse) {
@@ -261,8 +263,8 @@ void TextNode::split_into_lines_by_rules(BlockBox& container, LayoutMode layout_
chunk_width = font.width(chunk.view) + font.glyph_spacing();
if (line_boxes.last().width() > 0 && chunk_width > available_width) {
- container.add_line_box();
- available_width = container.width();
+ containing_block.add_line_box();
+ available_width = context.available_width_at_line(line_boxes.size());
}
if (need_collapse & line_boxes.last().fragments().is_empty())
continue;
@@ -275,21 +277,21 @@ void TextNode::split_into_lines_by_rules(BlockBox& container, LayoutMode layout_
if (do_wrap_lines) {
if (available_width < 0) {
- container.add_line_box();
- available_width = container.width();
+ containing_block.add_line_box();
+ available_width = context.available_width_at_line(line_boxes.size());
}
}
if (do_wrap_breaks) {
if (chunk.is_break) {
- container.add_line_box();
- available_width = container.width();
+ containing_block.add_line_box();
+ available_width = context.available_width_at_line(line_boxes.size());
}
}
}
}
-void TextNode::split_into_lines(BlockBox& container, LayoutMode layout_mode)
+void TextNode::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode)
{
bool do_collapse = true;
bool do_wrap_lines = true;
@@ -313,7 +315,7 @@ void TextNode::split_into_lines(BlockBox& container, LayoutMode layout_mode)
do_wrap_breaks = true;
}
- split_into_lines_by_rules(container, layout_mode, do_collapse, do_wrap_lines, do_wrap_breaks);
+ split_into_lines_by_rules(context, layout_mode, do_collapse, do_wrap_lines, do_wrap_breaks);
}
}
diff --git a/Libraries/LibWeb/Layout/TextNode.h b/Libraries/LibWeb/Layout/TextNode.h
index 389cf0f3e8..e19692511e 100644
--- a/Libraries/LibWeb/Layout/TextNode.h
+++ b/Libraries/LibWeb/Layout/TextNode.h
@@ -48,12 +48,12 @@ public:
virtual void paint_fragment(PaintContext&, const LineBoxFragment&, PaintPhase) const override;
- virtual void split_into_lines(BlockBox& container, LayoutMode) override;
+ virtual void split_into_lines(InlineFormattingContext&, LayoutMode) override;
const CSS::StyleProperties& specified_style() const { return parent()->specified_style(); }
private:
- void split_into_lines_by_rules(BlockBox& container, LayoutMode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks);
+ void split_into_lines_by_rules(InlineFormattingContext&, LayoutMode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks);
void paint_cursor_if_needed(PaintContext&, const LineBoxFragment&) const;
template<typename Callback>