Ver Fonte

LibWeb: Don't do horizontal inline line layout twice for last line

After pruning empty last line boxes, we now avoid re-running the
horizontal fragment positioning step, since that would be wasted work.
Andreas Kling há 3 anos atrás
pai
commit
70a56d21dc

+ 1 - 3
Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp

@@ -201,9 +201,7 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode)
         line_box.trim_trailing_whitespace();
         line_box.trim_trailing_whitespace();
     }
     }
 
 
-    // If there's an empty line box at the bottom, just remove it instead of giving it height.
-    if (!containing_block().line_boxes().is_empty() && containing_block().line_boxes().last().fragments().is_empty())
-        containing_block().line_boxes().take_last();
+    line_builder.remove_last_line_if_empty();
 }
 }
 
 
 }
 }

+ 1 - 1
Userland/Libraries/LibWeb/Layout/LineBox.h

@@ -26,7 +26,7 @@ public:
     void trim_trailing_whitespace();
     void trim_trailing_whitespace();
 
 
     bool is_empty_or_ends_in_whitespace() const;
     bool is_empty_or_ends_in_whitespace() const;
-    bool is_empty() { return m_fragments.is_empty(); }
+    bool is_empty() const { return m_fragments.is_empty(); }
     bool ends_with_forced_line_break() const;
     bool ends_with_forced_line_break() const;
 
 
 private:
 private:

+ 21 - 4
Userland/Libraries/LibWeb/Layout/LineBuilder.cpp

@@ -12,11 +12,13 @@ namespace Web::Layout {
 LineBuilder::LineBuilder(InlineFormattingContext& context)
 LineBuilder::LineBuilder(InlineFormattingContext& context)
     : m_context(context)
     : m_context(context)
 {
 {
+    begin_new_line();
 }
 }
 
 
 LineBuilder::~LineBuilder()
 LineBuilder::~LineBuilder()
 {
 {
-    update_last_line();
+    if (m_last_line_needs_update)
+        update_last_line();
 }
 }
 
 
 void LineBuilder::break_line()
 void LineBuilder::break_line()
@@ -32,6 +34,8 @@ void LineBuilder::begin_new_line()
     auto space = m_context.available_space_for_line(m_current_y);
     auto space = m_context.available_space_for_line(m_current_y);
     m_available_width_for_current_line = space.right - space.left;
     m_available_width_for_current_line = space.right - space.left;
     m_max_height_on_current_line = 0;
     m_max_height_on_current_line = 0;
+
+    m_last_line_needs_update = true;
 }
 }
 
 
 void LineBuilder::append_box(Box& box)
 void LineBuilder::append_box(Box& box)
@@ -54,14 +58,17 @@ bool LineBuilder::should_break(LayoutMode layout_mode, float next_item_width, bo
         return true;
         return true;
     if (layout_mode == LayoutMode::OnlyRequiredLineBreaks)
     if (layout_mode == LayoutMode::OnlyRequiredLineBreaks)
         return false;
         return false;
-    auto current_line_width = 0.0f;
-    if (!m_context.containing_block().line_boxes().is_empty())
-        current_line_width = m_context.containing_block().line_boxes().last().width();
+    auto const& line_boxes = m_context.containing_block().line_boxes();
+    if (line_boxes.is_empty() || line_boxes.last().is_empty())
+        return false;
+    auto current_line_width = m_context.containing_block().line_boxes().last().width();
     return (current_line_width + next_item_width) > m_available_width_for_current_line;
     return (current_line_width + next_item_width) > m_available_width_for_current_line;
 }
 }
 
 
 void LineBuilder::update_last_line()
 void LineBuilder::update_last_line()
 {
 {
+    m_last_line_needs_update = false;
+
     if (m_context.containing_block().line_boxes().is_empty())
     if (m_context.containing_block().line_boxes().is_empty())
         return;
         return;
 
 
@@ -144,4 +151,14 @@ void LineBuilder::update_last_line()
     }
     }
 }
 }
 
 
+void LineBuilder::remove_last_line_if_empty()
+{
+    // If there's an empty line box at the bottom, just remove it instead of giving it height.
+    auto& line_boxes = m_context.containing_block().line_boxes();
+    if (!line_boxes.is_empty() && line_boxes.last().fragments().is_empty()) {
+        line_boxes.take_last();
+        m_last_line_needs_update = false;
+    }
+}
+
 }
 }

+ 4 - 0
Userland/Libraries/LibWeb/Layout/LineBuilder.h

@@ -33,6 +33,8 @@ public:
 
 
     void update_last_line();
     void update_last_line();
 
 
+    void remove_last_line_if_empty();
+
 private:
 private:
     bool should_break(LayoutMode, float next_item_width, bool should_force_break);
     bool should_break(LayoutMode, float next_item_width, bool should_force_break);
 
 
@@ -40,6 +42,8 @@ private:
     float m_available_width_for_current_line { 0 };
     float m_available_width_for_current_line { 0 };
     float m_current_y { 0 };
     float m_current_y { 0 };
     float m_max_height_on_current_line { 0 };
     float m_max_height_on_current_line { 0 };
+
+    bool m_last_line_needs_update { false };
 };
 };
 
 
 }
 }