From 797f51e1227a00a22531ca1bd945659c21a242ca Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 26 Feb 2022 09:24:40 +0100 Subject: [PATCH] LibWeb: Add border box top/bottom metrics to line box fragments This will allow us to support more kinds of vertical alignment. --- Userland/Libraries/LibWeb/Layout/FormattingContext.cpp | 8 ++++++-- .../LibWeb/Layout/InlineFormattingContext.cpp | 2 +- Userland/Libraries/LibWeb/Layout/LineBox.cpp | 4 ++-- Userland/Libraries/LibWeb/Layout/LineBox.h | 2 +- Userland/Libraries/LibWeb/Layout/LineBoxFragment.h | 10 +++++++++- Userland/Libraries/LibWeb/Layout/LineBuilder.cpp | 6 +++--- 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index 493c7496a19..dad0af1697d 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -219,8 +219,12 @@ float FormattingContext::compute_auto_height_for_block_level_element(FormattingS top = 0; if (!line_boxes.is_empty()) { for (auto& fragment : line_boxes.last().fragments()) { - if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value()) - bottom = fragment.offset().y() + fragment.height(); + float fragment_top = fragment.offset().y() - fragment.border_box_top(); + if (!top.has_value() || fragment_top < *top) + top = fragment_top; + float fragment_bottom = fragment.offset().y() + fragment.height() + fragment.border_box_bottom(); + if (!bottom.has_value() || fragment_bottom > *bottom) + bottom = fragment_bottom; } } } else { diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index 69922f368e6..3e4f0dd2858 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -90,7 +90,7 @@ void InlineFormattingContext::run(Box const&, LayoutMode layout_mode) for (auto& line_box : m_state.get(containing_block()).line_boxes) { float max_height = min_line_height; for (auto& fragment : line_box.fragments()) { - max_height = max(max_height, fragment.height()); + max_height = max(max_height, fragment.border_box_height()); } max_line_width = max(max_line_width, line_box.width()); content_height += max_height; diff --git a/Userland/Libraries/LibWeb/Layout/LineBox.cpp b/Userland/Libraries/LibWeb/Layout/LineBox.cpp index 330ace7f9ed..3152a43dd89 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBox.cpp @@ -15,7 +15,7 @@ namespace Web::Layout { -void LineBox::add_fragment(Node const& layout_node, int start, int length, float leading_size, float trailing_size, float content_width, float content_height, LineBoxFragment::Type fragment_type) +void LineBox::add_fragment(Node const& layout_node, int start, int length, float leading_size, float trailing_size, float content_width, float content_height, float border_box_top, float border_box_bottom, LineBoxFragment::Type fragment_type) { bool text_align_is_justify = layout_node.computed_values().text_align() == CSS::TextAlign::Justify; if (!text_align_is_justify && !m_fragments.is_empty() && &m_fragments.last().layout_node() == &layout_node) { @@ -24,7 +24,7 @@ void LineBox::add_fragment(Node const& layout_node, int start, int length, float m_fragments.last().m_length = (start - m_fragments.last().m_start) + length; m_fragments.last().set_width(m_fragments.last().width() + content_width); } else { - m_fragments.append(make(layout_node, start, length, Gfx::FloatPoint(m_width + leading_size, 0.0f), Gfx::FloatSize(content_width, content_height), fragment_type)); + m_fragments.append(make(layout_node, start, length, Gfx::FloatPoint(m_width + leading_size, 0.0f), Gfx::FloatSize(content_width, content_height), border_box_top, border_box_bottom, fragment_type)); } m_width += content_width + leading_size + trailing_size; diff --git a/Userland/Libraries/LibWeb/Layout/LineBox.h b/Userland/Libraries/LibWeb/Layout/LineBox.h index ca6156091f8..b4787472903 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBox.h +++ b/Userland/Libraries/LibWeb/Layout/LineBox.h @@ -18,7 +18,7 @@ public: float width() const { return m_width; } - void add_fragment(Node const& layout_node, int start, int length, float leading_size, float trailing_size, float content_width, float content_height, LineBoxFragment::Type = LineBoxFragment::Type::Normal); + void add_fragment(Node const& layout_node, int start, int length, float leading_size, float trailing_size, float content_width, float content_height, float border_box_top, float border_box_bottom, LineBoxFragment::Type = LineBoxFragment::Type::Normal); const NonnullOwnPtrVector& fragments() const { return m_fragments; } NonnullOwnPtrVector& fragments() { return m_fragments; } diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h index 6d9d72338ee..1b042ddc392 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -23,12 +23,14 @@ public: Trailing, }; - LineBoxFragment(Node const& layout_node, int start, int length, const Gfx::FloatPoint& offset, const Gfx::FloatSize& size, Type type) + LineBoxFragment(Node const& layout_node, int start, int length, Gfx::FloatPoint const& offset, Gfx::FloatSize const& size, float border_box_top, float border_box_bottom, Type type) : m_layout_node(layout_node) , m_start(start) , m_length(length) , m_offset(offset) , m_size(size) + , m_border_box_top(border_box_top) + , m_border_box_bottom(border_box_bottom) , m_type(type) { } @@ -48,6 +50,10 @@ public: float width() const { return m_size.width(); } float height() const { return m_size.height(); } + float border_box_height() const { return m_border_box_top + height() + m_border_box_bottom; } + float border_box_top() const { return m_border_box_top; } + float border_box_bottom() const { return m_border_box_bottom; } + float absolute_x() const { return absolute_rect().x(); } void paint(PaintContext&, PaintPhase); @@ -66,6 +72,8 @@ private: int m_length { 0 }; Gfx::FloatPoint m_offset; Gfx::FloatSize m_size; + float m_border_box_top { 0 }; + float m_border_box_bottom { 0 }; Type m_type { Type::Normal }; }; diff --git a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp index 3e1c3d8d36c..9d4b412a210 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -52,13 +52,13 @@ LineBox& LineBuilder::ensure_last_line_box() void LineBuilder::append_box(Box const& box, float leading_size, float trailing_size) { auto const& box_state = m_formatting_state.get(box); - ensure_last_line_box().add_fragment(box, 0, 0, leading_size, trailing_size, box_state.content_width, box_state.content_height); + ensure_last_line_box().add_fragment(box, 0, 0, leading_size, trailing_size, 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.content_height); } void LineBuilder::append_text_chunk(TextNode const& text_node, size_t offset_in_node, size_t length_in_node, float leading_size, float trailing_size, float content_width, float content_height) { - ensure_last_line_box().add_fragment(text_node, offset_in_node, length_in_node, leading_size, trailing_size, content_width, content_height); + ensure_last_line_box().add_fragment(text_node, offset_in_node, length_in_node, leading_size, trailing_size, content_width, content_height, 0, 0); m_max_height_on_current_line = max(m_max_height_on_current_line, content_height); } @@ -127,7 +127,7 @@ void LineBuilder::update_last_line() for (auto& fragment : line_box.fragments()) { float fragment_baseline; if (fragment.layout_node().is_box()) { - fragment_baseline = m_formatting_state.get(static_cast(fragment.layout_node())).content_height; + fragment_baseline = m_formatting_state.get(static_cast(fragment.layout_node())).border_box_height(); } else { float font_baseline = fragment.layout_node().font().baseline(); fragment_baseline = (max_height / 2.0f) + (font_baseline / 2.0f);