[LFC][IFC] Do not construct a dedicated run for the trailing (fully) collapsed whitespace.
https://bugs.webkit.org/show_bug.cgi?id=206428
<rdar://problem/58687058>

Reviewed by Antti Koivisto.

This patch reduces the final run count on a line from 2 to 1 in the common cases where the line ends in a collapsed trailing whitespace.
~3% progression on PerformanceTests/Layout/line-layout-simple.html.

* layout/inlineformatting/InlineFormattingContextQuirks.cpp:
(WebCore::Layout::InlineFormattingContext::Quirks::lineDescentNeedsCollapsing const):
* layout/inlineformatting/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::ContinuousContent::isEligible const):
(WebCore::Layout::LineBuilder::ContinuousContent::expand):
(WebCore::Layout::LineBuilder::close):
(WebCore::Layout::LineBuilder::alignContentVertically):
(WebCore::Layout::LineBuilder::runContentHeight const):
(WebCore::Layout::LineBuilder::CollapsibleContent::collapse):
(WebCore::Layout::LineBuilder::ContinuousContent::append): Deleted.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254780 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c71ff6c..b610920 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,25 @@
+2020-01-17  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Do not construct a dedicated run for the trailing (fully) collapsed whitespace.
+        https://bugs.webkit.org/show_bug.cgi?id=206428
+        <rdar://problem/58687058>
+
+        Reviewed by Antti Koivisto.
+
+        This patch reduces the final run count on a line from 2 to 1 in the common cases where the line ends in a collapsed trailing whitespace. 
+        ~3% progression on PerformanceTests/Layout/line-layout-simple.html.
+
+        * layout/inlineformatting/InlineFormattingContextQuirks.cpp:
+        (WebCore::Layout::InlineFormattingContext::Quirks::lineDescentNeedsCollapsing const):
+        * layout/inlineformatting/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineBuilder::ContinuousContent::isEligible const):
+        (WebCore::Layout::LineBuilder::ContinuousContent::expand):
+        (WebCore::Layout::LineBuilder::close):
+        (WebCore::Layout::LineBuilder::alignContentVertically):
+        (WebCore::Layout::LineBuilder::runContentHeight const):
+        (WebCore::Layout::LineBuilder::CollapsibleContent::collapse):
+        (WebCore::Layout::LineBuilder::ContinuousContent::append): Deleted.
+
 2020-01-17  Matt Lewis  <jlewis3@apple.com>
 
         Unreviewed, rolling out r254564.
diff --git a/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp b/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp
index 0896972..054b5dc4 100644
--- a/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp
@@ -47,13 +47,15 @@
         if (run.isContainerEnd() || layoutBox.style().verticalAlign() != VerticalAlign::Baseline)
             continue;
 
-        if (run.isLineBreak())
-            return false;
         if (run.isText()) {
             if (!run.isCollapsedToVisuallyEmpty())
                 return false;
             continue;
         }
