<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[278305] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/278305">278305</a></dd>
<dt>Author</dt> <dd>antti@apple.com</dd>
<dt>Date</dt> <dd>2021-06-01 06:58:23 -0700 (Tue, 01 Jun 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>Rename ComplexLineLayout to LegacyLineLayout
https://bugs.webkit.org/show_bug.cgi?id=226482

Reviewed by Alan Bujtas.

Since we now handle most inline content with LFC, rename the legacy path as "legacy".

* Headers.cmake:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* layout/integration/LayoutIntegrationInlineContentBuilder.cpp:
(WebCore::LayoutIntegration::lineOverflowWidth):
* rendering/InlineIterator.h:
(WebCore::IsolateTracker::addFakeRunIfNecessary):
(WebCore::InlineBidiResolver::appendRunInternal):
* rendering/LegacyLineLayout.cpp: Renamed from Source/WebCore/rendering/ComplexLineLayout.cpp.
(WebCore::LegacyLineLayout::LegacyLineLayout):
(WebCore::LegacyLineLayout::~LegacyLineLayout):
(WebCore::determineDirectionality):
(WebCore::createRun):
(WebCore::LegacyLineLayout::appendRunsForObject):
(WebCore::LegacyLineLayout::createRootInlineBox):
(WebCore::LegacyLineLayout::createAndAppendRootInlineBox):
(WebCore::LegacyLineLayout::createInlineBoxForRenderer):
(WebCore::dirtyLineBoxesForRenderer):
(WebCore::parentIsConstructedOrHaveNext):
(WebCore::LegacyLineLayout::createLineBoxes):
(WebCore::endsWithHTMLSpaces):
(WebCore::reachedEndOfTextRenderer):
(WebCore::LegacyLineLayout::constructLine):
(WebCore::LegacyLineLayout::textAlignmentForLine const):
(WebCore::updateLogicalWidthForLeftAlignedBlock):
(WebCore::updateLogicalWidthForRightAlignedBlock):
(WebCore::updateLogicalWidthForCenterAlignedBlock):
(WebCore::LegacyLineLayout::setMarginsForRubyRun):
(WebCore::setLogicalWidthForTextRun):
(WebCore::LegacyLineLayout::updateRubyForJustifiedText):
(WebCore::LegacyLineLayout::computeExpansionForJustifiedText):
(WebCore::LegacyLineLayout::updateLogicalWidthForAlignment):
(WebCore::updateLogicalInlinePositions):
(WebCore::LegacyLineLayout::computeInlineDirectionPositionsForLine):
(WebCore::expansionBehaviorForInlineTextBox):
(WebCore::applyExpansionBehavior):
(WebCore::inlineAncestorHasStartBorderPaddingOrMargin):
(WebCore::inlineAncestorHasEndBorderPaddingOrMargin):
(WebCore::isLastInFlowRun):
(WebCore::LegacyLineLayout::computeInlineDirectionPositionsForSegment):
(WebCore::LegacyLineLayout::removeInlineBox const):
(WebCore::LegacyLineLayout::computeBlockDirectionPositionsForLine):
(WebCore::isCollapsibleSpace):
(WebCore::findFirstTrailingSpace):
(WebCore::LegacyLineLayout::handleTrailingSpaces):
(WebCore::LegacyLineLayout::appendFloatingObjectToLastLine):
(WebCore::notifyResolverToResumeInIsolate):
(WebCore::setUpResolverToResumeInIsolate):
(WebCore::constructBidiRunsForSegment):
(WebCore::LegacyLineLayout::createLineBoxesFromBidiRuns):
(WebCore::deleteLineRange):
(WebCore::repaintDirtyFloats):
(WebCore::LegacyLineLayout::layoutRunsAndFloats):
(WebCore::LegacyLineLayout::restartLayoutRunsAndFloatsInRange):
(WebCore::LegacyLineLayout::layoutRunsAndFloatsInRange):
(WebCore::LegacyLineLayout::reattachCleanLineFloats):
(WebCore::LegacyLineLayout::linkToEndLineIfNeeded):
(WebCore::LegacyLineLayout::layoutLineBoxes):
(WebCore::LegacyLineLayout::checkFloatInCleanLine):
(WebCore::LegacyLineLayout::determineStartPosition):
(WebCore::LegacyLineLayout::determineEndPosition):
(WebCore::LegacyLineLayout::checkPaginationAndFloatsAtEndLine):
(WebCore::LegacyLineLayout::lineWidthForPaginatedLineChanged const):
(WebCore::LegacyLineLayout::matchedEndLine):
(WebCore::LegacyLineLayout::addOverflowFromInlineChildren):
(WebCore::LegacyLineLayout::lineCount const):
(WebCore::LegacyLineLayout::lineCountUntil const):
(WebCore::LegacyLineLayout::deleteEllipsisLineBoxes):
(WebCore::LegacyLineLayout::checkLinesForTextOverflow):
(WebCore::LegacyLineLayout::positionNewFloatOnLine):
(WebCore::LegacyLineLayout::updateFragmentForLine const):
(WebCore::LegacyLineLayout::style const):
(WebCore::LegacyLineLayout::layoutContext const):
* rendering/LegacyLineLayout.h: Renamed from Source/WebCore/rendering/ComplexLineLayout.h.
(WebCore::LegacyLineLayout::lineBoxes):
(WebCore::LegacyLineLayout::lineBoxes const):
(WebCore::LegacyLineLayout::firstRootBox const):
(WebCore::LegacyLineLayout::lastRootBox const):
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::willBeDestroyed):
(WebCore::RenderBlockFlow::layoutInlineChildren):
(WebCore::RenderBlockFlow::startAlignedOffsetForLine):
(WebCore::RenderBlockFlow::adjustLinePositionForPagination):
(WebCore::RenderBlockFlow::styleDidChange):
(WebCore::RenderBlockFlow::hitTestInlineChildren):
(WebCore::RenderBlockFlow::addOverflowFromInlineChildren):
(WebCore::RenderBlockFlow::inlineBlockBaseline const):
(WebCore::RenderBlockFlow::lineCount const):
(WebCore::RenderBlockFlow::paintInlineChildren):
(WebCore::RenderBlockFlow::hasLines const):
(WebCore::RenderBlockFlow::ensureLineBoxes):
* rendering/RenderBlockFlow.h:
(WebCore::RenderBlockFlow::firstRootBox const):
(WebCore::RenderBlockFlow::lastRootBox const):
(WebCore::RenderBlockFlow::hasLegacyLineLayout const):
(WebCore::RenderBlockFlow::legacyLineLayout const):
(WebCore::RenderBlockFlow::legacyLineLayout):
(WebCore::RenderBlockFlow::hasComplexLineLayout const): Deleted.
(WebCore::RenderBlockFlow::complexLineLayout const): Deleted.
(WebCore::RenderBlockFlow::complexLineLayout): Deleted.
* rendering/RenderText.cpp:
(WebCore::RenderText::usesLegacyLineLayoutPath const):
(WebCore::RenderText::usesComplexLineLayoutPath const): Deleted.
* rendering/RenderText.h:
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::removeLineBoxFromRenderObject):
(WebCore::RootInlineBox::extractLineBoxFromRenderObject):
(WebCore::RootInlineBox::attachLineBoxToRenderObject):
* rendering/line/LineBreaker.cpp:
(WebCore::LineBreaker::skipLeadingWhitespace):
* rendering/line/LineBreaker.h:
(WebCore::LineBreaker::positionNewFloatOnLine):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreHeaderscmake">trunk/Source/WebCore/Headers.cmake</a></li>
<li><a href="#trunkSourceWebCoreSourcestxt">trunk/Source/WebCore/Sources.txt</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorelayoutintegrationLayoutIntegrationInlineContentBuildercpp">trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingInlineIteratorh">trunk/Source/WebCore/rendering/InlineIterator.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockFlowcpp">trunk/Source/WebCore/rendering/RenderBlockFlow.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderBlockFlowh">trunk/Source/WebCore/rendering/RenderBlockFlow.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderTextcpp">trunk/Source/WebCore/rendering/RenderText.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderTexth">trunk/Source/WebCore/rendering/RenderText.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRootInlineBoxcpp">trunk/Source/WebCore/rendering/RootInlineBox.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderinglineLineBreakercpp">trunk/Source/WebCore/rendering/line/LineBreaker.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderinglineLineBreakerh">trunk/Source/WebCore/rendering/line/LineBreaker.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorerenderingLegacyLineLayoutcpp">trunk/Source/WebCore/rendering/LegacyLineLayout.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingLegacyLineLayouth">trunk/Source/WebCore/rendering/LegacyLineLayout.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorerenderingComplexLineLayoutcpp">trunk/Source/WebCore/rendering/ComplexLineLayout.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingComplexLineLayouth">trunk/Source/WebCore/rendering/ComplexLineLayout.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/ChangeLog      2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -1,3 +1,125 @@
</span><ins>+2021-06-01  Antti Koivisto  <antti@apple.com>
+
+        Rename ComplexLineLayout to LegacyLineLayout
+        https://bugs.webkit.org/show_bug.cgi?id=226482
+
+        Reviewed by Alan Bujtas.
+
+        Since we now handle most inline content with LFC, rename the legacy path as "legacy".
+
+        * Headers.cmake:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * layout/integration/LayoutIntegrationInlineContentBuilder.cpp:
+        (WebCore::LayoutIntegration::lineOverflowWidth):
+        * rendering/InlineIterator.h:
+        (WebCore::IsolateTracker::addFakeRunIfNecessary):
+        (WebCore::InlineBidiResolver::appendRunInternal):
+        * rendering/LegacyLineLayout.cpp: Renamed from Source/WebCore/rendering/ComplexLineLayout.cpp.
+        (WebCore::LegacyLineLayout::LegacyLineLayout):
+        (WebCore::LegacyLineLayout::~LegacyLineLayout):
+        (WebCore::determineDirectionality):
+        (WebCore::createRun):
+        (WebCore::LegacyLineLayout::appendRunsForObject):
+        (WebCore::LegacyLineLayout::createRootInlineBox):
+        (WebCore::LegacyLineLayout::createAndAppendRootInlineBox):
+        (WebCore::LegacyLineLayout::createInlineBoxForRenderer):
+        (WebCore::dirtyLineBoxesForRenderer):
+        (WebCore::parentIsConstructedOrHaveNext):
+        (WebCore::LegacyLineLayout::createLineBoxes):
+        (WebCore::endsWithHTMLSpaces):
+        (WebCore::reachedEndOfTextRenderer):
+        (WebCore::LegacyLineLayout::constructLine):
+        (WebCore::LegacyLineLayout::textAlignmentForLine const):
+        (WebCore::updateLogicalWidthForLeftAlignedBlock):
+        (WebCore::updateLogicalWidthForRightAlignedBlock):
+        (WebCore::updateLogicalWidthForCenterAlignedBlock):
+        (WebCore::LegacyLineLayout::setMarginsForRubyRun):
+        (WebCore::setLogicalWidthForTextRun):
+        (WebCore::LegacyLineLayout::updateRubyForJustifiedText):
+        (WebCore::LegacyLineLayout::computeExpansionForJustifiedText):
+        (WebCore::LegacyLineLayout::updateLogicalWidthForAlignment):
+        (WebCore::updateLogicalInlinePositions):
+        (WebCore::LegacyLineLayout::computeInlineDirectionPositionsForLine):
+        (WebCore::expansionBehaviorForInlineTextBox):
+        (WebCore::applyExpansionBehavior):
+        (WebCore::inlineAncestorHasStartBorderPaddingOrMargin):
+        (WebCore::inlineAncestorHasEndBorderPaddingOrMargin):
+        (WebCore::isLastInFlowRun):
+        (WebCore::LegacyLineLayout::computeInlineDirectionPositionsForSegment):
+        (WebCore::LegacyLineLayout::removeInlineBox const):
+        (WebCore::LegacyLineLayout::computeBlockDirectionPositionsForLine):
+        (WebCore::isCollapsibleSpace):
+        (WebCore::findFirstTrailingSpace):
+        (WebCore::LegacyLineLayout::handleTrailingSpaces):
+        (WebCore::LegacyLineLayout::appendFloatingObjectToLastLine):
+        (WebCore::notifyResolverToResumeInIsolate):
+        (WebCore::setUpResolverToResumeInIsolate):
+        (WebCore::constructBidiRunsForSegment):
+        (WebCore::LegacyLineLayout::createLineBoxesFromBidiRuns):
+        (WebCore::deleteLineRange):
+        (WebCore::repaintDirtyFloats):
+        (WebCore::LegacyLineLayout::layoutRunsAndFloats):
+        (WebCore::LegacyLineLayout::restartLayoutRunsAndFloatsInRange):
+        (WebCore::LegacyLineLayout::layoutRunsAndFloatsInRange):
+        (WebCore::LegacyLineLayout::reattachCleanLineFloats):
+        (WebCore::LegacyLineLayout::linkToEndLineIfNeeded):
+        (WebCore::LegacyLineLayout::layoutLineBoxes):
+        (WebCore::LegacyLineLayout::checkFloatInCleanLine):
+        (WebCore::LegacyLineLayout::determineStartPosition):
+        (WebCore::LegacyLineLayout::determineEndPosition):
+        (WebCore::LegacyLineLayout::checkPaginationAndFloatsAtEndLine):
+        (WebCore::LegacyLineLayout::lineWidthForPaginatedLineChanged const):
+        (WebCore::LegacyLineLayout::matchedEndLine):
+        (WebCore::LegacyLineLayout::addOverflowFromInlineChildren):
+        (WebCore::LegacyLineLayout::lineCount const):
+        (WebCore::LegacyLineLayout::lineCountUntil const):
+        (WebCore::LegacyLineLayout::deleteEllipsisLineBoxes):
+        (WebCore::LegacyLineLayout::checkLinesForTextOverflow):
+        (WebCore::LegacyLineLayout::positionNewFloatOnLine):
+        (WebCore::LegacyLineLayout::updateFragmentForLine const):
+        (WebCore::LegacyLineLayout::style const):
+        (WebCore::LegacyLineLayout::layoutContext const):
+        * rendering/LegacyLineLayout.h: Renamed from Source/WebCore/rendering/ComplexLineLayout.h.
+        (WebCore::LegacyLineLayout::lineBoxes):
+        (WebCore::LegacyLineLayout::lineBoxes const):
+        (WebCore::LegacyLineLayout::firstRootBox const):
+        (WebCore::LegacyLineLayout::lastRootBox const):
+        * rendering/RenderBlockFlow.cpp:
+        (WebCore::RenderBlockFlow::willBeDestroyed):
+        (WebCore::RenderBlockFlow::layoutInlineChildren):
+        (WebCore::RenderBlockFlow::startAlignedOffsetForLine):
+        (WebCore::RenderBlockFlow::adjustLinePositionForPagination):
+        (WebCore::RenderBlockFlow::styleDidChange):
+        (WebCore::RenderBlockFlow::hitTestInlineChildren):
+        (WebCore::RenderBlockFlow::addOverflowFromInlineChildren):
+        (WebCore::RenderBlockFlow::inlineBlockBaseline const):
+        (WebCore::RenderBlockFlow::lineCount const):
+        (WebCore::RenderBlockFlow::paintInlineChildren):
+        (WebCore::RenderBlockFlow::hasLines const):
+        (WebCore::RenderBlockFlow::ensureLineBoxes):
+        * rendering/RenderBlockFlow.h:
+        (WebCore::RenderBlockFlow::firstRootBox const):
+        (WebCore::RenderBlockFlow::lastRootBox const):
+        (WebCore::RenderBlockFlow::hasLegacyLineLayout const):
+        (WebCore::RenderBlockFlow::legacyLineLayout const):
+        (WebCore::RenderBlockFlow::legacyLineLayout):
+        (WebCore::RenderBlockFlow::hasComplexLineLayout const): Deleted.
+        (WebCore::RenderBlockFlow::complexLineLayout const): Deleted.
+        (WebCore::RenderBlockFlow::complexLineLayout): Deleted.
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::usesLegacyLineLayoutPath const):
+        (WebCore::RenderText::usesComplexLineLayoutPath const): Deleted.
+        * rendering/RenderText.h:
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::removeLineBoxFromRenderObject):
+        (WebCore::RootInlineBox::extractLineBoxFromRenderObject):
+        (WebCore::RootInlineBox::attachLineBoxToRenderObject):
+        * rendering/line/LineBreaker.cpp:
+        (WebCore::LineBreaker::skipLeadingWhitespace):
+        * rendering/line/LineBreaker.h:
+        (WebCore::LineBreaker::positionNewFloatOnLine):
+
</ins><span class="cx"> 2021-06-01  Sam Weinig  <weinig@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Support calc() on components inside relative color syntax colors
</span></span></pre></div>
<a id="trunkSourceWebCoreHeaderscmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Headers.cmake (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Headers.cmake       2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/Headers.cmake  2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -1517,7 +1517,6 @@
</span><span class="cx">     rendering/BreakLines.h
</span><span class="cx">     rendering/ClipPathOperation.h
</span><span class="cx">     rendering/ClipRect.h
</span><del>-    rendering/ComplexLineLayout.h
</del><span class="cx">     rendering/EventRegion.h
</span><span class="cx">     rendering/FloatingObjects.h
</span><span class="cx">     rendering/GapRects.h
</span><span class="lines">@@ -1531,6 +1530,7 @@
</span><span class="cx">     rendering/InlineTextBox.h
</span><span class="cx">     rendering/LayerAncestorClippingStack.h
</span><span class="cx">     rendering/LayerFragment.h
</span><ins>+    rendering/LegacyLineLayout.h
</ins><span class="cx">     rendering/MarkedText.h
</span><span class="cx">     rendering/OrderIterator.h
</span><span class="cx">     rendering/OverlapTestRequestClient.h
</span></span></pre></div>
<a id="trunkSourceWebCoreSourcestxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Sources.txt (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Sources.txt 2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/Sources.txt    2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -2240,7 +2240,6 @@
</span><span class="cx"> rendering/CSSFilter.cpp
</span><span class="cx"> rendering/CaretRectComputation.cpp
</span><span class="cx"> rendering/ClipRect.cpp
</span><del>-rendering/ComplexLineLayout.cpp
</del><span class="cx"> rendering/ContentfulPaintChecker.cpp
</span><span class="cx"> rendering/CounterNode.cpp
</span><span class="cx"> rendering/EllipsisBox.cpp
</span><span class="lines">@@ -2266,6 +2265,7 @@
</span><span class="cx"> rendering/LayerOverlapMap.cpp
</span><span class="cx"> rendering/LayoutDisallowedScope.cpp
</span><span class="cx"> rendering/LayoutRepainter.cpp
</span><ins>+rendering/LegacyLineLayout.cpp
</ins><span class="cx"> rendering/MarkedText.cpp
</span><span class="cx"> rendering/MarkedTextStyle.cpp
</span><span class="cx"> rendering/OrderIterator.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj   2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj      2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -5291,7 +5291,7 @@
</span><span class="cx">          E4E39AFB1330EFA8003AB274 /* LegacyTileLayerPool.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E39AFA1330EFA8003AB274 /* LegacyTileLayerPool.h */; };
</span><span class="cx">          E4E8B4EC216B79E500B8834D /* SystemFontDatabaseCoreText.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E8B4EA216B79E500B8834D /* SystemFontDatabaseCoreText.h */; };
</span><span class="cx">          E4E8B4F5216B956500B8834D /* FontCascadeDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E8B4F2216B8B6000B8834D /* FontCascadeDescription.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-               E4E94D6122FF158A00DD191F /* ComplexLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A1AC7822FAFD500017B75B /* ComplexLineLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><ins>+                E4E94D6122FF158A00DD191F /* LegacyLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A1AC7822FAFD500017B75B /* LegacyLineLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">           E4F0BE3125712F6E009E7431 /* CaretRectComputation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F0BE2E25710A75009E7431 /* CaretRectComputation.h */; };
</span><span class="cx">          E4F38D1B2626F13B007B1064 /* DefaultResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F38D192626F13B007B1064 /* DefaultResourceLoadPriority.h */; };
</span><span class="cx">          E4F9EEF3156DA00700D23E7E /* StyleSheetContents.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F9EEF1156D84C400D23E7E /* StyleSheetContents.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -14486,7 +14486,7 @@
</span><span class="cx">          BCEA477C097CAAC80094C9E4 /* CSSComputedStyleDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSSComputedStyleDeclaration.cpp; sourceTree = "<group>"; };
</span><span class="cx">          BCEA477D097CAAC80094C9E4 /* CSSComputedStyleDeclaration.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSComputedStyleDeclaration.h; sourceTree = "<group>"; };
</span><span class="cx">          BCEA478C097CAAC80094C9E4 /* CSSValueKeywords.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CSSValueKeywords.in; sourceTree = "<group>"; };
</span><del>-               BCEA4813097D93020094C9E4 /* ComplexLineLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexLineLayout.cpp; sourceTree = "<group>"; };
</del><ins>+                BCEA4813097D93020094C9E4 /* LegacyLineLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LegacyLineLayout.cpp; sourceTree = "<group>"; };
</ins><span class="cx">           BCEA4815097D93020094C9E4 /* BreakLines.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BreakLines.cpp; sourceTree = "<group>"; };
</span><span class="cx">          BCEA4816097D93020094C9E4 /* BreakLines.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BreakLines.h; sourceTree = "<group>"; };
</span><span class="cx">          BCEA481A097D93020094C9E4 /* InlineTextBox.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InlineTextBox.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -16632,7 +16632,7 @@
</span><span class="cx">          E4A007821B820EC8002C5A6E /* DataURLDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataURLDecoder.h; sourceTree = "<group>"; };
</span><span class="cx">          E4A007841B820ED3002C5A6E /* DataURLDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataURLDecoder.cpp; sourceTree = "<group>"; };
</span><span class="cx">          E4A1822F1F13BE5800FEF698 /* StyleInvalidationFunctions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StyleInvalidationFunctions.h; sourceTree = "<group>"; };
</span><del>-               E4A1AC7822FAFD500017B75B /* ComplexLineLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComplexLineLayout.h; sourceTree = "<group>"; };
</del><ins>+                E4A1AC7822FAFD500017B75B /* LegacyLineLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyLineLayout.h; sourceTree = "<group>"; };
</ins><span class="cx">           E4A664C42521B777007081DC /* LayoutIntegrationRunIteratorModernPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutIntegrationRunIteratorModernPath.h; sourceTree = "<group>"; };
</span><span class="cx">          E4A664C52521B778007081DC /* LayoutIntegrationRunIteratorLegacyPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutIntegrationRunIteratorLegacyPath.h; sourceTree = "<group>"; };
</span><span class="cx">          E4A664C62521B778007081DC /* LayoutIntegrationRunIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutIntegrationRunIterator.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -30151,8 +30151,6 @@
</span><span class="cx">                          5803715F1A66F00A00BAF519 /* ClipRect.cpp */,
</span><span class="cx">                          580371601A66F00A00BAF519 /* ClipRect.h */,
</span><span class="cx">                          BCDD454D1236C95C009A7985 /* ColumnInfo.h */,
</span><del>-                               BCEA4813097D93020094C9E4 /* ComplexLineLayout.cpp */,
-                               E4A1AC7822FAFD500017B75B /* ComplexLineLayout.h */,
</del><span class="cx">                           CA7E9B4824361DC5004E89F6 /* ContentfulPaintChecker.cpp */,
</span><span class="cx">                          CA7E9B4724361DC5004E89F6 /* ContentfulPaintChecker.h */,
</span><span class="cx">                          9392F14F0AD1862300691BD4 /* CounterNode.cpp */,
</span><span class="lines">@@ -30210,6 +30208,8 @@
</span><span class="cx">                          9BD1F6801F0462B8001C9CDD /* LayoutDisallowedScope.h */,
</span><span class="cx">                          A120ACA113F9984600FE4AC7 /* LayoutRepainter.cpp */,
</span><span class="cx">                          A120ACA013F9983700FE4AC7 /* LayoutRepainter.h */,
</span><ins>+                               BCEA4813097D93020094C9E4 /* LegacyLineLayout.cpp */,
+                               E4A1AC7822FAFD500017B75B /* LegacyLineLayout.h */,
</ins><span class="cx">                           9BA273F3172206BB0097CE47 /* LogicalSelectionOffsetCaches.h */,
</span><span class="cx">                          CE1866421F72E5B400A0CAB6 /* MarkedText.cpp */,
</span><span class="cx">                          CE1866431F72E5B400A0CAB6 /* MarkedText.h */,
</span><span class="lines">@@ -32044,7 +32044,7 @@
</span><span class="cx">                          E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */,
</span><span class="cx">                          0F60F32B1DFBB10700416D6C /* CommonVM.h in Headers */,
</span><span class="cx">                          7C93F34A1AA6BA5E00A98BAB /* CompiledContentExtension.h in Headers */,
</span><del>-                               E4E94D6122FF158A00DD191F /* ComplexLineLayout.h in Headers */,
</del><ins>+                                E4E94D6122FF158A00DD191F /* LegacyLineLayout.h in Headers */,
</ins><span class="cx">                           C2F4E78C1E45C3EF006D7105 /* ComplexTextController.h in Headers */,
</span><span class="cx">                          E4BA50901BCFBD9500E34EF7 /* ComposedTreeAncestorIterator.h in Headers */,
</span><span class="cx">                          E44FA1851BCA6B5A0091B6EF /* ComposedTreeIterator.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutintegrationLayoutIntegrationInlineContentBuildercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp        2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp   2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx"> 
</span><span class="cx"> inline static float lineOverflowWidth(const RenderBlockFlow& flow, InlineLayoutUnit lineBoxLogicalWidth, InlineLayoutUnit lineContentLogicalWidth)
</span><span class="cx"> {
</span><del>-    // FIXME: It's the copy of the lets-adjust-overflow-for-the-caret behavior from ComplexLineLayout::addOverflowFromInlineChildren.
</del><ins>+    // FIXME: It's the copy of the lets-adjust-overflow-for-the-caret behavior from LegacyLineLayout::addOverflowFromInlineChildren.
</ins><span class="cx">     auto endPadding = flow.hasOverflowClip() ? flow.paddingEnd() : 0_lu;
</span><span class="cx">     if (!endPadding)
</span><span class="cx">         endPadding = flow.endPaddingWidthForCaret();
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingComplexLineLayoutcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/rendering/ComplexLineLayout.cpp (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/ComplexLineLayout.cpp     2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/ComplexLineLayout.cpp        2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -1,2327 +0,0 @@
</span><del>-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003-2019 Apple Inc. All right reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2013 ChangSeok Oh <shivamidow@gmail.com>
- * Copyright (C) 2013 Adobe Systems Inc. All right reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "ComplexLineLayout.h"
-
-#include "AXObjectCache.h"
-#include "BidiResolver.h"
-#include "BreakingContext.h"
-#include "FloatingObjects.h"
-#include "HTMLParserIdioms.h"
-#include "InlineElementBox.h"
-#include "InlineIterator.h"
-#include "InlineTextBox.h"
-#include "InlineTextBoxStyle.h"
-#include "LineLayoutState.h"
-#include "Logging.h"
-#include "RenderBlockFlow.h"
-#include "RenderFragmentContainer.h"
-#include "RenderFragmentedFlow.h"
-#include "RenderLayoutState.h"
-#include "RenderLineBreak.h"
-#include "RenderRubyBase.h"
-#include "RenderRubyText.h"
-#include "RenderSVGText.h"
-#include "RenderView.h"
-#include "SVGRootInlineBox.h"
-#include "Settings.h"
-#include "TrailingFloatsRootInlineBox.h"
-#include "VerticalPositionCache.h"
-#include <wtf/StdLibExtras.h>
-
-namespace WebCore {
-
-ComplexLineLayout::ComplexLineLayout(RenderBlockFlow& flow)
-    : m_flow(flow)
-{
-}
-
-ComplexLineLayout::~ComplexLineLayout()
-{
-    if (m_flow.containsFloats())
-        m_flow.floatingObjects()->clearLineBoxTreePointers();
-
-    lineBoxes().deleteLineBoxTree();
-};
-
-static void determineDirectionality(TextDirection& dir, InlineIterator iter)
-{
-    while (!iter.atEnd()) {
-        if (iter.atParagraphSeparator())
-            return;
-        if (UChar current = iter.current()) {
-            UCharDirection charDirection = u_charDirection(current);
-            if (charDirection == U_LEFT_TO_RIGHT) {
-                dir = TextDirection::LTR;
-                return;
-            }
-            if (charDirection == U_RIGHT_TO_LEFT || charDirection == U_RIGHT_TO_LEFT_ARABIC) {
-                dir = TextDirection::RTL;
-                return;
-            }
-        }
-        iter.increment();
-    }
-}
-
-inline std::unique_ptr<BidiRun> createRun(int start, int end, RenderObject& obj, InlineBidiResolver& resolver)
-{
-    return makeUnique<BidiRun>(start, end, obj, resolver.context(), resolver.dir());
-}
-
-void ComplexLineLayout::appendRunsForObject(BidiRunList<BidiRun>* runs, int start, int end, RenderObject& obj, InlineBidiResolver& resolver)
-{
-    if (start > end || RenderBlock::shouldSkipCreatingRunsForObject(obj))
-        return;
-
-    LineWhitespaceCollapsingState& lineWhitespaceCollapsingState = resolver.whitespaceCollapsingState();
-    bool haveNextTransition = (lineWhitespaceCollapsingState.currentTransition() < lineWhitespaceCollapsingState.numTransitions());
-    InlineIterator nextTransition;
-    if (haveNextTransition)
-        nextTransition = lineWhitespaceCollapsingState.transitions()[lineWhitespaceCollapsingState.currentTransition()];
-    if (lineWhitespaceCollapsingState.betweenTransitions()) {
-        if (!haveNextTransition || (&obj != nextTransition.renderer()))
-            return;
-        // This is a new start point. Stop ignoring objects and
-        // adjust our start.
-        start = nextTransition.offset();
-        lineWhitespaceCollapsingState.incrementCurrentTransition();
-        if (start < end) {
-            appendRunsForObject(runs, start, end, obj, resolver);
-            return;
-        }
-    } else {
-        if (!haveNextTransition || (&obj != nextTransition.renderer())) {
-            if (runs)
-                runs->appendRun(createRun(start, end, obj, resolver));
-            return;
-        }
-
-        // An end transition has been encountered within our object. We need to append a run with our endpoint.
-        if (static_cast<int>(nextTransition.offset() + 1) <= end) {
-            lineWhitespaceCollapsingState.incrementCurrentTransition();
-            // The end of the line is before the object we're inspecting. Skip everything and return
-            if (nextTransition.refersToEndOfPreviousNode())
-                return;
-            if (static_cast<int>(nextTransition.offset() + 1) > start && runs)
-                runs->appendRun(createRun(start, nextTransition.offset() + 1, obj, resolver));
-            appendRunsForObject(runs, nextTransition.offset() + 1, end, obj, resolver);
-        } else if (runs)
-            runs->appendRun(createRun(start, end, obj, resolver));
-    }
-}
-
-std::unique_ptr<RootInlineBox> ComplexLineLayout::createRootInlineBox()
-{
-    if (is<RenderSVGText>(m_flow)) {
-        auto box = makeUnique<SVGRootInlineBox>(downcast<RenderSVGText>(m_flow));
-        box->setHasVirtualLogicalHeight();
-        return box;
-    }
-        
-    return makeUnique<RootInlineBox>(m_flow);
-}
-
-RootInlineBox* ComplexLineLayout::createAndAppendRootInlineBox()
-{
-    auto newRootBox = createRootInlineBox();
-    RootInlineBox* rootBox = newRootBox.get();
-    m_lineBoxes.appendLineBox(WTFMove(newRootBox));
-
-    if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && firstRootBox() == rootBox) {
-        if (AXObjectCache* cache = m_flow.document().existingAXObjectCache())
-            cache->deferRecomputeIsIgnored(m_flow.element());
-    }
-
-    return rootBox;
-}
-
-InlineBox* ComplexLineLayout::createInlineBoxForRenderer(RenderObject* renderer, bool isOnlyRun)
-{
-    if (renderer == &m_flow)
-        return createAndAppendRootInlineBox();
-
-    if (is<RenderText>(*renderer))
-        return downcast<RenderText>(*renderer).createInlineTextBox();
-
-    if (is<RenderBox>(*renderer)) {
-        // FIXME: This is terrible. This branch returns an *owned* pointer!
-        return downcast<RenderBox>(*renderer).createInlineBox().release();
-    }
-
-    if (is<RenderLineBreak>(*renderer)) {
-        // FIXME: This is terrible. This branch returns an *owned* pointer!
-        auto inlineBox = downcast<RenderLineBreak>(*renderer).createInlineBox().release();
-        // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
-        // (Note the use of strict mode. In "almost strict" mode, we don't treat the box for <br> as text.)
-        inlineBox->setBehavesLikeText(isOnlyRun || renderer->document().inNoQuirksMode() || renderer->isLineBreakOpportunity());
-        return inlineBox;
-    }
-
-    return downcast<RenderInline>(*renderer).createAndAppendInlineFlowBox();
-}
-
-static inline void dirtyLineBoxesForRenderer(RenderObject& renderer, bool fullLayout)
-{
-    if (is<RenderText>(renderer)) {
-        RenderText& renderText = downcast<RenderText>(renderer);
-        updateCounterIfNeeded(renderText);
-        renderText.dirtyLineBoxes(fullLayout);
-    } else if (is<RenderLineBreak>(renderer))
-        downcast<RenderLineBreak>(renderer).dirtyLineBoxes(fullLayout);
-    else
-        downcast<RenderInline>(renderer).dirtyLineBoxes(fullLayout);
-}
-
-static bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
-{
-    do {
-        if (parentBox->isConstructed() || parentBox->nextOnLine())
-            return true;
-        parentBox = parentBox->parent();
-    } while (parentBox);
-    return false;
-}
-
-InlineFlowBox* ComplexLineLayout::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox)
-{
-    // See if we have an unconstructed line box for this object that is also
-    // the last item on the line.
-    unsigned lineDepth = 1;
-    InlineFlowBox* parentBox = nullptr;
-    InlineFlowBox* result = nullptr;
-    bool hasDefaultLineBoxContain = style().lineBoxContain() == RenderStyle::initialLineBoxContain();
-    do {
-        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(is<RenderInline>(*obj) || obj == &m_flow);
-
-        RenderInline* inlineFlow = obj != &m_flow ? downcast<RenderInline>(obj) : nullptr;
-
-        // Get the last box we made for this render object.
-        parentBox = inlineFlow ? inlineFlow->lastLineBox() : downcast<RenderBlockFlow>(*obj).lastRootBox();
-
-        // If this box or its ancestor is constructed then it is from a previous line, and we need
-        // to make a new box for our line. If this box or its ancestor is unconstructed but it has
-        // something following it on the line, then we know we have to make a new box
-        // as well. In this situation our inline has actually been split in two on
-        // the same line (this can happen with very fancy language mixtures).
-        bool constructedNewBox = false;
-        bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
-        bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox);
-        if (allowedToConstructNewBox && !canUseExistingParentBox) {
-            // We need to make a new box for this render object. Once
-            // made, we need to place it at the end of the current line.
-            InlineBox* newBox = createInlineBoxForRenderer(obj);
-            parentBox = downcast<InlineFlowBox>(newBox);
-            parentBox->setIsFirstLine(lineInfo.isFirstLine());
-            parentBox->setIsHorizontal(m_flow.isHorizontalWritingMode());
-            if (!hasDefaultLineBoxContain)
-                parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
-            constructedNewBox = true;
-        }
-
-        if (constructedNewBox || canUseExistingParentBox) {
-            if (!result)
-                result = parentBox;
-
-            // If we have hit the block itself, then |box| represents the root
-            // inline box for the line, and it doesn't have to be appended to any parent
-            // inline.
-            if (childBox)
-                parentBox->addToLine(childBox);
-
-            if (!constructedNewBox || obj == &m_flow)
-                break;
-
-            childBox = parentBox;
-        }
-
-        // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
-        // intermediate inline flows.
-        obj = (++lineDepth >= cMaxLineDepth) ? &m_flow : obj->parent();
-
-    } while (true);
-
-    return result;
-}
-
-template<typename CharacterType> static inline bool endsWithHTMLSpaces(const CharacterType* characters, unsigned position, unsigned end)
-{
-    for (unsigned i = position; i < end; ++i) {
-        if (!isHTMLSpace(characters[i]))
-            return false;
-    }
-    return true;
-}
-
-static bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
-{
-    BidiRun* run = bidiRuns.logicallyLastRun();
-    if (!run)
-        return true;
-    if (!is<RenderText>(run->renderer()))
-        return false;
-    auto& text = downcast<RenderText>(run->renderer()).text();
-    unsigned position = run->stop();
-    unsigned length = text.length();
-    if (text.is8Bit())
-        return endsWithHTMLSpaces(text.characters8(), position, length);
-    return endsWithHTMLSpaces(text.characters16(), position, length);
-}
-
-RootInlineBox* ComplexLineLayout::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
-{
-    ASSERT(bidiRuns.firstRun());
-
-    InlineFlowBox* parentBox = 0;
-    int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace();
-    
-    for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
-        // Create a box for our object.
-        bool isOnlyRun = (runCount == 1);
-        if (runCount == 2 && !r->renderer().isListMarker())
-            isOnlyRun = (!style().isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->renderer().isListMarker();
-
-        if (lineInfo.isEmpty())
-            continue;
-
-        InlineBox* box = createInlineBoxForRenderer(&r->renderer(), isOnlyRun);
-        r->setBox(box);
-
-        // If we have no parent box yet, or if the run is not simply a sibling,
-        // then we need to construct inline boxes as necessary to properly enclose the
-        // run's inline box. Segments can only be siblings at the root level, as
-        // they are positioned separately.
-        if (!parentBox || &parentBox->renderer() != r->renderer().parent()) {
-            // Create new inline boxes all the way back to the appropriate insertion point.
-            RenderObject* parentToUse = r->renderer().parent();
-            parentBox = createLineBoxes(parentToUse, lineInfo, box);
-        } else {
-            // Append the inline box to this line.
-            parentBox->addToLine(box);
-        }
-
-        bool visuallyOrdered = r->renderer().style().rtlOrdering() == Order::Visual;
-        box->setBidiLevel(r->level());
-
-        if (is<InlineTextBox>(*box)) {
-            auto& textBox = downcast<InlineTextBox>(*box);
-            textBox.setStart(r->m_start);
-            textBox.setLen(r->m_stop - r->m_start);
-            textBox.setDirOverride(r->dirOverride(visuallyOrdered));
-            if (r->m_hasHyphen)
-                textBox.setHasHyphen(true);
-        }
-    }
-
-    // We should have a root inline box. It should be unconstructed and
-    // be the last continuation of our line list.
-    ASSERT(lastRootBox() && !lastRootBox()->isConstructed());
-
-    // Set bits on our inline flow boxes that indicate which sides should
-    // paint borders/margins/padding. This knowledge will ultimately be used when
-    // we determine the horizontal positions and widths of all the inline boxes on
-    // the line.
-    bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->renderer().isText() ? !reachedEndOfTextRenderer(bidiRuns) : !is<RenderInline>(bidiRuns.logicallyLastRun()->renderer());
-    lastRootBox()->determineSpacingForFlowBoxes(lineInfo.isLastLine(), isLogicallyLastRunWrapped, &bidiRuns.logicallyLastRun()->renderer());
-
-    // Now mark the line boxes as being constructed.
-    lastRootBox()->setConstructed();
-
-    // Return the last line.
-    return lastRootBox();
-}
-
-TextAlignMode ComplexLineLayout::textAlignmentForLine(bool endsWithSoftBreak) const
-{
-    if (auto overrideAlignment = m_flow.overrideTextAlignmentForLine(endsWithSoftBreak))
-        return *overrideAlignment;
-
-    TextAlignMode alignment = style().textAlign();
-#if ENABLE(CSS3_TEXT)
-    TextJustify textJustify = style().textJustify();
-    if (alignment == TextAlignMode::Justify && textJustify == TextJustify::None)
-        return style().direction() == TextDirection::LTR ? TextAlignMode::Left : TextAlignMode::Right;
-#endif
-
-    if (endsWithSoftBreak)
-        return alignment;
-
-#if !ENABLE(CSS3_TEXT)
-    return (alignment == TextAlignMode::Justify) ? TextAlignMode::Start : alignment;
-#else
-    if (alignment != TextAlignMode::Justify)
-        return alignment;
-
-    TextAlignLast alignmentLast = style().textAlignLast();
-    switch (alignmentLast) {
-    case TextAlignLast::Start:
-        return TextAlignMode::Start;
-    case TextAlignLast::End:
-        return TextAlignMode::End;
-    case TextAlignLast::Left:
-        return TextAlignMode::Left;
-    case TextAlignLast::Right:
-        return TextAlignMode::Right;
-    case TextAlignLast::Center:
-        return TextAlignMode::Center;
-    case TextAlignLast::Justify:
-        return TextAlignMode::Justify;
-    case TextAlignLast::Auto:
-        if (textJustify == TextJustify::Distribute)
-            return TextAlignMode::Justify;
-        return TextAlignMode::Start;
-    }
-    return alignment;
-#endif
-}
-
-static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
-{
-    // The direction of the block should determine what happens with wide lines.
-    // In particular with RTL blocks, wide lines should still spill out to the left.
-    if (isLeftToRightDirection) {
-        if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
-            trailingSpaceRun->box()->setLogicalWidth(std::max<float>(0, trailingSpaceRun->box()->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
-        return;
-    }
-
-    if (trailingSpaceRun)
-        trailingSpaceRun->box()->setLogicalWidth(0);
-    else if (totalLogicalWidth > availableLogicalWidth)
-        logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
-}
-
-static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
-{
-    // Wide lines spill out of the block based off direction.
-    // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
-    // side of the block.
-    if (isLeftToRightDirection) {
-        if (trailingSpaceRun) {
-            totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
-            trailingSpaceRun->box()->setLogicalWidth(0);
-        }
-        logicalLeft += std::max(0.f, availableLogicalWidth - totalLogicalWidth);
-        return;
-    }
-
-    if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
-        trailingSpaceRun->box()->setLogicalWidth(std::max<float>(0, trailingSpaceRun->box()->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
-        totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
-    } else
-        logicalLeft += availableLogicalWidth - totalLogicalWidth;
-}
-
-static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
-{
-    float trailingSpaceWidth = 0;
-    if (trailingSpaceRun) {
-        totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
-        trailingSpaceWidth = std::min(trailingSpaceRun->box()->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
-        trailingSpaceRun->box()->setLogicalWidth(std::max<float>(0, trailingSpaceWidth));
-    }
-    if (isLeftToRightDirection)
-        logicalLeft += std::max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
-    else
-        logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
-}
-
-void ComplexLineLayout::setMarginsForRubyRun(BidiRun* run, RenderRubyRun& renderer, RenderObject* previousObject, const LineInfo& lineInfo)
-{
-    float startOverhang;
-    float endOverhang;
-    RenderObject* nextObject = 0;
-    for (BidiRun* runWithNextObject = run->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
-        if (!runWithNextObject->renderer().isOutOfFlowPositioned() && !runWithNextObject->box()->isLineBreak()) {
-            nextObject = &runWithNextObject->renderer();
-            break;
-        }
-    }
-    renderer.getOverhang(lineInfo.isFirstLine(), renderer.style().isLeftToRightDirection() ? previousObject : nextObject, renderer.style().isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
-    m_flow.setMarginStartForChild(renderer, LayoutUnit(-startOverhang));
-    m_flow.setMarginEndForChild(renderer, LayoutUnit(-endOverhang));
-}
-
-static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText& renderer, float xPos, const LineInfo& lineInfo,
-    GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
-{
-    HashSet<const Font*> fallbackFonts;
-    GlyphOverflow glyphOverflow;
-
-    const FontCascade& font = lineStyle(*renderer.parent(), lineInfo).fontCascade();
-    // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
-    if (lineBox->fitsToGlyphs()) {
-        // If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
-        // will keep us from computing glyph bounds in nearly all cases.
-        bool includeRootLine = lineBox->includesRootLineBoxFontOrLeading();
-        int baselineShift = lineBox->verticalPositionForBox(run->box(), verticalPositionCache);
-        int rootDescent = includeRootLine ? font.fontMetrics().descent() : 0;
-        int rootAscent = includeRootLine ? font.fontMetrics().ascent() : 0;
-        int boxAscent = font.fontMetrics().ascent() - baselineShift;
-        int boxDescent = font.fontMetrics().descent() + baselineShift;
-        if (boxAscent > rootDescent ||  boxDescent > rootAscent)
-            glyphOverflow.computeBounds = true; 
-    }
-    
-    LayoutUnit hyphenWidth;
-    if (downcast<InlineTextBox>(*run->box()).hasHyphen())
-        hyphenWidth = measureHyphenWidth(renderer, font, &fallbackFonts);
-
-    float measuredWidth = 0;
-
-    bool kerningIsEnabled = font.enableKerning();
-    bool canUseSimpleFontCodePath = renderer.canUseSimpleFontCodePath();
-    
-    // Since we don't cache glyph overflows, we need to re-measure the run if
-    // the style is linebox-contain: glyph.
-    if (!lineBox->fitsToGlyphs() && canUseSimpleFontCodePath) {
-        unsigned lastEndOffset = run->m_start;
-        bool atFirstWordMeasurement = true;
-        for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) {
-            WordMeasurement& wordMeasurement = wordMeasurements[i];
-            if (wordMeasurement.width <= 0 || wordMeasurement.startOffset == wordMeasurement.endOffset)
-                continue;
-            if (wordMeasurement.renderer != &renderer || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop)
-                continue;
-
-            lastEndOffset = wordMeasurement.endOffset;
-            if (kerningIsEnabled && lastEndOffset == run->m_stop) {
-                int wordLength = lastEndOffset - wordMeasurement.startOffset;
-                GlyphOverflow overflow;
-                measuredWidth += renderer.width(wordMeasurement.startOffset, wordLength, xPos + measuredWidth, lineInfo.isFirstLine(),
-                    &wordMeasurement.fallbackFonts, &overflow);
-                UChar c = renderer.characterAt(wordMeasurement.startOffset);
-                // renderer.width() omits word-spacing value for leading whitespace, so let's just add it back here.
-                if (!atFirstWordMeasurement && FontCascade::treatAsSpace(c))
-                    measuredWidth += renderer.style().fontCascade().wordSpacing();
-            } else
-                measuredWidth += wordMeasurement.width;
-            atFirstWordMeasurement = false;
-
-            for (auto& font : wordMeasurement.fallbackFonts)
-                fallbackFonts.add(font);
-        }
-        if (measuredWidth && lastEndOffset != run->m_stop) {
-            // If we don't have enough cached data, we'll measure the run again.
-            measuredWidth = 0;
-            fallbackFonts.clear();
-        }
-    }
-
-    if (!measuredWidth)
-        measuredWidth = renderer.width(run->m_start, run->m_stop - run->m_start, xPos, lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
-
-    ASSERT(measuredWidth >= 0);
-    ASSERT(hyphenWidth >= 0);
-
-    run->box()->setLogicalWidth(measuredWidth + hyphenWidth);
-    if (!fallbackFonts.isEmpty()) {
-        ASSERT(run->box()->behavesLikeText());
-        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(downcast<InlineTextBox>(run->box()), std::make_pair(Vector<const Font*>(), GlyphOverflow())).iterator;
-        ASSERT(it->value.first.isEmpty());
-        it->value.first = copyToVector(fallbackFonts);
-        run->box()->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
-    }
-
-    // Include text decoration visual overflow as part of the glyph overflow.
-    if (!renderer.style().textDecorationsInEffect().isEmpty())
-        glyphOverflow.extendTo(visualOverflowForDecorations(run->box()->lineStyle(), downcast<InlineTextBox>(run->box())));
-
-    if (!glyphOverflow.isEmpty()) {
-        ASSERT(run->box()->behavesLikeText());
-        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(downcast<InlineTextBox>(run->box()), std::make_pair(Vector<const Font*>(), GlyphOverflow())).iterator;
-        it->value.second = glyphOverflow;
-        run->box()->clearKnownToHaveNoOverflow();
-    }
-}
-
-void ComplexLineLayout::updateRubyForJustifiedText(RenderRubyRun& rubyRun, BidiRun& r, const Vector<unsigned, 16>& expansionOpportunities, unsigned& expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth, size_t& i)
-{
-    if (!rubyRun.rubyBase() || !rubyRun.rubyBase()->firstRootBox() || rubyRun.rubyBase()->firstRootBox()->nextRootBox() || !r.renderer().style().collapseWhiteSpace())
-        return;
-
-    auto& rubyBase = *rubyRun.rubyBase();
-    auto& rootBox = *rubyBase.firstRootBox();
-
-    float totalExpansion = 0;
-    unsigned totalOpportunitiesInRun = 0;
-    for (auto* leafChild = rootBox.firstLeafDescendant(); leafChild; leafChild = leafChild->nextLeafOnLine()) {
-        if (!leafChild->isInlineTextBox())
-            continue;
-
-        unsigned opportunitiesInRun = expansionOpportunities[i++];
-        ASSERT(opportunitiesInRun <= expansionOpportunityCount);
-        auto expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
-        totalExpansion += expansion;
-        totalOpportunitiesInRun += opportunitiesInRun;
-    }
-
-    ASSERT(!rubyRun.hasOverridingLogicalWidth());
-    float newBaseWidth = rubyRun.logicalWidth() + totalExpansion + m_flow.marginStartForChild(rubyRun) + m_flow.marginEndForChild(rubyRun);
-    float newRubyRunWidth = rubyRun.logicalWidth() + totalExpansion;
-    rubyBase.setInitialOffset((newRubyRunWidth - newBaseWidth) / 2);
-    rubyRun.setOverridingLogicalWidth(LayoutUnit(newRubyRunWidth));
-    rubyRun.setNeedsLayout(MarkOnlyThis);
-    rootBox.markDirty();
-    if (RenderRubyText* rubyText = rubyRun.rubyText()) {
-        if (RootInlineBox* textRootBox = rubyText->firstRootBox())
-            textRootBox->markDirty();
-    }
-    rubyRun.layoutBlock(true);
-    rubyRun.clearOverridingLogicalWidth();
-    r.box()->setExpansion(newRubyRunWidth - r.box()->logicalWidth());
-
-    totalLogicalWidth += totalExpansion;
-    expansionOpportunityCount -= totalOpportunitiesInRun;
-}
-
-void ComplexLineLayout::computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, const Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float totalLogicalWidth, float availableLogicalWidth)
-{
-    if (!expansionOpportunityCount || availableLogicalWidth <= totalLogicalWidth)
-        return;
-
-    size_t i = 0;
-    for (BidiRun* run = firstRun; run; run = run->next()) {
-        if (!run->box() || run == trailingSpaceRun)
-            continue;
-        
-        if (is<RenderText>(run->renderer())) {
-            unsigned opportunitiesInRun = expansionOpportunities[i++];
-            
-            ASSERT(opportunitiesInRun <= expansionOpportunityCount);
-            
-            // Only justify text if whitespace is collapsed.
-            if (run->renderer().style().collapseWhiteSpace()) {
-                InlineTextBox& textBox = downcast<InlineTextBox>(*run->box());
-                float expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
-                textBox.setExpansion(expansion);
-                totalLogicalWidth += expansion;
-            }
-            expansionOpportunityCount -= opportunitiesInRun;
-        } else if (is<RenderRubyRun>(run->renderer()))
-            updateRubyForJustifiedText(downcast<RenderRubyRun>(run->renderer()), *run, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth, i);
-
-        if (!expansionOpportunityCount)
-            break;
-    }
-}
-
-void ComplexLineLayout::updateLogicalWidthForAlignment(RenderBlockFlow& flow, const TextAlignMode& textAlign, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount)
-{
-    TextDirection direction;
-    if (rootInlineBox && flow.style().unicodeBidi() == Plaintext)
-        direction = rootInlineBox->direction();
-    else
-        direction = flow.style().direction();
-
-    bool isLeftToRightDirection = flow.style().isLeftToRightDirection();
-
-    // Armed with the total width of the line (without justification),
-    // we now examine our text-align property in order to determine where to position the
-    // objects horizontally. The total width of the line can be increased if we end up
-    // justifying text.
-    switch (textAlign) {
-    case TextAlignMode::Left:
-    case TextAlignMode::WebKitLeft:
-        updateLogicalWidthForLeftAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        break;
-    case TextAlignMode::Right:
-    case TextAlignMode::WebKitRight:
-        updateLogicalWidthForRightAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        break;
-    case TextAlignMode::Center:
-    case TextAlignMode::WebKitCenter:
-        updateLogicalWidthForCenterAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        break;
-    case TextAlignMode::Justify:
-        flow.adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
-        if (expansionOpportunityCount) {
-            if (trailingSpaceRun) {
-                totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
-                trailingSpaceRun->box()->setLogicalWidth(0);
-            }
-            break;
-        }
-        FALLTHROUGH;
-    case TextAlignMode::Start:
-        if (direction == TextDirection::LTR)
-            updateLogicalWidthForLeftAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        else
-            updateLogicalWidthForRightAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        break;
-    case TextAlignMode::End:
-        if (direction == TextDirection::LTR)
-            updateLogicalWidthForRightAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        else
-            updateLogicalWidthForLeftAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
-        break;
-    }
-}
-
-static void updateLogicalInlinePositions(RenderBlockFlow& block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine,
-    IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
-{
-    LayoutUnit lineLogicalHeight = block.minLineHeightForReplacedRenderer(firstLine, boxLogicalHeight);
-    lineLogicalLeft = block.logicalLeftOffsetForLine(block.logicalHeight(), shouldIndentText, lineLogicalHeight);
-    lineLogicalRight = block.logicalRightOffsetForLine(block.logicalHeight(), shouldIndentText, lineLogicalHeight);
-    availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
-}
-
-void ComplexLineLayout::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
-{
-    TextAlignMode textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
-    
-    // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted line of an element. For example, the first line of an anonymous block 
-    // box is only affected if it is the first child of its parent element."
-    // CSS3 "text-indent", "-webkit-each-line" affects the first line of the block container as well as each line after a forced line break,
-    // but does not affect lines after a soft wrap break.
-    bool isFirstLine = lineInfo.isFirstLine() && !(m_flow.isAnonymousBlock() && m_flow.parent()->firstChild() != &m_flow);
-    bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak();
-    IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLineBreak, style());
-    float lineLogicalLeft;
-    float lineLogicalRight;
-    float availableLogicalWidth;
-    updateLogicalInlinePositions(m_flow, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, 0);
-    bool needsWordSpacing;
-
-    if (firstRun && firstRun->renderer().isReplaced()) {
-        RenderBox& renderBox = downcast<RenderBox>(firstRun->renderer());
-        updateLogicalInlinePositions(m_flow, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, renderBox.logicalHeight());
-    }
-
-    computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
-    // The widths of all runs are now known. We can now place every inline box (and
-    // compute accurate widths for the inline flow boxes).
-    needsWordSpacing = false;
-    lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing);
-}
-
-static inline ExpansionBehavior expansionBehaviorForInlineTextBox(RenderBlockFlow& block, InlineTextBox& textBox, BidiRun* previousRun, BidiRun* nextRun, TextAlignMode textAlign, bool isAfterExpansion)
-{
-    // Tatechuyoko is modeled as the Object Replacement Character (U+FFFC), which can never have expansion opportunities inside nor intrinsically adjacent to it.
-    if (textBox.renderer().style().textCombine() == TextCombine::Horizontal)
-        return ForbidLeftExpansion | ForbidRightExpansion;
-
-    ExpansionBehavior result = 0;
-    bool setLeftExpansion = false;
-    bool setRightExpansion = false;
-    if (textAlign == TextAlignMode::Justify) {
-        // If the next box is ruby, and we're justifying, and the first box in the ruby base has a leading expansion, and we are a text box, then force a trailing expansion.
-        if (nextRun && is<RenderRubyRun>(nextRun->renderer()) && downcast<RenderRubyRun>(nextRun->renderer()).rubyBase() && nextRun->renderer().style().collapseWhiteSpace()) {
-            auto& rubyBase = *downcast<RenderRubyRun>(nextRun->renderer()).rubyBase();
-            if (rubyBase.firstRootBox() && !rubyBase.firstRootBox()->nextRootBox()) {
-                if (auto* leafChild = rubyBase.firstRootBox()->firstLeafDescendant()) {
-                    if (is<InlineTextBox>(*leafChild)) {
-                        // FIXME: This leftExpansionOpportunity doesn't actually work because it doesn't perform the UBA
-                        if (FontCascade::leftExpansionOpportunity(downcast<RenderText>(leafChild->renderer()).stringView(), leafChild->direction())) {
-                            setRightExpansion = true;
-                            result |= ForceRightExpansion;
-                        }
-                    }
-                }
-            }
-        }
-        // Same thing, except if we're following a ruby
-        if (previousRun && is<RenderRubyRun>(previousRun->renderer()) && downcast<RenderRubyRun>(previousRun->renderer()).rubyBase() && previousRun->renderer().style().collapseWhiteSpace()) {
-            auto& rubyBase = *downcast<RenderRubyRun>(previousRun->renderer()).rubyBase();
-            if (rubyBase.firstRootBox() && !rubyBase.firstRootBox()->nextRootBox()) {
-                if (auto* leafChild = rubyBase.firstRootBox()->lastLeafDescendant()) {
-                    if (is<InlineTextBox>(*leafChild)) {
-                        // FIXME: This leftExpansionOpportunity doesn't actually work because it doesn't perform the UBA
-                        if (FontCascade::rightExpansionOpportunity(downcast<RenderText>(leafChild->renderer()).stringView(), leafChild->direction())) {
-                            setLeftExpansion = true;
-                            result |= ForceLeftExpansion;
-                        }
-                    }
-                }
-            }
-        }
-        // If we're the first box inside a ruby base, forbid a leading expansion, and vice-versa
-        if (is<RenderRubyBase>(block)) {
-            RenderRubyBase& rubyBase = downcast<RenderRubyBase>(block);
-            if (&textBox == rubyBase.firstRootBox()->firstLeafDescendant()) {
-                setLeftExpansion = true;
-                result |= ForbidLeftExpansion;
-            } if (&textBox == rubyBase.firstRootBox()->lastLeafDescendant()) {
-                setRightExpansion = true;
-                result |= ForbidRightExpansion;
-            }
-        }
-    }
-    if (!setLeftExpansion)
-        result |= isAfterExpansion ? ForbidLeftExpansion : AllowLeftExpansion;
-    if (!setRightExpansion)
-        result |= AllowRightExpansion;
-    return result;
-}
-
-static inline void applyExpansionBehavior(InlineTextBox& textBox, ExpansionBehavior expansionBehavior)
-{
-    switch (expansionBehavior & LeftExpansionMask) {
-    case ForceLeftExpansion:
-        textBox.setForceLeftExpansion();
-        break;
-    case ForbidLeftExpansion:
-        textBox.setCanHaveLeftExpansion(false);
-        break;
-    case AllowLeftExpansion:
-        textBox.setCanHaveLeftExpansion(true);
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-        break;
-    }
-    switch (expansionBehavior & RightExpansionMask) {
-    case ForceRightExpansion:
-        textBox.setForceRightExpansion();
-        break;
-    case ForbidRightExpansion:
-        textBox.setCanHaveRightExpansion(false);
-        break;
-    case AllowRightExpansion:
-        textBox.setCanHaveRightExpansion(true);
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-        break;
-    }
-}
-
-static bool inlineAncestorHasStartBorderPaddingOrMargin(const RenderBlockFlow& block, const InlineBox& box)
-{
-    bool isLTR = block.style().isLeftToRightDirection();
-    for (auto* currentBox = box.parent(); currentBox; currentBox = currentBox->parent()) {
-        if ((isLTR && currentBox->marginBorderPaddingLogicalLeft() > 0)
-            || (!isLTR && currentBox->marginBorderPaddingLogicalRight() > 0))
-            return true;
-    }
-    return false;
-}
-
-static bool inlineAncestorHasEndBorderPaddingOrMargin(const RenderBlockFlow& block, const InlineBox& box)
-{
-    bool isLTR = block.style().isLeftToRightDirection();
-    for (auto* currentBox = box.parent(); currentBox; currentBox = currentBox->parent()) {
-        if ((isLTR && currentBox->marginBorderPaddingLogicalRight() > 0)
-            || (!isLTR && currentBox->marginBorderPaddingLogicalLeft() > 0))
-            return true;
-    }
-    return false;
-}
-    
-static bool isLastInFlowRun(BidiRun& runToCheck)
-{
-    for (auto* run = runToCheck.next(); run; run = run->next()) {
-        if (!run->box() || run->renderer().isOutOfFlowPositioned() || run->box()->isLineBreak())
-            continue;
-        return false;
-    }
-    return true;
-}
-
-BidiRun* ComplexLineLayout::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, TextAlignMode textAlign, float& lineLogicalLeft,
-    float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
-    WordMeasurements& wordMeasurements)
-{
-    bool needsWordSpacing = false;
-    bool canHangPunctuationAtStart = style().hangingPunctuation().contains(HangingPunctuation::First);
-    bool canHangPunctuationAtEnd = style().hangingPunctuation().contains(HangingPunctuation::Last);
-    bool isLTR = style().isLeftToRightDirection();
-    float contentWidth = 0;
-    unsigned expansionOpportunityCount = 0;
-    bool isAfterExpansion = is<RenderRubyBase>(m_flow) ? downcast<RenderRubyBase>(m_flow).isAfterExpansion() : true;
-    Vector<unsigned, 16> expansionOpportunities;
-
-    HashMap<InlineTextBox*, LayoutUnit> logicalSpacingForInlineTextBoxes;
-    auto collectSpacingLogicalWidths = [&] () {
-        auto totalSpacingWidth = LayoutUnit { };
-        // Collect the spacing positions (margin, border padding) for the textboxes by traversing the inline tree of the current line.
-        Vector<InlineBox*> queue;
-        queue.append(lineBox);
-        // 1. Visit each inline box in a preorder fashion
-        // 2. Accumulate the spacing when we find an InlineFlowBox (inline container e.g. span)
-        // 3. Add the InlineTextBoxes to the hashmap
-        while (!queue.isEmpty()) {
-            while (true) {
-                auto* inlineBox = queue.last();
-                if (is<InlineFlowBox>(inlineBox)) {
-                    auto& inlineFlowBox = downcast<InlineFlowBox>(*inlineBox);
-                    totalSpacingWidth += inlineFlowBox.marginBorderPaddingLogicalLeft();
-                    if (auto* child = inlineFlowBox.firstChild()) {
-                        queue.append(child);
-                        continue;
-                    }
-                    break;
-                }
-                if (is<InlineTextBox>(inlineBox))
-                    logicalSpacingForInlineTextBoxes.add(downcast<InlineTextBox>(inlineBox), totalSpacingWidth);
-                break;
-            }
-            while (!queue.isEmpty()) {
-                auto& inlineBox = *queue.takeLast();
-                if (is<InlineFlowBox>(inlineBox))
-                    totalSpacingWidth += downcast<InlineFlowBox>(inlineBox).marginBorderPaddingLogicalRight();
-                if (auto* nextSibling = inlineBox.nextOnLine()) {
-                    queue.append(nextSibling);
-                    break;
-                }
-            }
-        }
-    };
-    collectSpacingLogicalWidths();
-
-    BidiRun* run = firstRun;
-    BidiRun* previousRun = nullptr;
-    for (; run; run = run->next()) {
-        auto computeExpansionOpportunities = [&expansionOpportunities, &expansionOpportunityCount, textAlign, &isAfterExpansion] (RenderBlockFlow& block,
-            InlineTextBox& textBox, BidiRun* previousRun, BidiRun* nextRun, const StringView& stringView, TextDirection direction)
-        {
-            if (stringView.isEmpty()) {
-                // Empty runs should still produce an entry in expansionOpportunities list so that the number of items matches the number of runs.
-                expansionOpportunities.append(0);
-                return;
-            }
-            ExpansionBehavior expansionBehavior = expansionBehaviorForInlineTextBox(block, textBox, previousRun, nextRun, textAlign, isAfterExpansion);
-            applyExpansionBehavior(textBox, expansionBehavior);
-            unsigned opportunitiesInRun;
-            std::tie(opportunitiesInRun, isAfterExpansion) = FontCascade::expansionOpportunityCount(stringView, direction, expansionBehavior);
-            expansionOpportunities.append(opportunitiesInRun);
-            expansionOpportunityCount += opportunitiesInRun;
-        };
-        if (!run->box() || run->renderer().isOutOfFlowPositioned() || run->box()->isLineBreak()) {
-            // Positioned objects are only participating to figure out their correct static x position.
-            // They have no effect on the width. Similarly, line break boxes have no effect on the width.
-            continue;
-        }
-        if (is<RenderText>(run->renderer())) {
-            auto& renderText = downcast<RenderText>(run->renderer());
-            auto& textBox = downcast<InlineTextBox>(*run->box());
-            if (canHangPunctuationAtStart && lineInfo.isFirstLine() && (isLTR || isLastInFlowRun(*run))
-                && !inlineAncestorHasStartBorderPaddingOrMargin(m_flow, *run->box())) {
-                float hangStartWidth = renderText.hangablePunctuationStartWidth(run->m_start);
-                availableLogicalWidth += hangStartWidth;
-                if (style().isLeftToRightDirection())
-                    lineLogicalLeft -= hangStartWidth;
-                canHangPunctuationAtStart = false;
-            }
-            
-            if (canHangPunctuationAtEnd && lineInfo.isLastLine() && run->m_stop > 0 && (!isLTR || isLastInFlowRun(*run))
-                && !inlineAncestorHasEndBorderPaddingOrMargin(m_flow, *run->box())) {
-                float hangEndWidth = renderText.hangablePunctuationEndWidth(run->m_stop - 1);
-                availableLogicalWidth += hangEndWidth;
-                if (!style().isLeftToRightDirection())
-                    lineLogicalLeft -= hangEndWidth;
-                canHangPunctuationAtEnd = false;
-            }
-            
-            if (textAlign == TextAlignMode::Justify && run != trailingSpaceRun)
-                computeExpansionOpportunities(m_flow, textBox, previousRun, run->next(), renderText.stringView(run->m_start, run->m_stop), run->box()->direction());
-
-            if (unsigned length = renderText.text().length()) {
-                if (!run->m_start && needsWordSpacing && isSpaceOrNewline(renderText.characterAt(run->m_start)))
-                    contentWidth += lineStyle(*renderText.parent(), lineInfo).fontCascade().wordSpacing();
-                // run->m_start == run->m_stop should only be true iff the run is a replaced run for bidi: isolate.
-                ASSERT(run->m_stop > 0 || run->m_start == run->m_stop);
-                needsWordSpacing = run->m_stop == length && !isSpaceOrNewline(renderText.characterAt(run->m_stop - 1));
-            }
-            auto currentLogicalLeftPosition = logicalSpacingForInlineTextBoxes.get(&textBox) + contentWidth;
-            setLogicalWidthForTextRun(lineBox, run, renderText, currentLogicalLeftPosition, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements);
-        } else {
-            canHangPunctuationAtStart = false;
-            bool encounteredJustifiedRuby = false;
-            if (is<RenderRubyRun>(run->renderer()) && textAlign == TextAlignMode::Justify && run != trailingSpaceRun && downcast<RenderRubyRun>(run->renderer()).rubyBase()) {
-                auto* rubyBase = downcast<RenderRubyRun>(run->renderer()).rubyBase();
-                if (rubyBase->firstRootBox() && !rubyBase->firstRootBox()->nextRootBox() && run->renderer().style().collapseWhiteSpace()) {
-                    rubyBase->setIsAfterExpansion(isAfterExpansion);
-                    for (auto* leafChild = rubyBase->firstRootBox()->firstLeafDescendant(); leafChild; leafChild = leafChild->nextLeafOnLine()) {
-                        if (!is<InlineTextBox>(*leafChild))
-                            continue;
-                        encounteredJustifiedRuby = true;
-                        computeExpansionOpportunities(*rubyBase, downcast<InlineTextBox>(*leafChild), nullptr, nullptr,
-                            downcast<RenderText>(leafChild->renderer()).stringView(), leafChild->direction());
-                    }
-                }
-            }
-
-            if (!encounteredJustifiedRuby)
-                isAfterExpansion = false;
-
-            if (!is<RenderInline>(run->renderer())) {
-                auto& renderBox = downcast<RenderBox>(run->renderer());
-                if (is<RenderRubyRun>(renderBox))
-                    setMarginsForRubyRun(run, downcast<RenderRubyRun>(renderBox), previousRun ? &previousRun->renderer() : nullptr, lineInfo);
-                run->box()->setLogicalWidth(m_flow.logicalWidthForChild(renderBox));
-                contentWidth += m_flow.marginStartForChild(renderBox) + m_flow.marginEndForChild(renderBox);
-            }
-        }
-
-        contentWidth += run->box()->logicalWidth();
-        previousRun = run;
-    }
-
-    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
-        // FIXME: see <webkit.org/b/139393#c11>
-        int lastValidExpansionOpportunitiesIndex = expansionOpportunities.size() - 1;
-        while (lastValidExpansionOpportunitiesIndex >= 0 && !expansionOpportunities.at(lastValidExpansionOpportunitiesIndex))
-            --lastValidExpansionOpportunitiesIndex;
-        if (lastValidExpansionOpportunitiesIndex >= 0) {
-            ASSERT(expansionOpportunities.at(lastValidExpansionOpportunitiesIndex));
-            expansionOpportunities.at(lastValidExpansionOpportunitiesIndex)--;
-            expansionOpportunityCount--;
-        }
-    }
-
-    if (is<RenderRubyBase>(m_flow) && !expansionOpportunityCount)
-        textAlign = TextAlignMode::Center;
-
-    auto totalLogicalWidth = contentWidth + lineBox->getFlowSpacingLogicalWidth();
-    updateLogicalWidthForAlignment(m_flow, textAlign, lineBox, trailingSpaceRun, lineLogicalLeft, totalLogicalWidth, availableLogicalWidth, expansionOpportunityCount);
-    computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth);
-    return run;
-}
-
-void ComplexLineLayout::removeInlineBox(BidiRun& run, const RootInlineBox& rootLineBox) const
-{
-    auto* inlineBox = run.box();
-#if ASSERT_ENABLED
-    auto* inlineParent = inlineBox->parent();
-    while (inlineParent && inlineParent != &rootLineBox) {
-        ASSERT(!inlineParent->isDirty());
-        inlineParent = inlineParent->parent();
-    }
-    ASSERT(!rootLineBox.isDirty());
-#endif
-    auto* parent = inlineBox->parent();
-    inlineBox->removeFromParent();
-
-    auto& renderer = run.renderer();
-    if (is<RenderText>(renderer))
-        downcast<RenderText>(renderer).removeTextBox(downcast<InlineTextBox>(*inlineBox));
-    delete inlineBox;
-    run.setBox(nullptr);
-    // removeFromParent() unnecessarily dirties the ancestor subtree.
-    auto* ancestor = parent;
-    while (ancestor) {
-        ancestor->markDirty(false);
-        if (ancestor == &rootLineBox)
-            break;
-        ancestor = ancestor->parent();
-    }
-}
-
-void ComplexLineLayout::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache)
-{
-    m_flow.setLogicalHeight(lineBox->alignBoxesInBlockDirection(m_flow.logicalHeight(), textBoxDataMap, verticalPositionCache));
-
-    // Now make sure we place replaced render objects correctly.
-    for (auto* run = firstRun; run; run = run->next()) {
-        ASSERT(run->box());
-        if (!run->box())
-            continue; // Skip runs with no line boxes.
-
-        // Align positioned boxes with the top of the line box. This is
-        // a reasonable approximation of an appropriate y position.
-        auto& renderer = run->renderer();
-        if (renderer.isOutOfFlowPositioned())
-            run->box()->setLogicalTop(m_flow.logicalHeight());
-
-        // Position is used to properly position both replaced elements and
-        // to update the static normal flow x/y of positioned elements.
-        bool inlineBoxIsRedundant = false;
-        if (is<RenderText>(renderer)) {
-            auto& inlineTextBox = downcast<InlineTextBox>(*run->box());
-            downcast<RenderText>(renderer).positionLineBox(inlineTextBox);
-            inlineBoxIsRedundant = !inlineTextBox.hasTextContent();
-        } else if (is<RenderBox>(renderer)) {
-            downcast<RenderBox>(renderer).positionLineBox(downcast<InlineElementBox>(*run->box()));
-            inlineBoxIsRedundant = renderer.isOutOfFlowPositioned();
-        } else if (is<RenderLineBreak>(renderer))
-            downcast<RenderLineBreak>(renderer).replaceInlineBoxWrapper(downcast<InlineElementBox>(*run->box()));
-        // Check if we need to keep this box on the line at all.
-        if (inlineBoxIsRedundant)
-            removeInlineBox(*run, *lineBox);
-    }
-}
-
-static inline bool isCollapsibleSpace(UChar character, const RenderText& renderer)
-{
-    if (character == ' ' || character == '\t' || character == softHyphen)
-        return true;
-    if (character == '\n')
-        return !renderer.style().preserveNewline();
-    if (character == noBreakSpace)
-        return renderer.style().nbspMode() == NBSPMode::Space;
-    return false;
-}
-
-template <typename CharacterType>
-static inline unsigned findFirstTrailingSpace(const RenderText& lastText, const CharacterType* characters, unsigned start, unsigned stop)
-{
-    unsigned firstSpace = stop;
-    while (firstSpace > start) {
-        UChar current = characters[firstSpace - 1];
-        if (!isCollapsibleSpace(current, lastText))
-            break;
-        firstSpace--;
-    }
-
-    return firstSpace;
-}
-
-inline BidiRun* ComplexLineLayout::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
-{
-    if (!bidiRuns.runCount()
-        || !bidiRuns.logicallyLastRun()->renderer().style().breakOnlyAfterWhiteSpace()
-        || !bidiRuns.logicallyLastRun()->renderer().style().autoWrap())
-        return nullptr;
-
-    BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
-    const RenderObject& lastObject = trailingSpaceRun->renderer();
-    if (!is<RenderText>(lastObject))
-        return nullptr;
-
-    const RenderText& lastText = downcast<RenderText>(lastObject);
-    unsigned firstSpace;
-    if (lastText.text().is8Bit())
-        firstSpace = findFirstTrailingSpace(lastText, lastText.text().characters8(), trailingSpaceRun->start(), trailingSpaceRun->stop());
-    else
-        firstSpace = findFirstTrailingSpace(lastText, lastText.text().characters16(), trailingSpaceRun->start(), trailingSpaceRun->stop());
-
-    if (firstSpace == trailingSpaceRun->stop())
-        return nullptr;
-
-    TextDirection direction = style().direction();
-    bool shouldReorder = trailingSpaceRun != (direction == TextDirection::LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
-    if (firstSpace != trailingSpaceRun->start()) {
-        BidiContext* baseContext = currentContext;
-        while (BidiContext* parent = baseContext->parent())
-            baseContext = parent;
-
-        std::unique_ptr<BidiRun> newTrailingRun = makeUnique<BidiRun>(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->renderer(), baseContext, U_OTHER_NEUTRAL);
-        trailingSpaceRun->m_stop = firstSpace;
-        trailingSpaceRun = newTrailingRun.get();
-        if (direction == TextDirection::LTR)
-            bidiRuns.appendRun(WTFMove(newTrailingRun));
-        else
-            bidiRuns.prependRun(WTFMove(newTrailingRun));
-        return trailingSpaceRun;
-    }
-    if (!shouldReorder)
-        return trailingSpaceRun;
-
-    if (direction == TextDirection::LTR) {
-        bidiRuns.moveRunToEnd(trailingSpaceRun);
-        trailingSpaceRun->m_level = 0;
-    } else {
-        bidiRuns.moveRunToBeginning(trailingSpaceRun);
-        trailingSpaceRun->m_level = 1;
-    }
-    return trailingSpaceRun;
-}
-
-void ComplexLineLayout::appendFloatingObjectToLastLine(FloatingObject& floatingObject)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject.originatingLine());
-    ASSERT(lastRootBox());
-    floatingObject.setOriginatingLine(*lastRootBox());
-    lastRootBox()->appendFloat(floatingObject.renderer());
-}
-
-static inline void notifyResolverToResumeInIsolate(InlineBidiResolver& resolver, RenderObject* root, RenderObject* startObject)
-{
-    if (root != startObject) {
-        RenderObject* parent = startObject->parent();
-        notifyResolverToResumeInIsolate(resolver, root, parent);
-        notifyObserverEnteredObject(&resolver, startObject);
-    }
-}
-
-static inline void setUpResolverToResumeInIsolate(InlineBidiResolver& resolver, InlineBidiResolver& topResolver, BidiRun& isolatedRun, RenderObject* root, RenderObject* startObject)
-{
-    // Set up m_whitespaceCollapsingState
-    resolver.whitespaceCollapsingState() = topResolver.whitespaceCollapsingState();
-    resolver.whitespaceCollapsingState().setCurrentTransition(topResolver.whitespaceCollapsingTransitionForIsolatedRun(isolatedRun));
-
-    // Set up m_nestedIsolateCount
-    notifyResolverToResumeInIsolate(resolver, root, startObject);
-}
-
-// FIXME: BidiResolver should have this logic.
-static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfRuns, VisualDirectionOverride override, bool previousLineBrokeCleanly)
-{
-    // FIXME: We should pass a BidiRunList into createBidiRunsForLine instead
-    // of the resolver owning the runs.
-    ASSERT(&topResolver.runs() == &bidiRuns);
-    ASSERT(topResolver.position() != endOfRuns);
-    RenderObject* currentRoot = topResolver.position().root();
-    topResolver.createBidiRunsForLine(endOfRuns, override, previousLineBrokeCleanly);
-
-    while (!topResolver.isolatedRuns().isEmpty()) {
-        // It does not matter which order we resolve the runs as long as we resolve them all.
-        auto isolatedRun = WTFMove(topResolver.isolatedRuns().last());
-        topResolver.isolatedRuns().removeLast();
-        currentRoot = &isolatedRun.root;
-
-        RenderObject& startObject = isolatedRun.object;
-
-        // Only inlines make sense with unicode-bidi: isolate (blocks are already isolated).
-        // FIXME: Because enterIsolate is not passed a RenderObject, we have to crawl up the
-        // tree to see which parent inline is the isolate. We could change enterIsolate
-        // to take a RenderObject and do this logic there, but that would be a layering
-        // violation for BidiResolver (which knows nothing about RenderObject).
-        RenderInline* isolatedInline = downcast<RenderInline>(highestContainingIsolateWithinRoot(startObject, currentRoot));
-        ASSERT(isolatedInline);
-
-        InlineBidiResolver isolatedResolver;
-        EUnicodeBidi unicodeBidi = isolatedInline->style().unicodeBidi();
-        TextDirection direction;
-        if (unicodeBidi == Plaintext)
-            determineDirectionality(direction, InlineIterator(isolatedInline, &isolatedRun.object, 0));
-        else {
-            ASSERT(unicodeBidi == Isolate || unicodeBidi == IsolateOverride);
-            direction = isolatedInline->style().direction();
-        }
-        isolatedResolver.setStatus(BidiStatus(direction, isOverride(unicodeBidi)));
-
-        setUpResolverToResumeInIsolate(isolatedResolver, topResolver, isolatedRun.runToReplace, isolatedInline, &startObject);
-
-        // The starting position is the beginning of the first run within the isolate that was identified
-        // during the earlier call to createBidiRunsForLine. This can be but is not necessarily the
-        // first run within the isolate.
-        InlineIterator iter = InlineIterator(isolatedInline, &startObject, isolatedRun.position);
-        isolatedResolver.setPositionIgnoringNestedIsolates(iter);
-
-        // We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns().
-        // FIXME: What should end and previousLineBrokeCleanly be?
-        // rniwa says previousLineBrokeCleanly is just a WinIE hack and could always be false here?
-        isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, previousLineBrokeCleanly);
-        // Note that we do not delete the runs from the resolver.
-        // We're not guaranteed to get any BidiRuns in the previous step. If we don't, we allow the placeholder
-        // itself to be turned into an InlineBox. We can't remove it here without potentially losing track of
-        // the logically last run.
-        if (isolatedResolver.runs().runCount())
-            bidiRuns.replaceRunWithRuns(&isolatedRun.runToReplace, isolatedResolver.runs());
-
-        // If we encountered any nested isolate runs, just move them
-        // to the top resolver's list for later processing.
-        while (!isolatedResolver.isolatedRuns().isEmpty()) {
-            auto runWithContext = WTFMove(isolatedResolver.isolatedRuns().last());
-            isolatedResolver.isolatedRuns().removeLast();
-            topResolver.setWhitespaceCollapsingTransitionForIsolatedRun(runWithContext.runToReplace, isolatedResolver.whitespaceCollapsingTransitionForIsolatedRun(runWithContext.runToReplace));
-            topResolver.isolatedRuns().append(WTFMove(runWithContext));
-        }
-    }
-}
-
-// This function constructs line boxes for all of the text runs in the resolver and computes their position.
-RootInlineBox* ComplexLineLayout::createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
-{
-    if (!bidiRuns.runCount())
-        return nullptr;
-
-    // FIXME: Why is this only done when we had runs?
-    lineInfo.setLastLine(!end.renderer());
-
-    RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo);
-    if (!lineBox)
-        return nullptr;
-
-    lineBox->setBidiLevel(bidiLevel);
-    lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly());
-    
-    bool isSVGRootInlineBox = is<SVGRootInlineBox>(*lineBox);
-    
-    GlyphOverflowAndFallbackFontsMap textBoxDataMap;
-    
-    // Now we position all of our text runs horizontally.
-    if (!isSVGRootInlineBox)
-        computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wordMeasurements);
-    
-    // Now position our text runs vertically.
-    computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
-    
-    // SVG text layout code computes vertical & horizontal positions on its own.
-    // Note that we still need to execute computeVerticalPositionsForLine() as
-    // it calls InlineTextBox::positionLineBox(), which tracks whether the box
-    // contains reversed text or not. If we wouldn't do that editing and thus
-    // text selection in RTL boxes would not work as expected.
-    if (isSVGRootInlineBox) {
-        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_flow.isSVGText());
-        downcast<SVGRootInlineBox>(*lineBox).computePerCharacterLayoutInformation();
-    }
-    
-    // Compute our overflow now.
-    lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
-    
-    return lineBox;
-}
-
-static void deleteLineRange(LineLayoutState& layoutState, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
-{
-    RootInlineBox* boxToDelete = startLine;
-    while (boxToDelete && boxToDelete != stopLine) {
-        layoutState.updateRepaintRangeFromBox(boxToDelete);
-        // Note: deleteLineRange(firstRootBox()) is not identical to deleteLineBoxTree().
-        // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
-        RootInlineBox* next = boxToDelete->nextRootBox();
-        boxToDelete->deleteLine();
-        boxToDelete = next;
-    }
-}
-
-static void repaintDirtyFloats(LineLayoutState::FloatList& floats)
-{
-    // Floats that did not have layout did not repaint when we laid them out. They would have
-    // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
-    // painted.
-    for (auto& floatBox : floats) {
-        if (floatBox->everHadLayout())
-            continue;
-        auto& box = floatBox->renderer();
-        if (!box.x() && !box.y() && box.checkForRepaintDuringLayout())
-            box.repaint();
-    }
-}
-
-void ComplexLineLayout::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
-{
-    // We want to skip ahead to the first dirty line
-    InlineBidiResolver resolver;
-    RootInlineBox* startLine = determineStartPosition(layoutState, resolver);
-    
-    unsigned consecutiveHyphenatedLines = 0;
-    if (startLine) {
-        for (RootInlineBox* line = startLine->prevRootBox(); line && line->isHyphenated(); line = line->prevRootBox())
-            consecutiveHyphenatedLines++;
-    }
-
-    // FIXME: This would make more sense outside of this function, but since
-    // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
-    // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
-    if (layoutState.isFullLayout() && hasInlineChild && !m_flow.selfNeedsLayout()) {
-        m_flow.setNeedsLayout(MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
-        if (!layoutContext().needsFullRepaint() && m_flow.layerRepaintRects()) {
-            // Because we waited until we were already inside layout to discover
-            // that the block really needed a full layout, we missed our chance to repaint the layer
-            // before layout started. Luckily the layer has cached the repaint rect for its original
-            // position and size, and so we can use that to make a repaint happen now.
-            m_flow.repaintUsingContainer(m_flow.containerForRepaint(), m_flow.layerRepaintRects()->clippedOverflowRect);
-        }
-    }
-
-    if (m_flow.containsFloats())
-        layoutState.floatList().setLastFloat(m_flow.floatingObjects()->set().last().get());
-
-    // We also find the first clean line and extract these lines. We will add them back
-    // if we determine that we're able to synchronize after handling all our dirty lines.
-    InlineIterator cleanLineStart;
-    BidiStatus cleanLineBidiStatus;
-    if (!layoutState.isFullLayout() && startLine)
-        determineEndPosition(layoutState, startLine, cleanLineStart, cleanLineBidiStatus);
-
-    if (startLine) {
-        if (!layoutState.usesRepaintBounds())
-            layoutState.setRepaintRange(m_flow.logicalHeight());
-        deleteLineRange(layoutState, startLine);
-    }
-
-    if (!layoutState.isFullLayout() && lastRootBox() && lastRootBox()->endsWithBreak()) {
-        // If the last line before the start line ends with a line break that clear floats,
-        // adjust the height accordingly.
-        // A line break can be either the first or the last object on a line, depending on its direction.
-        if (InlineBox* lastLeafDescendant = lastRootBox()->lastLeafDescendant()) {
-            RenderObject* lastObject = &lastLeafDescendant->renderer();
-            if (!lastObject->isBR())
-                lastObject = &lastRootBox()->firstLeafDescendant()->renderer();
-            if (lastObject->isBR()) {
-                auto clear = RenderStyle::usedClear(*lastObject);
-                if (clear != UsedClear::None)
-                    m_flow.clearFloats(clear);
-            }
-        }
-    }
-
-    layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines);
-    linkToEndLineIfNeeded(layoutState);
-    repaintDirtyFloats(layoutState.floatList());
-}
-
-// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
-inline const InlineIterator& ComplexLineLayout::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver,  const InlineIterator& oldEnd)
-{
-    m_flow.removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
-    m_flow.setLogicalHeight(newLogicalHeight);
-    resolver.setPositionIgnoringNestedIsolates(oldEnd);
-    return oldEnd;
-}
-
-void ComplexLineLayout::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
-{
-    const RenderStyle& styleToUse = style();
-    bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
-    LineWhitespaceCollapsingState& lineWhitespaceCollapsingState = resolver.whitespaceCollapsingState();
-    InlineIterator end = resolver.position();
-    bool checkForEndLineMatch = layoutState.endLine();
-    RenderTextInfo renderTextInfo;
-    VerticalPositionCache verticalPositionCache;
-
-    LineBreaker lineBreaker(m_flow);
-
-    while (!end.atEnd()) {
-        // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
-        if (checkForEndLineMatch) {
-            layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus));
-            if (layoutState.endLineMatched()) {
-                resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
-                layoutState.marginInfo().clearMargin();
-                break;
-            }
-        }
-
-        lineWhitespaceCollapsingState.reset();
-
-        layoutState.lineInfo().setEmpty(true);
-        layoutState.lineInfo().resetRunsFromLeadingWhitespace();
-
-        const InlineIterator oldEnd = end;
-        bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
-        FloatingObject* lastFloatFromPreviousLine = (m_flow.containsFloats()) ? m_flow.floatingObjects()->set().last().get() : nullptr;
-
-        WordMeasurements wordMeasurements;
-        end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
-        m_flow.cachePriorCharactersIfNeeded(renderTextInfo.lineBreakIterator);
-        renderTextInfo.lineBreakIterator.resetPriorContext();
-        if (resolver.position().atEnd()) {
-            // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
-            // Once BidiRunList is separated from BidiResolver this will not be needed.
-            resolver.runs().clear();
-            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
-            layoutState.setCheckForFloatsFromLastLine(true);
-            resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
-            break;
-        }
-
-        ASSERT(end != resolver.position());
-
-        // This is a short-cut for empty lines.
-        if (layoutState.lineInfo().isEmpty()) {
-            if (lastRootBox())
-                lastRootBox()->setLineBreakInfo(end.renderer(), end.offset(), resolver.status());
-        } else {
-            VisualDirectionOverride override = (styleToUse.rtlOrdering() == Order::Visual ? (styleToUse.direction() == TextDirection::LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
-
-            if (isNewUBAParagraph && styleToUse.unicodeBidi() == Plaintext && !resolver.context()->parent()) {
-                TextDirection direction = styleToUse.direction();
-                determineDirectionality(direction, resolver.position());
-                resolver.setStatus(BidiStatus(direction, isOverride(styleToUse.unicodeBidi())));
-            }
-            // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
-            BidiRunList<BidiRun>& bidiRuns = resolver.runs();
-            constructBidiRunsForSegment(resolver, bidiRuns, end, override, layoutState.lineInfo().previousLineBrokeCleanly());
-            ASSERT(resolver.position() == end);
-
-            BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrokeCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : nullptr;
-
-            if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
-                bidiRuns.logicallyLastRun()->m_hasHyphen = true;
-                consecutiveHyphenatedLines++;
-            } else
-                consecutiveHyphenatedLines = 0;
-
-            // Now that the runs have been ordered, we create the line boxes.
-            // At the same time we figure out where border/padding/margin should be applied for
-            // inline flow boxes.
-
-            LayoutUnit oldLogicalHeight = m_flow.logicalHeight();
-            RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status().context->level(), bidiRuns, end, layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, wordMeasurements);
-
-            bidiRuns.clear();
-            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
-
-            if (lineBox) {
-                lineBox->setLineBreakInfo(end.renderer(), end.offset(), resolver.status());
-                if (layoutState.usesRepaintBounds())
-                    layoutState.updateRepaintRangeFromBox(lineBox);
-                
-                LayoutUnit adjustment;
-                bool overflowsFragment = false;
-                
-                layoutState.marginInfo().setAtBeforeSideOfBlock(false);
-
-                if (paginated)
-                    m_flow.adjustLinePositionForPagination(lineBox, adjustment, overflowsFragment, layoutState.fragmentedFlow());
-                if (adjustment) {
-                    IndentTextOrNot shouldIndentText = layoutState.lineInfo().isFirstLine() ? IndentText : DoNotIndentText;
-                    LayoutUnit oldLineWidth = m_flow.availableLogicalWidthForLine(oldLogicalHeight, shouldIndentText);
-                    lineBox->adjustBlockDirectionPosition(adjustment);
-                    if (layoutState.usesRepaintBounds())
-                        layoutState.updateRepaintRangeFromBox(lineBox);
-
-                    if (m_flow.availableLogicalWidthForLine(oldLogicalHeight + adjustment, shouldIndentText) != oldLineWidth) {
-                        // We have to delete this line, remove all floats that got added, and let line layout re-run.
-                        lineBox->deleteLine();
-                        end = restartLayoutRunsAndFloatsInRange(oldLogicalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, oldEnd);
-                        continue;
-                    }
-
-                    m_flow.setLogicalHeight(lineBox->lineBoxBottom());
-                }
-                    
-                if (paginated) {
-                    if (layoutState.fragmentedFlow())
-                        updateFragmentForLine(lineBox);
-                }
-            }
-        }
-
-        for (size_t i = 0; i < lineBreaker.positionedObjects().size(); ++i)
-            setStaticPositions(m_flow, *lineBreaker.positionedObjects()[i], DoNotIndentText);
-
-        if (!layoutState.lineInfo().isEmpty()) {
-            layoutState.lineInfo().setFirstLine(false);
-            m_flow.clearFloats(lineBreaker.usedClear());
-        }
-
-        if (m_flow.floatingObjects() && lastRootBox()) {
-            const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
-            auto it = floatingObjectSet.begin();
-            auto end = floatingObjectSet.end();
-            if (auto* lastFloat = layoutState.floatList().lastFloat()) {
-                auto lastFloatIterator = floatingObjectSet.find(lastFloat);
-                ASSERT(lastFloatIterator != end);
-                ++lastFloatIterator;
-                it = lastFloatIterator;
-            }
-            for (; it != end; ++it) {
-                auto& floatingObject = *it;
-                appendFloatingObjectToLastLine(*floatingObject);
-                // If a float's geometry has changed, give up on syncing with clean lines.
-                auto* floatWithRect = layoutState.floatList().floatWithRect(floatingObject->renderer());
-                if (!floatWithRect || floatWithRect->rect() != floatingObject->frameRect())
-                    checkForEndLineMatch = false;
-            }
-            layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
-        }
-
-        lineWhitespaceCollapsingState.reset();
-        resolver.setPosition(end, numberOfIsolateAncestors(end));
-    }
-
-    // In case we already adjusted the line positions during this layout to avoid widows
-    // then we need to ignore the possibility of having a new widows situation.
-    // Otherwise, we risk leaving empty containers which is against the block fragmentation principles.
-    if (paginated && !style().hasAutoWidows() && !m_flow.didBreakAtLineToAvoidWidow()) {
-        // Check the line boxes to make sure we didn't create unacceptable widows.
-        // However, we'll prioritize orphans - so nothing we do here should create
-        // a new orphan.
-
-        RootInlineBox* lineBox = lastRootBox();
-
-        // Count from the end of the block backwards, to see how many hanging
-        // lines we have.
-        RootInlineBox* firstLineInBlock = firstRootBox();
-        int numLinesHanging = 1;
-        while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
-            ++numLinesHanging;
-            lineBox = lineBox->prevRootBox();
-        }
-
-        // If there were no breaks in the block, we didn't create any widows.
-        if (!lineBox || !lineBox->isFirstAfterPageBreak() || lineBox == firstLineInBlock) {
-            if (m_flow.shouldBreakAtLineToAvoidWidow()) {
-                // This is the case when the previous line layout marks a line to break at to avoid widows
-                // but the current layout does not produce that line. It happens when layout constraints unexpectedly
-                // change in between layouts (note that these paginated line layouts run within the same layout frame
-                // as opposed to two subsequent full layouts).
-                ASSERT_NOT_REACHED();
-                m_flow.clearShouldBreakAtLineToAvoidWidow();
-            }
-            return;
-        }
-
-        if (numLinesHanging < style().widows()) {
-            // We have detected a widow. Now we need to work out how many
-            // lines there are on the previous page, and how many we need
-            // to steal.
-            int numLinesNeeded = style().widows() - numLinesHanging;
-            RootInlineBox* currentFirstLineOfNewPage = lineBox;
-
-            // Count the number of lines in the previous page.
-            lineBox = lineBox->prevRootBox();
-            int numLinesInPreviousPage = 1;
-            while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
-                ++numLinesInPreviousPage;
-                lineBox = lineBox->prevRootBox();
-            }
-
-            // If there was an explicit value for orphans, respect that. If not, we still
-            // shouldn't create a situation where we make an orphan bigger than the initial value.
-            // This means that setting widows implies we also care about orphans, but given
-            // the specification says the initial orphan value is non-zero, this is ok. The
-            // author is always free to set orphans explicitly as well.
-            int orphans = style().hasAutoOrphans() ? style().initialOrphans() : style().orphans();
-            int numLinesAvailable = numLinesInPreviousPage - orphans;
-            if (numLinesAvailable <= 0)
-                return;
-
-            int numLinesToTake = std::min(numLinesAvailable, numLinesNeeded);
-            // Wind back from our first widowed line.
-            lineBox = currentFirstLineOfNewPage;
-            for (int i = 0; i < numLinesToTake; ++i)
-                lineBox = lineBox->prevRootBox();
-
-            // We now want to break at this line. Remember for next layout and trigger relayout.
-            m_flow.setBreakAtLineToAvoidWidow(lineCountUntil(lineBox));
-            m_flow.markLinesDirtyInBlockRange(lastRootBox()->lineBoxBottom(), lineBox->lineBoxBottom(), lineBox);
-        }
-    }
-    m_flow.clearDidBreakAtLineToAvoidWidow();
-}
-
-void ComplexLineLayout::reattachCleanLineFloats(RootInlineBox& cleanLine, LayoutUnit delta, bool isFirstCleanLine)
-{
-    auto* cleanLineFloats = cleanLine.floatsPtr();
-    if (!cleanLineFloats)
-        return;
-
-    for (auto& floatingBox : *cleanLineFloats) {
-        if (!floatingBox)
-            continue;
-        auto* floatingObject = m_flow.insertFloatingObject(*floatingBox);
-        if (isFirstCleanLine && floatingObject->originatingLine()) {
-            // Float box does not belong to this line anymore.
-            ASSERT_WITH_SECURITY_IMPLICATION(cleanLine.prevRootBox() == floatingObject->originatingLine());
-            cleanLine.removeFloat(*floatingBox);
-            continue;
-        }
-        ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject->originatingLine());
-        floatingObject->setOriginatingLine(cleanLine);
-        m_flow.setLogicalHeight(m_flow.logicalTopForChild(*floatingBox) - m_flow.marginBeforeForChild(*floatingBox) + delta);
-        m_flow.positionNewFloats();
-    }
-}
-
-void ComplexLineLayout::linkToEndLineIfNeeded(LineLayoutState& layoutState)
-{
-    auto* firstCleanLine = layoutState.endLine();
-    if (firstCleanLine) {
-        if (layoutState.endLineMatched()) {
-            bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
-            // Attach all the remaining lines, and then adjust their y-positions as needed.
-            LayoutUnit delta = m_flow.logicalHeight() - layoutState.endLineLogicalTop();
-            for (auto* line = firstCleanLine; line; line = line->nextRootBox()) {
-                line->attachLine();
-                if (paginated) {
-                    delta -= line->paginationStrut();
-                    bool overflowsFragment;
-                    m_flow.adjustLinePositionForPagination(line, delta, overflowsFragment, layoutState.fragmentedFlow());
-                }
-                if (delta) {
-                    layoutState.updateRepaintRangeFromBox(line, delta);
-                    line->adjustBlockDirectionPosition(delta);
-                }
-                if (layoutState.fragmentedFlow())
-                    updateFragmentForLine(line);
-                reattachCleanLineFloats(*line, delta, line == firstCleanLine);
-            }
-            m_flow.setLogicalHeight(lastRootBox()->lineBoxBottom());
-        } else {
-            // Delete all the remaining lines.
-            deleteLineRange(layoutState, layoutState.endLine());
-        }
-    }
-    
-    if (m_flow.floatingObjects() && (layoutState.checkForFloatsFromLastLine() || m_flow.positionNewFloats()) && lastRootBox()) {
-        // In case we have a float on the last line, it might not be positioned up to now.
-        // This has to be done before adding in the bottom border/padding, or the float will
-        // include the padding incorrectly. -dwh
-        if (layoutState.checkForFloatsFromLastLine()) {
-            LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
-            LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
-            auto newLineBox = makeUnique<TrailingFloatsRootInlineBox>(m_flow);
-            auto trailingFloatsLineBox = newLineBox.get();
-            m_lineBoxes.appendLineBox(WTFMove(newLineBox));
-            trailingFloatsLineBox->setConstructed();
-            GlyphOverflowAndFallbackFontsMap textBoxDataMap;
-            VerticalPositionCache verticalPositionCache;
-            LayoutUnit blockLogicalHeight = m_flow.logicalHeight();
-            trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
-            trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
-            trailingFloatsLineBox->setPaginatedLineWidth(m_flow.availableLogicalWidthForContent(blockLogicalHeight));
-            LayoutRect logicalLayoutOverflow(0_lu, blockLogicalHeight, 1_lu, bottomLayoutOverflow - blockLogicalHeight);
-            LayoutRect logicalVisualOverflow(0_lu, blockLogicalHeight, 1_lu, bottomVisualOverflow - blockLogicalHeight);
-            trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
-            if (layoutState.fragmentedFlow())
-                updateFragmentForLine(trailingFloatsLineBox);
-        }
-
-        const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
-        auto it = floatingObjectSet.begin();
-        auto end = floatingObjectSet.end();
-        if (auto* lastFloat = layoutState.floatList().lastFloat()) {
-            auto lastFloatIterator = floatingObjectSet.find(lastFloat);
-            ASSERT(lastFloatIterator != end);
-            ++lastFloatIterator;
-            it = lastFloatIterator;
-        }
-        for (; it != end; ++it)
-            appendFloatingObjectToLastLine(**it);
-        layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
-    }
-}
-
-void ComplexLineLayout::layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom)
-{
-    m_flow.setLogicalHeight(m_flow.borderAndPaddingBefore());
-    
-    // Lay out our hypothetical grid line as though it occurs at the top of the block.
-    if (layoutContext().layoutState() && layoutContext().layoutState()->lineGrid() == &m_flow)
-        m_flow.layoutLineGridBox();
-
-    RenderFragmentedFlow* fragmentedFlow = m_flow.enclosingFragmentedFlow();
-    bool clearLinesForPagination = firstRootBox() && fragmentedFlow && !fragmentedFlow->hasFragments();
-
-    // Figure out if we should clear out our line boxes.
-    // FIXME: Handle resize eventually!
-    bool isFullLayout = !firstRootBox() || m_flow.selfNeedsLayout() || relayoutChildren || clearLinesForPagination;
-    LineLayoutState layoutState(m_flow, isFullLayout, repaintLogicalTop, repaintLogicalBottom, fragmentedFlow);
-
-    if (isFullLayout)
-        lineBoxes().deleteLineBoxes();
-
-    // Text truncation kicks in in two cases:
-    //     1) If your overflow isn't visible and your text-overflow-mode isn't clip.
-    //     2) If you're an anonymous block with a block parent that satisfies #1.
-    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate. This is insanely
-    // difficult to figure out in general (especially in the middle of doing layout), so we only handle the
-    // simple case of an anonymous block truncating when it's parent is clipped.
-    auto* parent = m_flow.parent();
-    bool hasTextOverflow = (style().textOverflow() == TextOverflow::Ellipsis && m_flow.hasOverflowClip())
-        || (m_flow.isAnonymousBlock() && parent && parent->isRenderBlock() && parent->style().textOverflow() == TextOverflow::Ellipsis && parent->hasOverflowClip());
-
-    // Walk all the lines and delete our ellipsis line boxes if they exist.
-    if (hasTextOverflow)
-        deleteEllipsisLineBoxes();
-
-    if (m_flow.firstChild()) {
-        // In full layout mode, clear the line boxes of children upfront. Otherwise,
-        // siblings can run into stale root lineboxes during layout. Then layout
-        // the replaced elements later. In partial layout mode, line boxes are not
-        // deleted and only dirtied. In that case, we can layout the replaced
-        // elements at the same time.
-        bool hasInlineChild = false;
-        Vector<RenderBox*> replacedChildren;
-        for (InlineWalker walker(m_flow); !walker.atEnd(); walker.advance()) {
-            RenderObject& o = *walker.current();
-
-            if (!hasInlineChild && o.isInline())
-                hasInlineChild = true;
-
-            if (o.isReplaced() || o.isFloating() || o.isOutOfFlowPositioned()) {
-                RenderBox& box = downcast<RenderBox>(o);
-
-                if (relayoutChildren || box.hasRelativeDimensions())
-                    box.setChildNeedsLayout(MarkOnlyThis);
-
-                // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
-                if (relayoutChildren && box.needsPreferredWidthsRecalculation())
-                    box.setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
-
-                if (box.isOutOfFlowPositioned())
-                    box.containingBlock()->insertPositionedObject(box);
-                else if (box.isFloating())
-                    layoutState.floatList().append(FloatWithRect::create(box));
-                else if (isFullLayout || box.needsLayout()) {
-                    // Replaced element.
-                    if (isFullLayout && is<RenderRubyRun>(box)) {
-                        // FIXME: This resets the overhanging margins that we set during line layout (see computeInlineDirectionPositionsForSegment)
-                        // Find a more suitable place for this.
-                        m_flow.setMarginStartForChild(box, 0);
-                        m_flow.setMarginEndForChild(box, 0);
-                    }
-                    box.dirtyLineBoxes(isFullLayout);
-                    if (isFullLayout)
-                        replacedChildren.append(&box);
-                    else
-                        box.layoutIfNeeded();
-                }
-            } else if (o.isTextOrLineBreak() || (is<RenderInline>(o) && !walker.atEndOfInline())) {
-                if (is<RenderInline>(o))
-                    downcast<RenderInline>(o).updateAlwaysCreateLineBoxes(layoutState.isFullLayout());
-                if (layoutState.isFullLayout() || o.selfNeedsLayout())
-                    dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
-                o.clearNeedsLayout();
-            }
-        }
-
-        for (size_t i = 0; i < replacedChildren.size(); i++)
-            replacedChildren[i]->layoutIfNeeded();
-
-        layoutRunsAndFloats(layoutState, hasInlineChild);
-    }
-
-    // Expand the last line to accommodate Ruby and emphasis marks.
-    int lastLineAnnotationsAdjustment = 0;
-    if (lastRootBox()) {
-        LayoutUnit lowestAllowedPosition = std::max(lastRootBox()->lineBottom(), m_flow.logicalHeight() + m_flow.paddingAfter());
-        if (!style().isFlippedLinesWritingMode())
-            lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
-        else
-            lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
-    }
-    
-    // Now do the handling of the bottom of the block, adding in our bottom border/padding and
-    // determining the correct collapsed bottom margin information. This collapse is only necessary
-    // if our last child was an anonymous inline block that might need to propagate margin information out to
-    // us.
-    LayoutUnit afterEdge = m_flow.borderAndPaddingAfter() + m_flow.scrollbarLogicalHeight() + lastLineAnnotationsAdjustment;
-    m_flow.setLogicalHeight(m_flow.logicalHeight() + afterEdge);
-
-    if (!firstRootBox() && m_flow.hasLineIfEmpty())
-        m_flow.setLogicalHeight(m_flow.logicalHeight() + m_flow.lineHeight(true, m_flow.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
-
-    // See if we have any lines that spill out of our block. If we do, then we will possibly need to
-    // truncate text.
-    if (hasTextOverflow)
-        checkLinesForTextOverflow();
-}
-
-void ComplexLineLayout::checkFloatInCleanLine(RootInlineBox& cleanLine, RenderBox& floatBoxOnCleanLine, FloatWithRect& matchingFloatWithRect,
-    bool& encounteredNewFloat, bool& dirtiedByFloat)
-{
-    ASSERT_WITH_SECURITY_IMPLICATION(!floatBoxOnCleanLine.style().deletionHasBegun());
-    if (&matchingFloatWithRect.renderer() != &floatBoxOnCleanLine) {
-        encounteredNewFloat = true;
-        return;
-    }
-    floatBoxOnCleanLine.layoutIfNeeded();
-    LayoutRect originalFloatRect = matchingFloatWithRect.rect();
-    LayoutSize newSize(
-        floatBoxOnCleanLine.width() + floatBoxOnCleanLine.horizontalMarginExtent(),
-        floatBoxOnCleanLine.height() + floatBoxOnCleanLine.verticalMarginExtent());
-    
-    // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats as dirty.
-    if (originalFloatRect.size() == newSize && (floatBoxOnCleanLine.style().styleType() != PseudoId::FirstLetter || !floatBoxOnCleanLine.style().initialLetterDrop()))
-        return;
-
-    LayoutUnit floatTop = m_flow.isHorizontalWritingMode() ? originalFloatRect.y() : originalFloatRect.x();
-    LayoutUnit floatHeight = m_flow.isHorizontalWritingMode() ? std::max(originalFloatRect.height(), newSize.height())
-        : std::max(originalFloatRect.width(), newSize.width());
-    floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop);
-    cleanLine.markDirty();
-    m_flow.markLinesDirtyInBlockRange(cleanLine.lineBoxBottom(), floatTop + floatHeight, &cleanLine);
-    LayoutRect newFloatRect = originalFloatRect;
-    newFloatRect.setSize(newSize);
-    matchingFloatWithRect.adjustRect(newFloatRect);
-    dirtiedByFloat = true;
-}
-
-RootInlineBox* ComplexLineLayout::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
-{
-    RootInlineBox* currentLine = nullptr;
-    RootInlineBox* lastLine = nullptr;
-
-    // FIXME: This entire float-checking block needs to be broken into a new function.
-    auto& floats = layoutState.floatList();
-    bool dirtiedByFloat = false;
-    if (!layoutState.isFullLayout()) {
-        // Paginate all of the clean lines.
-        bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
-        LayoutUnit paginationDelta;
-        auto floatsIterator = floats.begin();
-        auto end = floats.end();
-        for (currentLine = firstRootBox(); currentLine && !currentLine->isDirty(); currentLine = currentLine->nextRootBox()) {
-            if (paginated) {
-                if (lineWidthForPaginatedLineChanged(currentLine, 0, layoutState.fragmentedFlow())) {
-                    currentLine->markDirty();
-                    break;
-                }
-                paginationDelta -= currentLine->paginationStrut();
-                bool overflowsFragment;
-                m_flow.adjustLinePositionForPagination(currentLine, paginationDelta, overflowsFragment, layoutState.fragmentedFlow());
-                if (paginationDelta) {
-                    if (m_flow.containsFloats() || !floats.isEmpty()) {
-                        // FIXME: Do better eventually. For now if we ever shift because of pagination and floats are present just go to a full layout.
-                        layoutState.markForFullLayout();
-                        break;
-                    }
-
-                    layoutState.updateRepaintRangeFromBox(currentLine, paginationDelta);
-                    currentLine->adjustBlockDirectionPosition(paginationDelta);
-                }
-                if (layoutState.fragmentedFlow())
-                    updateFragmentForLine(currentLine);
-            }
-
-            if (auto* cleanLineFloats = currentLine->floatsPtr()) {
-                // If a new float has been inserted before this line or before its last known float, just do a full layout.
-                bool encounteredNewFloat = false;
-                for (auto& floatBoxOnCleanLine : *cleanLineFloats) {
-                    ASSERT(floatsIterator != end);
-                    if (!floatBoxOnCleanLine)
-                        continue;
-                    checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat);
-                    ++floatsIterator;
-                    if (floatsIterator == end || encounteredNewFloat) {
-                        layoutState.markForFullLayout();
-                        break;
-                    }
-                }
-                if (dirtiedByFloat || encounteredNewFloat)
-                    break;
-            }
-        }
-        // Check if a new float has been inserted after the last known float.
-        if (floatsIterator != end) {
-            if (!currentLine)
-                layoutState.markForFullLayout();
-            else {
-                for (; floatsIterator != end; ++floatsIterator) {
-                    auto& floatWithRect = *floatsIterator;
-                    if (!floatWithRect->renderer().needsLayout())
-                        continue;
-                    layoutState.markForFullLayout();
-                    break;
-                }
-            }
-        }
-    }
-
-    if (layoutState.isFullLayout()) {
-        m_lineBoxes.deleteLineBoxTree();
-        currentLine = nullptr;
-        ASSERT(!firstRootBox() && !lastRootBox());
-    } else {
-        if (currentLine) {
-            // We have a dirty line.
-            if (RootInlineBox* prevRootBox = currentLine->prevRootBox()) {
-                // We have a previous line.
-                if (!dirtiedByFloat && (!prevRootBox->endsWithBreak()
-                    || !prevRootBox->lineBreakObj()
-                    || (is<RenderText>(*prevRootBox->lineBreakObj())
-                    && prevRootBox->lineBreakPos() >= downcast<RenderText>(*prevRootBox->lineBreakObj()).text().length()))) {
-                    // The previous line didn't break cleanly or broke at a newline
-                    // that has been deleted, so treat it as dirty too.
-                    currentLine = prevRootBox;
-                }
-            }
-        }
-        // If we have no dirty lines, then last is just the last root box.
-        lastLine = currentLine ? currentLine->prevRootBox() : lastRootBox();
-    }
-
-    if (!floats.isEmpty()) {
-        LayoutUnit savedLogicalHeight = m_flow.logicalHeight();
-        // Restore floats from clean lines.
-        RootInlineBox* line = firstRootBox();
-        while (line != currentLine) {
-            if (auto* cleanLineFloats = line->floatsPtr()) {
-                for (auto& floatingBox : *cleanLineFloats) {
-                    if (!floatingBox)
-                        continue;
-                    auto* floatingObject = m_flow.insertFloatingObject(*floatingBox);
-                    ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject->originatingLine());
-                    floatingObject->setOriginatingLine(*line);
-                    m_flow.setLogicalHeight(m_flow.logicalTopForChild(*floatingBox) - m_flow.marginBeforeForChild(*floatingBox));
-                    m_flow.positionNewFloats();
-                    floats.setLastCleanFloat(*floatingBox);
-                }
-            }
-            line = line->nextRootBox();
-        }
-        m_flow.setLogicalHeight(savedLogicalHeight);
-    }
-
-    layoutState.lineInfo().setFirstLine(!lastLine);
-    layoutState.lineInfo().setPreviousLineBrokeCleanly(!lastLine || lastLine->endsWithBreak());
-
-    if (lastLine) {
-        m_flow.setLogicalHeight(lastLine->lineBoxBottom());
-        InlineIterator iter = InlineIterator(&m_flow, lastLine->lineBreakObj(), lastLine->lineBreakPos());
-        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
-        resolver.setStatus(lastLine->lineBreakBidiStatus());
-    } else {
-        TextDirection direction = style().direction();
-        if (style().unicodeBidi() == Plaintext)
-            determineDirectionality(direction, InlineIterator(&m_flow, bidiFirstSkippingEmptyInlines(m_flow), 0));
-        resolver.setStatus(BidiStatus(direction, isOverride(style().unicodeBidi())));
-        InlineIterator iter = InlineIterator(&m_flow, bidiFirstSkippingEmptyInlines(m_flow, &resolver), 0);
-        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
-    }
-    return currentLine;
-}
-
-void ComplexLineLayout::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
-{
-    auto iteratorForFirstDirtyFloat = [](LineLayoutState::FloatList& floats) {
-        auto lastCleanFloat = floats.lastCleanFloat();
-        if (!lastCleanFloat)
-            return floats.begin();
-        auto* lastCleanFloatWithRect = floats.floatWithRect(*lastCleanFloat);
-        ASSERT(lastCleanFloatWithRect);
-        return ++floats.find(*lastCleanFloatWithRect);
-    };
-
-    ASSERT(!layoutState.endLine());
-    auto floatsIterator = iteratorForFirstDirtyFloat(layoutState.floatList());
-    auto end = layoutState.floatList().end();
-    RootInlineBox* lastLine = nullptr;
-    for (RootInlineBox* currentLine = startLine->nextRootBox(); currentLine; currentLine = currentLine->nextRootBox()) {
-        if (!currentLine->isDirty()) {
-            if (auto* cleanLineFloats = currentLine->floatsPtr()) {
-                bool encounteredNewFloat = false;
-                bool dirtiedByFloat = false;
-                for (auto& floatBoxOnCleanLine : *cleanLineFloats) {
-                    if (!floatBoxOnCleanLine)
-                        continue;
-                    ASSERT(floatsIterator != end);
-                    checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat);
-                    ++floatsIterator;
-                    if (floatsIterator == end || encounteredNewFloat)
-                        return;
-                }
-            }
-        }
-        if (currentLine->isDirty())
-            lastLine = nullptr;
-        else if (!lastLine)
-            lastLine = currentLine;
-    }
-
-    if (!lastLine)
-        return;
-
-    // At this point, |last| is the first line in a run of clean lines that ends with the last line
-    // in the block.
-    RootInlineBox* previousLine = lastLine->prevRootBox();
-    cleanLineStart = InlineIterator(&m_flow, previousLine->lineBreakObj(), previousLine->lineBreakPos());
-    cleanLineBidiStatus = previousLine->lineBreakBidiStatus();
-    layoutState.setEndLineLogicalTop(previousLine->lineBoxBottom());
-
-    for (RootInlineBox* line = lastLine; line; line = line->nextRootBox()) {
-        // Disconnect all line boxes from their render objects while preserving their connections to one another.
-        line->extractLine();
-    }
-    layoutState.setEndLine(lastLine);
-}
-
-bool ComplexLineLayout::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
-{
-    LayoutUnit lineDelta = m_flow.logicalHeight() - layoutState.endLineLogicalTop();
-
-    bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
-    if (paginated && layoutState.fragmentedFlow()) {
-        // Check all lines from here to the end, and see if the hypothetical new position for the lines will result
-        // in a different available line width.
-        for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; lineBox = lineBox->nextRootBox()) {
-            if (paginated) {
-                // This isn't the real move we're going to do, so don't update the line box's pagination
-                // strut yet.
-                LayoutUnit oldPaginationStrut = lineBox->paginationStrut();
-                bool overflowsFragment;
-                lineDelta -= oldPaginationStrut;
-                m_flow.adjustLinePositionForPagination(lineBox, lineDelta, overflowsFragment, layoutState.fragmentedFlow());
-                lineBox->setPaginationStrut(oldPaginationStrut);
-            }
-            if (lineWidthForPaginatedLineChanged(lineBox, lineDelta, layoutState.fragmentedFlow()))
-                return false;
-        }
-    }
-    
-    if (!lineDelta || !m_flow.floatingObjects())
-        return true;
-    
-    // See if any floats end in the range along which we want to shift the lines vertically.
-    LayoutUnit logicalTop = std::min(m_flow.logicalHeight(), layoutState.endLineLogicalTop());
-
-    RootInlineBox* lastLine = layoutState.endLine();
-    while (RootInlineBox* nextLine = lastLine->nextRootBox())
-        lastLine = nextLine;
-
-    LayoutUnit logicalBottom = lastLine->lineBoxBottom() + absoluteValue(lineDelta);
-
-    const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
-    auto end = floatingObjectSet.end();
-    for (auto it = floatingObjectSet.begin(); it != end; ++it) {
-        const auto& floatingObject = *it->get();
-        if (m_flow.logicalBottomForFloat(floatingObject) >= logicalTop && m_flow.logicalBottomForFloat(floatingObject) < logicalBottom)
-            return false;
-    }
-
-    return true;
-}
-
-bool ComplexLineLayout::lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta, RenderFragmentedFlow* fragmentedFlow) const
-{
-    if (!fragmentedFlow)
-        return false;
-
-    RenderFragmentContainer* currentFragment = m_flow.fragmentAtBlockOffset(rootBox->lineBoxTop() + lineDelta);
-    // Just bail if the fragment didn't change.
-    if (rootBox->containingFragment() == currentFragment)
-        return false;
-    return rootBox->paginatedLineWidth() != m_flow.availableLogicalWidthForContent(currentFragment);
-}
-
-bool ComplexLineLayout::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
-{
-    if (resolver.position() == endLineStart) {
-        if (resolver.status() != endLineStatus)
-            return false;
-        return checkPaginationAndFloatsAtEndLine(layoutState);
-    }
-
-    // The first clean line doesn't match, but we can check a handful of following lines to try
-    // to match back up.
-    static const int numLines = 8; // The # of lines we're willing to match against.
-    RootInlineBox* originalEndLine = layoutState.endLine();
-    RootInlineBox* line = originalEndLine;
-    for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
-        if (line->lineBreakObj() == resolver.position().renderer() && line->lineBreakPos() == resolver.position().offset()) {
-            // We have a match.
-            if (line->lineBreakBidiStatus() != resolver.status())
-                return false; // ...but the bidi state doesn't match.
-            
-            bool matched = false;
-            RootInlineBox* result = line->nextRootBox();
-            layoutState.setEndLine(result);
-            if (result) {
-                layoutState.setEndLineLogicalTop(line->lineBoxBottom());
-                matched = checkPaginationAndFloatsAtEndLine(layoutState);
-            }
-
-            // Now delete the lines that we failed to sync.
-            deleteLineRange(layoutState, originalEndLine, result);
-            return matched;
-        }
-    }
-
-    return false;
-}
-
-void ComplexLineLayout::addOverflowFromInlineChildren()
-{
-    LayoutUnit endPadding = m_flow.hasOverflowClip() ? m_flow.paddingEnd() : 0_lu;
-    // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
-    if (!endPadding)
-        endPadding = m_flow.endPaddingWidthForCaret();
-    if (m_flow.hasOverflowClip() && !endPadding && m_flow.element() && m_flow.element()->isRootEditableElement() && style().isLeftToRightDirection())
-        endPadding = 1;
-    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
-        m_flow.addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
-        RenderFragmentContainer* fragment = m_flow.enclosingFragmentedFlow() ? curr->containingFragment() : nullptr;
-        if (fragment)
-            fragment->addLayoutOverflowForBox(&m_flow, curr->paddedLayoutOverflowRect(endPadding));
-        if (!m_flow.hasOverflowClip()) {
-            LayoutRect childVisualOverflowRect = curr->visualOverflowRect(curr->lineTop(), curr->lineBottom());
-            m_flow.addVisualOverflow(childVisualOverflowRect);
-            if (fragment)
-                fragment->addVisualOverflowForBox(&m_flow, childVisualOverflowRect);
-        }
-    }
-}
-
-size_t ComplexLineLayout::lineCount() const
-{
-    size_t count = 0;
-    for (auto* box = firstRootBox(); box; box = box->nextRootBox())
-        ++count;
-
-    return count;
-}
-
-size_t ComplexLineLayout::lineCountUntil(const RootInlineBox* stopRootInlineBox) const
-{
-    size_t count = 0;
-    for (auto* box = firstRootBox(); box; box = box->nextRootBox()) {
-        ++count;
-        if (box == stopRootInlineBox)
-            break;
-    }
-
-    return count;
-}
-
-void ComplexLineLayout::deleteEllipsisLineBoxes()
-{
-    TextAlignMode textAlign = style().textAlign();
-    bool ltr = style().isLeftToRightDirection();
-    IndentTextOrNot shouldIndentText = IndentText;
-    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
-        if (curr->hasEllipsisBox()) {
-            curr->clearTruncation();
-
-            // Shift the line back where it belongs if we cannot accomodate an ellipsis.
-            float logicalLeft = m_flow.logicalLeftOffsetForLine(curr->lineTop(), shouldIndentText);
-            float availableLogicalWidth = m_flow.logicalRightOffsetForLine(curr->lineTop(), DoNotIndentText) - logicalLeft;
-            float totalLogicalWidth = curr->logicalWidth();
-            updateLogicalWidthForAlignment(m_flow, textAlign, curr, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
-
-            if (ltr)
-                curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0);
-            else
-                curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft), 0);
-        }
-        shouldIndentText = DoNotIndentText;
-    }
-}
-
-void ComplexLineLayout::checkLinesForTextOverflow()
-{
-    // Determine the width of the ellipsis using the current font.
-    // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
-    const FontCascade& font = style().fontCascade();
-    static MainThreadNeverDestroyed<const AtomString> ellipsisStr(&horizontalEllipsis, 1);
-    const FontCascade& firstLineFont = m_flow.firstLineStyle().fontCascade();
-    float firstLineEllipsisWidth = firstLineFont.width(m_flow.constructTextRun(&horizontalEllipsis, 1, m_flow.firstLineStyle()));
-    float ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(m_flow.constructTextRun(&horizontalEllipsis, 1, style()));
-
-    // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
-    // if the right edge of a line box exceeds that. For RTL, we use the left edge of the padding box and
-    // check the left edge of the line box to see if it is less
-    // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
-    bool ltr = style().isLeftToRightDirection();
-    TextAlignMode textAlign = style().textAlign();
-    bool firstLine = true;
-    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
-        IndentTextOrNot shouldIndentText = firstLine ? IndentText : DoNotIndentText;
-        LayoutUnit blockRightEdge = m_flow.logicalRightOffsetForLine(curr->lineTop(), shouldIndentText);
-        LayoutUnit blockLeftEdge = m_flow.logicalLeftOffsetForLine(curr->lineTop(), shouldIndentText);
-        LayoutUnit lineBoxEdge { ltr ? curr->x() + curr->logicalWidth() : curr->x() };
-        if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
-            // This line spills out of our box in the appropriate direction. Now we need to see if the line
-            // can be truncated. In order for truncation to be possible, the line must have sufficient space to
-            // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
-            // space.
-            LayoutUnit width { firstLine ? firstLineEllipsisWidth : ellipsisWidth };
-            LayoutUnit blockEdge { ltr ? blockRightEdge : blockLeftEdge };
-            if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)) {
-                float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
-
-                float logicalLeft = 0; // We are only interested in the delta from the base position.
-                float truncatedWidth = m_flow.availableLogicalWidthForLine(curr->lineTop(), shouldIndentText);
-                updateLogicalWidthForAlignment(m_flow, textAlign, curr, nullptr, logicalLeft, totalLogicalWidth, truncatedWidth, 0);
-                if (ltr)
-                    curr->adjustLogicalPosition(logicalLeft, 0);
-                else
-                    curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0);
-            }
-        }
-        firstLine = false;
-    }
-}
-
-bool ComplexLineLayout::positionNewFloatOnLine(const FloatingObject& newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
-{
-    if (!m_flow.positionNewFloats())
-        return false;
-
-    width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
-
-    // We only connect floats to lines for pagination purposes if the floats occur at the start of
-    // the line and the previous line had a hard break (so this line is either the first in the block
-    // or follows a <br>).
-    if (!newFloat.paginationStrut() || !lineInfo.previousLineBrokeCleanly() || !lineInfo.isEmpty())
-        return true;
-
-    const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
-    ASSERT(floatingObjectSet.last().get() == &newFloat);
-
-    LayoutUnit floatLogicalTop = m_flow.logicalTopForFloat(newFloat);
-    LayoutUnit paginationStrut = newFloat.paginationStrut();
-
-    if (floatLogicalTop - paginationStrut != m_flow.logicalHeight() + lineInfo.floatPaginationStrut())
-        return true;
-
-    auto it = floatingObjectSet.end();
-    --it; // Last float is newFloat, skip that one.
-    auto begin = floatingObjectSet.begin();
-    while (it != begin) {
-        --it;
-        auto& floatingObject = *it->get();
-        if (&floatingObject == lastFloatFromPreviousLine)
-            break;
-        if (m_flow.logicalTopForFloat(floatingObject) == m_flow.logicalHeight() + lineInfo.floatPaginationStrut()) {
-            floatingObject.setPaginationStrut(paginationStrut + floatingObject.paginationStrut());
-            RenderBox& floatBox = floatingObject.renderer();
-            m_flow.setLogicalTopForChild(floatBox, m_flow.logicalTopForChild(floatBox) + m_flow.marginBeforeForChild(floatBox) + paginationStrut);
-
-            if (m_flow.updateFragmentRangeForBoxChild(floatBox))
-                floatBox.setNeedsLayout(MarkOnlyThis);
-            else if (is<RenderBlock>(floatBox))
-                downcast<RenderBlock>(floatBox).setChildNeedsLayout(MarkOnlyThis);
-            floatBox.layoutIfNeeded();
-
-            // Save the old logical top before calling removePlacedObject which will set
-            // isPlaced to false. Otherwise it will trigger an assert in logicalTopForFloat.
-            LayoutUnit oldLogicalTop = m_flow.logicalTopForFloat(floatingObject);
-            m_flow.floatingObjects()->removePlacedObject(&floatingObject);
-            m_flow.setLogicalTopForFloat(floatingObject, oldLogicalTop + paginationStrut);
-            m_flow.floatingObjects()->addPlacedObject(&floatingObject);
-        }
-    }
-
-    // Just update the line info's pagination strut without altering our logical height yet. If the line ends up containing
-    // no content, then we don't want to improperly grow the height of the block.
-    lineInfo.setFloatPaginationStrut(lineInfo.floatPaginationStrut() + paginationStrut);
-    return true;
-}
-
-void ComplexLineLayout::updateFragmentForLine(RootInlineBox* lineBox) const
-{
-    ASSERT(lineBox);
-
-    if (!m_flow.hasFragmentRangeInFragmentedFlow())
-        lineBox->clearContainingFragment();
-    else {
-        if (auto containingFragment = m_flow.fragmentAtBlockOffset(lineBox->lineBoxTop()))
-            lineBox->setContainingFragment(*containingFragment);
-        else
-            lineBox->clearContainingFragment();
-    }
-
-    RootInlineBox* prevLineBox = lineBox->prevRootBox();
-    if (!prevLineBox)
-        return;
-
-    // This check is more accurate than the one in |adjustLinePositionForPagination| because it takes into
-    // account just the container changes between lines. The before mentioned function doesn't set the flag
-    // correctly if the line is positioned at the top of the last fragment container.
-    if (lineBox->containingFragment() != prevLineBox->containingFragment())
-        lineBox->setIsFirstAfterPageBreak(true);
-}
-
-const RenderStyle& ComplexLineLayout::style() const
-{
-    return m_flow.style();
-}
-
-const FrameViewLayoutContext& ComplexLineLayout::layoutContext() const
-{
-    return m_flow.view().frameView().layoutContext();
-}
-
-
-}
</del></span></pre></div>
<a id="trunkSourceWebCorerenderingComplexLineLayouth"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/rendering/ComplexLineLayout.h (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/ComplexLineLayout.h       2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/ComplexLineLayout.h  2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -1,117 +0,0 @@
</span><del>-/*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include "InlineFlowBox.h"
-#include "LineWidth.h"
-#include "RenderLineBoxList.h"
-#include "RenderStyleConstants.h"
-#include "TrailingObjects.h"
-
-namespace WebCore {
-
-class BidiContext;
-class FloatingObject;
-class FloatWithRect;
-class FrameViewLayoutContext;
-class InlineBox;
-class InlineIterator;
-class LineInfo;
-class LineLayoutState;
-class RenderBlockFlow;
-class RenderObject;
-class RenderRubyRun;
-class RootInlineBox;
-class VerticalPositionCache;
-struct BidiStatus;
-struct WordMeasurement;
-
-template <class Run> class BidiRunList;
-typedef Vector<WordMeasurement, 64> WordMeasurements;
-
-class ComplexLineLayout {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
-    ComplexLineLayout(RenderBlockFlow&);
-    ~ComplexLineLayout();
-
-    RenderLineBoxList& lineBoxes() { return m_lineBoxes; }
-    const RenderLineBoxList& lineBoxes() const { return m_lineBoxes; }
-
-    RootInlineBox* firstRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.firstLineBox()); }
-    RootInlineBox* lastRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.lastLineBox()); }
-
-    void layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
-
-    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
-    bool positionNewFloatOnLine(const FloatingObject& newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
-    void addOverflowFromInlineChildren();
-
-    size_t lineCount() const;
-    size_t lineCountUntil(const RootInlineBox*) const;
-
-    static void appendRunsForObject(BidiRunList<BidiRun>*, int start, int end, RenderObject&, InlineBidiResolver&);
-    static void updateLogicalWidthForAlignment(RenderBlockFlow&, const TextAlignMode&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
-
-private:
-    std::unique_ptr<RootInlineBox> createRootInlineBox();
-    RootInlineBox* createAndAppendRootInlineBox();
-    InlineBox* createInlineBoxForRenderer(RenderObject*, bool isOnlyRun = false);
-    InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox*);
-    TextAlignMode textAlignmentForLine(bool endsWithSoftBreak) const;
-    void setMarginsForRubyRun(BidiRun*, RenderRubyRun&, RenderObject* previousObject, const LineInfo&);
-    void updateRubyForJustifiedText(RenderRubyRun&, BidiRun&, const Vector<unsigned, 16>& expansionOpportunities, unsigned& expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth, size_t&);
-    void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, const Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float totalLogicalWidth, float availableLogicalWidth);
-    void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
-    BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, TextAlignMode, float& logicalLeft, float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
-    void removeInlineBox(BidiRun&, const RootInlineBox&) const;
-    void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&);
-    inline BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext);
-    void appendFloatingObjectToLastLine(FloatingObject&);
-    RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
-    void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
-    inline const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator& oldEnd);
-    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
-    void reattachCleanLineFloats(RootInlineBox& cleanLine, LayoutUnit delta, bool isFirstCleanLine);
-    void linkToEndLineIfNeeded(LineLayoutState&);
-    void checkFloatInCleanLine(RootInlineBox& cleanLine, RenderBox& floatBoxOnCleanLine, FloatWithRect& matchingFloatWithRect, bool& encounteredNewFloat, bool& dirtiedByFloat);
-    RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
-    void determineEndPosition(LineLayoutState&, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
-    bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
-    bool lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta, RenderFragmentedFlow*) const;
-    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
-    void deleteEllipsisLineBoxes();
-    void checkLinesForTextOverflow();
-    void updateFragmentForLine(RootInlineBox*) const;
-
-    const RenderStyle& style() const;
-    const FrameViewLayoutContext& layoutContext() const;
-
-    RenderBlockFlow& m_flow;
-    RenderLineBoxList m_lineBoxes;
-};
-
-};
</del></span></pre></div>
<a id="trunkSourceWebCorerenderingInlineIteratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/InlineIterator.h (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/InlineIterator.h  2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/InlineIterator.h     2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -537,7 +537,7 @@
</span><span class="cx">             addPlaceholderRunForIsolatedInline(resolver, obj, pos, root);
</span><span class="cx">         }
</span><span class="cx">         m_haveAddedFakeRunForRootIsolate = true;
</span><del>-        ComplexLineLayout::appendRunsForObject(nullptr, pos, end, obj, resolver);
</del><ins>+        LegacyLineLayout::appendRunsForObject(nullptr, pos, end, obj, resolver);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -559,7 +559,7 @@
</span><span class="cx">             if (isolateTracker.inIsolate())
</span><span class="cx">                 isolateTracker.addFakeRunIfNecessary(*obj, start, obj->length(), *m_sor.root(), *this);
</span><span class="cx">             else
</span><del>-                ComplexLineLayout::appendRunsForObject(&m_runs, start, obj->length(), *obj, *this);
</del><ins>+                LegacyLineLayout::appendRunsForObject(&m_runs, start, obj->length(), *obj, *this);
</ins><span class="cx">             // FIXME: start/obj should be an InlineIterator instead of two separate variables.
</span><span class="cx">             start = 0;
</span><span class="cx">             obj = bidiNextSkippingEmptyInlines(*m_sor.root(), obj, &isolateTracker);
</span><span class="lines">@@ -575,7 +575,7 @@
</span><span class="cx">             if (isolateTracker.inIsolate())
</span><span class="cx">                 isolateTracker.addFakeRunIfNecessary(*obj, start, obj->length(), *m_sor.root(), *this);
</span><span class="cx">             else
</span><del>-                ComplexLineLayout::appendRunsForObject(&m_runs, start, end, *obj, *this);
</del><ins>+                LegacyLineLayout::appendRunsForObject(&m_runs, start, end, *obj, *this);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         m_eor.increment();
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingLegacyLineLayoutcppfromrev278304trunkSourceWebCorerenderingComplexLineLayoutcpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/rendering/LegacyLineLayout.cpp (from rev 278304, trunk/Source/WebCore/rendering/ComplexLineLayout.cpp) (0 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/LegacyLineLayout.cpp                              (rev 0)
+++ trunk/Source/WebCore/rendering/LegacyLineLayout.cpp 2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -0,0 +1,2327 @@
</span><ins>+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003-2019 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2013 ChangSeok Oh <shivamidow@gmail.com>
+ * Copyright (C) 2013 Adobe Systems Inc. All right reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "LegacyLineLayout.h"
+
+#include "AXObjectCache.h"
+#include "BidiResolver.h"
+#include "BreakingContext.h"
+#include "FloatingObjects.h"
+#include "HTMLParserIdioms.h"
+#include "InlineElementBox.h"
+#include "InlineIterator.h"
+#include "InlineTextBox.h"
+#include "InlineTextBoxStyle.h"
+#include "LineLayoutState.h"
+#include "Logging.h"
+#include "RenderBlockFlow.h"
+#include "RenderFragmentContainer.h"
+#include "RenderFragmentedFlow.h"
+#include "RenderLayoutState.h"
+#include "RenderLineBreak.h"
+#include "RenderRubyBase.h"
+#include "RenderRubyText.h"
+#include "RenderSVGText.h"
+#include "RenderView.h"
+#include "SVGRootInlineBox.h"
+#include "Settings.h"
+#include "TrailingFloatsRootInlineBox.h"
+#include "VerticalPositionCache.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+LegacyLineLayout::LegacyLineLayout(RenderBlockFlow& flow)
+    : m_flow(flow)
+{
+}
+
+LegacyLineLayout::~LegacyLineLayout()
+{
+    if (m_flow.containsFloats())
+        m_flow.floatingObjects()->clearLineBoxTreePointers();
+
+    lineBoxes().deleteLineBoxTree();
+};
+
+static void determineDirectionality(TextDirection& dir, InlineIterator iter)
+{
+    while (!iter.atEnd()) {
+        if (iter.atParagraphSeparator())
+            return;
+        if (UChar current = iter.current()) {
+            UCharDirection charDirection = u_charDirection(current);
+            if (charDirection == U_LEFT_TO_RIGHT) {
+                dir = TextDirection::LTR;
+                return;
+            }
+            if (charDirection == U_RIGHT_TO_LEFT || charDirection == U_RIGHT_TO_LEFT_ARABIC) {
+                dir = TextDirection::RTL;
+                return;
+            }
+        }
+        iter.increment();
+    }
+}
+
+inline std::unique_ptr<BidiRun> createRun(int start, int end, RenderObject& obj, InlineBidiResolver& resolver)
+{
+    return makeUnique<BidiRun>(start, end, obj, resolver.context(), resolver.dir());
+}
+
+void LegacyLineLayout::appendRunsForObject(BidiRunList<BidiRun>* runs, int start, int end, RenderObject& obj, InlineBidiResolver& resolver)
+{
+    if (start > end || RenderBlock::shouldSkipCreatingRunsForObject(obj))
+        return;
+
+    LineWhitespaceCollapsingState& lineWhitespaceCollapsingState = resolver.whitespaceCollapsingState();
+    bool haveNextTransition = (lineWhitespaceCollapsingState.currentTransition() < lineWhitespaceCollapsingState.numTransitions());
+    InlineIterator nextTransition;
+    if (haveNextTransition)
+        nextTransition = lineWhitespaceCollapsingState.transitions()[lineWhitespaceCollapsingState.currentTransition()];
+    if (lineWhitespaceCollapsingState.betweenTransitions()) {
+        if (!haveNextTransition || (&obj != nextTransition.renderer()))
+            return;
+        // This is a new start point. Stop ignoring objects and
+        // adjust our start.
+        start = nextTransition.offset();
+        lineWhitespaceCollapsingState.incrementCurrentTransition();
+        if (start < end) {
+            appendRunsForObject(runs, start, end, obj, resolver);
+            return;
+        }
+    } else {
+        if (!haveNextTransition || (&obj != nextTransition.renderer())) {
+            if (runs)
+                runs->appendRun(createRun(start, end, obj, resolver));
+            return;
+        }
+
+        // An end transition has been encountered within our object. We need to append a run with our endpoint.
+        if (static_cast<int>(nextTransition.offset() + 1) <= end) {
+            lineWhitespaceCollapsingState.incrementCurrentTransition();
+            // The end of the line is before the object we're inspecting. Skip everything and return
+            if (nextTransition.refersToEndOfPreviousNode())
+                return;
+            if (static_cast<int>(nextTransition.offset() + 1) > start && runs)
+                runs->appendRun(createRun(start, nextTransition.offset() + 1, obj, resolver));
+            appendRunsForObject(runs, nextTransition.offset() + 1, end, obj, resolver);
+        } else if (runs)
+            runs->appendRun(createRun(start, end, obj, resolver));
+    }
+}
+
+std::unique_ptr<RootInlineBox> LegacyLineLayout::createRootInlineBox()
+{
+    if (is<RenderSVGText>(m_flow)) {
+        auto box = makeUnique<SVGRootInlineBox>(downcast<RenderSVGText>(m_flow));
+        box->setHasVirtualLogicalHeight();
+        return box;
+    }
+        
+    return makeUnique<RootInlineBox>(m_flow);
+}
+
+RootInlineBox* LegacyLineLayout::createAndAppendRootInlineBox()
+{
+    auto newRootBox = createRootInlineBox();
+    RootInlineBox* rootBox = newRootBox.get();
+    m_lineBoxes.appendLineBox(WTFMove(newRootBox));
+
+    if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && firstRootBox() == rootBox) {
+        if (AXObjectCache* cache = m_flow.document().existingAXObjectCache())
+            cache->deferRecomputeIsIgnored(m_flow.element());
+    }
+
+    return rootBox;
+}
+
+InlineBox* LegacyLineLayout::createInlineBoxForRenderer(RenderObject* renderer, bool isOnlyRun)
+{
+    if (renderer == &m_flow)
+        return createAndAppendRootInlineBox();
+
+    if (is<RenderText>(*renderer))
+        return downcast<RenderText>(*renderer).createInlineTextBox();
+
+    if (is<RenderBox>(*renderer)) {
+        // FIXME: This is terrible. This branch returns an *owned* pointer!
+        return downcast<RenderBox>(*renderer).createInlineBox().release();
+    }
+
+    if (is<RenderLineBreak>(*renderer)) {
+        // FIXME: This is terrible. This branch returns an *owned* pointer!
+        auto inlineBox = downcast<RenderLineBreak>(*renderer).createInlineBox().release();
+        // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
+        // (Note the use of strict mode. In "almost strict" mode, we don't treat the box for <br> as text.)
+        inlineBox->setBehavesLikeText(isOnlyRun || renderer->document().inNoQuirksMode() || renderer->isLineBreakOpportunity());
+        return inlineBox;
+    }
+
+    return downcast<RenderInline>(*renderer).createAndAppendInlineFlowBox();
+}
+
+static inline void dirtyLineBoxesForRenderer(RenderObject& renderer, bool fullLayout)
+{
+    if (is<RenderText>(renderer)) {
+        RenderText& renderText = downcast<RenderText>(renderer);
+        updateCounterIfNeeded(renderText);
+        renderText.dirtyLineBoxes(fullLayout);
+    } else if (is<RenderLineBreak>(renderer))
+        downcast<RenderLineBreak>(renderer).dirtyLineBoxes(fullLayout);
+    else
+        downcast<RenderInline>(renderer).dirtyLineBoxes(fullLayout);
+}
+
+static bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
+{
+    do {
+        if (parentBox->isConstructed() || parentBox->nextOnLine())
+            return true;
+        parentBox = parentBox->parent();
+    } while (parentBox);
+    return false;
+}
+
+InlineFlowBox* LegacyLineLayout::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox)
+{
+    // See if we have an unconstructed line box for this object that is also
+    // the last item on the line.
+    unsigned lineDepth = 1;
+    InlineFlowBox* parentBox = nullptr;
+    InlineFlowBox* result = nullptr;
+    bool hasDefaultLineBoxContain = style().lineBoxContain() == RenderStyle::initialLineBoxContain();
+    do {
+        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(is<RenderInline>(*obj) || obj == &m_flow);
+
+        RenderInline* inlineFlow = obj != &m_flow ? downcast<RenderInline>(obj) : nullptr;
+
+        // Get the last box we made for this render object.
+        parentBox = inlineFlow ? inlineFlow->lastLineBox() : downcast<RenderBlockFlow>(*obj).lastRootBox();
+
+        // If this box or its ancestor is constructed then it is from a previous line, and we need
+        // to make a new box for our line. If this box or its ancestor is unconstructed but it has
+        // something following it on the line, then we know we have to make a new box
+        // as well. In this situation our inline has actually been split in two on
+        // the same line (this can happen with very fancy language mixtures).
+        bool constructedNewBox = false;
+        bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
+        bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox);
+        if (allowedToConstructNewBox && !canUseExistingParentBox) {
+            // We need to make a new box for this render object. Once
+            // made, we need to place it at the end of the current line.
+            InlineBox* newBox = createInlineBoxForRenderer(obj);
+            parentBox = downcast<InlineFlowBox>(newBox);
+            parentBox->setIsFirstLine(lineInfo.isFirstLine());
+            parentBox->setIsHorizontal(m_flow.isHorizontalWritingMode());
+            if (!hasDefaultLineBoxContain)
+                parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
+            constructedNewBox = true;
+        }
+
+        if (constructedNewBox || canUseExistingParentBox) {
+            if (!result)
+                result = parentBox;
+
+            // If we have hit the block itself, then |box| represents the root
+            // inline box for the line, and it doesn't have to be appended to any parent
+            // inline.
+            if (childBox)
+                parentBox->addToLine(childBox);
+
+            if (!constructedNewBox || obj == &m_flow)
+                break;
+
+            childBox = parentBox;
+        }
+
+        // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
+        // intermediate inline flows.
+        obj = (++lineDepth >= cMaxLineDepth) ? &m_flow : obj->parent();
+
+    } while (true);
+
+    return result;
+}
+
+template<typename CharacterType> static inline bool endsWithHTMLSpaces(const CharacterType* characters, unsigned position, unsigned end)
+{
+    for (unsigned i = position; i < end; ++i) {
+        if (!isHTMLSpace(characters[i]))
+            return false;
+    }
+    return true;
+}
+
+static bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
+{
+    BidiRun* run = bidiRuns.logicallyLastRun();
+    if (!run)
+        return true;
+    if (!is<RenderText>(run->renderer()))
+        return false;
+    auto& text = downcast<RenderText>(run->renderer()).text();
+    unsigned position = run->stop();
+    unsigned length = text.length();
+    if (text.is8Bit())
+        return endsWithHTMLSpaces(text.characters8(), position, length);
+    return endsWithHTMLSpaces(text.characters16(), position, length);
+}
+
+RootInlineBox* LegacyLineLayout::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
+{
+    ASSERT(bidiRuns.firstRun());
+
+    InlineFlowBox* parentBox = 0;
+    int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace();
+    
+    for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
+        // Create a box for our object.
+        bool isOnlyRun = (runCount == 1);
+        if (runCount == 2 && !r->renderer().isListMarker())
+            isOnlyRun = (!style().isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->renderer().isListMarker();
+
+        if (lineInfo.isEmpty())
+            continue;
+
+        InlineBox* box = createInlineBoxForRenderer(&r->renderer(), isOnlyRun);
+        r->setBox(box);
+
+        // If we have no parent box yet, or if the run is not simply a sibling,
+        // then we need to construct inline boxes as necessary to properly enclose the
+        // run's inline box. Segments can only be siblings at the root level, as
+        // they are positioned separately.
+        if (!parentBox || &parentBox->renderer() != r->renderer().parent()) {
+            // Create new inline boxes all the way back to the appropriate insertion point.
+            RenderObject* parentToUse = r->renderer().parent();
+            parentBox = createLineBoxes(parentToUse, lineInfo, box);
+        } else {
+            // Append the inline box to this line.
+            parentBox->addToLine(box);
+        }
+
+        bool visuallyOrdered = r->renderer().style().rtlOrdering() == Order::Visual;
+        box->setBidiLevel(r->level());
+
+        if (is<InlineTextBox>(*box)) {
+            auto& textBox = downcast<InlineTextBox>(*box);
+            textBox.setStart(r->m_start);
+            textBox.setLen(r->m_stop - r->m_start);
+            textBox.setDirOverride(r->dirOverride(visuallyOrdered));
+            if (r->m_hasHyphen)
+                textBox.setHasHyphen(true);
+        }
+    }
+
+    // We should have a root inline box. It should be unconstructed and
+    // be the last continuation of our line list.
+    ASSERT(lastRootBox() && !lastRootBox()->isConstructed());
+
+    // Set bits on our inline flow boxes that indicate which sides should
+    // paint borders/margins/padding. This knowledge will ultimately be used when
+    // we determine the horizontal positions and widths of all the inline boxes on
+    // the line.
+    bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->renderer().isText() ? !reachedEndOfTextRenderer(bidiRuns) : !is<RenderInline>(bidiRuns.logicallyLastRun()->renderer());
+    lastRootBox()->determineSpacingForFlowBoxes(lineInfo.isLastLine(), isLogicallyLastRunWrapped, &bidiRuns.logicallyLastRun()->renderer());
+
+    // Now mark the line boxes as being constructed.
+    lastRootBox()->setConstructed();
+
+    // Return the last line.
+    return lastRootBox();
+}
+
+TextAlignMode LegacyLineLayout::textAlignmentForLine(bool endsWithSoftBreak) const
+{
+    if (auto overrideAlignment = m_flow.overrideTextAlignmentForLine(endsWithSoftBreak))
+        return *overrideAlignment;
+
+    TextAlignMode alignment = style().textAlign();
+#if ENABLE(CSS3_TEXT)
+    TextJustify textJustify = style().textJustify();
+    if (alignment == TextAlignMode::Justify && textJustify == TextJustify::None)
+        return style().direction() == TextDirection::LTR ? TextAlignMode::Left : TextAlignMode::Right;
+#endif
+
+    if (endsWithSoftBreak)
+        return alignment;
+
+#if !ENABLE(CSS3_TEXT)
+    return (alignment == TextAlignMode::Justify) ? TextAlignMode::Start : alignment;
+#else
+    if (alignment != TextAlignMode::Justify)
+        return alignment;
+
+    TextAlignLast alignmentLast = style().textAlignLast();
+    switch (alignmentLast) {
+    case TextAlignLast::Start:
+        return TextAlignMode::Start;
+    case TextAlignLast::End:
+        return TextAlignMode::End;
+    case TextAlignLast::Left:
+        return TextAlignMode::Left;
+    case TextAlignLast::Right:
+        return TextAlignMode::Right;
+    case TextAlignLast::Center:
+        return TextAlignMode::Center;
+    case TextAlignLast::Justify:
+        return TextAlignMode::Justify;
+    case TextAlignLast::Auto:
+        if (textJustify == TextJustify::Distribute)
+            return TextAlignMode::Justify;
+        return TextAlignMode::Start;
+    }
+    return alignment;
+#endif
+}
+
+static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    // The direction of the block should determine what happens with wide lines.
+    // In particular with RTL blocks, wide lines should still spill out to the left.
+    if (isLeftToRightDirection) {
+        if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
+            trailingSpaceRun->box()->setLogicalWidth(std::max<float>(0, trailingSpaceRun->box()->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
+        return;
+    }
+
+    if (trailingSpaceRun)
+        trailingSpaceRun->box()->setLogicalWidth(0);
+    else if (totalLogicalWidth > availableLogicalWidth)
+        logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
+}
+
+static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    // Wide lines spill out of the block based off direction.
+    // So even if text-align is right, if direction is LTR, wide lines should overflow out of the right
+    // side of the block.
+    if (isLeftToRightDirection) {
+        if (trailingSpaceRun) {
+            totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
+            trailingSpaceRun->box()->setLogicalWidth(0);
+        }
+        logicalLeft += std::max(0.f, availableLogicalWidth - totalLogicalWidth);
+        return;
+    }
+
+    if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
+        trailingSpaceRun->box()->setLogicalWidth(std::max<float>(0, trailingSpaceRun->box()->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
+        totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
+    } else
+        logicalLeft += availableLogicalWidth - totalLogicalWidth;
+}
+
+static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    float trailingSpaceWidth = 0;
+    if (trailingSpaceRun) {
+        totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
+        trailingSpaceWidth = std::min(trailingSpaceRun->box()->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
+        trailingSpaceRun->box()->setLogicalWidth(std::max<float>(0, trailingSpaceWidth));
+    }
+    if (isLeftToRightDirection)
+        logicalLeft += std::max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
+    else
+        logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
+}
+
+void LegacyLineLayout::setMarginsForRubyRun(BidiRun* run, RenderRubyRun& renderer, RenderObject* previousObject, const LineInfo& lineInfo)
+{
+    float startOverhang;
+    float endOverhang;
+    RenderObject* nextObject = 0;
+    for (BidiRun* runWithNextObject = run->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
+        if (!runWithNextObject->renderer().isOutOfFlowPositioned() && !runWithNextObject->box()->isLineBreak()) {
+            nextObject = &runWithNextObject->renderer();
+            break;
+        }
+    }
+    renderer.getOverhang(lineInfo.isFirstLine(), renderer.style().isLeftToRightDirection() ? previousObject : nextObject, renderer.style().isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
+    m_flow.setMarginStartForChild(renderer, LayoutUnit(-startOverhang));
+    m_flow.setMarginEndForChild(renderer, LayoutUnit(-endOverhang));
+}
+
+static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText& renderer, float xPos, const LineInfo& lineInfo,
+    GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
+{
+    HashSet<const Font*> fallbackFonts;
+    GlyphOverflow glyphOverflow;
+
+    const FontCascade& font = lineStyle(*renderer.parent(), lineInfo).fontCascade();
+    // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
+    if (lineBox->fitsToGlyphs()) {
+        // If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
+        // will keep us from computing glyph bounds in nearly all cases.
+        bool includeRootLine = lineBox->includesRootLineBoxFontOrLeading();
+        int baselineShift = lineBox->verticalPositionForBox(run->box(), verticalPositionCache);
+        int rootDescent = includeRootLine ? font.fontMetrics().descent() : 0;
+        int rootAscent = includeRootLine ? font.fontMetrics().ascent() : 0;
+        int boxAscent = font.fontMetrics().ascent() - baselineShift;
+        int boxDescent = font.fontMetrics().descent() + baselineShift;
+        if (boxAscent > rootDescent ||  boxDescent > rootAscent)
+            glyphOverflow.computeBounds = true; 
+    }
+    
+    LayoutUnit hyphenWidth;
+    if (downcast<InlineTextBox>(*run->box()).hasHyphen())
+        hyphenWidth = measureHyphenWidth(renderer, font, &fallbackFonts);
+
+    float measuredWidth = 0;
+
+    bool kerningIsEnabled = font.enableKerning();
+    bool canUseSimpleFontCodePath = renderer.canUseSimpleFontCodePath();
+    
+    // Since we don't cache glyph overflows, we need to re-measure the run if
+    // the style is linebox-contain: glyph.
+    if (!lineBox->fitsToGlyphs() && canUseSimpleFontCodePath) {
+        unsigned lastEndOffset = run->m_start;
+        bool atFirstWordMeasurement = true;
+        for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) {
+            WordMeasurement& wordMeasurement = wordMeasurements[i];
+            if (wordMeasurement.width <= 0 || wordMeasurement.startOffset == wordMeasurement.endOffset)
+                continue;
+            if (wordMeasurement.renderer != &renderer || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop)
+                continue;
+
+            lastEndOffset = wordMeasurement.endOffset;
+            if (kerningIsEnabled && lastEndOffset == run->m_stop) {
+                int wordLength = lastEndOffset - wordMeasurement.startOffset;
+                GlyphOverflow overflow;
+                measuredWidth += renderer.width(wordMeasurement.startOffset, wordLength, xPos + measuredWidth, lineInfo.isFirstLine(),
+                    &wordMeasurement.fallbackFonts, &overflow);
+                UChar c = renderer.characterAt(wordMeasurement.startOffset);
+                // renderer.width() omits word-spacing value for leading whitespace, so let's just add it back here.
+                if (!atFirstWordMeasurement && FontCascade::treatAsSpace(c))
+                    measuredWidth += renderer.style().fontCascade().wordSpacing();
+            } else
+                measuredWidth += wordMeasurement.width;
+            atFirstWordMeasurement = false;
+
+            for (auto& font : wordMeasurement.fallbackFonts)
+                fallbackFonts.add(font);
+        }
+        if (measuredWidth && lastEndOffset != run->m_stop) {
+            // If we don't have enough cached data, we'll measure the run again.
+            measuredWidth = 0;
+            fallbackFonts.clear();
+        }
+    }
+
+    if (!measuredWidth)
+        measuredWidth = renderer.width(run->m_start, run->m_stop - run->m_start, xPos, lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
+
+    ASSERT(measuredWidth >= 0);
+    ASSERT(hyphenWidth >= 0);
+
+    run->box()->setLogicalWidth(measuredWidth + hyphenWidth);
+    if (!fallbackFonts.isEmpty()) {
+        ASSERT(run->box()->behavesLikeText());
+        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(downcast<InlineTextBox>(run->box()), std::make_pair(Vector<const Font*>(), GlyphOverflow())).iterator;
+        ASSERT(it->value.first.isEmpty());
+        it->value.first = copyToVector(fallbackFonts);
+        run->box()->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
+    }
+
+    // Include text decoration visual overflow as part of the glyph overflow.
+    if (!renderer.style().textDecorationsInEffect().isEmpty())
+        glyphOverflow.extendTo(visualOverflowForDecorations(run->box()->lineStyle(), downcast<InlineTextBox>(run->box())));
+
+    if (!glyphOverflow.isEmpty()) {
+        ASSERT(run->box()->behavesLikeText());
+        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(downcast<InlineTextBox>(run->box()), std::make_pair(Vector<const Font*>(), GlyphOverflow())).iterator;
+        it->value.second = glyphOverflow;
+        run->box()->clearKnownToHaveNoOverflow();
+    }
+}
+
+void LegacyLineLayout::updateRubyForJustifiedText(RenderRubyRun& rubyRun, BidiRun& r, const Vector<unsigned, 16>& expansionOpportunities, unsigned& expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth, size_t& i)
+{
+    if (!rubyRun.rubyBase() || !rubyRun.rubyBase()->firstRootBox() || rubyRun.rubyBase()->firstRootBox()->nextRootBox() || !r.renderer().style().collapseWhiteSpace())
+        return;
+
+    auto& rubyBase = *rubyRun.rubyBase();
+    auto& rootBox = *rubyBase.firstRootBox();
+
+    float totalExpansion = 0;
+    unsigned totalOpportunitiesInRun = 0;
+    for (auto* leafChild = rootBox.firstLeafDescendant(); leafChild; leafChild = leafChild->nextLeafOnLine()) {
+        if (!leafChild->isInlineTextBox())
+            continue;
+
+        unsigned opportunitiesInRun = expansionOpportunities[i++];
+        ASSERT(opportunitiesInRun <= expansionOpportunityCount);
+        auto expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
+        totalExpansion += expansion;
+        totalOpportunitiesInRun += opportunitiesInRun;
+    }
+
+    ASSERT(!rubyRun.hasOverridingLogicalWidth());
+    float newBaseWidth = rubyRun.logicalWidth() + totalExpansion + m_flow.marginStartForChild(rubyRun) + m_flow.marginEndForChild(rubyRun);
+    float newRubyRunWidth = rubyRun.logicalWidth() + totalExpansion;
+    rubyBase.setInitialOffset((newRubyRunWidth - newBaseWidth) / 2);
+    rubyRun.setOverridingLogicalWidth(LayoutUnit(newRubyRunWidth));
+    rubyRun.setNeedsLayout(MarkOnlyThis);
+    rootBox.markDirty();
+    if (RenderRubyText* rubyText = rubyRun.rubyText()) {
+        if (RootInlineBox* textRootBox = rubyText->firstRootBox())
+            textRootBox->markDirty();
+    }
+    rubyRun.layoutBlock(true);
+    rubyRun.clearOverridingLogicalWidth();
+    r.box()->setExpansion(newRubyRunWidth - r.box()->logicalWidth());
+
+    totalLogicalWidth += totalExpansion;
+    expansionOpportunityCount -= totalOpportunitiesInRun;
+}
+
+void LegacyLineLayout::computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, const Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float totalLogicalWidth, float availableLogicalWidth)
+{
+    if (!expansionOpportunityCount || availableLogicalWidth <= totalLogicalWidth)
+        return;
+
+    size_t i = 0;
+    for (BidiRun* run = firstRun; run; run = run->next()) {
+        if (!run->box() || run == trailingSpaceRun)
+            continue;
+        
+        if (is<RenderText>(run->renderer())) {
+            unsigned opportunitiesInRun = expansionOpportunities[i++];
+            
+            ASSERT(opportunitiesInRun <= expansionOpportunityCount);
+            
+            // Only justify text if whitespace is collapsed.
+            if (run->renderer().style().collapseWhiteSpace()) {
+                InlineTextBox& textBox = downcast<InlineTextBox>(*run->box());
+                float expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
+                textBox.setExpansion(expansion);
+                totalLogicalWidth += expansion;
+            }
+            expansionOpportunityCount -= opportunitiesInRun;
+        } else if (is<RenderRubyRun>(run->renderer()))
+            updateRubyForJustifiedText(downcast<RenderRubyRun>(run->renderer()), *run, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth, i);
+
+        if (!expansionOpportunityCount)
+            break;
+    }
+}
+
+void LegacyLineLayout::updateLogicalWidthForAlignment(RenderBlockFlow& flow, const TextAlignMode& textAlign, const RootInlineBox* rootInlineBox, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount)
+{
+    TextDirection direction;
+    if (rootInlineBox && flow.style().unicodeBidi() == Plaintext)
+        direction = rootInlineBox->direction();
+    else
+        direction = flow.style().direction();
+
+    bool isLeftToRightDirection = flow.style().isLeftToRightDirection();
+
+    // Armed with the total width of the line (without justification),
+    // we now examine our text-align property in order to determine where to position the
+    // objects horizontally. The total width of the line can be increased if we end up
+    // justifying text.
+    switch (textAlign) {
+    case TextAlignMode::Left:
+    case TextAlignMode::WebKitLeft:
+        updateLogicalWidthForLeftAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case TextAlignMode::Right:
+    case TextAlignMode::WebKitRight:
+        updateLogicalWidthForRightAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case TextAlignMode::Center:
+    case TextAlignMode::WebKitCenter:
+        updateLogicalWidthForCenterAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case TextAlignMode::Justify:
+        flow.adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
+        if (expansionOpportunityCount) {
+            if (trailingSpaceRun) {
+                totalLogicalWidth -= trailingSpaceRun->box()->logicalWidth();
+                trailingSpaceRun->box()->setLogicalWidth(0);
+            }
+            break;
+        }
+        FALLTHROUGH;
+    case TextAlignMode::Start:
+        if (direction == TextDirection::LTR)
+            updateLogicalWidthForLeftAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        else
+            updateLogicalWidthForRightAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case TextAlignMode::End:
+        if (direction == TextDirection::LTR)
+            updateLogicalWidthForRightAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        else
+            updateLogicalWidthForLeftAlignedBlock(isLeftToRightDirection, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    }
+}
+
+static void updateLogicalInlinePositions(RenderBlockFlow& block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine,
+    IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
+{
+    LayoutUnit lineLogicalHeight = block.minLineHeightForReplacedRenderer(firstLine, boxLogicalHeight);
+    lineLogicalLeft = block.logicalLeftOffsetForLine(block.logicalHeight(), shouldIndentText, lineLogicalHeight);
+    lineLogicalRight = block.logicalRightOffsetForLine(block.logicalHeight(), shouldIndentText, lineLogicalHeight);
+    availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
+}
+
+void LegacyLineLayout::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
+{
+    TextAlignMode textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
+    
+    // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted line of an element. For example, the first line of an anonymous block 
+    // box is only affected if it is the first child of its parent element."
+    // CSS3 "text-indent", "-webkit-each-line" affects the first line of the block container as well as each line after a forced line break,
+    // but does not affect lines after a soft wrap break.
+    bool isFirstLine = lineInfo.isFirstLine() && !(m_flow.isAnonymousBlock() && m_flow.parent()->firstChild() != &m_flow);
+    bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak();
+    IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLineBreak, style());
+    float lineLogicalLeft;
+    float lineLogicalRight;
+    float availableLogicalWidth;
+    updateLogicalInlinePositions(m_flow, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, 0);
+    bool needsWordSpacing;
+
+    if (firstRun && firstRun->renderer().isReplaced()) {
+        RenderBox& renderBox = downcast<RenderBox>(firstRun->renderer());
+        updateLogicalInlinePositions(m_flow, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, renderBox.logicalHeight());
+    }
+
+    computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
+    // The widths of all runs are now known. We can now place every inline box (and
+    // compute accurate widths for the inline flow boxes).
+    needsWordSpacing = false;
+    lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing);
+}
+
+static inline ExpansionBehavior expansionBehaviorForInlineTextBox(RenderBlockFlow& block, InlineTextBox& textBox, BidiRun* previousRun, BidiRun* nextRun, TextAlignMode textAlign, bool isAfterExpansion)
+{
+    // Tatechuyoko is modeled as the Object Replacement Character (U+FFFC), which can never have expansion opportunities inside nor intrinsically adjacent to it.
+    if (textBox.renderer().style().textCombine() == TextCombine::Horizontal)
+        return ForbidLeftExpansion | ForbidRightExpansion;
+
+    ExpansionBehavior result = 0;
+    bool setLeftExpansion = false;
+    bool setRightExpansion = false;
+    if (textAlign == TextAlignMode::Justify) {
+        // If the next box is ruby, and we're justifying, and the first box in the ruby base has a leading expansion, and we are a text box, then force a trailing expansion.
+        if (nextRun && is<RenderRubyRun>(nextRun->renderer()) && downcast<RenderRubyRun>(nextRun->renderer()).rubyBase() && nextRun->renderer().style().collapseWhiteSpace()) {
+            auto& rubyBase = *downcast<RenderRubyRun>(nextRun->renderer()).rubyBase();
+            if (rubyBase.firstRootBox() && !rubyBase.firstRootBox()->nextRootBox()) {
+                if (auto* leafChild = rubyBase.firstRootBox()->firstLeafDescendant()) {
+                    if (is<InlineTextBox>(*leafChild)) {
+                        // FIXME: This leftExpansionOpportunity doesn't actually work because it doesn't perform the UBA
+                        if (FontCascade::leftExpansionOpportunity(downcast<RenderText>(leafChild->renderer()).stringView(), leafChild->direction())) {
+                            setRightExpansion = true;
+                            result |= ForceRightExpansion;
+                        }
+                    }
+                }
+            }
+        }
+        // Same thing, except if we're following a ruby
+        if (previousRun && is<RenderRubyRun>(previousRun->renderer()) && downcast<RenderRubyRun>(previousRun->renderer()).rubyBase() && previousRun->renderer().style().collapseWhiteSpace()) {
+            auto& rubyBase = *downcast<RenderRubyRun>(previousRun->renderer()).rubyBase();
+            if (rubyBase.firstRootBox() && !rubyBase.firstRootBox()->nextRootBox()) {
+                if (auto* leafChild = rubyBase.firstRootBox()->lastLeafDescendant()) {
+                    if (is<InlineTextBox>(*leafChild)) {
+                        // FIXME: This leftExpansionOpportunity doesn't actually work because it doesn't perform the UBA
+                        if (FontCascade::rightExpansionOpportunity(downcast<RenderText>(leafChild->renderer()).stringView(), leafChild->direction())) {
+                            setLeftExpansion = true;
+                            result |= ForceLeftExpansion;
+                        }
+                    }
+                }
+            }
+        }
+        // If we're the first box inside a ruby base, forbid a leading expansion, and vice-versa
+        if (is<RenderRubyBase>(block)) {
+            RenderRubyBase& rubyBase = downcast<RenderRubyBase>(block);
+            if (&textBox == rubyBase.firstRootBox()->firstLeafDescendant()) {
+                setLeftExpansion = true;
+                result |= ForbidLeftExpansion;
+            } if (&textBox == rubyBase.firstRootBox()->lastLeafDescendant()) {
+                setRightExpansion = true;
+                result |= ForbidRightExpansion;
+            }
+        }
+    }
+    if (!setLeftExpansion)
+        result |= isAfterExpansion ? ForbidLeftExpansion : AllowLeftExpansion;
+    if (!setRightExpansion)
+        result |= AllowRightExpansion;
+    return result;
+}
+
+static inline void applyExpansionBehavior(InlineTextBox& textBox, ExpansionBehavior expansionBehavior)
+{
+    switch (expansionBehavior & LeftExpansionMask) {
+    case ForceLeftExpansion:
+        textBox.setForceLeftExpansion();
+        break;
+    case ForbidLeftExpansion:
+        textBox.setCanHaveLeftExpansion(false);
+        break;
+    case AllowLeftExpansion:
+        textBox.setCanHaveLeftExpansion(true);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    switch (expansionBehavior & RightExpansionMask) {
+    case ForceRightExpansion:
+        textBox.setForceRightExpansion();
+        break;
+    case ForbidRightExpansion:
+        textBox.setCanHaveRightExpansion(false);
+        break;
+    case AllowRightExpansion:
+        textBox.setCanHaveRightExpansion(true);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+static bool inlineAncestorHasStartBorderPaddingOrMargin(const RenderBlockFlow& block, const InlineBox& box)
+{
+    bool isLTR = block.style().isLeftToRightDirection();
+    for (auto* currentBox = box.parent(); currentBox; currentBox = currentBox->parent()) {
+        if ((isLTR && currentBox->marginBorderPaddingLogicalLeft() > 0)
+            || (!isLTR && currentBox->marginBorderPaddingLogicalRight() > 0))
+            return true;
+    }
+    return false;
+}
+
+static bool inlineAncestorHasEndBorderPaddingOrMargin(const RenderBlockFlow& block, const InlineBox& box)
+{
+    bool isLTR = block.style().isLeftToRightDirection();
+    for (auto* currentBox = box.parent(); currentBox; currentBox = currentBox->parent()) {
+        if ((isLTR && currentBox->marginBorderPaddingLogicalRight() > 0)
+            || (!isLTR && currentBox->marginBorderPaddingLogicalLeft() > 0))
+            return true;
+    }
+    return false;
+}
+    
+static bool isLastInFlowRun(BidiRun& runToCheck)
+{
+    for (auto* run = runToCheck.next(); run; run = run->next()) {
+        if (!run->box() || run->renderer().isOutOfFlowPositioned() || run->box()->isLineBreak())
+            continue;
+        return false;
+    }
+    return true;
+}
+
+BidiRun* LegacyLineLayout::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, TextAlignMode textAlign, float& lineLogicalLeft,
+    float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
+    WordMeasurements& wordMeasurements)
+{
+    bool needsWordSpacing = false;
+    bool canHangPunctuationAtStart = style().hangingPunctuation().contains(HangingPunctuation::First);
+    bool canHangPunctuationAtEnd = style().hangingPunctuation().contains(HangingPunctuation::Last);
+    bool isLTR = style().isLeftToRightDirection();
+    float contentWidth = 0;
+    unsigned expansionOpportunityCount = 0;
+    bool isAfterExpansion = is<RenderRubyBase>(m_flow) ? downcast<RenderRubyBase>(m_flow).isAfterExpansion() : true;
+    Vector<unsigned, 16> expansionOpportunities;
+
+    HashMap<InlineTextBox*, LayoutUnit> logicalSpacingForInlineTextBoxes;
+    auto collectSpacingLogicalWidths = [&] () {
+        auto totalSpacingWidth = LayoutUnit { };
+        // Collect the spacing positions (margin, border padding) for the textboxes by traversing the inline tree of the current line.
+        Vector<InlineBox*> queue;
+        queue.append(lineBox);
+        // 1. Visit each inline box in a preorder fashion
+        // 2. Accumulate the spacing when we find an InlineFlowBox (inline container e.g. span)
+        // 3. Add the InlineTextBoxes to the hashmap
+        while (!queue.isEmpty()) {
+            while (true) {
+                auto* inlineBox = queue.last();
+                if (is<InlineFlowBox>(inlineBox)) {
+                    auto& inlineFlowBox = downcast<InlineFlowBox>(*inlineBox);
+                    totalSpacingWidth += inlineFlowBox.marginBorderPaddingLogicalLeft();
+                    if (auto* child = inlineFlowBox.firstChild()) {
+                        queue.append(child);
+                        continue;
+                    }
+                    break;
+                }
+                if (is<InlineTextBox>(inlineBox))
+                    logicalSpacingForInlineTextBoxes.add(downcast<InlineTextBox>(inlineBox), totalSpacingWidth);
+                break;
+            }
+            while (!queue.isEmpty()) {
+                auto& inlineBox = *queue.takeLast();
+                if (is<InlineFlowBox>(inlineBox))
+                    totalSpacingWidth += downcast<InlineFlowBox>(inlineBox).marginBorderPaddingLogicalRight();
+                if (auto* nextSibling = inlineBox.nextOnLine()) {
+                    queue.append(nextSibling);
+                    break;
+                }
+            }
+        }
+    };
+    collectSpacingLogicalWidths();
+
+    BidiRun* run = firstRun;
+    BidiRun* previousRun = nullptr;
+    for (; run; run = run->next()) {
+        auto computeExpansionOpportunities = [&expansionOpportunities, &expansionOpportunityCount, textAlign, &isAfterExpansion] (RenderBlockFlow& block,
+            InlineTextBox& textBox, BidiRun* previousRun, BidiRun* nextRun, const StringView& stringView, TextDirection direction)
+        {
+            if (stringView.isEmpty()) {
+                // Empty runs should still produce an entry in expansionOpportunities list so that the number of items matches the number of runs.
+                expansionOpportunities.append(0);
+                return;
+            }
+            ExpansionBehavior expansionBehavior = expansionBehaviorForInlineTextBox(block, textBox, previousRun, nextRun, textAlign, isAfterExpansion);
+            applyExpansionBehavior(textBox, expansionBehavior);
+            unsigned opportunitiesInRun;
+            std::tie(opportunitiesInRun, isAfterExpansion) = FontCascade::expansionOpportunityCount(stringView, direction, expansionBehavior);
+            expansionOpportunities.append(opportunitiesInRun);
+            expansionOpportunityCount += opportunitiesInRun;
+        };
+        if (!run->box() || run->renderer().isOutOfFlowPositioned() || run->box()->isLineBreak()) {
+            // Positioned objects are only participating to figure out their correct static x position.
+            // They have no effect on the width. Similarly, line break boxes have no effect on the width.
+            continue;
+        }
+        if (is<RenderText>(run->renderer())) {
+            auto& renderText = downcast<RenderText>(run->renderer());
+            auto& textBox = downcast<InlineTextBox>(*run->box());
+            if (canHangPunctuationAtStart && lineInfo.isFirstLine() && (isLTR || isLastInFlowRun(*run))
+                && !inlineAncestorHasStartBorderPaddingOrMargin(m_flow, *run->box())) {
+                float hangStartWidth = renderText.hangablePunctuationStartWidth(run->m_start);
+                availableLogicalWidth += hangStartWidth;
+                if (style().isLeftToRightDirection())
+                    lineLogicalLeft -= hangStartWidth;
+                canHangPunctuationAtStart = false;
+            }
+            
+            if (canHangPunctuationAtEnd && lineInfo.isLastLine() && run->m_stop > 0 && (!isLTR || isLastInFlowRun(*run))
+                && !inlineAncestorHasEndBorderPaddingOrMargin(m_flow, *run->box())) {
+                float hangEndWidth = renderText.hangablePunctuationEndWidth(run->m_stop - 1);
+                availableLogicalWidth += hangEndWidth;
+                if (!style().isLeftToRightDirection())
+                    lineLogicalLeft -= hangEndWidth;
+                canHangPunctuationAtEnd = false;
+            }
+            
+            if (textAlign == TextAlignMode::Justify && run != trailingSpaceRun)
+                computeExpansionOpportunities(m_flow, textBox, previousRun, run->next(), renderText.stringView(run->m_start, run->m_stop), run->box()->direction());
+
+            if (unsigned length = renderText.text().length()) {
+                if (!run->m_start && needsWordSpacing && isSpaceOrNewline(renderText.characterAt(run->m_start)))
+                    contentWidth += lineStyle(*renderText.parent(), lineInfo).fontCascade().wordSpacing();
+                // run->m_start == run->m_stop should only be true iff the run is a replaced run for bidi: isolate.
+                ASSERT(run->m_stop > 0 || run->m_start == run->m_stop);
+                needsWordSpacing = run->m_stop == length && !isSpaceOrNewline(renderText.characterAt(run->m_stop - 1));
+            }
+            auto currentLogicalLeftPosition = logicalSpacingForInlineTextBoxes.get(&textBox) + contentWidth;
+            setLogicalWidthForTextRun(lineBox, run, renderText, currentLogicalLeftPosition, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements);
+        } else {
+            canHangPunctuationAtStart = false;
+            bool encounteredJustifiedRuby = false;
+            if (is<RenderRubyRun>(run->renderer()) && textAlign == TextAlignMode::Justify && run != trailingSpaceRun && downcast<RenderRubyRun>(run->renderer()).rubyBase()) {
+                auto* rubyBase = downcast<RenderRubyRun>(run->renderer()).rubyBase();
+                if (rubyBase->firstRootBox() && !rubyBase->firstRootBox()->nextRootBox() && run->renderer().style().collapseWhiteSpace()) {
+                    rubyBase->setIsAfterExpansion(isAfterExpansion);
+                    for (auto* leafChild = rubyBase->firstRootBox()->firstLeafDescendant(); leafChild; leafChild = leafChild->nextLeafOnLine()) {
+                        if (!is<InlineTextBox>(*leafChild))
+                            continue;
+                        encounteredJustifiedRuby = true;
+                        computeExpansionOpportunities(*rubyBase, downcast<InlineTextBox>(*leafChild), nullptr, nullptr,
+                            downcast<RenderText>(leafChild->renderer()).stringView(), leafChild->direction());
+                    }
+                }
+            }
+
+            if (!encounteredJustifiedRuby)
+                isAfterExpansion = false;
+
+            if (!is<RenderInline>(run->renderer())) {
+                auto& renderBox = downcast<RenderBox>(run->renderer());
+                if (is<RenderRubyRun>(renderBox))
+                    setMarginsForRubyRun(run, downcast<RenderRubyRun>(renderBox), previousRun ? &previousRun->renderer() : nullptr, lineInfo);
+                run->box()->setLogicalWidth(m_flow.logicalWidthForChild(renderBox));
+                contentWidth += m_flow.marginStartForChild(renderBox) + m_flow.marginEndForChild(renderBox);
+            }
+        }
+
+        contentWidth += run->box()->logicalWidth();
+        previousRun = run;
+    }
+
+    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
+        // FIXME: see <webkit.org/b/139393#c11>
+        int lastValidExpansionOpportunitiesIndex = expansionOpportunities.size() - 1;
+        while (lastValidExpansionOpportunitiesIndex >= 0 && !expansionOpportunities.at(lastValidExpansionOpportunitiesIndex))
+            --lastValidExpansionOpportunitiesIndex;
+        if (lastValidExpansionOpportunitiesIndex >= 0) {
+            ASSERT(expansionOpportunities.at(lastValidExpansionOpportunitiesIndex));
+            expansionOpportunities.at(lastValidExpansionOpportunitiesIndex)--;
+            expansionOpportunityCount--;
+        }
+    }
+
+    if (is<RenderRubyBase>(m_flow) && !expansionOpportunityCount)
+        textAlign = TextAlignMode::Center;
+
+    auto totalLogicalWidth = contentWidth + lineBox->getFlowSpacingLogicalWidth();
+    updateLogicalWidthForAlignment(m_flow, textAlign, lineBox, trailingSpaceRun, lineLogicalLeft, totalLogicalWidth, availableLogicalWidth, expansionOpportunityCount);
+    computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth);
+    return run;
+}
+
+void LegacyLineLayout::removeInlineBox(BidiRun& run, const RootInlineBox& rootLineBox) const
+{
+    auto* inlineBox = run.box();
+#if ASSERT_ENABLED
+    auto* inlineParent = inlineBox->parent();
+    while (inlineParent && inlineParent != &rootLineBox) {
+        ASSERT(!inlineParent->isDirty());
+        inlineParent = inlineParent->parent();
+    }
+    ASSERT(!rootLineBox.isDirty());
+#endif
+    auto* parent = inlineBox->parent();
+    inlineBox->removeFromParent();
+
+    auto& renderer = run.renderer();
+    if (is<RenderText>(renderer))
+        downcast<RenderText>(renderer).removeTextBox(downcast<InlineTextBox>(*inlineBox));
+    delete inlineBox;
+    run.setBox(nullptr);
+    // removeFromParent() unnecessarily dirties the ancestor subtree.
+    auto* ancestor = parent;
+    while (ancestor) {
+        ancestor->markDirty(false);
+        if (ancestor == &rootLineBox)
+            break;
+        ancestor = ancestor->parent();
+    }
+}
+
+void LegacyLineLayout::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache)
+{
+    m_flow.setLogicalHeight(lineBox->alignBoxesInBlockDirection(m_flow.logicalHeight(), textBoxDataMap, verticalPositionCache));
+
+    // Now make sure we place replaced render objects correctly.
+    for (auto* run = firstRun; run; run = run->next()) {
+        ASSERT(run->box());
+        if (!run->box())
+            continue; // Skip runs with no line boxes.
+
+        // Align positioned boxes with the top of the line box. This is
+        // a reasonable approximation of an appropriate y position.
+        auto& renderer = run->renderer();
+        if (renderer.isOutOfFlowPositioned())
+            run->box()->setLogicalTop(m_flow.logicalHeight());
+
+        // Position is used to properly position both replaced elements and
+        // to update the static normal flow x/y of positioned elements.
+        bool inlineBoxIsRedundant = false;
+        if (is<RenderText>(renderer)) {
+            auto& inlineTextBox = downcast<InlineTextBox>(*run->box());
+            downcast<RenderText>(renderer).positionLineBox(inlineTextBox);
+            inlineBoxIsRedundant = !inlineTextBox.hasTextContent();
+        } else if (is<RenderBox>(renderer)) {
+            downcast<RenderBox>(renderer).positionLineBox(downcast<InlineElementBox>(*run->box()));
+            inlineBoxIsRedundant = renderer.isOutOfFlowPositioned();
+        } else if (is<RenderLineBreak>(renderer))
+            downcast<RenderLineBreak>(renderer).replaceInlineBoxWrapper(downcast<InlineElementBox>(*run->box()));
+        // Check if we need to keep this box on the line at all.
+        if (inlineBoxIsRedundant)
+            removeInlineBox(*run, *lineBox);
+    }
+}
+
+static inline bool isCollapsibleSpace(UChar character, const RenderText& renderer)
+{
+    if (character == ' ' || character == '\t' || character == softHyphen)
+        return true;
+    if (character == '\n')
+        return !renderer.style().preserveNewline();
+    if (character == noBreakSpace)
+        return renderer.style().nbspMode() == NBSPMode::Space;
+    return false;
+}
+
+template <typename CharacterType>
+static inline unsigned findFirstTrailingSpace(const RenderText& lastText, const CharacterType* characters, unsigned start, unsigned stop)
+{
+    unsigned firstSpace = stop;
+    while (firstSpace > start) {
+        UChar current = characters[firstSpace - 1];
+        if (!isCollapsibleSpace(current, lastText))
+            break;
+        firstSpace--;
+    }
+
+    return firstSpace;
+}
+
+inline BidiRun* LegacyLineLayout::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
+{
+    if (!bidiRuns.runCount()
+        || !bidiRuns.logicallyLastRun()->renderer().style().breakOnlyAfterWhiteSpace()
+        || !bidiRuns.logicallyLastRun()->renderer().style().autoWrap())
+        return nullptr;
+
+    BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
+    const RenderObject& lastObject = trailingSpaceRun->renderer();
+    if (!is<RenderText>(lastObject))
+        return nullptr;
+
+    const RenderText& lastText = downcast<RenderText>(lastObject);
+    unsigned firstSpace;
+    if (lastText.text().is8Bit())
+        firstSpace = findFirstTrailingSpace(lastText, lastText.text().characters8(), trailingSpaceRun->start(), trailingSpaceRun->stop());
+    else
+        firstSpace = findFirstTrailingSpace(lastText, lastText.text().characters16(), trailingSpaceRun->start(), trailingSpaceRun->stop());
+
+    if (firstSpace == trailingSpaceRun->stop())
+        return nullptr;
+
+    TextDirection direction = style().direction();
+    bool shouldReorder = trailingSpaceRun != (direction == TextDirection::LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
+    if (firstSpace != trailingSpaceRun->start()) {
+        BidiContext* baseContext = currentContext;
+        while (BidiContext* parent = baseContext->parent())
+            baseContext = parent;
+
+        std::unique_ptr<BidiRun> newTrailingRun = makeUnique<BidiRun>(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->renderer(), baseContext, U_OTHER_NEUTRAL);
+        trailingSpaceRun->m_stop = firstSpace;
+        trailingSpaceRun = newTrailingRun.get();
+        if (direction == TextDirection::LTR)
+            bidiRuns.appendRun(WTFMove(newTrailingRun));
+        else
+            bidiRuns.prependRun(WTFMove(newTrailingRun));
+        return trailingSpaceRun;
+    }
+    if (!shouldReorder)
+        return trailingSpaceRun;
+
+    if (direction == TextDirection::LTR) {
+        bidiRuns.moveRunToEnd(trailingSpaceRun);
+        trailingSpaceRun->m_level = 0;
+    } else {
+        bidiRuns.moveRunToBeginning(trailingSpaceRun);
+        trailingSpaceRun->m_level = 1;
+    }
+    return trailingSpaceRun;
+}
+
+void LegacyLineLayout::appendFloatingObjectToLastLine(FloatingObject& floatingObject)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject.originatingLine());
+    ASSERT(lastRootBox());
+    floatingObject.setOriginatingLine(*lastRootBox());
+    lastRootBox()->appendFloat(floatingObject.renderer());
+}
+
+static inline void notifyResolverToResumeInIsolate(InlineBidiResolver& resolver, RenderObject* root, RenderObject* startObject)
+{
+    if (root != startObject) {
+        RenderObject* parent = startObject->parent();
+        notifyResolverToResumeInIsolate(resolver, root, parent);
+        notifyObserverEnteredObject(&resolver, startObject);
+    }
+}
+
+static inline void setUpResolverToResumeInIsolate(InlineBidiResolver& resolver, InlineBidiResolver& topResolver, BidiRun& isolatedRun, RenderObject* root, RenderObject* startObject)
+{
+    // Set up m_whitespaceCollapsingState
+    resolver.whitespaceCollapsingState() = topResolver.whitespaceCollapsingState();
+    resolver.whitespaceCollapsingState().setCurrentTransition(topResolver.whitespaceCollapsingTransitionForIsolatedRun(isolatedRun));
+
+    // Set up m_nestedIsolateCount
+    notifyResolverToResumeInIsolate(resolver, root, startObject);
+}
+
+// FIXME: BidiResolver should have this logic.
+static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfRuns, VisualDirectionOverride override, bool previousLineBrokeCleanly)
+{
+    // FIXME: We should pass a BidiRunList into createBidiRunsForLine instead
+    // of the resolver owning the runs.
+    ASSERT(&topResolver.runs() == &bidiRuns);
+    ASSERT(topResolver.position() != endOfRuns);
+    RenderObject* currentRoot = topResolver.position().root();
+    topResolver.createBidiRunsForLine(endOfRuns, override, previousLineBrokeCleanly);
+
+    while (!topResolver.isolatedRuns().isEmpty()) {
+        // It does not matter which order we resolve the runs as long as we resolve them all.
+        auto isolatedRun = WTFMove(topResolver.isolatedRuns().last());
+        topResolver.isolatedRuns().removeLast();
+        currentRoot = &isolatedRun.root;
+
+        RenderObject& startObject = isolatedRun.object;
+
+        // Only inlines make sense with unicode-bidi: isolate (blocks are already isolated).
+        // FIXME: Because enterIsolate is not passed a RenderObject, we have to crawl up the
+        // tree to see which parent inline is the isolate. We could change enterIsolate
+        // to take a RenderObject and do this logic there, but that would be a layering
+        // violation for BidiResolver (which knows nothing about RenderObject).
+        RenderInline* isolatedInline = downcast<RenderInline>(highestContainingIsolateWithinRoot(startObject, currentRoot));
+        ASSERT(isolatedInline);
+
+        InlineBidiResolver isolatedResolver;
+        EUnicodeBidi unicodeBidi = isolatedInline->style().unicodeBidi();
+        TextDirection direction;
+        if (unicodeBidi == Plaintext)
+            determineDirectionality(direction, InlineIterator(isolatedInline, &isolatedRun.object, 0));
+        else {
+            ASSERT(unicodeBidi == Isolate || unicodeBidi == IsolateOverride);
+            direction = isolatedInline->style().direction();
+        }
+        isolatedResolver.setStatus(BidiStatus(direction, isOverride(unicodeBidi)));
+
+        setUpResolverToResumeInIsolate(isolatedResolver, topResolver, isolatedRun.runToReplace, isolatedInline, &startObject);
+
+        // The starting position is the beginning of the first run within the isolate that was identified
+        // during the earlier call to createBidiRunsForLine. This can be but is not necessarily the
+        // first run within the isolate.
+        InlineIterator iter = InlineIterator(isolatedInline, &startObject, isolatedRun.position);
+        isolatedResolver.setPositionIgnoringNestedIsolates(iter);
+
+        // We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns().
+        // FIXME: What should end and previousLineBrokeCleanly be?
+        // rniwa says previousLineBrokeCleanly is just a WinIE hack and could always be false here?
+        isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, previousLineBrokeCleanly);
+        // Note that we do not delete the runs from the resolver.
+        // We're not guaranteed to get any BidiRuns in the previous step. If we don't, we allow the placeholder
+        // itself to be turned into an InlineBox. We can't remove it here without potentially losing track of
+        // the logically last run.
+        if (isolatedResolver.runs().runCount())
+            bidiRuns.replaceRunWithRuns(&isolatedRun.runToReplace, isolatedResolver.runs());
+
+        // If we encountered any nested isolate runs, just move them
+        // to the top resolver's list for later processing.
+        while (!isolatedResolver.isolatedRuns().isEmpty()) {
+            auto runWithContext = WTFMove(isolatedResolver.isolatedRuns().last());
+            isolatedResolver.isolatedRuns().removeLast();
+            topResolver.setWhitespaceCollapsingTransitionForIsolatedRun(runWithContext.runToReplace, isolatedResolver.whitespaceCollapsingTransitionForIsolatedRun(runWithContext.runToReplace));
+            topResolver.isolatedRuns().append(WTFMove(runWithContext));
+        }
+    }
+}
+
+// This function constructs line boxes for all of the text runs in the resolver and computes their position.
+RootInlineBox* LegacyLineLayout::createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
+{
+    if (!bidiRuns.runCount())
+        return nullptr;
+
+    // FIXME: Why is this only done when we had runs?
+    lineInfo.setLastLine(!end.renderer());
+
+    RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo);
+    if (!lineBox)
+        return nullptr;
+
+    lineBox->setBidiLevel(bidiLevel);
+    lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly());
+    
+    bool isSVGRootInlineBox = is<SVGRootInlineBox>(*lineBox);
+    
+    GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+    
+    // Now we position all of our text runs horizontally.
+    if (!isSVGRootInlineBox)
+        computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wordMeasurements);
+    
+    // Now position our text runs vertically.
+    computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
+    
+    // SVG text layout code computes vertical & horizontal positions on its own.
+    // Note that we still need to execute computeVerticalPositionsForLine() as
+    // it calls InlineTextBox::positionLineBox(), which tracks whether the box
+    // contains reversed text or not. If we wouldn't do that editing and thus
+    // text selection in RTL boxes would not work as expected.
+    if (isSVGRootInlineBox) {
+        RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_flow.isSVGText());
+        downcast<SVGRootInlineBox>(*lineBox).computePerCharacterLayoutInformation();
+    }
+    
+    // Compute our overflow now.
+    lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
+    
+    return lineBox;
+}
+
+static void deleteLineRange(LineLayoutState& layoutState, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
+{
+    RootInlineBox* boxToDelete = startLine;
+    while (boxToDelete && boxToDelete != stopLine) {
+        layoutState.updateRepaintRangeFromBox(boxToDelete);
+        // Note: deleteLineRange(firstRootBox()) is not identical to deleteLineBoxTree().
+        // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
+        RootInlineBox* next = boxToDelete->nextRootBox();
+        boxToDelete->deleteLine();
+        boxToDelete = next;
+    }
+}
+
+static void repaintDirtyFloats(LineLayoutState::FloatList& floats)
+{
+    // Floats that did not have layout did not repaint when we laid them out. They would have
+    // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
+    // painted.
+    for (auto& floatBox : floats) {
+        if (floatBox->everHadLayout())
+            continue;
+        auto& box = floatBox->renderer();
+        if (!box.x() && !box.y() && box.checkForRepaintDuringLayout())
+            box.repaint();
+    }
+}
+
+void LegacyLineLayout::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
+{
+    // We want to skip ahead to the first dirty line
+    InlineBidiResolver resolver;
+    RootInlineBox* startLine = determineStartPosition(layoutState, resolver);
+    
+    unsigned consecutiveHyphenatedLines = 0;
+    if (startLine) {
+        for (RootInlineBox* line = startLine->prevRootBox(); line && line->isHyphenated(); line = line->prevRootBox())
+            consecutiveHyphenatedLines++;
+    }
+
+    // FIXME: This would make more sense outside of this function, but since
+    // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
+    // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
+    if (layoutState.isFullLayout() && hasInlineChild && !m_flow.selfNeedsLayout()) {
+        m_flow.setNeedsLayout(MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
+        if (!layoutContext().needsFullRepaint() && m_flow.layerRepaintRects()) {
+            // Because we waited until we were already inside layout to discover
+            // that the block really needed a full layout, we missed our chance to repaint the layer
+            // before layout started. Luckily the layer has cached the repaint rect for its original
+            // position and size, and so we can use that to make a repaint happen now.
+            m_flow.repaintUsingContainer(m_flow.containerForRepaint(), m_flow.layerRepaintRects()->clippedOverflowRect);
+        }
+    }
+
+    if (m_flow.containsFloats())
+        layoutState.floatList().setLastFloat(m_flow.floatingObjects()->set().last().get());
+
+    // We also find the first clean line and extract these lines. We will add them back
+    // if we determine that we're able to synchronize after handling all our dirty lines.
+    InlineIterator cleanLineStart;
+    BidiStatus cleanLineBidiStatus;
+    if (!layoutState.isFullLayout() && startLine)
+        determineEndPosition(layoutState, startLine, cleanLineStart, cleanLineBidiStatus);
+
+    if (startLine) {
+        if (!layoutState.usesRepaintBounds())
+            layoutState.setRepaintRange(m_flow.logicalHeight());
+        deleteLineRange(layoutState, startLine);
+    }
+
+    if (!layoutState.isFullLayout() && lastRootBox() && lastRootBox()->endsWithBreak()) {
+        // If the last line before the start line ends with a line break that clear floats,
+        // adjust the height accordingly.
+        // A line break can be either the first or the last object on a line, depending on its direction.
+        if (InlineBox* lastLeafDescendant = lastRootBox()->lastLeafDescendant()) {
+            RenderObject* lastObject = &lastLeafDescendant->renderer();
+            if (!lastObject->isBR())
+                lastObject = &lastRootBox()->firstLeafDescendant()->renderer();
+            if (lastObject->isBR()) {
+                auto clear = RenderStyle::usedClear(*lastObject);
+                if (clear != UsedClear::None)
+                    m_flow.clearFloats(clear);
+            }
+        }
+    }
+
+    layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines);
+    linkToEndLineIfNeeded(layoutState);
+    repaintDirtyFloats(layoutState.floatList());
+}
+
+// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
+inline const InlineIterator& LegacyLineLayout::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver,  const InlineIterator& oldEnd)
+{
+    m_flow.removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
+    m_flow.setLogicalHeight(newLogicalHeight);
+    resolver.setPositionIgnoringNestedIsolates(oldEnd);
+    return oldEnd;
+}
+
+void LegacyLineLayout::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
+{
+    const RenderStyle& styleToUse = style();
+    bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
+    LineWhitespaceCollapsingState& lineWhitespaceCollapsingState = resolver.whitespaceCollapsingState();
+    InlineIterator end = resolver.position();
+    bool checkForEndLineMatch = layoutState.endLine();
+    RenderTextInfo renderTextInfo;
+    VerticalPositionCache verticalPositionCache;
+
+    LineBreaker lineBreaker(m_flow);
+
+    while (!end.atEnd()) {
+        // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
+        if (checkForEndLineMatch) {
+            layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus));
+            if (layoutState.endLineMatched()) {
+                resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
+                layoutState.marginInfo().clearMargin();
+                break;
+            }
+        }
+
+        lineWhitespaceCollapsingState.reset();
+
+        layoutState.lineInfo().setEmpty(true);
+        layoutState.lineInfo().resetRunsFromLeadingWhitespace();
+
+        const InlineIterator oldEnd = end;
+        bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
+        FloatingObject* lastFloatFromPreviousLine = (m_flow.containsFloats()) ? m_flow.floatingObjects()->set().last().get() : nullptr;
+
+        WordMeasurements wordMeasurements;
+        end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
+        m_flow.cachePriorCharactersIfNeeded(renderTextInfo.lineBreakIterator);
+        renderTextInfo.lineBreakIterator.resetPriorContext();
+        if (resolver.position().atEnd()) {
+            // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
+            // Once BidiRunList is separated from BidiResolver this will not be needed.
+            resolver.runs().clear();
+            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
+            layoutState.setCheckForFloatsFromLastLine(true);
+            resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
+            break;
+        }
+
+        ASSERT(end != resolver.position());
+
+        // This is a short-cut for empty lines.
+        if (layoutState.lineInfo().isEmpty()) {
+            if (lastRootBox())
+                lastRootBox()->setLineBreakInfo(end.renderer(), end.offset(), resolver.status());
+        } else {
+            VisualDirectionOverride override = (styleToUse.rtlOrdering() == Order::Visual ? (styleToUse.direction() == TextDirection::LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
+
+            if (isNewUBAParagraph && styleToUse.unicodeBidi() == Plaintext && !resolver.context()->parent()) {
+                TextDirection direction = styleToUse.direction();
+                determineDirectionality(direction, resolver.position());
+                resolver.setStatus(BidiStatus(direction, isOverride(styleToUse.unicodeBidi())));
+            }
+            // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
+            BidiRunList<BidiRun>& bidiRuns = resolver.runs();
+            constructBidiRunsForSegment(resolver, bidiRuns, end, override, layoutState.lineInfo().previousLineBrokeCleanly());
+            ASSERT(resolver.position() == end);
+
+            BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrokeCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : nullptr;
+
+            if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
+                bidiRuns.logicallyLastRun()->m_hasHyphen = true;
+                consecutiveHyphenatedLines++;
+            } else
+                consecutiveHyphenatedLines = 0;
+
+            // Now that the runs have been ordered, we create the line boxes.
+            // At the same time we figure out where border/padding/margin should be applied for
+            // inline flow boxes.
+
+            LayoutUnit oldLogicalHeight = m_flow.logicalHeight();
+            RootInlineBox* lineBox = createLineBoxesFromBidiRuns(resolver.status().context->level(), bidiRuns, end, layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, wordMeasurements);
+
+            bidiRuns.clear();
+            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
+
+            if (lineBox) {
+                lineBox->setLineBreakInfo(end.renderer(), end.offset(), resolver.status());
+                if (layoutState.usesRepaintBounds())
+                    layoutState.updateRepaintRangeFromBox(lineBox);
+                
+                LayoutUnit adjustment;
+                bool overflowsFragment = false;
+                
+                layoutState.marginInfo().setAtBeforeSideOfBlock(false);
+
+                if (paginated)
+                    m_flow.adjustLinePositionForPagination(lineBox, adjustment, overflowsFragment, layoutState.fragmentedFlow());
+                if (adjustment) {
+                    IndentTextOrNot shouldIndentText = layoutState.lineInfo().isFirstLine() ? IndentText : DoNotIndentText;
+                    LayoutUnit oldLineWidth = m_flow.availableLogicalWidthForLine(oldLogicalHeight, shouldIndentText);
+                    lineBox->adjustBlockDirectionPosition(adjustment);
+                    if (layoutState.usesRepaintBounds())
+                        layoutState.updateRepaintRangeFromBox(lineBox);
+
+                    if (m_flow.availableLogicalWidthForLine(oldLogicalHeight + adjustment, shouldIndentText) != oldLineWidth) {
+                        // We have to delete this line, remove all floats that got added, and let line layout re-run.
+                        lineBox->deleteLine();
+                        end = restartLayoutRunsAndFloatsInRange(oldLogicalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, oldEnd);
+                        continue;
+                    }
+
+                    m_flow.setLogicalHeight(lineBox->lineBoxBottom());
+                }
+                    
+                if (paginated) {
+                    if (layoutState.fragmentedFlow())
+                        updateFragmentForLine(lineBox);
+                }
+            }
+        }
+
+        for (size_t i = 0; i < lineBreaker.positionedObjects().size(); ++i)
+            setStaticPositions(m_flow, *lineBreaker.positionedObjects()[i], DoNotIndentText);
+
+        if (!layoutState.lineInfo().isEmpty()) {
+            layoutState.lineInfo().setFirstLine(false);
+            m_flow.clearFloats(lineBreaker.usedClear());
+        }
+
+        if (m_flow.floatingObjects() && lastRootBox()) {
+            const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
+            auto it = floatingObjectSet.begin();
+            auto end = floatingObjectSet.end();
+            if (auto* lastFloat = layoutState.floatList().lastFloat()) {
+                auto lastFloatIterator = floatingObjectSet.find(lastFloat);
+                ASSERT(lastFloatIterator != end);
+                ++lastFloatIterator;
+                it = lastFloatIterator;
+            }
+            for (; it != end; ++it) {
+                auto& floatingObject = *it;
+                appendFloatingObjectToLastLine(*floatingObject);
+                // If a float's geometry has changed, give up on syncing with clean lines.
+                auto* floatWithRect = layoutState.floatList().floatWithRect(floatingObject->renderer());
+                if (!floatWithRect || floatWithRect->rect() != floatingObject->frameRect())
+                    checkForEndLineMatch = false;
+            }
+            layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
+        }
+
+        lineWhitespaceCollapsingState.reset();
+        resolver.setPosition(end, numberOfIsolateAncestors(end));
+    }
+
+    // In case we already adjusted the line positions during this layout to avoid widows
+    // then we need to ignore the possibility of having a new widows situation.
+    // Otherwise, we risk leaving empty containers which is against the block fragmentation principles.
+    if (paginated && !style().hasAutoWidows() && !m_flow.didBreakAtLineToAvoidWidow()) {
+        // Check the line boxes to make sure we didn't create unacceptable widows.
+        // However, we'll prioritize orphans - so nothing we do here should create
+        // a new orphan.
+
+        RootInlineBox* lineBox = lastRootBox();
+
+        // Count from the end of the block backwards, to see how many hanging
+        // lines we have.
+        RootInlineBox* firstLineInBlock = firstRootBox();
+        int numLinesHanging = 1;
+        while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
+            ++numLinesHanging;
+            lineBox = lineBox->prevRootBox();
+        }
+
+        // If there were no breaks in the block, we didn't create any widows.
+        if (!lineBox || !lineBox->isFirstAfterPageBreak() || lineBox == firstLineInBlock) {
+            if (m_flow.shouldBreakAtLineToAvoidWidow()) {
+                // This is the case when the previous line layout marks a line to break at to avoid widows
+                // but the current layout does not produce that line. It happens when layout constraints unexpectedly
+                // change in between layouts (note that these paginated line layouts run within the same layout frame
+                // as opposed to two subsequent full layouts).
+                ASSERT_NOT_REACHED();
+                m_flow.clearShouldBreakAtLineToAvoidWidow();
+            }
+            return;
+        }
+
+        if (numLinesHanging < style().widows()) {
+            // We have detected a widow. Now we need to work out how many
+            // lines there are on the previous page, and how many we need
+            // to steal.
+            int numLinesNeeded = style().widows() - numLinesHanging;
+            RootInlineBox* currentFirstLineOfNewPage = lineBox;
+
+            // Count the number of lines in the previous page.
+            lineBox = lineBox->prevRootBox();
+            int numLinesInPreviousPage = 1;
+            while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
+                ++numLinesInPreviousPage;
+                lineBox = lineBox->prevRootBox();
+            }
+
+            // If there was an explicit value for orphans, respect that. If not, we still
+            // shouldn't create a situation where we make an orphan bigger than the initial value.
+            // This means that setting widows implies we also care about orphans, but given
+            // the specification says the initial orphan value is non-zero, this is ok. The
+            // author is always free to set orphans explicitly as well.
+            int orphans = style().hasAutoOrphans() ? style().initialOrphans() : style().orphans();
+            int numLinesAvailable = numLinesInPreviousPage - orphans;
+            if (numLinesAvailable <= 0)
+                return;
+
+            int numLinesToTake = std::min(numLinesAvailable, numLinesNeeded);
+            // Wind back from our first widowed line.
+            lineBox = currentFirstLineOfNewPage;
+            for (int i = 0; i < numLinesToTake; ++i)
+                lineBox = lineBox->prevRootBox();
+
+            // We now want to break at this line. Remember for next layout and trigger relayout.
+            m_flow.setBreakAtLineToAvoidWidow(lineCountUntil(lineBox));
+            m_flow.markLinesDirtyInBlockRange(lastRootBox()->lineBoxBottom(), lineBox->lineBoxBottom(), lineBox);
+        }
+    }
+    m_flow.clearDidBreakAtLineToAvoidWidow();
+}
+
+void LegacyLineLayout::reattachCleanLineFloats(RootInlineBox& cleanLine, LayoutUnit delta, bool isFirstCleanLine)
+{
+    auto* cleanLineFloats = cleanLine.floatsPtr();
+    if (!cleanLineFloats)
+        return;
+
+    for (auto& floatingBox : *cleanLineFloats) {
+        if (!floatingBox)
+            continue;
+        auto* floatingObject = m_flow.insertFloatingObject(*floatingBox);
+        if (isFirstCleanLine && floatingObject->originatingLine()) {
+            // Float box does not belong to this line anymore.
+            ASSERT_WITH_SECURITY_IMPLICATION(cleanLine.prevRootBox() == floatingObject->originatingLine());
+            cleanLine.removeFloat(*floatingBox);
+            continue;
+        }
+        ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject->originatingLine());
+        floatingObject->setOriginatingLine(cleanLine);
+        m_flow.setLogicalHeight(m_flow.logicalTopForChild(*floatingBox) - m_flow.marginBeforeForChild(*floatingBox) + delta);
+        m_flow.positionNewFloats();
+    }
+}
+
+void LegacyLineLayout::linkToEndLineIfNeeded(LineLayoutState& layoutState)
+{
+    auto* firstCleanLine = layoutState.endLine();
+    if (firstCleanLine) {
+        if (layoutState.endLineMatched()) {
+            bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
+            // Attach all the remaining lines, and then adjust their y-positions as needed.
+            LayoutUnit delta = m_flow.logicalHeight() - layoutState.endLineLogicalTop();
+            for (auto* line = firstCleanLine; line; line = line->nextRootBox()) {
+                line->attachLine();
+                if (paginated) {
+                    delta -= line->paginationStrut();
+                    bool overflowsFragment;
+                    m_flow.adjustLinePositionForPagination(line, delta, overflowsFragment, layoutState.fragmentedFlow());
+                }
+                if (delta) {
+                    layoutState.updateRepaintRangeFromBox(line, delta);
+                    line->adjustBlockDirectionPosition(delta);
+                }
+                if (layoutState.fragmentedFlow())
+                    updateFragmentForLine(line);
+                reattachCleanLineFloats(*line, delta, line == firstCleanLine);
+            }
+            m_flow.setLogicalHeight(lastRootBox()->lineBoxBottom());
+        } else {
+            // Delete all the remaining lines.
+            deleteLineRange(layoutState, layoutState.endLine());
+        }
+    }
+    
+    if (m_flow.floatingObjects() && (layoutState.checkForFloatsFromLastLine() || m_flow.positionNewFloats()) && lastRootBox()) {
+        // In case we have a float on the last line, it might not be positioned up to now.
+        // This has to be done before adding in the bottom border/padding, or the float will
+        // include the padding incorrectly. -dwh
+        if (layoutState.checkForFloatsFromLastLine()) {
+            LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
+            LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
+            auto newLineBox = makeUnique<TrailingFloatsRootInlineBox>(m_flow);
+            auto trailingFloatsLineBox = newLineBox.get();
+            m_lineBoxes.appendLineBox(WTFMove(newLineBox));
+            trailingFloatsLineBox->setConstructed();
+            GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+            VerticalPositionCache verticalPositionCache;
+            LayoutUnit blockLogicalHeight = m_flow.logicalHeight();
+            trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
+            trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
+            trailingFloatsLineBox->setPaginatedLineWidth(m_flow.availableLogicalWidthForContent(blockLogicalHeight));
+            LayoutRect logicalLayoutOverflow(0_lu, blockLogicalHeight, 1_lu, bottomLayoutOverflow - blockLogicalHeight);
+            LayoutRect logicalVisualOverflow(0_lu, blockLogicalHeight, 1_lu, bottomVisualOverflow - blockLogicalHeight);
+            trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
+            if (layoutState.fragmentedFlow())
+                updateFragmentForLine(trailingFloatsLineBox);
+        }
+
+        const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
+        auto it = floatingObjectSet.begin();
+        auto end = floatingObjectSet.end();
+        if (auto* lastFloat = layoutState.floatList().lastFloat()) {
+            auto lastFloatIterator = floatingObjectSet.find(lastFloat);
+            ASSERT(lastFloatIterator != end);
+            ++lastFloatIterator;
+            it = lastFloatIterator;
+        }
+        for (; it != end; ++it)
+            appendFloatingObjectToLastLine(**it);
+        layoutState.floatList().setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last().get() : nullptr);
+    }
+}
+
+void LegacyLineLayout::layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom)
+{
+    m_flow.setLogicalHeight(m_flow.borderAndPaddingBefore());
+    
+    // Lay out our hypothetical grid line as though it occurs at the top of the block.
+    if (layoutContext().layoutState() && layoutContext().layoutState()->lineGrid() == &m_flow)
+        m_flow.layoutLineGridBox();
+
+    RenderFragmentedFlow* fragmentedFlow = m_flow.enclosingFragmentedFlow();
+    bool clearLinesForPagination = firstRootBox() && fragmentedFlow && !fragmentedFlow->hasFragments();
+
+    // Figure out if we should clear out our line boxes.
+    // FIXME: Handle resize eventually!
+    bool isFullLayout = !firstRootBox() || m_flow.selfNeedsLayout() || relayoutChildren || clearLinesForPagination;
+    LineLayoutState layoutState(m_flow, isFullLayout, repaintLogicalTop, repaintLogicalBottom, fragmentedFlow);
+
+    if (isFullLayout)
+        lineBoxes().deleteLineBoxes();
+
+    // Text truncation kicks in in two cases:
+    //     1) If your overflow isn't visible and your text-overflow-mode isn't clip.
+    //     2) If you're an anonymous block with a block parent that satisfies #1.
+    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate. This is insanely
+    // difficult to figure out in general (especially in the middle of doing layout), so we only handle the
+    // simple case of an anonymous block truncating when it's parent is clipped.
+    auto* parent = m_flow.parent();
+    bool hasTextOverflow = (style().textOverflow() == TextOverflow::Ellipsis && m_flow.hasOverflowClip())
+        || (m_flow.isAnonymousBlock() && parent && parent->isRenderBlock() && parent->style().textOverflow() == TextOverflow::Ellipsis && parent->hasOverflowClip());
+
+    // Walk all the lines and delete our ellipsis line boxes if they exist.
+    if (hasTextOverflow)
+        deleteEllipsisLineBoxes();
+
+    if (m_flow.firstChild()) {
+        // In full layout mode, clear the line boxes of children upfront. Otherwise,
+        // siblings can run into stale root lineboxes during layout. Then layout
+        // the replaced elements later. In partial layout mode, line boxes are not
+        // deleted and only dirtied. In that case, we can layout the replaced
+        // elements at the same time.
+        bool hasInlineChild = false;
+        Vector<RenderBox*> replacedChildren;
+        for (InlineWalker walker(m_flow); !walker.atEnd(); walker.advance()) {
+            RenderObject& o = *walker.current();
+
+            if (!hasInlineChild && o.isInline())
+                hasInlineChild = true;
+
+            if (o.isReplaced() || o.isFloating() || o.isOutOfFlowPositioned()) {
+                RenderBox& box = downcast<RenderBox>(o);
+
+                if (relayoutChildren || box.hasRelativeDimensions())
+                    box.setChildNeedsLayout(MarkOnlyThis);
+
+                // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
+                if (relayoutChildren && box.needsPreferredWidthsRecalculation())
+                    box.setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
+
+                if (box.isOutOfFlowPositioned())
+                    box.containingBlock()->insertPositionedObject(box);
+                else if (box.isFloating())
+                    layoutState.floatList().append(FloatWithRect::create(box));
+                else if (isFullLayout || box.needsLayout()) {
+                    // Replaced element.
+                    if (isFullLayout && is<RenderRubyRun>(box)) {
+                        // FIXME: This resets the overhanging margins that we set during line layout (see computeInlineDirectionPositionsForSegment)
+                        // Find a more suitable place for this.
+                        m_flow.setMarginStartForChild(box, 0);
+                        m_flow.setMarginEndForChild(box, 0);
+                    }
+                    box.dirtyLineBoxes(isFullLayout);
+                    if (isFullLayout)
+                        replacedChildren.append(&box);
+                    else
+                        box.layoutIfNeeded();
+                }
+            } else if (o.isTextOrLineBreak() || (is<RenderInline>(o) && !walker.atEndOfInline())) {
+                if (is<RenderInline>(o))
+                    downcast<RenderInline>(o).updateAlwaysCreateLineBoxes(layoutState.isFullLayout());
+                if (layoutState.isFullLayout() || o.selfNeedsLayout())
+                    dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
+                o.clearNeedsLayout();
+            }
+        }
+
+        for (size_t i = 0; i < replacedChildren.size(); i++)
+            replacedChildren[i]->layoutIfNeeded();
+
+        layoutRunsAndFloats(layoutState, hasInlineChild);
+    }
+
+    // Expand the last line to accommodate Ruby and emphasis marks.
+    int lastLineAnnotationsAdjustment = 0;
+    if (lastRootBox()) {
+        LayoutUnit lowestAllowedPosition = std::max(lastRootBox()->lineBottom(), m_flow.logicalHeight() + m_flow.paddingAfter());
+        if (!style().isFlippedLinesWritingMode())
+            lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
+        else
+            lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
+    }
+    
+    // Now do the handling of the bottom of the block, adding in our bottom border/padding and
+    // determining the correct collapsed bottom margin information. This collapse is only necessary
+    // if our last child was an anonymous inline block that might need to propagate margin information out to
+    // us.
+    LayoutUnit afterEdge = m_flow.borderAndPaddingAfter() + m_flow.scrollbarLogicalHeight() + lastLineAnnotationsAdjustment;
+    m_flow.setLogicalHeight(m_flow.logicalHeight() + afterEdge);
+
+    if (!firstRootBox() && m_flow.hasLineIfEmpty())
+        m_flow.setLogicalHeight(m_flow.logicalHeight() + m_flow.lineHeight(true, m_flow.isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
+
+    // See if we have any lines that spill out of our block. If we do, then we will possibly need to
+    // truncate text.
+    if (hasTextOverflow)
+        checkLinesForTextOverflow();
+}
+
+void LegacyLineLayout::checkFloatInCleanLine(RootInlineBox& cleanLine, RenderBox& floatBoxOnCleanLine, FloatWithRect& matchingFloatWithRect,
+    bool& encounteredNewFloat, bool& dirtiedByFloat)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!floatBoxOnCleanLine.style().deletionHasBegun());
+    if (&matchingFloatWithRect.renderer() != &floatBoxOnCleanLine) {
+        encounteredNewFloat = true;
+        return;
+    }
+    floatBoxOnCleanLine.layoutIfNeeded();
+    LayoutRect originalFloatRect = matchingFloatWithRect.rect();
+    LayoutSize newSize(
+        floatBoxOnCleanLine.width() + floatBoxOnCleanLine.horizontalMarginExtent(),
+        floatBoxOnCleanLine.height() + floatBoxOnCleanLine.verticalMarginExtent());
+    
+    // We have to reset the cap-height alignment done by the first-letter floats when initial-letter is set, so just always treat first-letter floats as dirty.
+    if (originalFloatRect.size() == newSize && (floatBoxOnCleanLine.style().styleType() != PseudoId::FirstLetter || !floatBoxOnCleanLine.style().initialLetterDrop()))
+        return;
+
+    LayoutUnit floatTop = m_flow.isHorizontalWritingMode() ? originalFloatRect.y() : originalFloatRect.x();
+    LayoutUnit floatHeight = m_flow.isHorizontalWritingMode() ? std::max(originalFloatRect.height(), newSize.height())
+        : std::max(originalFloatRect.width(), newSize.width());
+    floatHeight = std::min(floatHeight, LayoutUnit::max() - floatTop);
+    cleanLine.markDirty();
+    m_flow.markLinesDirtyInBlockRange(cleanLine.lineBoxBottom(), floatTop + floatHeight, &cleanLine);
+    LayoutRect newFloatRect = originalFloatRect;
+    newFloatRect.setSize(newSize);
+    matchingFloatWithRect.adjustRect(newFloatRect);
+    dirtiedByFloat = true;
+}
+
+RootInlineBox* LegacyLineLayout::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
+{
+    RootInlineBox* currentLine = nullptr;
+    RootInlineBox* lastLine = nullptr;
+
+    // FIXME: This entire float-checking block needs to be broken into a new function.
+    auto& floats = layoutState.floatList();
+    bool dirtiedByFloat = false;
+    if (!layoutState.isFullLayout()) {
+        // Paginate all of the clean lines.
+        bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
+        LayoutUnit paginationDelta;
+        auto floatsIterator = floats.begin();
+        auto end = floats.end();
+        for (currentLine = firstRootBox(); currentLine && !currentLine->isDirty(); currentLine = currentLine->nextRootBox()) {
+            if (paginated) {
+                if (lineWidthForPaginatedLineChanged(currentLine, 0, layoutState.fragmentedFlow())) {
+                    currentLine->markDirty();
+                    break;
+                }
+                paginationDelta -= currentLine->paginationStrut();
+                bool overflowsFragment;
+                m_flow.adjustLinePositionForPagination(currentLine, paginationDelta, overflowsFragment, layoutState.fragmentedFlow());
+                if (paginationDelta) {
+                    if (m_flow.containsFloats() || !floats.isEmpty()) {
+                        // FIXME: Do better eventually. For now if we ever shift because of pagination and floats are present just go to a full layout.
+                        layoutState.markForFullLayout();
+                        break;
+                    }
+
+                    layoutState.updateRepaintRangeFromBox(currentLine, paginationDelta);
+                    currentLine->adjustBlockDirectionPosition(paginationDelta);
+                }
+                if (layoutState.fragmentedFlow())
+                    updateFragmentForLine(currentLine);
+            }
+
+            if (auto* cleanLineFloats = currentLine->floatsPtr()) {
+                // If a new float has been inserted before this line or before its last known float, just do a full layout.
+                bool encounteredNewFloat = false;
+                for (auto& floatBoxOnCleanLine : *cleanLineFloats) {
+                    ASSERT(floatsIterator != end);
+                    if (!floatBoxOnCleanLine)
+                        continue;
+                    checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat);
+                    ++floatsIterator;
+                    if (floatsIterator == end || encounteredNewFloat) {
+                        layoutState.markForFullLayout();
+                        break;
+                    }
+                }
+                if (dirtiedByFloat || encounteredNewFloat)
+                    break;
+            }
+        }
+        // Check if a new float has been inserted after the last known float.
+        if (floatsIterator != end) {
+            if (!currentLine)
+                layoutState.markForFullLayout();
+            else {
+                for (; floatsIterator != end; ++floatsIterator) {
+                    auto& floatWithRect = *floatsIterator;
+                    if (!floatWithRect->renderer().needsLayout())
+                        continue;
+                    layoutState.markForFullLayout();
+                    break;
+                }
+            }
+        }
+    }
+
+    if (layoutState.isFullLayout()) {
+        m_lineBoxes.deleteLineBoxTree();
+        currentLine = nullptr;
+        ASSERT(!firstRootBox() && !lastRootBox());
+    } else {
+        if (currentLine) {
+            // We have a dirty line.
+            if (RootInlineBox* prevRootBox = currentLine->prevRootBox()) {
+                // We have a previous line.
+                if (!dirtiedByFloat && (!prevRootBox->endsWithBreak()
+                    || !prevRootBox->lineBreakObj()
+                    || (is<RenderText>(*prevRootBox->lineBreakObj())
+                    && prevRootBox->lineBreakPos() >= downcast<RenderText>(*prevRootBox->lineBreakObj()).text().length()))) {
+                    // The previous line didn't break cleanly or broke at a newline
+                    // that has been deleted, so treat it as dirty too.
+                    currentLine = prevRootBox;
+                }
+            }
+        }
+        // If we have no dirty lines, then last is just the last root box.
+        lastLine = currentLine ? currentLine->prevRootBox() : lastRootBox();
+    }
+
+    if (!floats.isEmpty()) {
+        LayoutUnit savedLogicalHeight = m_flow.logicalHeight();
+        // Restore floats from clean lines.
+        RootInlineBox* line = firstRootBox();
+        while (line != currentLine) {
+            if (auto* cleanLineFloats = line->floatsPtr()) {
+                for (auto& floatingBox : *cleanLineFloats) {
+                    if (!floatingBox)
+                        continue;
+                    auto* floatingObject = m_flow.insertFloatingObject(*floatingBox);
+                    ASSERT_WITH_SECURITY_IMPLICATION(!floatingObject->originatingLine());
+                    floatingObject->setOriginatingLine(*line);
+                    m_flow.setLogicalHeight(m_flow.logicalTopForChild(*floatingBox) - m_flow.marginBeforeForChild(*floatingBox));
+                    m_flow.positionNewFloats();
+                    floats.setLastCleanFloat(*floatingBox);
+                }
+            }
+            line = line->nextRootBox();
+        }
+        m_flow.setLogicalHeight(savedLogicalHeight);
+    }
+
+    layoutState.lineInfo().setFirstLine(!lastLine);
+    layoutState.lineInfo().setPreviousLineBrokeCleanly(!lastLine || lastLine->endsWithBreak());
+
+    if (lastLine) {
+        m_flow.setLogicalHeight(lastLine->lineBoxBottom());
+        InlineIterator iter = InlineIterator(&m_flow, lastLine->lineBreakObj(), lastLine->lineBreakPos());
+        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
+        resolver.setStatus(lastLine->lineBreakBidiStatus());
+    } else {
+        TextDirection direction = style().direction();
+        if (style().unicodeBidi() == Plaintext)
+            determineDirectionality(direction, InlineIterator(&m_flow, bidiFirstSkippingEmptyInlines(m_flow), 0));
+        resolver.setStatus(BidiStatus(direction, isOverride(style().unicodeBidi())));
+        InlineIterator iter = InlineIterator(&m_flow, bidiFirstSkippingEmptyInlines(m_flow, &resolver), 0);
+        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
+    }
+    return currentLine;
+}
+
+void LegacyLineLayout::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
+{
+    auto iteratorForFirstDirtyFloat = [](LineLayoutState::FloatList& floats) {
+        auto lastCleanFloat = floats.lastCleanFloat();
+        if (!lastCleanFloat)
+            return floats.begin();
+        auto* lastCleanFloatWithRect = floats.floatWithRect(*lastCleanFloat);
+        ASSERT(lastCleanFloatWithRect);
+        return ++floats.find(*lastCleanFloatWithRect);
+    };
+
+    ASSERT(!layoutState.endLine());
+    auto floatsIterator = iteratorForFirstDirtyFloat(layoutState.floatList());
+    auto end = layoutState.floatList().end();
+    RootInlineBox* lastLine = nullptr;
+    for (RootInlineBox* currentLine = startLine->nextRootBox(); currentLine; currentLine = currentLine->nextRootBox()) {
+        if (!currentLine->isDirty()) {
+            if (auto* cleanLineFloats = currentLine->floatsPtr()) {
+                bool encounteredNewFloat = false;
+                bool dirtiedByFloat = false;
+                for (auto& floatBoxOnCleanLine : *cleanLineFloats) {
+                    if (!floatBoxOnCleanLine)
+                        continue;
+                    ASSERT(floatsIterator != end);
+                    checkFloatInCleanLine(*currentLine, *floatBoxOnCleanLine, *floatsIterator, encounteredNewFloat, dirtiedByFloat);
+                    ++floatsIterator;
+                    if (floatsIterator == end || encounteredNewFloat)
+                        return;
+                }
+            }
+        }
+        if (currentLine->isDirty())
+            lastLine = nullptr;
+        else if (!lastLine)
+            lastLine = currentLine;
+    }
+
+    if (!lastLine)
+        return;
+
+    // At this point, |last| is the first line in a run of clean lines that ends with the last line
+    // in the block.
+    RootInlineBox* previousLine = lastLine->prevRootBox();
+    cleanLineStart = InlineIterator(&m_flow, previousLine->lineBreakObj(), previousLine->lineBreakPos());
+    cleanLineBidiStatus = previousLine->lineBreakBidiStatus();
+    layoutState.setEndLineLogicalTop(previousLine->lineBoxBottom());
+
+    for (RootInlineBox* line = lastLine; line; line = line->nextRootBox()) {
+        // Disconnect all line boxes from their render objects while preserving their connections to one another.
+        line->extractLine();
+    }
+    layoutState.setEndLine(lastLine);
+}
+
+bool LegacyLineLayout::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
+{
+    LayoutUnit lineDelta = m_flow.logicalHeight() - layoutState.endLineLogicalTop();
+
+    bool paginated = layoutContext().layoutState() && layoutContext().layoutState()->isPaginated();
+    if (paginated && layoutState.fragmentedFlow()) {
+        // Check all lines from here to the end, and see if the hypothetical new position for the lines will result
+        // in a different available line width.
+        for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; lineBox = lineBox->nextRootBox()) {
+            if (paginated) {
+                // This isn't the real move we're going to do, so don't update the line box's pagination
+                // strut yet.
+                LayoutUnit oldPaginationStrut = lineBox->paginationStrut();
+                bool overflowsFragment;
+                lineDelta -= oldPaginationStrut;
+                m_flow.adjustLinePositionForPagination(lineBox, lineDelta, overflowsFragment, layoutState.fragmentedFlow());
+                lineBox->setPaginationStrut(oldPaginationStrut);
+            }
+            if (lineWidthForPaginatedLineChanged(lineBox, lineDelta, layoutState.fragmentedFlow()))
+                return false;
+        }
+    }
+    
+    if (!lineDelta || !m_flow.floatingObjects())
+        return true;
+    
+    // See if any floats end in the range along which we want to shift the lines vertically.
+    LayoutUnit logicalTop = std::min(m_flow.logicalHeight(), layoutState.endLineLogicalTop());
+
+    RootInlineBox* lastLine = layoutState.endLine();
+    while (RootInlineBox* nextLine = lastLine->nextRootBox())
+        lastLine = nextLine;
+
+    LayoutUnit logicalBottom = lastLine->lineBoxBottom() + absoluteValue(lineDelta);
+
+    const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
+    auto end = floatingObjectSet.end();
+    for (auto it = floatingObjectSet.begin(); it != end; ++it) {
+        const auto& floatingObject = *it->get();
+        if (m_flow.logicalBottomForFloat(floatingObject) >= logicalTop && m_flow.logicalBottomForFloat(floatingObject) < logicalBottom)
+            return false;
+    }
+
+    return true;
+}
+
+bool LegacyLineLayout::lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta, RenderFragmentedFlow* fragmentedFlow) const
+{
+    if (!fragmentedFlow)
+        return false;
+
+    RenderFragmentContainer* currentFragment = m_flow.fragmentAtBlockOffset(rootBox->lineBoxTop() + lineDelta);
+    // Just bail if the fragment didn't change.
+    if (rootBox->containingFragment() == currentFragment)
+        return false;
+    return rootBox->paginatedLineWidth() != m_flow.availableLogicalWidthForContent(currentFragment);
+}
+
+bool LegacyLineLayout::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
+{
+    if (resolver.position() == endLineStart) {
+        if (resolver.status() != endLineStatus)
+            return false;
+        return checkPaginationAndFloatsAtEndLine(layoutState);
+    }
+
+    // The first clean line doesn't match, but we can check a handful of following lines to try
+    // to match back up.
+    static const int numLines = 8; // The # of lines we're willing to match against.
+    RootInlineBox* originalEndLine = layoutState.endLine();
+    RootInlineBox* line = originalEndLine;
+    for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
+        if (line->lineBreakObj() == resolver.position().renderer() && line->lineBreakPos() == resolver.position().offset()) {
+            // We have a match.
+            if (line->lineBreakBidiStatus() != resolver.status())
+                return false; // ...but the bidi state doesn't match.
+            
+            bool matched = false;
+            RootInlineBox* result = line->nextRootBox();
+            layoutState.setEndLine(result);
+            if (result) {
+                layoutState.setEndLineLogicalTop(line->lineBoxBottom());
+                matched = checkPaginationAndFloatsAtEndLine(layoutState);
+            }
+
+            // Now delete the lines that we failed to sync.
+            deleteLineRange(layoutState, originalEndLine, result);
+            return matched;
+        }
+    }
+
+    return false;
+}
+
+void LegacyLineLayout::addOverflowFromInlineChildren()
+{
+    LayoutUnit endPadding = m_flow.hasOverflowClip() ? m_flow.paddingEnd() : 0_lu;
+    // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
+    if (!endPadding)
+        endPadding = m_flow.endPaddingWidthForCaret();
+    if (m_flow.hasOverflowClip() && !endPadding && m_flow.element() && m_flow.element()->isRootEditableElement() && style().isLeftToRightDirection())
+        endPadding = 1;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        m_flow.addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
+        RenderFragmentContainer* fragment = m_flow.enclosingFragmentedFlow() ? curr->containingFragment() : nullptr;
+        if (fragment)
+            fragment->addLayoutOverflowForBox(&m_flow, curr->paddedLayoutOverflowRect(endPadding));
+        if (!m_flow.hasOverflowClip()) {
+            LayoutRect childVisualOverflowRect = curr->visualOverflowRect(curr->lineTop(), curr->lineBottom());
+            m_flow.addVisualOverflow(childVisualOverflowRect);
+            if (fragment)
+                fragment->addVisualOverflowForBox(&m_flow, childVisualOverflowRect);
+        }
+    }
+}
+
+size_t LegacyLineLayout::lineCount() const
+{
+    size_t count = 0;
+    for (auto* box = firstRootBox(); box; box = box->nextRootBox())
+        ++count;
+
+    return count;
+}
+
+size_t LegacyLineLayout::lineCountUntil(const RootInlineBox* stopRootInlineBox) const
+{
+    size_t count = 0;
+    for (auto* box = firstRootBox(); box; box = box->nextRootBox()) {
+        ++count;
+        if (box == stopRootInlineBox)
+            break;
+    }
+
+    return count;
+}
+
+void LegacyLineLayout::deleteEllipsisLineBoxes()
+{
+    TextAlignMode textAlign = style().textAlign();
+    bool ltr = style().isLeftToRightDirection();
+    IndentTextOrNot shouldIndentText = IndentText;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        if (curr->hasEllipsisBox()) {
+            curr->clearTruncation();
+
+            // Shift the line back where it belongs if we cannot accomodate an ellipsis.
+            float logicalLeft = m_flow.logicalLeftOffsetForLine(curr->lineTop(), shouldIndentText);
+            float availableLogicalWidth = m_flow.logicalRightOffsetForLine(curr->lineTop(), DoNotIndentText) - logicalLeft;
+            float totalLogicalWidth = curr->logicalWidth();
+            updateLogicalWidthForAlignment(m_flow, textAlign, curr, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
+
+            if (ltr)
+                curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0);
+            else
+                curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft), 0);
+        }
+        shouldIndentText = DoNotIndentText;
+    }
+}
+
+void LegacyLineLayout::checkLinesForTextOverflow()
+{
+    // Determine the width of the ellipsis using the current font.
+    // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
+    const FontCascade& font = style().fontCascade();
+    static MainThreadNeverDestroyed<const AtomString> ellipsisStr(&horizontalEllipsis, 1);
+    const FontCascade& firstLineFont = m_flow.firstLineStyle().fontCascade();
+    float firstLineEllipsisWidth = firstLineFont.width(m_flow.constructTextRun(&horizontalEllipsis, 1, m_flow.firstLineStyle()));
+    float ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(m_flow.constructTextRun(&horizontalEllipsis, 1, style()));
+
+    // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
+    // if the right edge of a line box exceeds that. For RTL, we use the left edge of the padding box and
+    // check the left edge of the line box to see if it is less
+    // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
+    bool ltr = style().isLeftToRightDirection();
+    TextAlignMode textAlign = style().textAlign();
+    bool firstLine = true;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        IndentTextOrNot shouldIndentText = firstLine ? IndentText : DoNotIndentText;
+        LayoutUnit blockRightEdge = m_flow.logicalRightOffsetForLine(curr->lineTop(), shouldIndentText);
+        LayoutUnit blockLeftEdge = m_flow.logicalLeftOffsetForLine(curr->lineTop(), shouldIndentText);
+        LayoutUnit lineBoxEdge { ltr ? curr->x() + curr->logicalWidth() : curr->x() };
+        if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
+            // This line spills out of our box in the appropriate direction. Now we need to see if the line
+            // can be truncated. In order for truncation to be possible, the line must have sufficient space to
+            // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
+            // space.
+            LayoutUnit width { firstLine ? firstLineEllipsisWidth : ellipsisWidth };
+            LayoutUnit blockEdge { ltr ? blockRightEdge : blockLeftEdge };
+            if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)) {
+                float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
+
+                float logicalLeft = 0; // We are only interested in the delta from the base position.
+                float truncatedWidth = m_flow.availableLogicalWidthForLine(curr->lineTop(), shouldIndentText);
+                updateLogicalWidthForAlignment(m_flow, textAlign, curr, nullptr, logicalLeft, totalLogicalWidth, truncatedWidth, 0);
+                if (ltr)
+                    curr->adjustLogicalPosition(logicalLeft, 0);
+                else
+                    curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0);
+            }
+        }
+        firstLine = false;
+    }
+}
+
+bool LegacyLineLayout::positionNewFloatOnLine(const FloatingObject& newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
+{
+    if (!m_flow.positionNewFloats())
+        return false;
+
+    width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
+
+    // We only connect floats to lines for pagination purposes if the floats occur at the start of
+    // the line and the previous line had a hard break (so this line is either the first in the block
+    // or follows a <br>).
+    if (!newFloat.paginationStrut() || !lineInfo.previousLineBrokeCleanly() || !lineInfo.isEmpty())
+        return true;
+
+    const FloatingObjectSet& floatingObjectSet = m_flow.floatingObjects()->set();
+    ASSERT(floatingObjectSet.last().get() == &newFloat);
+
+    LayoutUnit floatLogicalTop = m_flow.logicalTopForFloat(newFloat);
+    LayoutUnit paginationStrut = newFloat.paginationStrut();
+
+    if (floatLogicalTop - paginationStrut != m_flow.logicalHeight() + lineInfo.floatPaginationStrut())
+        return true;
+
+    auto it = floatingObjectSet.end();
+    --it; // Last float is newFloat, skip that one.
+    auto begin = floatingObjectSet.begin();
+    while (it != begin) {
+        --it;
+        auto& floatingObject = *it->get();
+        if (&floatingObject == lastFloatFromPreviousLine)
+            break;
+        if (m_flow.logicalTopForFloat(floatingObject) == m_flow.logicalHeight() + lineInfo.floatPaginationStrut()) {
+            floatingObject.setPaginationStrut(paginationStrut + floatingObject.paginationStrut());
+            RenderBox& floatBox = floatingObject.renderer();
+            m_flow.setLogicalTopForChild(floatBox, m_flow.logicalTopForChild(floatBox) + m_flow.marginBeforeForChild(floatBox) + paginationStrut);
+
+            if (m_flow.updateFragmentRangeForBoxChild(floatBox))
+                floatBox.setNeedsLayout(MarkOnlyThis);
+            else if (is<RenderBlock>(floatBox))
+                downcast<RenderBlock>(floatBox).setChildNeedsLayout(MarkOnlyThis);
+            floatBox.layoutIfNeeded();
+
+            // Save the old logical top before calling removePlacedObject which will set
+            // isPlaced to false. Otherwise it will trigger an assert in logicalTopForFloat.
+            LayoutUnit oldLogicalTop = m_flow.logicalTopForFloat(floatingObject);
+            m_flow.floatingObjects()->removePlacedObject(&floatingObject);
+            m_flow.setLogicalTopForFloat(floatingObject, oldLogicalTop + paginationStrut);
+            m_flow.floatingObjects()->addPlacedObject(&floatingObject);
+        }
+    }
+
+    // Just update the line info's pagination strut without altering our logical height yet. If the line ends up containing
+    // no content, then we don't want to improperly grow the height of the block.
+    lineInfo.setFloatPaginationStrut(lineInfo.floatPaginationStrut() + paginationStrut);
+    return true;
+}
+
+void LegacyLineLayout::updateFragmentForLine(RootInlineBox* lineBox) const
+{
+    ASSERT(lineBox);
+
+    if (!m_flow.hasFragmentRangeInFragmentedFlow())
+        lineBox->clearContainingFragment();
+    else {
+        if (auto containingFragment = m_flow.fragmentAtBlockOffset(lineBox->lineBoxTop()))
+            lineBox->setContainingFragment(*containingFragment);
+        else
+            lineBox->clearContainingFragment();
+    }
+
+    RootInlineBox* prevLineBox = lineBox->prevRootBox();
+    if (!prevLineBox)
+        return;
+
+    // This check is more accurate than the one in |adjustLinePositionForPagination| because it takes into
+    // account just the container changes between lines. The before mentioned function doesn't set the flag
+    // correctly if the line is positioned at the top of the last fragment container.
+    if (lineBox->containingFragment() != prevLineBox->containingFragment())
+        lineBox->setIsFirstAfterPageBreak(true);
+}
+
+const RenderStyle& LegacyLineLayout::style() const
+{
+    return m_flow.style();
+}
+
+const FrameViewLayoutContext& LegacyLineLayout::layoutContext() const
+{
+    return m_flow.view().frameView().layoutContext();
+}
+
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorerenderingLegacyLineLayouthfromrev278304trunkSourceWebCorerenderingComplexLineLayouth"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebCore/rendering/LegacyLineLayout.h (from rev 278304, trunk/Source/WebCore/rendering/ComplexLineLayout.h) (0 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/LegacyLineLayout.h                                (rev 0)
+++ trunk/Source/WebCore/rendering/LegacyLineLayout.h   2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -0,0 +1,117 @@
</span><ins>+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "InlineFlowBox.h"
+#include "LineWidth.h"
+#include "RenderLineBoxList.h"
+#include "RenderStyleConstants.h"
+#include "TrailingObjects.h"
+
+namespace WebCore {
+
+class BidiContext;
+class FloatingObject;
+class FloatWithRect;
+class FrameViewLayoutContext;
+class InlineBox;
+class InlineIterator;
+class LineInfo;
+class LineLayoutState;
+class RenderBlockFlow;
+class RenderObject;
+class RenderRubyRun;
+class RootInlineBox;
+class VerticalPositionCache;
+struct BidiStatus;
+struct WordMeasurement;
+
+template <class Run> class BidiRunList;
+typedef Vector<WordMeasurement, 64> WordMeasurements;
+
+class LegacyLineLayout {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    LegacyLineLayout(RenderBlockFlow&);
+    ~LegacyLineLayout();
+
+    RenderLineBoxList& lineBoxes() { return m_lineBoxes; }
+    const RenderLineBoxList& lineBoxes() const { return m_lineBoxes; }
+
+    RootInlineBox* firstRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.firstLineBox()); }
+    RootInlineBox* lastRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.lastLineBox()); }
+
+    void layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
+
+    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
+    bool positionNewFloatOnLine(const FloatingObject& newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
+    void addOverflowFromInlineChildren();
+
+    size_t lineCount() const;
+    size_t lineCountUntil(const RootInlineBox*) const;
+
+    static void appendRunsForObject(BidiRunList<BidiRun>*, int start, int end, RenderObject&, InlineBidiResolver&);
+    static void updateLogicalWidthForAlignment(RenderBlockFlow&, const TextAlignMode&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
+
+private:
+    std::unique_ptr<RootInlineBox> createRootInlineBox();
+    RootInlineBox* createAndAppendRootInlineBox();
+    InlineBox* createInlineBoxForRenderer(RenderObject*, bool isOnlyRun = false);
+    InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox*);
+    TextAlignMode textAlignmentForLine(bool endsWithSoftBreak) const;
+    void setMarginsForRubyRun(BidiRun*, RenderRubyRun&, RenderObject* previousObject, const LineInfo&);
+    void updateRubyForJustifiedText(RenderRubyRun&, BidiRun&, const Vector<unsigned, 16>& expansionOpportunities, unsigned& expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth, size_t&);
+    void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, const Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float totalLogicalWidth, float availableLogicalWidth);
+    void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
+    BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, TextAlignMode, float& logicalLeft, float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
+    void removeInlineBox(BidiRun&, const RootInlineBox&) const;
+    void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&);
+    inline BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext);
+    void appendFloatingObjectToLastLine(FloatingObject&);
+    RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
+    void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
+    inline const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator& oldEnd);
+    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
+    void reattachCleanLineFloats(RootInlineBox& cleanLine, LayoutUnit delta, bool isFirstCleanLine);
+    void linkToEndLineIfNeeded(LineLayoutState&);
+    void checkFloatInCleanLine(RootInlineBox& cleanLine, RenderBox& floatBoxOnCleanLine, FloatWithRect& matchingFloatWithRect, bool& encounteredNewFloat, bool& dirtiedByFloat);
+    RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
+    void determineEndPosition(LineLayoutState&, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
+    bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
+    bool lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta, RenderFragmentedFlow*) const;
+    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
+    void deleteEllipsisLineBoxes();
+    void checkLinesForTextOverflow();
+    void updateFragmentForLine(RootInlineBox*) const;
+
+    const RenderStyle& style() const;
+    const FrameViewLayoutContext& layoutContext() const;
+
+    RenderBlockFlow& m_flow;
+    RenderLineBoxList m_lineBoxes;
+};
+
+};
</ins></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockFlowcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.cpp (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlockFlow.cpp       2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.cpp  2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -24,7 +24,6 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "RenderBlockFlow.h"
</span><span class="cx"> 
</span><del>-#include "ComplexLineLayout.h"
</del><span class="cx"> #include "Editor.h"
</span><span class="cx"> #include "FloatingObjects.h"
</span><span class="cx"> #include "Frame.h"
</span><span class="lines">@@ -40,6 +39,7 @@
</span><span class="cx"> #include "LayoutIntegrationLineLayout.h"
</span><span class="cx"> #include "LayoutIntegrationRunIterator.h"
</span><span class="cx"> #include "LayoutRepainter.h"
</span><ins>+#include "LegacyLineLayout.h"
</ins><span class="cx"> #include "Logging.h"
</span><span class="cx"> #include "RenderCombineText.h"
</span><span class="cx"> #include "RenderFlexibleBox.h"
</span><span class="lines">@@ -154,8 +154,8 @@
</span><span class="cx">             parent()->dirtyLinesFromChangedChild(*this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (complexLineLayout())
-        complexLineLayout()->lineBoxes().deleteLineBoxes();
</del><ins>+    if (legacyLineLayout())
+        legacyLineLayout()->lineBoxes().deleteLineBoxes();
</ins><span class="cx"> 
</span><span class="cx">     blockWillBeDestroyed();
</span><span class="cx"> 
</span><span class="lines">@@ -700,10 +700,10 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (!complexLineLayout())
-        m_lineLayout = makeUnique<ComplexLineLayout>(*this);
</del><ins>+    if (!legacyLineLayout())
+        m_lineLayout = makeUnique<LegacyLineLayout>(*this);
</ins><span class="cx"> 
</span><del>-    complexLineLayout()->layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</del><ins>+    legacyLineLayout()->layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderBlockFlow::layoutBlockChild(RenderBox& child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
</span><span class="lines">@@ -970,7 +970,7 @@
</span><span class="cx">     float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), DoNotIndentText);
</span><span class="cx">     float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), DoNotIndentText) - logicalLeft;
</span><span class="cx"> 
</span><del>-    ComplexLineLayout::updateLogicalWidthForAlignment(*this, textAlign, nullptr, nullptr, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
</del><ins>+    LegacyLineLayout::updateLogicalWidthForAlignment(*this, textAlign, nullptr, nullptr, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
</ins><span class="cx"> 
</span><span class="cx">     if (!style().isLeftToRightDirection())
</span><span class="cx">         return LayoutUnit(logicalWidth() - logicalLeft);
</span><span class="lines">@@ -1802,7 +1802,7 @@
</span><span class="cx">     LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
</span><span class="cx">     overflowsFragment = (lineHeight > remainingLogicalHeight);
</span><span class="cx"> 
</span><del>-    int lineIndex = complexLineLayout()->lineCountUntil(lineBox);
</del><ins>+    int lineIndex = legacyLineLayout()->lineCountUntil(lineBox);
</ins><span class="cx">     if (remainingLogicalHeight < lineHeight || (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex)) {
</span><span class="cx">         if (lineBreakToAvoidWidow() == lineIndex)
</span><span class="cx">             clearShouldBreakAtLineToAvoidWidowIfNeeded(*this);
</span><span class="lines">@@ -2131,7 +2131,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (diff >= StyleDifference::Repaint) {
</span><span class="cx">         auto shouldInvalidateLineLayoutPath = [&] {
</span><del>-            if (selfNeedsLayout() || complexLineLayout())
</del><ins>+            if (selfNeedsLayout() || legacyLineLayout())
</ins><span class="cx">                 return true;
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx">             if (modernLineLayout() && !LayoutIntegration::LineLayout::canUseForAfterStyleChange(*this, diff))
</span><span class="lines">@@ -3017,7 +3017,7 @@
</span><span class="cx">         return modernLineLayout()->hitTest(request, result, locationInContainer, accumulatedOffset, hitTestAction);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return complexLineLayout() && complexLineLayout()->lineBoxes().hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
</del><ins>+    return legacyLineLayout() && legacyLineLayout()->lineBoxes().hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderBlockFlow::addOverflowFromInlineChildren()
</span><span class="lines">@@ -3029,8 +3029,8 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><del>-    if (complexLineLayout())
-        complexLineLayout()->addOverflowFromInlineChildren();
</del><ins>+    if (legacyLineLayout())
+        legacyLineLayout()->addOverflowFromInlineChildren();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderBlockFlow::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const
</span><span class="lines">@@ -3188,7 +3188,7 @@
</span><span class="cx">                 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight())).toInt() };
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (complexLineLayout()) {
</del><ins>+        if (legacyLineLayout()) {
</ins><span class="cx">             bool isFirstLine = lastRootBox() == firstRootBox();
</span><span class="cx">             const auto& style = isFirstLine ? firstLineStyle() : this->style();
</span><span class="cx">             // InlineFlowBox::placeBoxesInBlockDirection will flip lines in case of verticalLR mode, so we can assume verticalRL for now.
</span><span class="lines">@@ -3341,8 +3341,8 @@
</span><span class="cx">         if (modernLineLayout())
</span><span class="cx">             return modernLineLayout()->lineCount();
</span><span class="cx"> #endif
</span><del>-        if (complexLineLayout())
-            return complexLineLayout()->lineCount();
</del><ins>+        if (legacyLineLayout())
+            return legacyLineLayout()->lineCount();
</ins><span class="cx"> 
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="lines">@@ -3593,8 +3593,8 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (complexLineLayout())
-        complexLineLayout()->lineBoxes().paint(this, paintInfo, paintOffset);
</del><ins>+    if (legacyLineLayout())
+        legacyLineLayout()->lineBoxes().paint(this, paintInfo, paintOffset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool RenderBlockFlow::relayoutForPagination()
</span><span class="lines">@@ -3651,7 +3651,7 @@
</span><span class="cx">         return modernLineLayout()->lineCount();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    return complexLineLayout() && complexLineLayout()->lineBoxes().firstLineBox();
</del><ins>+    return legacyLineLayout() && legacyLineLayout()->lineBoxes().firstLineBox();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderBlockFlow::invalidateLineLayoutPath()
</span><span class="lines">@@ -3758,7 +3758,7 @@
</span><span class="cx"> 
</span><span class="cx">     setLineLayoutPath(ForceLineBoxesPath);
</span><span class="cx"> 
</span><del>-    if (complexLineLayout() || !hasLineLayout())
</del><ins>+    if (legacyLineLayout() || !hasLineLayout())
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     bool needsToPaginateComplexLines = [&] {
</span><span class="lines">@@ -3769,9 +3769,9 @@
</span><span class="cx">         return false;
</span><span class="cx">     }();
</span><span class="cx"> 
</span><del>-    m_lineLayout = makeUnique<ComplexLineLayout>(*this);
</del><ins>+    m_lineLayout = makeUnique<LegacyLineLayout>(*this);
</ins><span class="cx"> 
</span><del>-    auto& complexLineLayout = *this->complexLineLayout();
</del><ins>+    auto& legacyLineLayout = *this->legacyLineLayout();
</ins><span class="cx"> 
</span><span class="cx"> #if ASSERT_ENABLED
</span><span class="cx">     LayoutUnit oldHeight = logicalHeight();
</span><span class="lines">@@ -3783,14 +3783,14 @@
</span><span class="cx">     LayoutUnit repaintLogicalBottom;
</span><span class="cx">     if (needsToPaginateComplexLines) {
</span><span class="cx">         PaginatedLayoutStateMaintainer state(*this);
</span><del>-        complexLineLayout.layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</del><ins>+        legacyLineLayout.layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</ins><span class="cx">         // This matches relayoutToAvoidWidows.
</span><span class="cx">         if (shouldBreakAtLineToAvoidWidow())
</span><del>-            complexLineLayout.layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</del><ins>+            legacyLineLayout.layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</ins><span class="cx">         // FIXME: This is needed as long as simple and normal line layout produce different line breakings.
</span><span class="cx">         repaint();
</span><span class="cx">     } else
</span><del>-        complexLineLayout.layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</del><ins>+        legacyLineLayout.layoutLineBoxes(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
</ins><span class="cx"> 
</span><span class="cx">     updateLogicalHeight();
</span><span class="cx">     ASSERT(didNeedLayout || ceilf(logicalHeight()) == ceilf(oldHeight));
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderBlockFlowh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.h (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderBlockFlow.h 2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.h    2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -22,8 +22,8 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><del>-#include "ComplexLineLayout.h"
</del><span class="cx"> #include "FloatingObjects.h"
</span><ins>+#include "LegacyLineLayout.h"
</ins><span class="cx"> #include "LineWidth.h"
</span><span class="cx"> #include "RenderBlock.h"
</span><span class="cx"> #include "RenderLineBoxList.h"
</span><span class="lines">@@ -77,8 +77,8 @@
</span><span class="cx"> 
</span><span class="cx">     void dirtyLinesFromChangedChild(RenderObject& child) final
</span><span class="cx">     {
</span><del>-        if (complexLineLayout())
-            complexLineLayout()->lineBoxes().dirtyLinesFromChangedChild(*this, child);
</del><ins>+        if (legacyLineLayout())
+            legacyLineLayout()->lineBoxes().dirtyLinesFromChangedChild(*this, child);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void paintColumnRules(PaintInfo&, const LayoutPoint&) override;
</span><span class="lines">@@ -337,8 +337,8 @@
</span><span class="cx"> 
</span><span class="cx">     LayoutPoint flipFloatForWritingModeForChild(const FloatingObject&, const LayoutPoint&) const;
</span><span class="cx"> 
</span><del>-    RootInlineBox* firstRootBox() const { return complexLineLayout() ? complexLineLayout()->firstRootBox() : nullptr; }
-    RootInlineBox* lastRootBox() const { return complexLineLayout() ? complexLineLayout()->lastRootBox() : nullptr; }
</del><ins>+    RootInlineBox* firstRootBox() const { return legacyLineLayout() ? legacyLineLayout()->firstRootBox() : nullptr; }
+    RootInlineBox* lastRootBox() const { return legacyLineLayout() ? legacyLineLayout()->lastRootBox() : nullptr; }
</ins><span class="cx"> 
</span><span class="cx">     void setChildrenInline(bool) final;
</span><span class="cx"> 
</span><span class="lines">@@ -357,8 +357,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool containsNonZeroBidiLevel() const;
</span><span class="cx"> 
</span><del>-    const ComplexLineLayout* complexLineLayout() const;
-    ComplexLineLayout* complexLineLayout();
</del><ins>+    const LegacyLineLayout* legacyLineLayout() const;
+    LegacyLineLayout* legacyLineLayout();
</ins><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx">     const LayoutIntegration::LineLayout* modernLineLayout() const;
</span><span class="cx">     LayoutIntegration::LineLayout* modernLineLayout();
</span><span class="lines">@@ -541,7 +541,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     bool hasLineLayout() const;
</span><del>-    bool hasComplexLineLayout() const;
</del><ins>+    bool hasLegacyLineLayout() const;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx">     bool hasModernLineLayout() const;
</span><span class="lines">@@ -590,12 +590,12 @@
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx">         std::unique_ptr<LayoutIntegration::LineLayout>,
</span><span class="cx"> #endif
</span><del>-        std::unique_ptr<ComplexLineLayout>
</del><ins>+        std::unique_ptr<LegacyLineLayout>
</ins><span class="cx">     > m_lineLayout;
</span><span class="cx"> 
</span><span class="cx">     friend class LineBreaker;
</span><span class="cx">     friend class LineWidth; // Needs to know FloatingObject
</span><del>-    friend class ComplexLineLayout;
</del><ins>+    friend class LegacyLineLayout;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline bool RenderBlockFlow::hasLineLayout() const
</span><span class="lines">@@ -603,19 +603,19 @@
</span><span class="cx">     return !WTF::holds_alternative<WTF::Monostate>(m_lineLayout);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool RenderBlockFlow::hasComplexLineLayout() const
</del><ins>+inline bool RenderBlockFlow::hasLegacyLineLayout() const
</ins><span class="cx"> {
</span><del>-    return WTF::holds_alternative<std::unique_ptr<ComplexLineLayout>>(m_lineLayout);
</del><ins>+    return WTF::holds_alternative<std::unique_ptr<LegacyLineLayout>>(m_lineLayout);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline const ComplexLineLayout* RenderBlockFlow::complexLineLayout() const
</del><ins>+inline const LegacyLineLayout* RenderBlockFlow::legacyLineLayout() const
</ins><span class="cx"> {
</span><del>-    return hasComplexLineLayout() ? WTF::get<std::unique_ptr<ComplexLineLayout>>(m_lineLayout).get() : nullptr;
</del><ins>+    return hasLegacyLineLayout() ? WTF::get<std::unique_ptr<LegacyLineLayout>>(m_lineLayout).get() : nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline ComplexLineLayout* RenderBlockFlow::complexLineLayout()
</del><ins>+inline LegacyLineLayout* RenderBlockFlow::legacyLineLayout()
</ins><span class="cx"> {
</span><del>-    return hasComplexLineLayout() ? WTF::get<std::unique_ptr<ComplexLineLayout>>(m_lineLayout).get() : nullptr;
</del><ins>+    return hasLegacyLineLayout() ? WTF::get<std::unique_ptr<LegacyLineLayout>>(m_lineLayout).get() : nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderTextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderText.cpp (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderText.cpp    2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/RenderText.cpp       2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -1504,7 +1504,7 @@
</span><span class="cx">     m_containsReversedText |= !textBox.isLeftToRightDirection();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RenderText::usesComplexLineLayoutPath() const
</del><ins>+bool RenderText::usesLegacyLineLayoutPath() const
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx">     return !LayoutIntegration::LineLayout::containing(*this);
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderTexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderText.h (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderText.h      2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/RenderText.h 2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -167,7 +167,7 @@
</span><span class="cx">     void setCandidateComputedTextSize(float size) { m_candidateComputedTextSize = size; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    bool usesComplexLineLayoutPath() const;
</del><ins>+    bool usesLegacyLineLayoutPath() const;
</ins><span class="cx"> 
</span><span class="cx">     StringView stringView(unsigned start = 0, std::optional<unsigned> stop = std::nullopt) const;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRootInlineBoxcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RootInlineBox.cpp (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RootInlineBox.cpp 2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/RootInlineBox.cpp    2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -734,19 +734,19 @@
</span><span class="cx"> 
</span><span class="cx"> void RootInlineBox::removeLineBoxFromRenderObject()
</span><span class="cx"> {
</span><del>-    // Null if we are destroying ComplexLineLayout.
-    if (auto* complexLineLayout = blockFlow().complexLineLayout())
-        complexLineLayout->lineBoxes().removeLineBox(this);
</del><ins>+    // Null if we are destroying LegacyLineLayout.
+    if (auto* legacyLineLayout = blockFlow().legacyLineLayout())
+        legacyLineLayout->lineBoxes().removeLineBox(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RootInlineBox::extractLineBoxFromRenderObject()
</span><span class="cx"> {
</span><del>-    blockFlow().complexLineLayout()->lineBoxes().extractLineBox(this);
</del><ins>+    blockFlow().legacyLineLayout()->lineBoxes().extractLineBox(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RootInlineBox::attachLineBoxToRenderObject()
</span><span class="cx"> {
</span><del>-    blockFlow().complexLineLayout()->lineBoxes().attachLineBox(this);
</del><ins>+    blockFlow().legacyLineLayout()->lineBoxes().attachLineBox(this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> LayoutRect RootInlineBox::paddedLayoutOverflowRect(LayoutUnit endPadding) const
</span></span></pre></div>
<a id="trunkSourceWebCorerenderinglineLineBreakercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/line/LineBreaker.cpp (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/line/LineBreaker.cpp      2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/line/LineBreaker.cpp 2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">                 lineInfo.incrementRunsFromLeadingWhitespace();
</span><span class="cx">             }
</span><span class="cx">         } else if (object.isFloating())
</span><del>-            m_block.complexLineLayout()->positionNewFloatOnLine(*m_block.insertFloatingObject(downcast<RenderBox>(object)), lastFloatFromPreviousLine, lineInfo, width);
</del><ins>+            m_block.legacyLineLayout()->positionNewFloatOnLine(*m_block.insertFloatingObject(downcast<RenderBox>(object)), lastFloatFromPreviousLine, lineInfo, width);
</ins><span class="cx">         else if (object.style().hasTextCombine() && is<RenderCombineText>(object)) {
</span><span class="cx">             downcast<RenderCombineText>(object).combineTextIfNeeded();
</span><span class="cx">             if (downcast<RenderCombineText>(object).isCombined())
</span></span></pre></div>
<a id="trunkSourceWebCorerenderinglineLineBreakerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/line/LineBreaker.h (278304 => 278305)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/line/LineBreaker.h        2021-06-01 13:50:16 UTC (rev 278304)
+++ trunk/Source/WebCore/rendering/line/LineBreaker.h   2021-06-01 13:58:23 UTC (rev 278305)
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">     FloatingObject* insertFloatingObject(RenderBox& floatBox) { return m_block.insertFloatingObject(floatBox); }
</span><span class="cx">     bool positionNewFloatOnLine(const FloatingObject& newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
</span><span class="cx">     {
</span><del>-        return m_block.complexLineLayout()->positionNewFloatOnLine(newFloat, lastFloatFromPreviousLine, lineInfo, width);
</del><ins>+        return m_block.legacyLineLayout()->positionNewFloatOnLine(newFloat, lastFloatFromPreviousLine, lineInfo, width);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RenderBlockFlow& m_block;
</span></span></pre>
</div>
</div>

</body>
</html>