diff options
Diffstat (limited to 'Libraries/LibWeb/Layout')
-rw-r--r-- | Libraries/LibWeb/Layout/BlockBox.cpp | 9 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BlockBox.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BlockFormattingContext.cpp | 46 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BlockFormattingContext.h | 11 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BreakNode.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/BreakNode.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/FormattingContext.cpp | 40 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/FormattingContext.h | 12 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/InlineFormattingContext.cpp | 52 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/InlineFormattingContext.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/InlineNode.cpp | 7 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/InlineNode.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Node.cpp | 15 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Node.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/ReplacedBox.cpp | 11 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/ReplacedBox.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/TextNode.cpp | 26 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/TextNode.h | 4 |
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> |