Only construct ComplexLineLayout when needed
https://bugs.webkit.org/show_bug.cgi?id=200625

Reviewed by Zalan Bujtas.

* rendering/ComplexLineLayout.cpp:
(WebCore::ComplexLineLayout::createInlineBoxForRenderer):
(WebCore::ComplexLineLayout::createLineBoxes):
(WebCore::ComplexLineLayout::constructLine):
(WebCore::ComplexLineLayout::updateLogicalWidthForAlignment):

Make static so this can be invoked without constructing complex line layout (from startAlignedOffsetForLine).

(WebCore::ComplexLineLayout::computeInlineDirectionPositionsForSegment):
(WebCore::ComplexLineLayout::deleteEllipsisLineBoxes):
(WebCore::ComplexLineLayout::checkLinesForTextOverflow):
(WebCore::ComplexLineLayout::startAlignedOffsetForLine): Deleted.

This is also used in block layout to set static positions of positioned objects.
Move to RenderBlockFlow where its only caller is.

* rendering/ComplexLineLayout.h:
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::RenderBlockFlow):
(WebCore::RenderBlockFlow::willBeDestroyed):
(WebCore::RenderBlockFlow::layoutInlineChildren):
(WebCore::RenderBlockFlow::updateStaticInlinePositionForChild):
(WebCore::RenderBlockFlow::startAlignedOffsetForLine):
(WebCore::RenderBlockFlow::deleteLines):
(WebCore::RenderBlockFlow::hitTestInlineChildren):
(WebCore::RenderBlockFlow::addOverflowFromInlineChildren):
(WebCore::RenderBlockFlow::paintInlineChildren):
(WebCore::RenderBlockFlow::hasLines const):
(WebCore::RenderBlockFlow::layoutSimpleLines):
(WebCore::RenderBlockFlow::deleteLineBoxesBeforeSimpleLineLayout):
(WebCore::RenderBlockFlow::ensureLineBoxes):
* rendering/RenderBlockFlow.h:
(WebCore::RenderBlockFlow::firstRootBox const):
(WebCore::RenderBlockFlow::lastRootBox const):
(WebCore::RenderBlockFlow::complexLineLayout):
(WebCore::RenderBlockFlow::lineBoxes): Deleted.
(WebCore::RenderBlockFlow::lineBoxes const): Deleted.
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::removeLineBoxFromRenderObject):
(WebCore::RootInlineBox::extractLineBoxFromRenderObject):
(WebCore::RootInlineBox::attachLineBoxToRenderObject):
* rendering/SimpleLineLayoutFunctions.cpp:
(WebCore::SimpleLineLayout::generateLineBoxTree):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@248528 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/rendering/RenderBlockFlow.cpp b/Source/WebCore/rendering/RenderBlockFlow.cpp
index 70b04d8..7f1e639 100644
--- a/Source/WebCore/rendering/RenderBlockFlow.cpp
+++ b/Source/WebCore/rendering/RenderBlockFlow.cpp
@@ -111,7 +111,6 @@
     , m_widthForTextAutosizing(-1)
     , m_lineCountForTextAutosizing(NOT_SET)
 #endif
-    , m_complexLineLayout(*this)
 {
     setChildrenInline(true);
 }
@@ -122,7 +121,6 @@
     , m_widthForTextAutosizing(-1)
     , m_lineCountForTextAutosizing(NOT_SET)
 #endif
-    , m_complexLineLayout(*this)
 {
     setChildrenInline(true);
 }
@@ -154,7 +152,8 @@
             parent()->dirtyLinesFromChangedChild(*this);
     }
 
-    lineBoxes().deleteLineBoxes();
+    if (m_complexLineLayout)
+        m_complexLineLayout->lineBoxes().deleteLineBoxes();
 
     blockWillBeDestroyed();
 
@@ -677,7 +676,11 @@
     }
 
     m_simpleLineLayout = nullptr;
-    complexLineLayout().layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
+
+    if (!m_complexLineLayout)
+        m_complexLineLayout = std::make_unique<ComplexLineLayout>(*this);
+
+    m_complexLineLayout->layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
 }
 
 void RenderBlockFlow::layoutBlockChild(RenderBox& child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
@@ -899,7 +902,7 @@
 void RenderBlockFlow::updateStaticInlinePositionForChild(RenderBox& child, LayoutUnit logicalTop, IndentTextOrNot shouldIndentText)
 {
     if (child.style().isOriginalDisplayInlineType())
-        setStaticInlinePositionForChild(child, logicalTop, complexLineLayout().startAlignedOffsetForLine(logicalTop, shouldIndentText));
+        setStaticInlinePositionForChild(child, logicalTop, startAlignedOffsetForLine(logicalTop, shouldIndentText));
     else
         setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop));
 }
@@ -913,6 +916,45 @@
     child.layer()->setStaticInlinePosition(inlinePosition);
 }
 