+
+        if (run.isLineBreak())
+            return false;
+
         if (run.isContainerStart()) {
             auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
             if (boxGeometry.horizontalBorder() || (boxGeometry.horizontalPadding() && boxGeometry.horizontalPadding().value()))
diff --git a/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp b/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp
index 7abf426..478f484 100644
--- a/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp
+++ b/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp
@@ -69,7 +69,7 @@
     ContinuousContent(const InlineItemRun&, bool textIsAlignJustify);
 
     bool isEligible(const InlineItemRun&) const;
-    void append(const InlineItemRun&);
+    void expand(const InlineItemRun&);
     LineBuilder::Run close();
 
     static bool canInlineItemRunBeExpanded(const InlineItemRun& run) { return run.isText() && !run.isCollapsed() && !run.isCollapsedToZeroAdvanceWidth(); }
@@ -96,18 +96,18 @@
 {
     if (!m_trailingRunCanBeExpanded)
         return false;
-    // Only non-collapsed text runs with the same layout box can be added as continuous content.
-    return inlineItemRun.isText() && !inlineItemRun.isCollapsedToZeroAdvanceWidth() && &m_initialInlineRun.layoutBox() == &inlineItemRun.layoutBox();
+    return inlineItemRun.isText() && &m_initialInlineRun.layoutBox() == &inlineItemRun.layoutBox();
 }
 
-void LineBuilder::ContinuousContent::append(const InlineItemRun& inlineItemRun)
+void LineBuilder::ContinuousContent::expand(const InlineItemRun& inlineItemRun)
 {
     // Merged content needs to be continuous.
     ASSERT(isEligible(inlineItemRun));
     m_trailingRunCanBeExpanded = canInlineItemRunBeExpanded(inlineItemRun);
 
     ASSERT(inlineItemRun.isText());
-    m_expandedLength += inlineItemRun.textContext()->length();
+    if (!inlineItemRun.isCollapsedToZeroAdvanceWidth())
+        m_expandedLength += inlineItemRun.textContext()->length();
     m_expandedWidth += inlineItemRun.logicalWidth();
 
     if (m_collectExpansionOpportunities) {
@@ -238,8 +238,7 @@
     visuallyCollapsePreWrapOverflowContent();
     auto hangingContent = collectHangingContent(isLastLineWithInlineContent);
 
-    auto mergedInlineItemRuns = [&] {
-        RunList runList;
+    auto mergedInlineItemRuns = [&] (auto& runList) {
         unsigned runIndex = 0;
         while (runIndex < m_inlineItemRuns.size()) {
             // Merge eligible runs.
@@ -251,13 +250,13 @@
             }
             auto mergedRuns = ContinuousContent { inlineItemRun, isTextAlignJustify() };
             for (runIndex = runIndex + 1; runIndex < m_inlineItemRuns.size() && mergedRuns.isEligible(m_inlineItemRuns[runIndex]); ++runIndex)
-                mergedRuns.append(m_inlineItemRuns[runIndex]);
+                mergedRuns.expand(m_inlineItemRuns[runIndex]);
             runList.append(mergedRuns.close());
         }
-        return runList;
     };
 
-    auto runList = mergedInlineItemRuns();
+    RunList runList;
+    mergedInlineItemRuns(runList);
     if (!m_isIntrinsicSizing) {
         for (auto& run : runList) {
             adjustBaselineAndLineHeight(run);
@@ -346,7 +345,7 @@
 
         switch (verticalAlign) {
         case VerticalAlign::Baseline:
-            if (run.isLineBreak() || run.isText())
+            if (run.isText() || run.isLineBreak())
                 logicalTop = baselineOffset() - ascent;
             else if (run.isContainerStart()) {
                 auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
@@ -791,7 +790,7 @@
     ASSERT_NOT_REACHED();
 }
 
-InlineLayoutUnit LineBuilder::runContentHeight(const Run& run) const
+inline InlineLayoutUnit LineBuilder::runContentHeight(const Run& run) const
 {
     ASSERT(!m_isIntrinsicSizing);
     auto& fontMetrics = run.style().fontMetrics();
@@ -901,14 +900,10 @@
     for (auto index = *m_firstRunIndex; index < m_inlineitemRunList.size(); ++index) {
         auto& run = m_inlineitemRunList[index];
         run.moveHorizontally(-accumulatedCollapsedWidth);
-        if (!run.isText()) {
-            ASSERT(run.isContainerStart() || run.isContainerEnd() || run.isLineBreak());
-            continue;
-        }
         if (run.isWhitespace()) {
             accumulatedCollapsedWidth += run.logicalWidth();
             run.setCollapsesToZeroAdvanceWidth();
-        } else {
+        } else if (run.isText()) {
             ASSERT(!hasSeenNonWhitespaceTextContent);
 #if ASSERT_ENABLED
             hasSeenNonWhitespaceTextContent = true;
@@ -918,6 +913,7 @@
             accumulatedCollapsedWidth += run.trailingLetterSpacing();
             run.removeTrailingLetterSpacing();
         }
+        ASSERT(run.isContainerStart() || run.isContainerEnd() || run.isLineBreak());
     }
     ASSERT(accumulatedCollapsedWidth == width());
     reset();