Quellcode durchsuchen

LibWeb: Store bottom edge location with each LineBox

Previously we were computing the bottom edge of a line box by finding
the bottommost fragment on the line.

That method didn't give correct results for line boxes with no fragments
(which is exactly what you get when inserting a bunch of <br> elements.)

To cover all situations, we now keep track of the bottommost edge in the
LineBox object itself.
Andreas Kling vor 3 Jahren
Ursprung
Commit
c6cf240f9a

+ 3 - 2
Userland/Libraries/LibWeb/Dump.cpp

@@ -229,11 +229,12 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho
             auto& line_box = block.line_boxes()[line_box_index];
             for (size_t i = 0; i < indent; ++i)
                 builder.append("  ");
-            builder.appendff("  {}line {}{} width: {}\n",
+            builder.appendff("  {}line {}{} width: {}, bottom: {}\n",
                 line_box_color_on,
                 line_box_index,
                 color_off,
-                (int)line_box.width());
+                line_box.width(),
+                line_box.bottom());
             for (size_t fragment_index = 0; fragment_index < line_box.fragments().size(); ++fragment_index) {
                 auto& fragment = line_box.fragments()[fragment_index];
                 for (size_t i = 0; i < indent; ++i)

+ 1 - 5
Userland/Libraries/LibWeb/Layout/FormattingContext.cpp

@@ -225,11 +225,7 @@ float FormattingContext::compute_auto_height_for_block_level_element(FormattingS
                     top = fragment_top;
             }
             // Find the bottom edge.
-            for (auto const& fragment : line_boxes.last().fragments()) {
-                float fragment_bottom = fragment.offset().y() + fragment.height() + fragment.border_box_bottom();
-                if (!bottom.has_value() || fragment_bottom > *bottom)
-                    bottom = fragment_bottom;
-            }
+            bottom = line_boxes.last().bottom();
         }
     } else {
         // If it has block-level children, the height is the distance between

+ 2 - 0
Userland/Libraries/LibWeb/Layout/LineBox.h

@@ -16,6 +16,7 @@ public:
     LineBox() { }
 
     float width() const { return m_width; }
+    float bottom() const { return m_bottom; }
 
     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);
 
@@ -34,6 +35,7 @@ private:
 
     Vector<LineBoxFragment> m_fragments;
     float m_width { 0 };
+    float m_bottom { 0 };
 };
 
 }

+ 5 - 1
Userland/Libraries/LibWeb/Layout/LineBuilder.cpp

@@ -96,7 +96,7 @@ void LineBuilder::update_last_line()
 
     auto text_align = m_context.containing_block().computed_values().text_align();
     float x_offset = m_context.available_space_for_line(m_current_y).left;
-
+    float bottom = m_current_y + m_context.containing_block().line_height();
     float excess_horizontal_space = m_containing_block_state.content_width - line_box.width();
 
     switch (text_align) {
@@ -175,6 +175,8 @@ void LineBuilder::update_last_line()
         last_fragment_x_adjustment = new_fragment_x - fragment.offset().x();
         fragment.set_offset({ new_fragment_x, new_fragment_y });
 
+        bottom = max(bottom, new_fragment_y + fragment.height() + fragment.border_box_bottom());
+
         if (text_align == CSS::TextAlign::Justify
             && fragment.is_justifiable_whitespace()
             && fragment.width() != justified_space_width) {
@@ -191,6 +193,8 @@ void LineBuilder::update_last_line()
 
     if (!line_box.fragments().is_empty())
         line_box.m_width += last_fragment_x_adjustment;
+
+    line_box.m_bottom = bottom;
 }
 
 void LineBuilder::remove_last_line_if_empty()