From 9e9db9a9ddb40d22f5291bcec1e84ce7d4964481 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Fri, 12 Sep 2025 10:06:27 +0200 Subject: [PATCH] LibWeb: Store correct text offsets in PaintableFragment Previously, we were collapsing whitespace in Layout::TextNode and then passed the resulting string for further processing through ChunkIterator -> InlineLevelIterator -> InlineFormattingContext -> LineBuilder -> LineBoxFragment -> PaintableFragment. Our painting tree is where we deal with things like range offsets into the underlying text nodes, but since we modified the original string, the offsets were wrong. This changes the way we generate fragments: * Layout::TextNode no longer collapses whitespace as part of its stored "text for rendering", but moves this logic to ChunkIterator which splits up this text into separate views whenever whitespace needs to be collapsed. * Layout::LineBox now only extends the last fragment if its end offset is equal to the new fragment's start offset. Otherwise, there's a gap caused by collapsing whitespace and we need to generate a separate fragment for that in order to have a correct start offset. Some tests need new baselines because of the fixed start offsets. Fixes #566. --- Libraries/LibWeb/Dump.cpp | 17 +-- Libraries/LibWeb/HTML/HTMLElement.cpp | 32 ++-- .../LibWeb/Layout/InlineFormattingContext.cpp | 3 +- .../LibWeb/Layout/InlineLevelIterator.cpp | 43 +++--- Libraries/LibWeb/Layout/InlineLevelIterator.h | 3 - Libraries/LibWeb/Layout/LayoutState.cpp | 2 +- Libraries/LibWeb/Layout/LineBox.cpp | 26 ++-- Libraries/LibWeb/Layout/LineBoxFragment.cpp | 13 +- Libraries/LibWeb/Layout/LineBoxFragment.h | 4 +- Libraries/LibWeb/Layout/LineBuilder.cpp | 10 +- Libraries/LibWeb/Layout/TextNode.cpp | 143 ++++++++++++------ Libraries/LibWeb/Layout/TextNode.h | 13 +- Libraries/LibWeb/Layout/TreeBuilder.cpp | 4 +- Libraries/LibWeb/Painting/PaintableBox.h | 2 - .../LibWeb/Painting/PaintableFragment.cpp | 2 +- Tests/LibWeb/Layout/expected/acid1.txt | 34 +++-- .../bfc-fit-content-width-with-margin.txt | 18 +-- ...-consider-all-currently-stacked-floats.txt | 4 +- ...should-have-vertically-aligned-content.txt | 4 +- .../expected/block-and-inline/float-1.txt | 54 ++++--- ...at-clear-by-line-break-at-end-of-block.txt | 2 +- ...loat-initial-available-space-vs-height.txt | 2 +- .../block-and-inline/float-stress-1.txt | 62 +++++--- .../block-and-inline/float-stress-3.txt | 2 +- .../float-under-if-would-fit.txt | 4 +- ...ertical-clearance-for-text-after-break.txt | 4 +- .../floats-and-negative-margins.txt | 4 +- ...bfc-width-to-avoid-overlap-with-floats.txt | 24 ++- ...-contents-blockification-of-flex-items.txt | 4 +- .../Layout/expected/div_align_nested.txt | 4 +- ...flex-container-with-definite-max-width.txt | 2 +- ...-basis-with-indefinite-reference-value.txt | 2 +- .../expected/grid/inline-abspos-item.txt | 2 +- .../expected/grid/min-height-from-text.txt | 14 +- .../Layout/expected/object-fallback.txt | 2 +- Tests/LibWeb/Layout/expected/table/basic.txt | 2 +- .../border-spacing-with-percentage-width.txt | 2 +- .../Layout/expected/table/bottom-caption.txt | 2 +- .../expected/table/cell-with-max-width.txt | 12 +- .../expected/table/line-breaking-in-cells.txt | 4 +- .../table/long-caption-increases-width.txt | 4 +- .../table/top-caption-with-padding.txt | 2 +- ...th-distribution-of-max-width-increment.txt | 6 +- .../text-align-justify-with-forced-break.txt | 60 ++++---- ...-be-xhtml-file-should-decode-correctly.txt | 2 +- .../expected/selection-on-rendered-text.txt | 2 +- .../Text/expected/selectionchange-event.txt | 6 +- .../getter.txt | 8 +- .../innertext-whitespace-pre-line.txt | 6 +- .../input/selection-on-rendered-text.html | 1 + 50 files changed, 386 insertions(+), 298 deletions(-) diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp index 49a4fa0380c..e39678de7bd 100644 --- a/Libraries/LibWeb/Dump.cpp +++ b/Libraries/LibWeb/Dump.cpp @@ -389,20 +389,17 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho fragment.length_in_code_units(), fragment.absolute_rect(), fragment.baseline()); - if (is(fragment.layout_node())) { + if (fragment.length_in_code_units() > 0) { builder.append_repeated(" "sv, indent); - auto const& layout_text = static_cast(fragment.layout_node()); - auto fragment_text = layout_text.text_for_rendering().substring_view(fragment.start_offset(), fragment.length_in_code_units()); - builder.appendff(" \"{}\"\n", fragment_text); + builder.appendff(" \"{}\"\n", fragment.text()); } }; - if (is(layout_node) && static_cast(layout_node).children_are_inline()) { - auto& block = static_cast(layout_node); - for (size_t fragment_index = 0; block.paintable_with_lines() && fragment_index < block.paintable_with_lines()->fragments().size(); ++fragment_index) { - auto const& fragment = block.paintable_with_lines()->fragments()[fragment_index]; - dump_fragment(fragment, fragment_index); - } + if (auto const* block_container = as_if(layout_node); + block_container && block_container->children_are_inline() && block_container->paintable_with_lines()) { + size_t fragment_index = 0; + for (auto const& fragment : block_container->paintable_with_lines()->fragments()) + dump_fragment(fragment, fragment_index++); } if (is(layout_node) && layout_node.first_paintable()) { diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index 499b4468a6a..086d0cd348d 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -318,7 +318,8 @@ struct RequiredLineBreakCount { // https://html.spec.whatwg.org/multipage/dom.html#rendered-text-collection-steps static Vector> rendered_text_collection_steps(DOM::Node const& node) { - // 1. Let items be the result of running the rendered text collection steps with each child node of node in tree order, and then concatenating the results to a single list. + // 1. Let items be the result of running the rendered text collection steps with each child node of node in tree + // order, and then concatenating the results to a single list. Vector> items; node.for_each_child([&](auto const& child) { auto child_items = rendered_text_collection_steps(child); @@ -348,18 +349,22 @@ static Vector> rendered_text_collec if (computed_values.content_visibility() == CSS::ContentVisibility::Hidden) return items; - // 4. If node is a Text node, then for each CSS text box produced by node, in content order, - // compute the text of the box after application of the CSS 'white-space' processing rules - // and 'text-transform' rules, set items to the list of the resulting strings, and return items. + // 4. If node is a Text node, then for each CSS text box produced by node, in content order, compute the text of the + // box after application of the CSS 'white-space' processing rules and 'text-transform' rules, set items to the + // list of the resulting strings, and return items. - // FIXME: The CSS 'white-space' processing rules are slightly modified: - // collapsible spaces at the end of lines are always collapsed, - // but they are only removed if the line is the last line of the block, - // or it ends with a br element. Soft hyphens should be preserved. [CSSTEXT] + // FIXME: The CSS 'white-space' processing rules are slightly modified: collapsible spaces at the end of lines are + // always collapsed, but they are only removed if the line is the last line of the block, or it ends with a br + // element. Soft hyphens should be preserved. [CSSTEXT] - if (is(node)) { - auto const* layout_text_node = as(layout_node); - items.append(layout_text_node->text_for_rendering()); + if (auto const* layout_text_node = as_if(layout_node)) { + Layout::TextNode::ChunkIterator iterator { *layout_text_node, false, false }; + while (true) { + auto chunk = iterator.next(); + if (!chunk.has_value()) + break; + items.append(Utf16String::from_utf16(chunk.release_value().view)); + } return items; } @@ -430,9 +435,8 @@ Utf16String HTMLElement::get_the_text_steps() while (!results.is_empty() && results.last().has()) results.take_last(); - // 6. Replace each remaining run of consecutive required line break count items - // with a string consisting of as many U+000A LF code points as the maximum of the values - // in the required line break count items. + // 6. Replace each remaining run of consecutive required line break count items with a string consisting of as many + // U+000A LF code points as the maximum of the values in the required line break count items. StringBuilder builder(StringBuilder::Mode::UTF16); for (size_t i = 0; i < results.size(); ++i) { results[i].visit( diff --git a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index dcd68f7576b..4a19c3cebe2 100644 --- a/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -341,8 +341,7 @@ void InlineFormattingContext::generate_line_boxes() next_width = iterator.next_non_whitespace_sequence_width(); } - // If whitespace caused us to break, we swallow the whitespace instead of - // putting it on the next line. + // If whitespace caused us to break, we swallow the whitespace instead of putting it on the next line. if (is_whitespace && next_width > 0 && line_builder.break_if_needed(item.border_box_width() + next_width)) break; } else if (text_node.computed_values().text_overflow() == CSS::TextOverflow::Ellipsis diff --git a/Libraries/LibWeb/Layout/InlineLevelIterator.cpp b/Libraries/LibWeb/Layout/InlineLevelIterator.cpp index dafd8edf929..6f577f53a7c 100644 --- a/Libraries/LibWeb/Layout/InlineLevelIterator.cpp +++ b/Libraries/LibWeb/Layout/InlineLevelIterator.cpp @@ -490,11 +490,9 @@ Optional InlineLevelIterator::next_without_lookahead( if (!m_current_node) return {}; - if (is(*m_current_node)) { - auto& text_node = static_cast(*m_current_node); - + if (auto* text_node = as_if(*m_current_node)) { if (!m_text_node_context.has_value()) - enter_text_node(text_node); + enter_text_node(*text_node); auto chunk_opt = m_text_node_context->chunk_iterator.next(); if (!chunk_opt.has_value()) { @@ -511,7 +509,8 @@ Optional InlineLevelIterator::next_without_lookahead( if (text_type == Gfx::GlyphRun::TextType::Ltr || text_type == Gfx::GlyphRun::TextType::Rtl) m_text_node_context->last_known_direction = text_type; - if (m_text_node_context->do_respect_linebreaks && chunk.has_breaking_newline) { + auto do_respect_linebreak = m_text_node_context->chunk_iterator.should_respect_linebreaks(); + if (do_respect_linebreak && chunk.has_breaking_newline) { m_text_node_context->is_last_chunk = true; if (chunk.is_all_whitespace) text_type = Gfx::GlyphRun::TextType::EndPadding; @@ -520,15 +519,12 @@ Optional InlineLevelIterator::next_without_lookahead( if (text_type == Gfx::GlyphRun::TextType::ContextDependent) text_type = resolve_text_direction_from_context(); - if (m_text_node_context->do_respect_linebreaks && chunk.has_breaking_newline) { - return Item { - .type = Item::Type::ForcedBreak, - }; - } + if (do_respect_linebreak && chunk.has_breaking_newline) + return Item { .type = Item::Type::ForcedBreak }; - auto letter_spacing = text_node.computed_values().letter_spacing(); + auto letter_spacing = text_node->computed_values().letter_spacing(); // FIXME: We should apply word spacing to all word-separator characters not just breaking tabs - auto word_spacing = text_node.computed_values().word_spacing(); + auto word_spacing = text_node->computed_values().word_spacing(); auto x = 0.0f; if (chunk.has_breaking_tab) { @@ -541,13 +537,13 @@ Optional InlineLevelIterator::next_without_lookahead( } // https://drafts.csswg.org/css-text/#tab-size-property - CSS::CalculationResolutionContext calculation_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(text_node) }; - auto tab_size = text_node.computed_values().tab_size(); + CSS::CalculationResolutionContext calculation_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*text_node) }; + auto tab_size = text_node->computed_values().tab_size(); CSSPixels tab_width; tab_width = tab_size.visit( [&](CSS::LengthOrCalculated const& t) -> CSSPixels { return t.resolved(calculation_context) - .map([&](auto& it) { return it.to_px(text_node); }) + .map([&](auto& it) { return it.to_px(*text_node); }) .value_or(0); }, [&](CSS::NumberOrCalculated const& n) -> CSSPixels { @@ -585,16 +581,17 @@ Optional InlineLevelIterator::next_without_lookahead( CSSPixels chunk_width = CSSPixels::nearest_value_for(glyph_run->width() + x); // NOTE: We never consider `content: ""` to be collapsible whitespace. - bool is_generated_empty_string = text_node.is_generated() && chunk.length == 0; + bool is_generated_empty_string = text_node->is_generated() && chunk.length == 0; + auto collapse_whitespace = m_text_node_context->chunk_iterator.should_collapse_whitespace(); Item item { .type = Item::Type::Text, - .node = &text_node, + .node = text_node, .glyph_run = move(glyph_run), .offset_in_node = chunk.start, .length_in_node = chunk.length, .width = chunk_width, - .is_collapsible_whitespace = m_text_node_context->do_collapse && chunk.is_all_whitespace && !is_generated_empty_string, + .is_collapsible_whitespace = collapse_whitespace && chunk.is_all_whitespace && !is_generated_empty_string, }; add_extra_box_model_metrics_to_item(item, m_text_node_context->is_first_chunk, m_text_node_context->is_last_chunk); @@ -671,17 +668,11 @@ void InlineLevelIterator::enter_text_node(Layout::TextNode const& text_node) auto white_space_collapse = text_node.computed_values().white_space_collapse(); auto text_wrap_mode = text_node.computed_values().text_wrap_mode(); - bool do_collapse = white_space_collapse == CSS::WhiteSpaceCollapse::Collapse || white_space_collapse == CSS::WhiteSpaceCollapse::PreserveBreaks; + // https://drafts.csswg.org/css-text-4/#collapse bool do_wrap_lines = text_wrap_mode == CSS::TextWrapMode::Wrap; - bool do_respect_linebreaks = white_space_collapse == CSS::WhiteSpaceCollapse::Preserve || white_space_collapse == CSS::WhiteSpaceCollapse::PreserveBreaks || white_space_collapse == CSS::WhiteSpaceCollapse::BreakSpaces; - - if (text_node.dom_node().is_editable() && !text_node.dom_node().is_uninteresting_whitespace_node()) - do_collapse = false; + bool do_respect_linebreaks = first_is_one_of(white_space_collapse, CSS::WhiteSpaceCollapse::Preserve, CSS::WhiteSpaceCollapse::PreserveBreaks, CSS::WhiteSpaceCollapse::BreakSpaces); m_text_node_context = TextNodeContext { - .do_collapse = do_collapse, - .do_wrap_lines = do_wrap_lines, - .do_respect_linebreaks = do_respect_linebreaks, .is_first_chunk = true, .is_last_chunk = false, .chunk_iterator = TextNode::ChunkIterator { text_node, do_wrap_lines, do_respect_linebreaks }, diff --git a/Libraries/LibWeb/Layout/InlineLevelIterator.h b/Libraries/LibWeb/Layout/InlineLevelIterator.h index e6d5b79d29c..a0c9c9ba174 100644 --- a/Libraries/LibWeb/Layout/InlineLevelIterator.h +++ b/Libraries/LibWeb/Layout/InlineLevelIterator.h @@ -81,9 +81,6 @@ private: LayoutMode const m_layout_mode; struct TextNodeContext { - bool do_collapse {}; - bool do_wrap_lines {}; - bool do_respect_linebreaks {}; bool is_first_chunk {}; bool is_last_chunk {}; TextNode::ChunkIterator chunk_iterator; diff --git a/Libraries/LibWeb/Layout/LayoutState.cpp b/Libraries/LibWeb/Layout/LayoutState.cpp index 55c4a90c474..30f32199a22 100644 --- a/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Libraries/LibWeb/Layout/LayoutState.cpp @@ -289,7 +289,7 @@ void LayoutState::commit(Box& root) if (auto* paintable_with_lines = as_if(*paintable_box)) { for (size_t line_index = 0; line_index < used_values.line_boxes.size(); ++line_index) { auto& line_box = used_values.line_boxes[line_index]; - for (auto& fragment : line_box.fragments()) { + for (auto const& fragment : line_box.fragments()) { if (auto const* text_node = as_if(fragment.layout_node())) text_nodes.set(const_cast(text_node)); auto did_relocate_fragment = try_to_relocate_fragment_in_inline_node(fragment, line_index); diff --git a/Libraries/LibWeb/Layout/LineBox.cpp b/Libraries/LibWeb/Layout/LineBox.cpp index f1011fcd9ff..ca42ac582c1 100644 --- a/Libraries/LibWeb/Layout/LineBox.cpp +++ b/Libraries/LibWeb/Layout/LineBox.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2025, Jelle Raaijmakers * * SPDX-License-Identifier: BSD-2-Clause */ @@ -35,18 +36,24 @@ CSSPixels LineBox::bottom() const return m_bottom; } -void LineBox::add_fragment(Node const& layout_node, size_t start, size_t length, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, CSSPixels content_height, CSSPixels border_box_top, CSSPixels border_box_bottom, RefPtr glyph_run) +void LineBox::add_fragment(Node const& layout_node, size_t start, size_t length, CSSPixels leading_size, + CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, + CSSPixels content_height, CSSPixels border_box_top, CSSPixels border_box_bottom, RefPtr glyph_run) { bool text_align_is_justify = layout_node.computed_values().text_align() == CSS::TextAlign::Justify; - if (glyph_run && !text_align_is_justify && !m_fragments.is_empty() && &m_fragments.last().layout_node() == &layout_node && &m_fragments.last().m_glyph_run->font() == &glyph_run->font()) { + if (glyph_run && !text_align_is_justify && !m_fragments.is_empty() + && &m_fragments.last().layout_node() == &layout_node + && &m_fragments.last().m_glyph_run->font() == &glyph_run->font() + && m_fragments.last().start() + m_fragments.last().length_in_code_units() == start) { // The fragment we're adding is from the last Layout::Node on the line. // Expand the last fragment instead of adding a new one with the same Layout::Node. - m_fragments.last().m_length = (start - m_fragments.last().m_start) + length; + m_fragments.last().m_length_in_code_units += length; m_fragments.last().append_glyph_run(glyph_run, content_width); } else { CSSPixels inline_offset = leading_margin + leading_size + m_inline_length; CSSPixels block_offset = 0; - m_fragments.append(LineBoxFragment { layout_node, start, length, inline_offset, block_offset, content_width, content_height, border_box_top, m_direction, m_writing_mode, move(glyph_run) }); + m_fragments.append(LineBoxFragment { layout_node, start, length, inline_offset, block_offset, content_width, + content_height, border_box_top, m_direction, m_writing_mode, move(glyph_run) }); } m_inline_length += leading_margin + leading_size + content_width + trailing_size + trailing_margin; m_block_length = max(m_block_length, content_height + border_box_top + border_box_bottom); @@ -68,8 +75,7 @@ CSSPixels LineBox::calculate_or_trim_trailing_whitespace(RemoveTrailingWhitespac return whitespace_width; last_fragment = &m_fragments[--fragment_index]; - auto const* dom_node = last_fragment->layout_node().dom_node(); - if (dom_node) { + if (auto const* dom_node = last_fragment->layout_node().dom_node()) { auto cursor_position = dom_node->document().cursor_position(); if (cursor_position && cursor_position->node() == dom_node) return whitespace_width; @@ -90,9 +96,9 @@ CSSPixels LineBox::calculate_or_trim_trailing_whitespace(RemoveTrailingWhitespac if (last_text.is_null()) return whitespace_width; - size_t last_fragment_length = last_fragment->length(); - while (last_fragment_length) { - auto last_character = last_text.code_unit_at(--last_fragment_length); + size_t last_text_length = last_text.length_in_code_units(); + while (last_text_length) { + auto last_character = last_text.code_unit_at(--last_text_length); if (!is_ascii_space(last_character)) break; @@ -100,7 +106,7 @@ CSSPixels LineBox::calculate_or_trim_trailing_whitespace(RemoveTrailingWhitespac int last_character_width = font.glyph_width(last_character); whitespace_width += last_character_width; if (should_remove == RemoveTrailingWhitespace::Yes) { - last_fragment->m_length -= 1; + --last_fragment->m_length_in_code_units; last_fragment->set_inline_length(last_fragment->inline_length() - last_character_width); m_inline_length -= last_character_width; } diff --git a/Libraries/LibWeb/Layout/LineBoxFragment.cpp b/Libraries/LibWeb/Layout/LineBoxFragment.cpp index 5b4e39cfe71..f04716ed284 100644 --- a/Libraries/LibWeb/Layout/LineBoxFragment.cpp +++ b/Libraries/LibWeb/Layout/LineBoxFragment.cpp @@ -12,10 +12,12 @@ namespace Web::Layout { -LineBoxFragment::LineBoxFragment(Node const& layout_node, size_t start, size_t length, CSSPixels inline_offset, CSSPixels block_offset, CSSPixels inline_length, CSSPixels block_length, CSSPixels border_box_top, CSS::Direction direction, CSS::WritingMode writing_mode, RefPtr glyph_run) +LineBoxFragment::LineBoxFragment(Node const& layout_node, size_t start, size_t length_in_code_units, + CSSPixels inline_offset, CSSPixels block_offset, CSSPixels inline_length, CSSPixels block_length, + CSSPixels border_box_top, CSS::Direction direction, CSS::WritingMode writing_mode, RefPtr glyph_run) : m_layout_node(layout_node) , m_start(start) - , m_length(length) + , m_length_in_code_units(length_in_code_units) , m_inline_offset(inline_offset) , m_block_offset(block_offset) , m_inline_length(inline_length) @@ -48,10 +50,9 @@ CSSPixelSize LineBoxFragment::size() const bool LineBoxFragment::ends_in_whitespace() const { - auto text = this->text(); - if (text.is_empty()) + if (m_length_in_code_units == 0) return false; - return is_ascii_space(text.code_unit_at(text.length_in_code_units() - 1)); + return is_ascii_space(text().code_unit_at(m_length_in_code_units - 1)); } bool LineBoxFragment::is_justifiable_whitespace() const @@ -62,7 +63,7 @@ bool LineBoxFragment::is_justifiable_whitespace() const Utf16View LineBoxFragment::text() const { if (auto* text_node = as_if(layout_node())) - return text_node->text_for_rendering().substring_view(m_start, m_length); + return text_node->text_for_rendering().substring_view(m_start, m_length_in_code_units); return {}; } diff --git a/Libraries/LibWeb/Layout/LineBoxFragment.h b/Libraries/LibWeb/Layout/LineBoxFragment.h index 96719d10cbf..06fe2cae87f 100644 --- a/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -22,7 +22,7 @@ public: Node const& layout_node() const { return m_layout_node; } size_t start() const { return m_start; } - size_t length() const { return m_length; } + size_t length_in_code_units() const { return m_length_in_code_units; } CSSPixelPoint offset() const; CSSPixels inline_offset() const { return m_inline_offset; } @@ -61,7 +61,7 @@ private: GC::Ref m_layout_node; size_t m_start { 0 }; - size_t m_length { 0 }; + size_t m_length_in_code_units { 0 }; CSSPixels m_inline_offset; CSSPixels m_block_offset; CSSPixels m_inline_length; diff --git a/Libraries/LibWeb/Layout/LineBuilder.cpp b/Libraries/LibWeb/Layout/LineBuilder.cpp index dd6effa3f57..bd9202d5c9c 100644 --- a/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -86,7 +86,8 @@ void LineBuilder::append_box(Box const& box, CSSPixels leading_size, CSSPixels t { auto& box_state = m_layout_state.get_mutable(box); auto& line_box = ensure_last_line_box(); - line_box.add_fragment(box, 0, 0, leading_size, trailing_size, leading_margin, trailing_margin, box_state.content_width(), box_state.content_height(), box_state.border_box_top(), box_state.border_box_bottom()); + line_box.add_fragment(box, 0, 0, leading_size, trailing_size, leading_margin, trailing_margin, + box_state.content_width(), box_state.content_height(), box_state.border_box_top(), box_state.border_box_bottom()); m_max_height_on_current_line = max(m_max_height_on_current_line, box_state.margin_box_height()); box_state.containing_line_box_fragment = LineBoxFragmentCoordinate { @@ -98,7 +99,8 @@ void LineBuilder::append_box(Box const& box, CSSPixels leading_size, CSSPixels t void LineBuilder::append_text_chunk(TextNode const& text_node, size_t offset_in_node, size_t length_in_node, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, CSSPixels content_height, RefPtr glyph_run) { auto& line_box = ensure_last_line_box(); - line_box.add_fragment(text_node, offset_in_node, length_in_node, leading_size, trailing_size, leading_margin, trailing_margin, content_width, content_height, 0, 0, move(glyph_run)); + line_box.add_fragment(text_node, offset_in_node, length_in_node, leading_size, trailing_size, leading_margin, + trailing_margin, content_width, content_height, 0, 0, move(glyph_run)); m_max_height_on_current_line = max(m_max_height_on_current_line, line_box.block_length()); } @@ -300,9 +302,7 @@ void LineBuilder::update_last_line() CSSPixels uppermost_box_top = strut_top; CSSPixels lowermost_box_bottom = strut_bottom; - for (size_t i = 0; i < line_box.fragments().size(); ++i) { - auto& fragment = line_box.fragments()[i]; - + for (auto& fragment : line_box.fragments()) { CSSPixels new_fragment_inline_offset = inline_offset + fragment.inline_offset(); CSSPixels new_fragment_block_offset = 0; diff --git a/Libraries/LibWeb/Layout/TextNode.cpp b/Libraries/LibWeb/Layout/TextNode.cpp index f896e420602..271c8cfdf79 100644 --- a/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Libraries/LibWeb/Layout/TextNode.cpp @@ -282,10 +282,9 @@ static Utf16String apply_text_transform(Utf16String const& string, CSS::TextTran return apply_math_auto_text_transform(string); case CSS::TextTransform::Capitalize: return string.to_titlecase(locale, TrailingCodePointTransformation::PreserveExisting); - case CSS::TextTransform::FullSizeKana: { + case CSS::TextTransform::FullSizeKana: dbgln("FIXME: Implement text-transform full-size-kana"); return string; - } case CSS::TextTransform::FullWidth: return string.to_fullwidth(); } @@ -306,7 +305,6 @@ Utf16String const& TextNode::text_for_rendering() const return *m_text_for_rendering; } -// NOTE: This collapses whitespace into a single ASCII space if the CSS white-space property tells us to. void TextNode::compute_text_for_rendering() { if (dom_node().is_password_input()) { @@ -314,53 +312,85 @@ void TextNode::compute_text_for_rendering() return; } - bool collapse = first_is_one_of(computed_values().white_space_collapse(), CSS::WhiteSpaceCollapse::Collapse, CSS::WhiteSpaceCollapse::PreserveBreaks); - + // Apply text-transform + // FIXME: This can generate more code points than there were before; we need to find a better way to map the + // resulting paintable fragments' offsets into the original text node data. + // See: https://github.com/LadybirdBrowser/ladybird/issues/6177 auto parent_element = dom_node().parent_element(); auto const maybe_lang = parent_element ? parent_element->lang() : Optional {}; auto const lang = maybe_lang.has_value() ? maybe_lang.value() : Optional {}; + auto text = apply_text_transform(dom_node().data(), computed_values().text_transform(), lang); - auto data = apply_text_transform(dom_node().data(), computed_values().text_transform(), lang); - - // NOTE: A couple fast returns to avoid unnecessarily allocating a StringBuilder. - if (!collapse || data.is_empty()) { - m_text_for_rendering = move(data); + // The logic below deals with converting whitespace characters. If we don't have them, return early. + if (text.is_empty() || !any_of(text, is_ascii_space)) { + m_text_for_rendering = move(text); return; } - if (data.length_in_code_units() == 1) { - if (data.is_ascii_whitespace()) - m_text_for_rendering = " "_utf16; - else - m_text_for_rendering = move(data); - return; - } + // https://drafts.csswg.org/css-text-4/#white-space-phase-1 + bool convert_newlines = false; + bool convert_tabs = false; - if (!any_of(data, is_ascii_space)) { - m_text_for_rendering = move(data); - return; - } + // If white-space-collapse is set to collapse or preserve-breaks, white space characters are considered collapsible + // and are processed by performing the following steps: + auto white_space_collapse = computed_values().white_space_collapse(); + if (first_is_one_of(white_space_collapse, CSS::WhiteSpaceCollapse::Collapse, CSS::WhiteSpaceCollapse::PreserveBreaks)) { + // 1. FIXME: Any sequence of collapsible spaces and tabs immediately preceding or following a segment break is removed. - StringBuilder builder { StringBuilder::Mode::UTF16, data.length_in_code_units() }; - size_t index = 0; + // 2. Collapsible segment breaks are transformed for rendering according to the segment break transformation + // rules. + { + // https://drafts.csswg.org/css-text-4/#line-break-transform + // FIXME: When white-space-collapse is not collapse, segment breaks are not collapsible. For values other than + // collapse or preserve-spaces (which transforms them into spaces), segment breaks are instead transformed + // into a preserved line feed (U+000A). - auto skip_over_whitespace = [&] { - while (index < data.length_in_code_units() && is_ascii_space(data.code_unit_at(index))) - ++index; - }; + // When white-space-collapse is collapse, segment breaks are collapsible, and are collapsed as follows: + if (white_space_collapse == CSS::WhiteSpaceCollapse::Collapse) { + // 1. FIXME: First, any collapsible segment break immediately following another collapsible segment break is + // removed. - while (index < data.length_in_code_units()) { - if (is_ascii_space(data.code_unit_at(index))) { - builder.append(' '); - ++index; - skip_over_whitespace(); - } else { - builder.append_code_unit(data.code_unit_at(index)); - ++index; + // 2. FIXME: Then any remaining segment break is either transformed into a space (U+0020) or removed depending + // on the context before and after the break. The rules for this operation are UA-defined in this + // level. + convert_newlines = true; + } } + + // 3. Every collapsible tab is converted to a collapsible space (U+0020). + convert_tabs = true; + + // 4. Any collapsible space immediately following another collapsible space—even one outside the boundary of the + // inline containing that space, provided both spaces are within the same inline formatting context—is + // collapsed to have zero advance width. (It is invisible, but retains its soft wrap opportunity, if any.) + // AD-HOC: This is handled by TextNode::ChunkIterator by removing the space. } - m_text_for_rendering = builder.to_utf16_string(); + // If white-space-collapse is set to preserve-spaces, each tab and segment break is converted to a space. + if (white_space_collapse == CSS::WhiteSpaceCollapse::PreserveSpaces) { + convert_tabs = true; + convert_newlines = true; + } + + // AD-HOC: Prevent allocating a StringBuilder for a single space/newline/tab. + if (text == " "sv || (convert_tabs && text == "\t"sv) || (convert_newlines && text == "\n"sv)) { + m_text_for_rendering = " "_utf16; + return; + } + + // AD-HOC: It's important to not change the amount of code units in the resulting transformed text, so ChunkIterator + // can pass views to this string with associated code unit offsets that still match the original text. + if (convert_newlines || convert_tabs) { + StringBuilder text_builder { StringBuilder::Mode::UTF16, text.length_in_code_units() }; + for (auto code_point : text) { + if ((convert_newlines && code_point == '\n') || (convert_tabs && code_point == '\t')) + code_point = ' '; + text_builder.append_code_point(code_point); + } + text = text_builder.to_utf16_string(); + } + + m_text_for_rendering = move(text); } Unicode::Segmenter& TextNode::grapheme_segmenter() const @@ -373,22 +403,20 @@ Unicode::Segmenter& TextNode::grapheme_segmenter() const return *m_grapheme_segmenter; } -TextNode::ChunkIterator::ChunkIterator(TextNode const& text_node, bool wrap_lines, bool respect_linebreaks) - : m_wrap_lines(wrap_lines) - , m_respect_linebreaks(respect_linebreaks) - , m_view(text_node.text_for_rendering()) - , m_font_cascade_list(text_node.computed_values().font_list()) - , m_grapheme_segmenter(text_node.grapheme_segmenter()) +TextNode::ChunkIterator::ChunkIterator(TextNode const& text_node, bool should_wrap_lines, bool should_respect_linebreaks) + : ChunkIterator(text_node, text_node.text_for_rendering(), text_node.grapheme_segmenter(), should_wrap_lines, should_respect_linebreaks) { } -TextNode::ChunkIterator::ChunkIterator(TextNode const& text_node, Utf16View const& text, Unicode::Segmenter& grapheme_segmenter, bool wrap_lines, bool respect_linebreaks) - : m_wrap_lines(wrap_lines) - , m_respect_linebreaks(respect_linebreaks) +TextNode::ChunkIterator::ChunkIterator(TextNode const& text_node, Utf16View const& text, + Unicode::Segmenter& grapheme_segmenter, bool should_wrap_lines, bool should_respect_linebreaks) + : m_should_wrap_lines(should_wrap_lines) + , m_should_respect_linebreaks(should_respect_linebreaks) , m_view(text) , m_font_cascade_list(text_node.computed_values().font_list()) , m_grapheme_segmenter(grapheme_segmenter) { + m_should_collapse_whitespace = first_is_one_of(text_node.computed_values().white_space_collapse(), CSS::WhiteSpaceCollapse::Collapse, CSS::WhiteSpaceCollapse::PreserveBreaks); } static Gfx::GlyphRun::TextType text_type_for_code_point(u32 code_point) @@ -456,13 +484,18 @@ Optional TextNode::ChunkIterator::next_without_peek() if (m_current_index >= m_view.length_in_code_units()) return {}; - auto current_code_point = [this]() { + auto current_code_point = [this] { return m_view.code_point_at(m_current_index); }; - auto next_grapheme_boundary = [this]() { + auto next_grapheme_boundary = [this] { return m_grapheme_segmenter.next_boundary(m_current_index).value_or(m_view.length_in_code_units()); }; + // https://drafts.csswg.org/css-text-4/#collapsible-white-space + auto is_collapsible = [this](u32 code_point) { + return m_should_collapse_whitespace && is_ascii_space(code_point); + }; + auto code_point = current_code_point(); auto start_of_chunk = m_current_index; @@ -489,7 +522,7 @@ Optional TextNode::ChunkIterator::next_without_peek() return result.release_value(); } - if (m_respect_linebreaks && code_point == '\n') { + if (m_should_respect_linebreaks && code_point == '\n') { // Newline encountered, and we're supposed to preserve them. // If we have accumulated some code points in the current chunk, commit them now and continue with the newline next time. if (auto result = try_commit_chunk(start_of_chunk, m_current_index, false, broken_on_tab, font, text_type); result.has_value()) @@ -502,7 +535,19 @@ Optional TextNode::ChunkIterator::next_without_peek() return result.release_value(); } - if (m_wrap_lines) { + // If both this code point and the previous code point are collapsible, skip code points until we're at a non- + // collapsible code point. + if (is_collapsible(code_point) && m_current_index > 0 && is_collapsible(m_view.code_point_at(m_current_index - 1))) { + auto result = try_commit_chunk(start_of_chunk, m_current_index, false, broken_on_tab, font, text_type); + + while (m_current_index < m_view.length_in_code_units() && is_collapsible(current_code_point())) + m_current_index = next_grapheme_boundary(); + + if (result.has_value()) + return result.release_value(); + } + + if (m_should_wrap_lines) { if (text_type != text_type_for_code_point(code_point)) { if (auto result = try_commit_chunk(start_of_chunk, m_current_index, false, broken_on_tab, font, text_type); result.has_value()) return result.release_value(); diff --git a/Libraries/LibWeb/Layout/TextNode.h b/Libraries/LibWeb/Layout/TextNode.h index 4d651b65953..cb03cad1c15 100644 --- a/Libraries/LibWeb/Layout/TextNode.h +++ b/Libraries/LibWeb/Layout/TextNode.h @@ -42,8 +42,12 @@ public: class ChunkIterator { public: - ChunkIterator(TextNode const&, bool wrap_lines, bool respect_linebreaks); - ChunkIterator(TextNode const&, Utf16View const&, Unicode::Segmenter&, bool wrap_lines, bool respect_linebreaks); + ChunkIterator(TextNode const&, bool should_wrap_lines, bool should_respect_linebreaks); + ChunkIterator(TextNode const&, Utf16View const&, Unicode::Segmenter&, bool should_wrap_lines, bool should_respect_linebreaks); + + bool should_wrap_lines() const { return m_should_wrap_lines; } + bool should_respect_linebreaks() const { return m_should_respect_linebreaks; } + bool should_collapse_whitespace() const { return m_should_collapse_whitespace; } Optional next(); Optional peek(size_t); @@ -52,8 +56,9 @@ public: Optional next_without_peek(); Optional try_commit_chunk(size_t start, size_t end, bool has_breaking_newline, bool has_breaking_tab, Gfx::Font const&, Gfx::GlyphRun::TextType) const; - bool const m_wrap_lines; - bool const m_respect_linebreaks; + bool const m_should_wrap_lines; + bool const m_should_respect_linebreaks; + bool m_should_collapse_whitespace; Utf16View m_view; Gfx::FontCascadeList const& m_font_cascade_list; diff --git a/Libraries/LibWeb/Layout/TreeBuilder.cpp b/Libraries/LibWeb/Layout/TreeBuilder.cpp index e1d264f52e0..712dd3982e7 100644 --- a/Libraries/LibWeb/Layout/TreeBuilder.cpp +++ b/Libraries/LibWeb/Layout/TreeBuilder.cpp @@ -490,10 +490,10 @@ void TreeBuilder::restructure_block_node_in_inline_parent(NodeWithStyleAndBoxMod static bool is_ignorable_whitespace(Layout::Node const& node) { - if (node.is_text_node() && static_cast(node).text_for_rendering().is_ascii_whitespace()) + if (auto* text_node = as_if(node); text_node && text_node->text_for_rendering().is_ascii_whitespace()) return true; - if (node.is_anonymous() && node.is_block_container() && static_cast(node).children_are_inline()) { + if (node.is_anonymous() && node.is_block_container() && node.children_are_inline()) { bool contains_only_white_space = true; node.for_each_in_inclusive_subtree([&contains_only_white_space](auto& descendant) { if (auto* text_node = as_if(descendant)) { diff --git a/Libraries/LibWeb/Painting/PaintableBox.h b/Libraries/LibWeb/Painting/PaintableBox.h index deffeed5ece..aab276344a8 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Libraries/LibWeb/Painting/PaintableBox.h @@ -369,8 +369,6 @@ public: m_fragments.append(PaintableFragment { fragment }); } - void set_fragments(Vector&& fragments) { m_fragments = move(fragments); } - template void for_each_fragment(Callback callback) const { diff --git a/Libraries/LibWeb/Painting/PaintableFragment.cpp b/Libraries/LibWeb/Painting/PaintableFragment.cpp index 643d19f3ca5..e6d57494cb8 100644 --- a/Libraries/LibWeb/Painting/PaintableFragment.cpp +++ b/Libraries/LibWeb/Painting/PaintableFragment.cpp @@ -21,7 +21,7 @@ PaintableFragment::PaintableFragment(Layout::LineBoxFragment const& fragment) , m_size(fragment.size()) , m_baseline(fragment.baseline()) , m_start_offset(fragment.start()) - , m_length_in_code_units(fragment.length()) + , m_length_in_code_units(fragment.length_in_code_units()) , m_glyph_run(fragment.glyph_run()) , m_writing_mode(fragment.writing_mode()) { diff --git a/Tests/LibWeb/Layout/expected/acid1.txt b/Tests/LibWeb/Layout/expected/acid1.txt index 59fea336699..612518d3043 100644 --- a/Tests/LibWeb/Layout/expected/acid1.txt +++ b/Tests/LibWeb/Layout/expected/acid1.txt @@ -35,7 +35,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- TextNode <#text> (not painted) BlockContainer <(anonymous)> at [235,65] [0+0+0 139.96875 0+0+0] [0+0+0 19 0+0+0] children: not-inline continuation BlockContainer

