diff --git a/Tests/LibWeb/Layout/expected/inline-box-with-vertical-margins-vertical-align-top.txt b/Tests/LibWeb/Layout/expected/inline-box-with-vertical-margins-vertical-align-top.txt new file mode 100644 index 0000000000..c15b1aeece --- /dev/null +++ b/Tests/LibWeb/Layout/expected/inline-box-with-vertical-margins-vertical-align-top.txt @@ -0,0 +1,12 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x191 children: not-inline + BlockContainer at (8,8) content-size 784x175 children: inline + line 0 width: 210.828125, height: 175, bottom: 175, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 6, rect: [8,8 43.125x17.46875] + "Well, " + frag 1 from BlockContainer start: 0, length: 0, rect: [51,58 100x100] + frag 2 from TextNode start: 0, length: 9, rect: [151,8 67.703125x17.46875] + " friends." + TextNode <#text> + BlockContainer at (51,58) content-size 100x100 inline-block children: not-inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/inline-box-with-vertical-margins.txt b/Tests/LibWeb/Layout/expected/inline-box-with-vertical-margins.txt new file mode 100644 index 0000000000..cb06afebbd --- /dev/null +++ b/Tests/LibWeb/Layout/expected/inline-box-with-vertical-margins.txt @@ -0,0 +1,12 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x194.46875 children: not-inline + BlockContainer at (8,8) content-size 784x178.46875 children: inline + line 0 width: 210.828125, height: 178.46875, bottom: 178.46875, baseline: 175 + frag 0 from TextNode start: 0, length: 6, rect: [8,169 43.125x17.46875] + "Well, " + frag 1 from BlockContainer start: 0, length: 0, rect: [51,58 100x100] + frag 2 from TextNode start: 0, length: 9, rect: [151,169 67.703125x17.46875] + " friends." + TextNode <#text> + BlockContainer at (51,58) content-size 100x100 inline-block children: not-inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/expected/replaced-box-with-vertical-margins.txt b/Tests/LibWeb/Layout/expected/replaced-box-with-vertical-margins.txt new file mode 100644 index 0000000000..40d4e4c77e --- /dev/null +++ b/Tests/LibWeb/Layout/expected/replaced-box-with-vertical-margins.txt @@ -0,0 +1,12 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (0,0) content-size 800x232.46875 children: not-inline + BlockContainer at (8,8) content-size 784x216.46875 children: inline + line 0 width: 174.828125, height: 216.46875, bottom: 216.46875, baseline: 213 + frag 0 from TextNode start: 0, length: 6, rect: [8,207 43.125x17.46875] + "Well, " + frag 1 from ImageBox start: 0, length: 0, rect: [51,33 64x138] + frag 2 from TextNode start: 0, length: 9, rect: [115,207 67.703125x17.46875] + " friends." + TextNode <#text> + ImageBox at (51,33) content-size 64x138 children: not-inline + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/buggie.png b/Tests/LibWeb/Layout/input/buggie.png new file mode 100644 index 0000000000..94558bd2d3 Binary files /dev/null and b/Tests/LibWeb/Layout/input/buggie.png differ diff --git a/Tests/LibWeb/Layout/input/inline-box-with-vertical-margins-vertical-align-top.html b/Tests/LibWeb/Layout/input/inline-box-with-vertical-margins-vertical-align-top.html new file mode 100644 index 0000000000..c29aa6a08b --- /dev/null +++ b/Tests/LibWeb/Layout/input/inline-box-with-vertical-margins-vertical-align-top.html @@ -0,0 +1,16 @@ +Well,
friends. \ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/inline-box-with-vertical-margins.html b/Tests/LibWeb/Layout/input/inline-box-with-vertical-margins.html new file mode 100644 index 0000000000..5d97907368 --- /dev/null +++ b/Tests/LibWeb/Layout/input/inline-box-with-vertical-margins.html @@ -0,0 +1,15 @@ +Well,
friends. \ No newline at end of file diff --git a/Tests/LibWeb/Layout/input/replaced-box-with-vertical-margins.html b/Tests/LibWeb/Layout/input/replaced-box-with-vertical-margins.html new file mode 100644 index 0000000000..eddf1d5c29 --- /dev/null +++ b/Tests/LibWeb/Layout/input/replaced-box-with-vertical-margins.html @@ -0,0 +1,10 @@ +Well, friends. \ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index a430dfe5ba..0daee83ab7 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -110,7 +110,7 @@ CSSPixels box_baseline(LayoutState const& state, Box const& box) return box_state.border_box_top(); case CSS::VerticalAlign::Bottom: // Bottom: Align the bottom of the aligned subtree with the bottom of the line box. - return box_state.content_height() + box_state.border_box_bottom(); + return box_state.content_height() + box_state.margin_box_top(); case CSS::VerticalAlign::TextTop: // TextTop: Align the top of the box with the top of the parent's content area (see 10.6.1). return box.computed_values().font_size(); @@ -123,13 +123,13 @@ CSSPixels box_baseline(LayoutState const& state, Box const& box) } if (!box_state.line_boxes.is_empty()) - return box_state.border_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline(); + return box_state.margin_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline(); if (box.has_children() && !box.children_are_inline()) { auto const* child_box = box.last_child_of_type(); VERIFY(child_box); return box_baseline(state, *child_box); } - return box_state.border_box_height(); + return box_state.margin_box_height(); } CSSPixelRect margin_box_rect(Box const& box, LayoutState const& state) diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp index d040ce45d1..b617c00610 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp @@ -149,4 +149,9 @@ CSSPixelRect LineBoxFragment::selection_rect(Gfx::Font const& font) const return {}; } +bool LineBoxFragment::is_atomic_inline() const +{ + return layout_node().is_replaced_box() || (layout_node().display().is_inline_outside() && !layout_node().display().is_flow_inside()); +} + } diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h index b8566b57f5..26d96a5bbc 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -76,6 +76,8 @@ public: CSSPixelRect selection_rect(Gfx::Font const&) const; + bool is_atomic_inline() const; + private: Node const& m_layout_node; int m_start { 0 }; diff --git a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp index 89b735d208..b09adc0fe7 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -78,7 +78,7 @@ 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()); - m_max_height_on_current_line = max(m_max_height_on_current_line, box_state.border_box_height()); + 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 { .line_box_index = m_containing_block_state.line_boxes.size() - 1, @@ -235,11 +235,17 @@ void LineBuilder::update_last_line() CSSPixels new_fragment_y = 0; auto y_value_for_alignment = [&](CSS::VerticalAlign vertical_align) { + CSSPixels effective_box_top = fragment.border_box_top(); + if (fragment.is_atomic_inline()) { + auto const& fragment_box_state = m_layout_state.get(static_cast(fragment.layout_node())); + effective_box_top = fragment_box_state.margin_box_top(); + } + switch (vertical_align) { case CSS::VerticalAlign::Baseline: - return m_current_y + line_box_baseline - fragment.baseline() + fragment.border_box_top(); + return m_current_y + line_box_baseline - fragment.baseline() + effective_box_top; case CSS::VerticalAlign::Top: - return m_current_y + fragment.border_box_top(); + return m_current_y + effective_box_top; case CSS::VerticalAlign::Middle: case CSS::VerticalAlign::Bottom: case CSS::VerticalAlign::Sub: @@ -247,7 +253,7 @@ void LineBuilder::update_last_line() case CSS::VerticalAlign::TextBottom: case CSS::VerticalAlign::TextTop: // FIXME: These are all 'baseline' - return m_current_y + line_box_baseline - fragment.baseline() + fragment.border_box_top(); + return m_current_y + line_box_baseline - fragment.baseline() + effective_box_top; } VERIFY_NOT_REACHED(); }; @@ -268,7 +274,7 @@ void LineBuilder::update_last_line() CSSPixels bottom_of_inline_box = 0; { // FIXME: Support inline-table elements. - if (fragment.layout_node().is_replaced_box() || (fragment.layout_node().display().is_inline_outside() && !fragment.layout_node().display().is_flow_inside())) { + if (fragment.is_atomic_inline()) { auto const& fragment_box_state = m_layout_state.get(static_cast(fragment.layout_node())); top_of_inline_box = (fragment.offset().y() - fragment_box_state.margin_box_top()); bottom_of_inline_box = (fragment.offset().y() + fragment_box_state.content_height() + fragment_box_state.margin_box_bottom());