LibWeb: Add border box top/bottom metrics to line box fragments

This will allow us to support more kinds of vertical alignment.
This commit is contained in:
Andreas Kling 2022-02-26 09:24:40 +01:00
parent 8b369bf7bd
commit 797f51e122
Notes: sideshowbarker 2024-07-17 18:15:26 +09:00
6 changed files with 22 additions and 10 deletions

View File

@ -219,8 +219,12 @@ float FormattingContext::compute_auto_height_for_block_level_element(FormattingS
top = 0; top = 0;
if (!line_boxes.is_empty()) { if (!line_boxes.is_empty()) {
for (auto& fragment : line_boxes.last().fragments()) { for (auto& fragment : line_boxes.last().fragments()) {
if (!bottom.has_value() || (fragment.offset().y() + fragment.height()) > bottom.value()) float fragment_top = fragment.offset().y() - fragment.border_box_top();
bottom = fragment.offset().y() + fragment.height(); 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 { } else {

View File

@ -90,7 +90,7 @@ void InlineFormattingContext::run(Box const&, LayoutMode layout_mode)
for (auto& line_box : m_state.get(containing_block()).line_boxes) { for (auto& line_box : m_state.get(containing_block()).line_boxes) {
float max_height = min_line_height; float max_height = min_line_height;
for (auto& fragment : line_box.fragments()) { 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()); max_line_width = max(max_line_width, line_box.width());
content_height += max_height; content_height += max_height;

View File

@ -15,7 +15,7 @@
namespace Web::Layout { 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; 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) { 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().m_length = (start - m_fragments.last().m_start) + length;
m_fragments.last().set_width(m_fragments.last().width() + content_width); m_fragments.last().set_width(m_fragments.last().width() + content_width);
} else { } else {
m_fragments.append(make<LineBoxFragment>(layout_node, start, length, Gfx::FloatPoint(m_width + leading_size, 0.0f), Gfx::FloatSize(content_width, content_height), fragment_type)); m_fragments.append(make<LineBoxFragment>(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; m_width += content_width + leading_size + trailing_size;

View File

@ -18,7 +18,7 @@ public:
float width() const { return m_width; } 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<LineBoxFragment>& fragments() const { return m_fragments; } const NonnullOwnPtrVector<LineBoxFragment>& fragments() const { return m_fragments; }
NonnullOwnPtrVector<LineBoxFragment>& fragments() { return m_fragments; } NonnullOwnPtrVector<LineBoxFragment>& fragments() { return m_fragments; }

View File

@ -23,12 +23,14 @@ public:
Trailing, 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_layout_node(layout_node)
, m_start(start) , m_start(start)
, m_length(length) , m_length(length)
, m_offset(offset) , m_offset(offset)
, m_size(size) , m_size(size)
, m_border_box_top(border_box_top)
, m_border_box_bottom(border_box_bottom)
, m_type(type) , m_type(type)
{ {
} }
@ -48,6 +50,10 @@ public:
float width() const { return m_size.width(); } float width() const { return m_size.width(); }
float height() const { return m_size.height(); } 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(); } float absolute_x() const { return absolute_rect().x(); }
void paint(PaintContext&, PaintPhase); void paint(PaintContext&, PaintPhase);
@ -66,6 +72,8 @@ private:
int m_length { 0 }; int m_length { 0 };
Gfx::FloatPoint m_offset; Gfx::FloatPoint m_offset;
Gfx::FloatSize m_size; Gfx::FloatSize m_size;
float m_border_box_top { 0 };
float m_border_box_bottom { 0 };
Type m_type { Type::Normal }; Type m_type { Type::Normal };
}; };

View File

@ -52,13 +52,13 @@ LineBox& LineBuilder::ensure_last_line_box()
void LineBuilder::append_box(Box const& box, float leading_size, float trailing_size) void LineBuilder::append_box(Box const& box, float leading_size, float trailing_size)
{ {
auto const& box_state = m_formatting_state.get(box); 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); 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) 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); 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()) { for (auto& fragment : line_box.fragments()) {
float fragment_baseline; float fragment_baseline;
if (fragment.layout_node().is_box()) { if (fragment.layout_node().is_box()) {
fragment_baseline = m_formatting_state.get(static_cast<Box const&>(fragment.layout_node())).content_height; fragment_baseline = m_formatting_state.get(static_cast<Box const&>(fragment.layout_node())).border_box_height();
} else { } else {
float font_baseline = fragment.layout_node().font().baseline(); float font_baseline = fragment.layout_node().font().baseline();
fragment_baseline = (max_height / 2.0f) + (font_baseline / 2.0f); fragment_baseline = (max_height / 2.0f) + (font_baseline / 2.0f);