at [235,65] [0+0+0 139.96875 0+0+0] [0+0+0 19 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 5, rect: [235,65 27.5x19] baseline: 12.5 + frag 0 from TextNode start: 33, length: 5, rect: [235,65 27.5x19] baseline: 12.5 "bang " frag 1 from RadioButton start: 0, length: 0, rect: [262.5,65 12x12] baseline: 12 TextNode <#text> (not painted) @@ -46,7 +46,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- TextNode <#text> (not painted) BlockContainer <(anonymous)> at [235,84] [0+0+0 139.96875 0+0+0] [0+0+0 19 0+0+0] children: not-inline continuation BlockContainer

at [235,84] [0+0+0 139.96875 0+0+0] [0+0+0 19 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 8, rect: [235,84 45.171875x19] baseline: 12.5 + frag 0 from TextNode start: 33, length: 8, rect: [235,84 45.171875x19] baseline: 12.5 "whimper " frag 1 from RadioButton start: 0, length: 0, rect: [280.171875,84 12x12] baseline: 12 TextNode <#text> (not painted) @@ -94,19 +94,27 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer <(anonymous)> at [20,30] [0+0+0 480 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer

at [20,335] [0+0+0 480 0+0+0] [0+0+0 65 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 90, rect: [20,335 473.6875x13] baseline: 9.5 - "This is a nonsensical document, but syntactically valid HTML 4.0. All 100%-conformant CSS1" - frag 1 from TextNode start: 92, length: 74, rect: [20,348 396.96875x13] baseline: 9.5 + frag 0 from TextNode start: 13, length: 86, rect: [20,335 448.296875x13] baseline: 9.5 + "This is a nonsensical document, but syntactically valid HTML 4.0. All 100%-conformant " + frag 1 from TextNode start: 111, length: 4, rect: [468.296875,335 25.390625x13] baseline: 9.5 + "CSS1" + frag 2 from TextNode start: 116, length: 74, rect: [20,348 396.96875x13] baseline: 9.5 "agents should be able to render the document elements above this paragraph" - frag 2 from TextNode start: 167, length: 43, rect: [20,361 207.9375x13] baseline: 9.5 + frag 3 from TextNode start: 203, length: 43, rect: [20,361 207.9375x13] baseline: 9.5 "indistinguishably (to the pixel) from this " - frag 3 from TextNode start: 0, length: 31, rect: [330.96875,361 159.671875x13] baseline: 9.5 - " (except font rasterization and" - frag 4 from TextNode start: 32, length: 89, rect: [20,374 465.09375x13] baseline: 9.5 - "form widgets). All discrepancies should be traceable to CSS1 implementation shortcomings." - frag 5 from TextNode start: 122, length: 67, rect: [20,387 345.59375x13] baseline: 9.5 - "Once you have finished evaluating this test, you can return to the " - frag 6 from TextNode start: 0, length: 1, rect: [425.5,387 2.71875x13] baseline: 9.5 + frag 4 from TextNode start: 0, length: 1, rect: [330.96875,361 5x13] baseline: 9.5 + " " + frag 5 from TextNode start: 13, length: 30, rect: [335.96875,361 154.671875x13] baseline: 9.5 + "(except font rasterization and" + frag 6 from TextNode start: 44, length: 56, rect: [20,374 286.6875x13] baseline: 9.5 + "form widgets). All discrepancies should be traceable to " + frag 7 from TextNode start: 112, length: 33, rect: [306.6875,374 178.40625x13] baseline: 9.5 + "CSS1 implementation shortcomings." + frag 8 from TextNode start: 146, length: 53, rect: [20,387 271.421875x13] baseline: 9.5 + "Once you have finished evaluating this test, you can " + frag 9 from TextNode start: 211, length: 14, rect: [291.421875,387 74.171875x13] baseline: 9.5 + "return to the " + frag 10 from TextNode start: 0, length: 1, rect: [425.5,387 2.71875x13] baseline: 9.5 "." TextNode <#text> (not painted) InlineNode at [227.9375,361] [0+0+0 103.03125 0+0+0] [0+0+0 13 0+0+0] diff --git a/Tests/LibWeb/Layout/expected/bfc-fit-content-width-with-margin.txt b/Tests/LibWeb/Layout/expected/bfc-fit-content-width-with-margin.txt index f15758e6654..be69ca523ac 100644 --- a/Tests/LibWeb/Layout/expected/bfc-fit-content-width-with-margin.txt +++ b/Tests/LibWeb/Layout/expected/bfc-fit-content-width-with-margin.txt @@ -2,23 +2,23 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 304 0+0+0] [BFC] children: not-inline BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 288 0+0+8] children: not-inline BlockContainer at [243.1875,8] [235.1875+0+0 548.8125 0+0+0] [0+0+0 162 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 62, rect: [243.1875,8 515.390625x18] baseline: 13.796875 + frag 0 from TextNode start: 2, length: 62, rect: [243.1875,8 515.390625x18] baseline: 13.796875 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce" - frag 1 from TextNode start: 64, length: 68, rect: [243.1875,26 543.484375x18] baseline: 13.796875 + frag 1 from TextNode start: 65, length: 68, rect: [243.1875,26 543.484375x18] baseline: 13.796875 "cursus est eget nisl porta, id vulputate velit imperdiet. Vestibulum" - frag 2 from TextNode start: 133, length: 69, rect: [243.1875,44 533.765625x18] baseline: 13.796875 + frag 2 from TextNode start: 134, length: 69, rect: [243.1875,44 533.765625x18] baseline: 13.796875 "mollis ligula sit amet ligula aliquam, vitae vulputate magna iaculis." - frag 3 from TextNode start: 203, length: 68, rect: [243.1875,62 533.015625x18] baseline: 13.796875 + frag 3 from TextNode start: 204, length: 68, rect: [243.1875,62 533.015625x18] baseline: 13.796875 "Nulla et augue fringilla, molestie nulla blandit, condimentum risus." - frag 4 from TextNode start: 272, length: 58, rect: [243.1875,80 488.140625x18] baseline: 13.796875 + frag 4 from TextNode start: 273, length: 58, rect: [243.1875,80 488.140625x18] baseline: 13.796875 "Suspendisse lectus augue, sodales vitae metus ac, interdum" - frag 5 from TextNode start: 331, length: 63, rect: [243.1875,98 526.546875x18] baseline: 13.796875 + frag 5 from TextNode start: 332, length: 63, rect: [243.1875,98 526.546875x18] baseline: 13.796875 "volutpat arcu. Aenean eu placerat risus, at dictum lectus. Nunc" - frag 6 from TextNode start: 395, length: 64, rect: [243.1875,116 524.5x18] baseline: 13.796875 + frag 6 from TextNode start: 396, length: 64, rect: [243.1875,116 524.5x18] baseline: 13.796875 "maximus est eu risus porta tincidunt. Cras nec felis tellus. Sed" - frag 7 from TextNode start: 460, length: 66, rect: [243.1875,134 523.078125x18] baseline: 13.796875 + frag 7 from TextNode start: 461, length: 66, rect: [243.1875,134 523.078125x18] baseline: 13.796875 "euismod ultricies ipsum, eget ultricies nisl dignissim nec. Mauris" - frag 8 from TextNode start: 527, length: 21, rect: [243.1875,152 178.53125x18] baseline: 13.796875 + frag 8 from TextNode start: 528, length: 21, rect: [243.1875,152 178.53125x18] baseline: 13.796875 "aliquet rhoncus urna." TextNode <#text> (not painted) BlockContainer <(anonymous)> at [8,170] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/bfc-consider-all-currently-stacked-floats.txt b/Tests/LibWeb/Layout/expected/block-and-inline/bfc-consider-all-currently-stacked-floats.txt index a8996bc1eeb..1252eac45b7 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/bfc-consider-all-currently-stacked-floats.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/bfc-consider-all-currently-stacked-floats.txt @@ -4,7 +4,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- TextNode <#text> (not painted) BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 36 0+0+8] children: not-inline BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 18 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [137.109375,8 27.640625x18] baseline: 13.796875 + frag 0 from TextNode start: 3, length: 3, rect: [137.109375,8 27.640625x18] baseline: 13.796875 "bar" BlockContainer at [8,8] floating [0+0+0 100 0+0+0] [0+0+0 100 0+0+0] [BFC] children: not-inline TextNode <#text> (not painted) @@ -14,7 +14,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- TextNode <#text> (not painted) TextNode <#text> (not painted) BlockContainer

at [8,26] [0+0+0 784 0+0+0] [0+0+0 18 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [129.515625,26 27.203125x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 3, rect: [129.515625,26 27.203125x18] baseline: 13.796875 "baz" TextNode <#text> (not painted) BlockContainer at [108,26] floating [0+0+0 21.515625 0+0+0] [0+0+0 18 0+0+0] [BFC] children: inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/button-should-have-vertically-aligned-content.txt b/Tests/LibWeb/Layout/expected/block-and-inline/button-should-have-vertically-aligned-content.txt index c9e5725e2a1..4046e168d34 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/button-should-have-vertically-aligned-content.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/button-should-have-vertically-aligned-content.txt @@ -9,13 +9,13 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer <(anonymous)> at [22,29] [0+0+0 48.6875 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer at [32,39] [0+10+0 28.6875 0+10+0] [0+10+0 18 0+10+0] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [32,39 28.6875x18] baseline: 13.796875 + frag 0 from TextNode start: 13, length: 3, rect: [32,39 28.6875x18] baseline: 13.796875 "one" TextNode <#text> (not painted) BlockContainer <(anonymous)> at [22,67] [0+0+0 48.6875 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer at [32,77] [0+10+0 28.6875 0+10+0] [0+10+0 100 0+10+0] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [32.125,77 28.4375x18] baseline: 13.796875 + frag 0 from TextNode start: 13, length: 3, rect: [32.125,77 28.4375x18] baseline: 13.796875 "two" TextNode <#text> (not painted) BlockContainer <(anonymous)> at [22,187] [0+0+0 48.6875 0+0+0] [0+0+0 0 0+0+0] children: inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-1.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-1.txt index 4798a4a3269..f1200fc3cd5 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-1.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-1.txt @@ -46,43 +46,51 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer
at [8,8] [0+0+0 784 0+0+0] [0+0+0 342 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 47, rect: [228,8 414.5625x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 47, rect: [228,8 414.5625x18] baseline: 13.796875 "lorem ipsum lorem ipsum lorem ipsum lorem ipsum" - frag 1 from TextNode start: 49, length: 47, rect: [228,26 414.5625x18] baseline: 13.796875 + frag 1 from TextNode start: 53, length: 47, rect: [228,26 414.5625x18] baseline: 13.796875 "lorem ipsum lorem ipsum lorem ipsum lorem ipsum" - frag 2 from TextNode start: 97, length: 53, rect: [228,44 466.90625x18] baseline: 13.796875 + frag 2 from TextNode start: 101, length: 53, rect: [228,44 466.90625x18] baseline: 13.796875 "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 3 from TextNode start: 151, length: 65, rect: [188,62 573.5x18] baseline: 13.796875 + frag 3 from TextNode start: 155, length: 65, rect: [188,62 573.5x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum" - frag 4 from TextNode start: 217, length: 65, rect: [188,80 572.546875x18] baseline: 13.796875 - "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 5 from TextNode start: 283, length: 77, rect: [108,98 679.140625x18] baseline: 13.796875 + frag 4 from TextNode start: 221, length: 60, rect: [188,80 528.203125x18] baseline: 13.796875 + "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum " + frag 5 from TextNode start: 285, length: 5, rect: [716.203125,80 44.34375x18] baseline: 13.796875 + "lorem" + frag 6 from TextNode start: 291, length: 77, rect: [108,98 679.140625x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum" - frag 6 from TextNode start: 361, length: 89, rect: [8,116 783.828125x18] baseline: 13.796875 + frag 7 from TextNode start: 369, length: 89, rect: [8,116 783.828125x18] baseline: 13.796875 "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 7 from TextNode start: 451, length: 83, rect: [8,134 731.484375x18] baseline: 13.796875 + frag 8 from TextNode start: 459, length: 83, rect: [8,134 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 8 from TextNode start: 535, length: 83, rect: [8,152 731.484375x18] baseline: 13.796875 + frag 9 from TextNode start: 543, length: 18, rect: [8,152 158.9375x18] baseline: 13.796875 + "ipsum lorem ipsum " + frag 10 from TextNode start: 565, length: 65, rect: [166.9375,152 572.546875x18] baseline: 13.796875 + "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" + frag 11 from TextNode start: 631, length: 83, rect: [8,170 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 9 from TextNode start: 619, length: 83, rect: [8,170 731.484375x18] baseline: 13.796875 + frag 12 from TextNode start: 715, length: 83, rect: [8,188 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 10 from TextNode start: 703, length: 83, rect: [8,188 731.484375x18] baseline: 13.796875 + frag 13 from TextNode start: 799, length: 42, rect: [8,206 370.21875x18] baseline: 13.796875 + "ipsum lorem ipsum lorem ipsum lorem ipsum " + frag 14 from TextNode start: 845, length: 41, rect: [378.21875,206 361.265625x18] baseline: 13.796875 + "lorem ipsum lorem ipsum lorem ipsum lorem" + frag 15 from TextNode start: 887, length: 83, rect: [8,224 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 11 from TextNode start: 787, length: 83, rect: [8,206 731.484375x18] baseline: 13.796875 + frag 16 from TextNode start: 971, length: 83, rect: [8,242 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 12 from TextNode start: 871, length: 83, rect: [8,224 731.484375x18] baseline: 13.796875 + frag 17 from TextNode start: 1055, length: 66, rect: [8,260 581.5x18] baseline: 13.796875 + "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum " + frag 18 from TextNode start: 1125, length: 17, rect: [589.5,260 149.984375x18] baseline: 13.796875 + "lorem ipsum lorem" + frag 19 from TextNode start: 1143, length: 83, rect: [8,278 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 13 from TextNode start: 955, length: 83, rect: [8,242 731.484375x18] baseline: 13.796875 + frag 20 from TextNode start: 1227, length: 83, rect: [8,296 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 14 from TextNode start: 1039, length: 83, rect: [8,260 731.484375x18] baseline: 13.796875 + frag 21 from TextNode start: 1311, length: 83, rect: [8,314 731.484375x18] baseline: 13.796875 "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 15 from TextNode start: 1123, length: 83, rect: [8,278 731.484375x18] baseline: 13.796875 - "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 16 from TextNode start: 1207, length: 83, rect: [8,296 731.484375x18] baseline: 13.796875 - "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 17 from TextNode start: 1291, length: 83, rect: [8,314 731.484375x18] baseline: 13.796875 - "ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem" - frag 18 from TextNode start: 1375, length: 5, rect: [8,332 45.296875x18] baseline: 13.796875 + frag 22 from TextNode start: 1395, length: 5, rect: [8,332 45.296875x18] baseline: 13.796875 "ipsum" TextNode <#text> (not painted) BlockContainer <(anonymous)> at [8,350] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-clear-by-line-break-at-end-of-block.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-clear-by-line-break-at-end-of-block.txt index e2f4ee2b8d2..1cb5e79931d 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-clear-by-line-break-at-end-of-block.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-clear-by-line-break-at-end-of-block.txt @@ -2,7 +2,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 416 0+0+0] [BFC] children: not-inline BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 400 0+0+8] children: not-inline BlockContainer at [8,8] [0+0+0 784 0+0+0] [0+0+0 200 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [8,8 27.15625x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 3, rect: [8,8 27.15625x18] baseline: 13.796875 "foo" TextNode <#text> (not painted) BlockContainer at [292,8] floating [0+0+0 500 0+0+0] [0+0+0 200 0+0+0] [BFC] children: not-inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-initial-available-space-vs-height.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-initial-available-space-vs-height.txt index ee5215380d6..edcab404dd0 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-initial-available-space-vs-height.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-initial-available-space-vs-height.txt @@ -2,7 +2,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 414 0+0+0] [BFC] children: not-inline BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 6 0+0+8] children: not-inline BlockContainer at [8,8] [0+0+0 100 0+0+684] [0+0+0 6 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 1, rect: [8,8 4.328125x6] baseline: 4.5 + frag 0 from TextNode start: 5, length: 1, rect: [8,8 4.328125x6] baseline: 4.5 "H" TextNode <#text> (not painted) BlockContainer at [8,14] floating [0+0+0 100 0+0+0] [0+0+0 100 0+0+0] [BFC] children: not-inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-1.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-1.txt index 358121a1a53..dfa33e70f82 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-1.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-1.txt @@ -4,40 +4,54 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer at [9,9] [0+1+0 300 0+1+482] [0+1+0 250 0+1+0] children: inline - frag 0 from TextNode start: 1, length: 24, rect: [61,9 212x16] baseline: 12.796875 + frag 0 from TextNode start: 9, length: 24, rect: [61,9 212x16] baseline: 12.796875 "foo bar baz foo bar baz " - frag 1 from TextNode start: 1, length: 3, rect: [273,9 27.15625x16] baseline: 12.796875 + frag 1 from TextNode start: 9, length: 3, rect: [273,9 27.15625x16] baseline: 12.796875 "foo" - frag 2 from TextNode start: 5, length: 3, rect: [263,25 27.640625x16] baseline: 12.796875 + frag 2 from TextNode start: 13, length: 3, rect: [263,25 27.640625x16] baseline: 12.796875 "bar" - frag 3 from TextNode start: 9, length: 3, rect: [263,41 27.203125x16] baseline: 12.796875 + frag 3 from TextNode start: 17, length: 3, rect: [263,41 27.203125x16] baseline: 12.796875 "baz" - frag 4 from TextNode start: 13, length: 3, rect: [263,57 27.15625x16] baseline: 12.796875 + frag 4 from TextNode start: 21, length: 3, rect: [263,57 27.15625x16] baseline: 12.796875 "foo" - frag 5 from TextNode start: 17, length: 11, rect: [9,77 98x16] baseline: 12.796875 + frag 5 from TextNode start: 25, length: 8, rect: [9,77 70.84375x16] baseline: 12.796875 + "bar baz " + frag 6 from TextNode start: 41, length: 3, rect: [79.84375,77 27.15625x16] baseline: 12.796875 + "foo" + frag 7 from TextNode start: 45, length: 11, rect: [9,93 98x16] baseline: 12.796875 "bar baz foo" - frag 6 from TextNode start: 29, length: 11, rect: [9,93 98x16] baseline: 12.796875 - "bar baz foo" - frag 7 from TextNode start: 41, length: 7, rect: [9,109 62.84375x16] baseline: 12.796875 + frag 8 from TextNode start: 57, length: 7, rect: [9,109 62.84375x16] baseline: 12.796875 "bar baz" - frag 8 from TextNode start: 1, length: 7, rect: [9,125 62.796875x16] baseline: 12.796875 + frag 9 from TextNode start: 9, length: 7, rect: [9,125 62.796875x16] baseline: 12.796875 "foo bar" - frag 9 from TextNode start: 9, length: 31, rect: [9,141 274.359375x16] baseline: 12.796875 - "baz foo bar baz foo bar baz foo" - frag 10 from TextNode start: 41, length: 31, rect: [9,157 274.84375x16] baseline: 12.796875 - "bar baz foo bar baz foo bar baz" - frag 11 from TextNode start: 1, length: 23, rect: [61,173 204x16] baseline: 12.796875 + frag 10 from TextNode start: 17, length: 16, rect: [9,141 141.203125x16] baseline: 12.796875 + "baz foo bar baz " + frag 11 from TextNode start: 41, length: 15, rect: [150.203125,141 133.15625x16] baseline: 12.796875 + "foo bar baz foo" + frag 12 from TextNode start: 57, length: 8, rect: [9,157 70.84375x16] baseline: 12.796875 + "bar baz " + frag 13 from TextNode start: 73, length: 23, rect: [79.84375,157 204x16] baseline: 12.796875 "foo bar baz foo bar baz" - frag 12 from TextNode start: 1, length: 23, rect: [61,189 204x16] baseline: 12.796875 + frag 14 from TextNode start: 9, length: 23, rect: [61,173 204x16] baseline: 12.796875 + "foo bar baz foo bar baz" + frag 15 from TextNode start: 9, length: 23, rect: [61,189 204x16] baseline: 12.796875 + "foo bar baz foo bar baz" + frag 16 from TextNode start: 41, length: 24, rect: [61,205 212x16] baseline: 12.796875 + "foo bar baz foo bar baz " + frag 17 from TextNode start: 73, length: 3, rect: [273,205 27.15625x16] baseline: 12.796875 + "foo" + frag 18 from TextNode start: 77, length: 20, rect: [61,221 176.84375x16] baseline: 12.796875 + "bar baz foo bar baz " + frag 19 from TextNode start: 105, length: 7, rect: [237.84375,221 62.796875x16] baseline: 12.796875 + "foo bar" + frag 20 from TextNode start: 113, length: 16, rect: [9,237 141.203125x16] baseline: 12.796875 + "baz foo bar baz " + frag 21 from TextNode start: 137, length: 15, rect: [150.203125,237 133.15625x16] baseline: 12.796875 + "foo bar baz foo" + frag 22 from TextNode start: 153, length: 8, rect: [9,253 70.84375x16] baseline: 12.796875 + "bar baz " + frag 23 from TextNode start: 169, length: 23, rect: [79.84375,253 204x16] baseline: 12.796875 "foo bar baz foo bar baz" - frag 13 from TextNode start: 25, length: 27, rect: [61,205 239.15625x16] baseline: 12.796875 - "foo bar baz foo bar baz foo" - frag 14 from TextNode start: 53, length: 27, rect: [61,221 239.640625x16] baseline: 12.796875 - "bar baz foo bar baz foo bar" - frag 15 from TextNode start: 81, length: 31, rect: [9,237 274.359375x16] baseline: 12.796875 - "baz foo bar baz foo bar baz foo" - frag 16 from TextNode start: 113, length: 31, rect: [9,253 274.84375x16] baseline: 12.796875 - "bar baz foo bar baz foo bar baz" TextNode <#text> (not painted) BlockContainer at [10,10] floating [0+1+0 50 0+1+0] [0+1+0 50 0+1+0] [BFC] children: not-inline TextNode <#text> (not painted) diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-3.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-3.txt index 641d8d68abf..5a91b1ab737 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-3.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-stress-3.txt @@ -4,7 +4,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer at [9,9] [0+1+0 300 0+1+482] [0+1+0 250 0+1+0] children: inline - frag 0 from TextNode start: 1, length: 23, rect: [61,9 204x16] baseline: 12.796875 + frag 0 from TextNode start: 9, length: 23, rect: [61,9 204x16] baseline: 12.796875 "foo bar baz foo bar baz" TextNode <#text> (not painted) BlockContainer at [10,10] floating [0+1+0 50 0+1+0] [0+1+0 50 0+1+0] [BFC] children: not-inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt index 6c5df6d30ab..ced0ebf9166 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-under-if-would-fit.txt @@ -6,9 +6,9 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer <(anonymous)> at [8,8] [0+0+0 784 0+0+0] [0+0+0 0 0+0+0] children: inline TextNode <#text> (not painted) BlockContainer at [9,9] [0+1+0 100 0+1+682] [0+1+0 150 0+1+0] children: inline - frag 0 from TextNode start: 1, length: 11, rect: [9,9 99.109375x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 11, rect: [9,9 99.109375x18] baseline: 13.796875 "abc abc abc" - frag 1 from TextNode start: 13, length: 11, rect: [9,27 99.109375x18] baseline: 13.796875 + frag 1 from TextNode start: 21, length: 11, rect: [9,27 99.109375x18] baseline: 13.796875 "abc abc abc" TextNode <#text> (not painted) BlockContainer at [9,45] floating [0+0+0 80 0+0+0] [0+0+0 50 0+0+0] [BFC] children: not-inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/float-vertical-clearance-for-text-after-break.txt b/Tests/LibWeb/Layout/expected/block-and-inline/float-vertical-clearance-for-text-after-break.txt index cb5ef68b228..1511f165978 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/float-vertical-clearance-for-text-after-break.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/float-vertical-clearance-for-text-after-break.txt @@ -2,9 +2,9 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [0,0] [0+0+0 800 0+0+0] [0+0+0 102 0+0+0] [BFC] children: not-inline BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 86 0+0+8] children: not-inline BlockContainer at [8,8] [0+0+0 50 0+0+734] [0+0+0 86 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [8,58 27.15625x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 3, rect: [8,58 27.15625x18] baseline: 13.796875 "foo" - frag 1 from TextNode start: 1, length: 3, rect: [8,76 27.640625x18] baseline: 13.796875 + frag 1 from TextNode start: 5, length: 3, rect: [8,76 27.640625x18] baseline: 13.796875 "bar" TextNode <#text> (not painted) BlockContainer at [8,8] floating [0+0+0 50 0+0+0] [0+0+0 50 0+0+0] [BFC] children: not-inline diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/floats-and-negative-margins.txt b/Tests/LibWeb/Layout/expected/block-and-inline/floats-and-negative-margins.txt index 7d485345e49..7c5339fb1c2 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/floats-and-negative-margins.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/floats-and-negative-margins.txt @@ -3,12 +3,12 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [100,8] [100+0+0 200 0+0+500] [8+0+0 200 0+0+8] children: not-inline BlockContainer at [50,8] [-50+0+0 250 0+0+0] [0+0+0 200 0+0+0] children: inline BlockContainer at [50,8] floating [0+0+0 125 0+0+0] [0+0+0 18 0+0+0] [BFC] children: inline - frag 0 from TextNode start: 1, length: 1, rect: [50,8 9.34375x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 1, rect: [50,8 9.34375x18] baseline: 13.796875 "a" TextNode <#text> (not painted) TextNode <#text> (not painted) BlockContainer at [175,8] floating [0+0+0 125 0+0+0] [0+0+0 18 0+0+0] [BFC] children: inline - frag 0 from TextNode start: 1, length: 1, rect: [175,8 9.46875x18] baseline: 13.796875 + frag 0 from TextNode start: 5, length: 1, rect: [175,8 9.46875x18] baseline: 13.796875 "b" TextNode <#text> (not painted) TextNode <#text> (not painted) diff --git a/Tests/LibWeb/Layout/expected/block-and-inline/narrow-bfc-width-to-avoid-overlap-with-floats.txt b/Tests/LibWeb/Layout/expected/block-and-inline/narrow-bfc-width-to-avoid-overlap-with-floats.txt index 0f673e6ea91..d638bfd0e79 100644 --- a/Tests/LibWeb/Layout/expected/block-and-inline/narrow-bfc-width-to-avoid-overlap-with-floats.txt +++ b/Tests/LibWeb/Layout/expected/block-and-inline/narrow-bfc-width-to-avoid-overlap-with-floats.txt @@ -6,14 +6,22 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [18,18] [0+10+0 564 0+10+0] [0+10+0 90 0+10+0] [BFC] children: inline frag 0 from TextNode start: 0, length: 56, rect: [18,18 458.125x18] baseline: 13.796875 "Lorem ipsum dolor sit amet, consectetur adipiscing elit." - frag 1 from TextNode start: 57, length: 60, rect: [18,36 511.796875x18] baseline: 13.796875 - "Pellentesque vitae neque nunc. Nam fermentum libero a lectus" - frag 2 from TextNode start: 118, length: 67, rect: [18,54 537.078125x18] baseline: 13.796875 - "vulputate eleifend. Nam sagittis tristique augue, id sodales mauris" - frag 3 from TextNode start: 186, length: 65, rect: [18,72 537.34375x18] baseline: 13.796875 - "suscipit at. Vivamus eget placerat ex. Suspendisse potenti. Morbi" - frag 4 from TextNode start: 252, length: 57, rect: [18,90 455.375x18] baseline: 13.796875 - "pulvinar ipsum eget nulla dapibus, ac varius mi eleifend." + frag 1 from TextNode start: 57, length: 19, rect: [18,36 155.203125x18] baseline: 13.796875 + "Pellentesque vitae " + frag 2 from TextNode start: 80, length: 41, rect: [173.203125,36 356.59375x18] baseline: 13.796875 + "neque nunc. Nam fermentum libero a lectus" + frag 3 from TextNode start: 122, length: 33, rect: [18,54 258.640625x18] baseline: 13.796875 + "vulputate eleifend. Nam sagittis " + frag 4 from TextNode start: 159, length: 34, rect: [276.640625,54 278.4375x18] baseline: 13.796875 + "tristique augue, id sodales mauris" + frag 5 from TextNode start: 194, length: 39, rect: [18,72 316.96875x18] baseline: 13.796875 + "suscipit at. Vivamus eget placerat ex. " + frag 6 from TextNode start: 237, length: 26, rect: [334.96875,72 220.375x18] baseline: 13.796875 + "Suspendisse potenti. Morbi" + frag 7 from TextNode start: 264, length: 48, rect: [18,90 392.171875x18] baseline: 13.796875 + "pulvinar ipsum eget nulla dapibus, ac varius mi " + frag 8 from TextNode start: 316, length: 9, rect: [410.171875,90 63.203125x18] baseline: 13.796875 + "eleifend." TextNode <#text> (not painted) ViewportPaintable (Viewport<#document>) [0,0 800x600] overflow: [0,0 800x1008] diff --git a/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt b/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt index b135ee13e87..be2d54e63e8 100644 --- a/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt +++ b/Tests/LibWeb/Layout/expected/display-contents-blockification-of-flex-items.txt @@ -3,14 +3,14 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer at [8,8] [8+0+0 784 0+0+8] [8+0+0 28 0+0+8] children: not-inline Box at [8,8] flex-container(row) [0+0+0 784 0+0+0] [0+0+0 28 0+0+0] [FFC] children: not-inline BlockContainer <(anonymous)> at [8,8] flex-item [0+0+0 24.171875 0+0+0] [0+0+0 28 0+0+0] [BFC] children: inline - frag 0 from TextNode start: 1, length: 3, rect: [8,8 24.171875x18] baseline: 13.796875 + frag 0 from TextNode start: 3, length: 3, rect: [8,8 24.171875x18] baseline: 13.796875 "163" TextNode <#text> (not painted) TextNode <#text> (not painted) BlockContainer at [32.171875,8] flex-item [0+0+0 58.15625 0+0+0] [0+0+0 28 0+0+0] [BFC] children: not-inline Box at [37.171875,13] flex-container(row) [0+5+0 48.15625 0+5+0] [0+5+0 18 0+5+0] [FFC] children: not-inline BlockContainer <(anonymous)> at [37.171875,13] flex-item [0+0+0 48.15625 0+0+0] [0+0+0 18 0+0+0] [BFC] children: inline - frag 0 from TextNode start: 1, length: 5, rect: [37.171875,13 48.15625x18] baseline: 13.796875 + frag 0 from TextNode start: 9, length: 5, rect: [37.171875,13 48.15625x18] baseline: 13.796875 "Share" TextNode <#text> (not painted) TextNode <#text> (not painted) diff --git a/Tests/LibWeb/Layout/expected/div_align_nested.txt b/Tests/LibWeb/Layout/expected/div_align_nested.txt index 679ed108245..610eee995af 100644 --- a/Tests/LibWeb/Layout/expected/div_align_nested.txt +++ b/Tests/LibWeb/Layout/expected/div_align_nested.txt @@ -11,9 +11,9 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- TextNode <#text> (not painted) BlockContainer
at [8,126] [0+0+0 784 0+0+0] [0+0+0 136 0+0+0] children: not-inline BlockContainer <(anonymous)> at [8,126] [0+0+0 784 0+0+0] [0+0+0 36 0+0+0] children: inline - frag 0 from TextNode start: 1, length: 87, rect: [8,126 711.4375x18] baseline: 13.796875 + frag 0 from TextNode start: 9, length: 87, rect: [8,126 711.4375x18] baseline: 13.796875 "This text and the green square are both left aligned despite being nested in a div with" - frag 1 from TextNode start: 89, length: 14, rect: [8,144 94.296875x18] baseline: 13.796875 + frag 1 from TextNode start: 97, length: 14, rect: [8,144 94.296875x18] baseline: 13.796875 "align="right":" TextNode <#text> (not painted) BlockContainer at [8,162] [0+0+0 100 0+0+684] [0+0+0 100 0+0+0] children: inline diff --git a/Tests/LibWeb/Layout/expected/flex/flex-item-with-percentage-width-in-flex-container-with-definite-max-width.txt b/Tests/LibWeb/Layout/expected/flex/flex-item-with-percentage-width-in-flex-container-with-definite-max-width.txt index 6aa7d272bb1..ba0722ab66c 100644 --- a/Tests/LibWeb/Layout/expected/flex/flex-item-with-percentage-width-in-flex-container-with-definite-max-width.txt +++ b/Tests/LibWeb/Layout/expected/flex/flex-item-with-percentage-width-in-flex-container-with-definite-max-width.txt @@ -7,7 +7,7 @@ Viewport <#document> at [0,0] [0+0+0 800 0+0+0] [0+0+0 600 0+0+0] children: not- BlockContainer