+LayoutUnit RenderBlockFlow::startAlignedOffsetForLine(LayoutUnit position, IndentTextOrNot shouldIndentText)
+{
+    TextAlignMode textAlign = style().textAlign();
+    bool shouldApplyIndentText = false;
+    switch (textAlign) {
+    case TextAlignMode::Left:
+    case TextAlignMode::WebKitLeft:
+        shouldApplyIndentText = style().isLeftToRightDirection();
+        break;
+    case TextAlignMode::Right:
+    case TextAlignMode::WebKitRight:
+        shouldApplyIndentText = !style().isLeftToRightDirection();
+        break;
+    case TextAlignMode::Start:
+        shouldApplyIndentText = true;
+        break;
+    default:
+        shouldApplyIndentText = false;
+    }
+    // <rdar://problem/15427571>
+    // https://bugs.webkit.org/show_bug.cgi?id=124522
+    // This quirk is for legacy content that doesn't work properly with the center positioning scheme
+    // being honored (e.g., epubs).
+    if (shouldApplyIndentText || settings().useLegacyTextAlignPositionedElementBehavior()) // FIXME: Handle TextAlignMode::End here
+        return startOffsetForLine(position, shouldIndentText);
+
+    // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
+    float totalLogicalWidth = 0;
+    float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), DoNotIndentText);
+    float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), DoNotIndentText) - logicalLeft;
+
+    ComplexLineLayout::updateLogicalWidthForAlignment(*this, textAlign, nullptr, nullptr, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
+
+    if (!style().isLeftToRightDirection())
+        return LayoutUnit(logicalWidth() - logicalLeft);
+
+    return LayoutUnit(logicalLeft);
+}
+
 RenderBlockFlow::MarginValues RenderBlockFlow::marginValuesForChild(RenderBox& child) const
 {
     LayoutUnit childBeforePositive;
@@ -2067,10 +2109,10 @@
         m_floatingObjects->clearLineBoxTreePointers();
 
     if (m_simpleLineLayout) {
-        ASSERT(!lineBoxes().firstLineBox());
+        ASSERT(!m_complexLineLayout);
         m_simpleLineLayout = nullptr;
-    } else
-        lineBoxes().deleteLineBoxTree();
+    } else if (m_complexLineLayout)
+        m_complexLineLayout->lineBoxes().deleteLineBoxTree();
 
     RenderBlock::deleteLines();
 }
@@ -2907,7 +2949,7 @@
     if (auto simpleLineLayout = this->simpleLineLayout())
         return SimpleLineLayout::hitTestFlow(*this, *simpleLineLayout, request, result, locationInContainer, accumulatedOffset, hitTestAction);
 
-    return lineBoxes().hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
+    return m_complexLineLayout && m_complexLineLayout->lineBoxes().hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
 }
 
 void RenderBlockFlow::addOverflowFromInlineChildren()
@@ -2918,7 +2960,7 @@
         return;
     }
 
-    complexLineLayout().addOverflowFromInlineChildren();
+    m_complexLineLayout->addOverflowFromInlineChildren();
 }
 
 void RenderBlockFlow::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const
@@ -3500,7 +3542,9 @@
         SimpleLineLayout::paintFlow(*this, *simpleLineLayout, paintInfo, paintOffset);
         return;
     }
-    lineBoxes().paint(this, paintInfo, paintOffset);
+
+    if (m_complexLineLayout)
+        m_complexLineLayout->lineBoxes().paint(this, paintInfo, paintOffset);
 }
 
 bool RenderBlockFlow::relayoutForPagination()
@@ -3555,7 +3599,7 @@
     if (auto simpleLineLayout = this->simpleLineLayout())
         return simpleLineLayout->lineCount();
 
-    return lineBoxes().firstLineBox();
+    return m_complexLineLayout && m_complexLineLayout->lineBoxes().firstLineBox();
 }
 
 void RenderBlockFlow::invalidateLineLayoutPath()
@@ -3595,7 +3639,7 @@
     }
     for (auto& renderer : childrenOfType<RenderObject>(*this))
         renderer.clearNeedsLayout();
-    ASSERT(!lineBoxes().firstLineBox());
+    ASSERT(!m_complexLineLayout);
     LayoutUnit lineLayoutHeight = SimpleLineLayout::computeFlowHeight(*this, *m_simpleLineLayout);
     LayoutUnit lineLayoutTop = borderAndPaddingBefore();
     repaintLogicalTop = lineLayoutTop;
@@ -3606,7 +3650,10 @@
 void RenderBlockFlow::deleteLineBoxesBeforeSimpleLineLayout()
 {
     ASSERT(lineLayoutPath() == SimpleLinesPath);
-    lineBoxes().deleteLineBoxes();
+
+    if (m_complexLineLayout)
+        m_complexLineLayout->lineBoxes().deleteLineBoxes();
+
     for (auto& renderer : childrenOfType<RenderObject>(*this)) {
         if (is<RenderText>(renderer))
             downcast<RenderText>(renderer).deleteLineBoxesBeforeSimpleLineLayout();
@@ -3615,14 +3662,23 @@
         else
             ASSERT_NOT_REACHED();
     }
+
+    m_complexLineLayout = nullptr;
 }
 
 void RenderBlockFlow::ensureLineBoxes()
 {
+    if (!childrenInline())
+        return;
+
     setLineLayoutPath(ForceLineBoxesPath);
+
     if (!m_simpleLineLayout)
         return;
 
+    ASSERT(!m_complexLineLayout);
+    m_complexLineLayout = std::make_unique<ComplexLineLayout>(*this);
+
     if (SimpleLineLayout::canUseForLineBoxTree(*this, *m_simpleLineLayout)) {
         SimpleLineLayout::generateLineBoxTree(*this, *m_simpleLineLayout);
         m_simpleLineLayout = nullptr;
@@ -3641,14 +3697,14 @@
     LayoutUnit repaintLogicalBottom;
     if (isPaginated) {
         PaginatedLayoutStateMaintainer state(*this);
-        complexLineLayout().layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
+        m_complexLineLayout->layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
         // This matches relayoutToAvoidWidows.
         if (shouldBreakAtLineToAvoidWidow())
-            complexLineLayout().layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
+            m_complexLineLayout->layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
         // FIXME: This is needed as long as simple and normal line layout produce different line breakings.
         repaint();
     } else
-        complexLineLayout().layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
+        m_complexLineLayout->layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
 
     updateLogicalHeight();
     ASSERT(didNeedLayout || logicalHeight() == oldHeight);