<!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>[281424] trunk</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/281424">281424</a></dd>
<dt>Author</dt> <dd>zalan@apple.com</dd>
<dt>Date</dt> <dd>2021-08-22 17:03:10 -0700 (Sun, 22 Aug 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>[LFC][IFC] Add support for out-of-flow box static positioning
https://bugs.webkit.org/show_bug.cgi?id=229103

Reviewed by Antti Koivisto.

Source/WebCore:

This patch is in preparation for enabling positioned content for IFC handling.

In this patch we compute the static position for out-of-flow content inside the inline formatting context.
As per spec, the static position of an out-of-flow box is computed as if the position was set to static.
However it does not mean that the out-of-flow box should be involved in the inline layout process.
Instead we figure out this static position after the inline layout by looking at
the previous sibling (or parent) box's geometry and place the out-of-flow box at the logical right position.

* layout/formattingContexts/inline/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::layoutInFlowContent):
(WebCore::Layout::InlineFormattingContext::lineLayoutForIntergration):
(WebCore::Layout::InlineFormattingContext::computeStaticPositionForOutOfFlowContent):
(WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthConstraints):
(WebCore::Layout::InlineFormattingContext::collectContentIfNeeded):
(WebCore::Layout::InlineFormattingContext::collectInlineContentIfNeeded): Deleted.
* layout/formattingContexts/inline/InlineFormattingContext.h:

LayoutTests:

* fast/inline/out-of-flow-with-static-position-in-ifc-expected.html: Added.
* fast/inline/out-of-flow-with-static-position-in-ifc.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsTestExpectations">trunk/LayoutTests/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorelayoutformattingContextsinlineInlineFormattingContextcpp">trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp</a></li>
<li><a href="#trunkSourceWebCorelayoutformattingContextsinlineInlineFormattingContexth">trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastinlineoutofflowwithstaticpositioninifcexpectedhtml">trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc-expected.html</a></li>
<li><a href="#trunkLayoutTestsfastinlineoutofflowwithstaticpositioninifchtml">trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (281423 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2021-08-22 23:45:54 UTC (rev 281423)
+++ trunk/LayoutTests/ChangeLog 2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -1,5 +1,15 @@
</span><span class="cx"> 2021-08-22  Alan Bujtas  <zalan@apple.com>
</span><span class="cx"> 
</span><ins>+        [LFC][IFC] Add support for out-of-flow box static positioning
+        https://bugs.webkit.org/show_bug.cgi?id=229103
+
+        Reviewed by Antti Koivisto.
+
+        * fast/inline/out-of-flow-with-static-position-in-ifc-expected.html: Added.
+        * fast/inline/out-of-flow-with-static-position-in-ifc.html: Added.
+
+2021-08-22  Alan Bujtas  <zalan@apple.com>
+
</ins><span class="cx">         [LFC][IFC] Add support for vertical-align: sub
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=228217
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (281423 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations       2021-08-22 23:45:54 UTC (rev 281423)
+++ trunk/LayoutTests/TestExpectations  2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -5031,6 +5031,7 @@
</span><span class="cx"> 
</span><span class="cx"> webkit.org/b/226002 fast/layoutformattingcontext/table-simple-row-height.html [ Skip ]
</span><span class="cx"> webkit.org/b/226364 fast/layoutformattingcontext/table-with-percent-columns-and-spacing.html [ Skip ]
</span><ins>+fast/layoutformattingcontext/absolute-positioned-box-with-inline-sibling.html [ Skip ]
</ins><span class="cx"> [ Debug ] fast/layoutformattingcontext/table-fixed-width-with-max-distribution.html [ Skip ]
</span><span class="cx"> [ Debug ] fast/layoutformattingcontext/table-space-distribution-simple-mismatching.html [ Skip ]
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastinlineoutofflowwithstaticpositioninifcexpectedhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc-expected.html (0 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc-expected.html                              (rev 0)
+++ trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc-expected.html 2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+<style>
+body {
+  margin: 0px;
+  font-family: Ahem;
+}
+
+div {
+  line-height: 40px; 
+}
+
+img {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  background-color: green;
+}
+</style>
+<!-- out-of-flow boxes with static positioning in IFC -->
+<div>text</div>
+<div>text</div>
+<div>text</div>
+<div>text</div>
+<div><span></span>text</div>
+<div><span><span></span></span>text</div>
+<div><span>text</span>text</div>
+<div><span>text</span>text</div>
+<div><br></div>
+<div><br>text</div>
+<div><br><br></div>
+<div>text<br></div>
+<div>text<br></div>
+<img style="left: 0px; top: 0px;">
+<img style="left: 0px; top: 40px;">
+<img style="left: 64px; top: 80px;">
+<img style="left: 0px; top: 120px;"><img style="left: 64px; top: 120px;">
+<img style="left: 0px; top: 160px;"><img style="left: 64px; top: 160px;">
+<img style="left: 0px; top: 200px;"><img style="left: 64px; top: 200px;">
+<img style="left: 64px; top: 240px;"><img style="left: 128px; top: 240px;">
+<img style="left: 64px; top: 280px;"><img style="left: 128px; top: 280px;">
+<img style="left: 0px; top: 360px;">
+<img style="left: 64px; top: 400px;">
+<img style="left: 0px; top: 520px;">
+<img style="left: 0px; top: 560px;">
+<img style="left: 0px; top: 600px;">
</ins></span></pre></div>
<a id="trunkLayoutTestsfastinlineoutofflowwithstaticpositioninifchtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc.html (0 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc.html                               (rev 0)
+++ trunk/LayoutTests/fast/inline/out-of-flow-with-static-position-in-ifc.html  2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+<style>
+body {
+  margin: 0px;
+  font-family: Ahem;
+}
+
+div {
+  line-height: 40px; 
+}
+
+img {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  background-color: green;
+}
+</style>
+<!-- out-of-flow boxes with static positioning in IFC -->
+<div><img>text</div>
+<div><img><img>text</div>
+<div>text<img></div>
+<div><img>text<img></div>
+<div><span><img></span>text<img></div>
+<div><span><span><img></span></span>text<img></div>
+<div><span>text<img></span>text<img></div>
+<div><span>text</span><img>text<img></div>
+<div><br><img></div>
+<div><br>text<img></div>
+<div><br><br><img></div>
+<div>text<br><img></div>
+<div>text<br><img><img></div>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (281423 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-08-22 23:45:54 UTC (rev 281423)
+++ trunk/Source/WebCore/ChangeLog      2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2021-08-22  Alan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Add support for out-of-flow box static positioning
+        https://bugs.webkit.org/show_bug.cgi?id=229103
+
+        Reviewed by Antti Koivisto.
+
+        This patch is in preparation for enabling positioned content for IFC handling.
+
+        In this patch we compute the static position for out-of-flow content inside the inline formatting context.
+        As per spec, the static position of an out-of-flow box is computed as if the position was set to static.
+        However it does not mean that the out-of-flow box should be involved in the inline layout process.
+        Instead we figure out this static position after the inline layout by looking at
+        the previous sibling (or parent) box's geometry and place the out-of-flow box at the logical right position.
+
+        * layout/formattingContexts/inline/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::layoutInFlowContent):
+        (WebCore::Layout::InlineFormattingContext::lineLayoutForIntergration):
+        (WebCore::Layout::InlineFormattingContext::computeStaticPositionForOutOfFlowContent):
+        (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthConstraints):
+        (WebCore::Layout::InlineFormattingContext::collectContentIfNeeded):
+        (WebCore::Layout::InlineFormattingContext::collectInlineContentIfNeeded): Deleted.
+        * layout/formattingContexts/inline/InlineFormattingContext.h:
+
</ins><span class="cx"> 2021-08-22  Myles C. Maxfield  <mmaxfield@apple.com>
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r281389): canUseSimplifiedTextMeasuring() needs to match with WidthIterator::applyCSSVisibilityRules()
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineFormattingContextcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp (281423 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp        2021-08-22 23:45:54 UTC (rev 281423)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp   2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -136,10 +136,11 @@
</span><span class="cx">         layoutBox = nextInlineLevelBoxToLayout(*layoutBox, root());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    collectInlineContentIfNeeded();
</del><ins>+    collectContentIfNeeded();
</ins><span class="cx"> 
</span><span class="cx">     auto& inlineItems = formattingState().inlineItems();
</span><span class="cx">     lineLayout(inlineItems, { 0, inlineItems.size() }, constraints);
</span><ins>+    computeStaticPositionForOutOfFlowContent(formattingState().outOfFlowBoxes());
</ins><span class="cx">     LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root() << ")");
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -146,9 +147,10 @@
</span><span class="cx"> void InlineFormattingContext::lineLayoutForIntergration(InvalidationState& invalidationState, const ConstraintsForInFlowContent& constraints)
</span><span class="cx"> {
</span><span class="cx">     invalidateFormattingState(invalidationState);
</span><del>-    collectInlineContentIfNeeded();
</del><ins>+    collectContentIfNeeded();
</ins><span class="cx">     auto& inlineItems = formattingState().inlineItems();
</span><span class="cx">     lineLayout(inlineItems, { 0, inlineItems.size() }, constraints);
</span><ins>+    computeStaticPositionForOutOfFlowContent(formattingState().outOfFlowBoxes());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> LayoutUnit InlineFormattingContext::usedContentHeight() const
</span><span class="lines">@@ -253,6 +255,103 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InlineFormattingContext::computeStaticPositionForOutOfFlowContent(const FormattingState::OutOfFlowBoxList& outOfFlowBoxes)
+{
+    // This function computes the static position for out-of-flow content inside the inline formatting context.
+    // As per spec, the static position of an out-of-flow box is computed as if the position was set to static.
+    // However it does not mean that the out-of-flow box should be involved in the inline layout process.
+    // Instead we figure out this static position after the inline layout by looking at the previous/next sibling (or parent) box's geometry and
+    // place the out-of-flow box at the logical right position.
+    auto& formattingState = this->formattingState();
+    auto& lines = formattingState.lines();
+    auto& lineRuns = formattingState.lineRuns();
+
+    for (auto& outOfFlowBox : outOfFlowBoxes) {
+        auto& outOfFlowGeometry = formattingState.boxGeometry(*outOfFlowBox);
+        // Both previous float and out-of-flow boxes are skipped here. A series of adjoining out-of-flow boxes should all be placed
+        // at the same static position (they don't affect next-sibling positions) and while floats do participate in the inline layout
+        // their positions have already been taken into account during the inline layout.
+        auto previousContentSkippingFloats = [&]() -> const Layout::Box* {
+            auto* previousSibling = outOfFlowBox->previousSibling();
+            for (; previousSibling && previousSibling->isFloatingPositioned(); previousSibling = previousSibling->previousSibling()) { }
+            if (previousSibling)
+                return previousSibling;
+            // Parent is either the root here or another inline box (e.g. <span><img style="position: absolute"></span>)
+            auto& parent = outOfFlowBox->parent();
+            return &parent == &root() ? nullptr : &parent;
+        }();
+
+        if (!previousContentSkippingFloats) {
+            // This is the first (non-float)child. Let's place it to the left of the first run.
+            // <div><img style="position: absolute">text content</div>
+            ASSERT(lineRuns.size());
+            outOfFlowGeometry.setLogicalTopLeft({ lineRuns[0].logicalLeft(), lines[0].lineBoxLogicalRect().top() });
+            continue;
+        }
+
+        if (previousContentSkippingFloats->isOutOfFlowPositioned()) {
+            // Subsequent out-of-flow positioned boxes share the same static position.
+            // <div>text content<img style="position: absolute"><img style="position: absolute"></div>
+            outOfFlowGeometry.setLogicalTopLeft(BoxGeometry::borderBoxTopLeft(geometryForBox(*previousContentSkippingFloats)));
+            continue;
+        }
+
+        ASSERT(previousContentSkippingFloats->isInFlow());
+        auto placeOutOfFlowBoxAfterPreviousInFlowBox = [&] {
+            // The out-of-flow box should be placed after this inflow box.
+            // Skip to the last run of this layout box. The last run's geometry is used to compute the out-of-flow box's static position.
+            size_t lastRunIndexOnPreviousLayoutBox = 0;
+            for (; lastRunIndexOnPreviousLayoutBox < lineRuns.size() && &lineRuns[lastRunIndexOnPreviousLayoutBox].layoutBox() != previousContentSkippingFloats; ++lastRunIndexOnPreviousLayoutBox) { }
+            if (lastRunIndexOnPreviousLayoutBox == lineRuns.size()) {
+                // FIXME: In very rare cases, the previous box's content might have been completely collapsed and left us with no run.
+                ASSERT_NOT_IMPLEMENTED_YET();
+                return;
+            }
+            for (; lastRunIndexOnPreviousLayoutBox < lineRuns.size() && &lineRuns[lastRunIndexOnPreviousLayoutBox].layoutBox() == previousContentSkippingFloats; ++lastRunIndexOnPreviousLayoutBox) { }
+                --lastRunIndexOnPreviousLayoutBox;
+            // Let's check if the previous run is the last run on the current line and use the next run's left instead.
+            auto& previousRun = lineRuns[lastRunIndexOnPreviousLayoutBox];
+            auto* nextRun = lastRunIndexOnPreviousLayoutBox + 1 < lineRuns.size() ? &lineRuns[lastRunIndexOnPreviousLayoutBox + 1] : nullptr;
+
+            if (nextRun && nextRun->lineIndex() == previousRun.lineIndex()) {
+                // Previous and next runs are on the same line. The out-of-flow box is right at the previous run's logical right.
+                // <div>text<img style="position: absolute">content</div>
+                auto logicalLeft = previousRun.logicalRight();
+                if (previousContentSkippingFloats->isInlineBox() && !previousContentSkippingFloats->isAnonymous()) {
+                    // <div>text<span><img style="position: absolute">content</span></div>
+                    // or
+                    // <div>text<span>content</span><img style="position: absolute"></div>
+                    auto& inlineBoxBoxGeometry = geometryForBox(*previousContentSkippingFloats);
+                    logicalLeft = previousContentSkippingFloats == &outOfFlowBox->parent()
+                        ? BoxGeometry::borderBoxLeft(inlineBoxBoxGeometry) + inlineBoxBoxGeometry.contentBoxLeft()
+                        : BoxGeometry::borderBoxRect(inlineBoxBoxGeometry).right();
+                }
+                outOfFlowGeometry.setLogicalTopLeft({ logicalLeft, lines[previousRun.lineIndex()].lineBoxLogicalRect().top() });
+                return;
+            }
+
+            if (nextRun) {
+                // The out of flow box is placed at the beginning of the next line (where the first run on the line is).
+                // <div>text<br><img style="position: absolute"><img style="position: absolute">content</div>
+                outOfFlowGeometry.setLogicalTopLeft({ nextRun->logicalLeft(), lines[nextRun->lineIndex()].lineBoxLogicalRect().top() });
+                return;
+            }
+
+            auto& lastLineLogicalRect = lines[previousRun.lineIndex()].lineBoxLogicalRect();
+            // This out-of-flow box is the last box.
+            // FIXME: Use isLineBreak instead to cover preserved new lines too.
+            if (previousRun.layoutBox().isLineBreakBox()) {
+                // <div>text<br><img style="position: absolute"><img style="position: absolute"></div>
+                outOfFlowGeometry.setLogicalTopLeft({ lastLineLogicalRect.left(), lastLineLogicalRect.bottom() });
+                return;
+            }
+            // FIXME: We may need to check if this box actually fits the last line and move it over to the "next" line.
+            outOfFlowGeometry.setLogicalTopLeft({ previousRun.logicalRight(), lastLineLogicalRect.top() });
+        };
+        placeOutOfFlowBoxAfterPreviousInFlowBox();
+    }
+}
+
</ins><span class="cx"> IntrinsicWidthConstraints InlineFormattingContext::computedIntrinsicWidthConstraints()
</span><span class="cx"> {
</span><span class="cx">     auto& layoutState = this->layoutState();
</span><span class="lines">@@ -291,7 +390,7 @@
</span><span class="cx">         layoutBox = nextInlineLevelBoxToLayout(*layoutBox, root());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    collectInlineContentIfNeeded();
</del><ins>+    collectContentIfNeeded();
</ins><span class="cx"> 
</span><span class="cx">     auto maximumLineWidth = [&](auto availableWidth) {
</span><span class="cx">         // Switch to the min/max formatting root width values before formatting the lines.
</span><span class="lines">@@ -415,7 +514,7 @@
</span><span class="cx">     boxGeometry.setVerticalMargin({ contentHeightAndMargin.nonCollapsedMargin.before, contentHeightAndMargin.nonCollapsedMargin.after });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void InlineFormattingContext::collectInlineContentIfNeeded()
</del><ins>+void InlineFormattingContext::collectContentIfNeeded()
</ins><span class="cx"> {
</span><span class="cx">     auto& formattingState = this->formattingState();
</span><span class="cx">     if (!formattingState.inlineItems().isEmpty())
</span><span class="lines">@@ -424,24 +523,28 @@
</span><span class="cx">     // <span>text<span></span><img></span> -> [InlineBoxStart][InlineLevelBox][InlineBoxStart][InlineBoxEnd][InlineLevelBox][InlineBoxEnd]
</span><span class="cx">     ASSERT(root().hasInFlowOrFloatingChild());
</span><span class="cx">     LayoutQueue layoutQueue;
</span><del>-    layoutQueue.append(root().firstInFlowOrFloatingChild());
</del><ins>+    layoutQueue.append(root().firstChild());
</ins><span class="cx">     while (!layoutQueue.isEmpty()) {
</span><span class="cx">         while (true) {
</span><span class="cx">             auto& layoutBox = *layoutQueue.last();
</span><del>-            auto isBoxWithInlineContent = layoutBox.isInlineBox() && !layoutBox.isInlineTextBox() && !layoutBox.isLineBreakBox();
-            if (!isBoxWithInlineContent)
</del><ins>+            auto isInlineBoxWithInlineContent = layoutBox.isInlineBox() && !layoutBox.isInlineTextBox() && !layoutBox.isLineBreakBox() && !layoutBox.isOutOfFlowPositioned();
+            if (!isInlineBoxWithInlineContent)
</ins><span class="cx">                 break;
</span><span class="cx">             // This is the start of an inline box (e.g. <span>).
</span><span class="cx">             formattingState.addInlineItem({ layoutBox, InlineItem::Type::InlineBoxStart });
</span><span class="cx">             auto& inlineBoxWithInlineContent = downcast<ContainerBox>(layoutBox);
</span><del>-            if (!inlineBoxWithInlineContent.hasInFlowOrFloatingChild())
</del><ins>+            if (!inlineBoxWithInlineContent.hasChild())
</ins><span class="cx">                 break;
</span><del>-            layoutQueue.append(inlineBoxWithInlineContent.firstInFlowOrFloatingChild());
</del><ins>+            layoutQueue.append(inlineBoxWithInlineContent.firstChild());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         while (!layoutQueue.isEmpty()) {
</span><span class="cx">             auto& layoutBox = *layoutQueue.takeLast();
</span><del>-            if (is<LineBreakBox>(layoutBox)) {
</del><ins>+            if (layoutBox.isOutOfFlowPositioned()) {
+                // Let's not construct InlineItems for out-of-flow content as they don't participate in the inline layout.
+                // However to be able to static positioning them, we need to compute their approximate positions.
+                formattingState.addOutOfFlowBox(layoutBox);
+            } else if (is<LineBreakBox>(layoutBox)) {
</ins><span class="cx">                 auto& lineBreakBox = downcast<LineBreakBox>(layoutBox);
</span><span class="cx">                 formattingState.addInlineItem({ layoutBox, lineBreakBox.isOptional() ? InlineItem::Type::WordBreakOpportunity : InlineItem::Type::HardLineBreak });
</span><span class="cx">             } else if (layoutBox.isFloatingPositioned())
</span><span class="lines">@@ -455,7 +558,7 @@
</span><span class="cx">             else
</span><span class="cx">                 ASSERT_NOT_REACHED();
</span><span class="cx"> 
</span><del>-            if (auto* nextSibling = layoutBox.nextInFlowOrFloatingSibling()) {
</del><ins>+            if (auto* nextSibling = layoutBox.nextSibling()) {
</ins><span class="cx">                 layoutQueue.append(nextSibling);
</span><span class="cx">                 break;
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceWebCorelayoutformattingContextsinlineInlineFormattingContexth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h (281423 => 281424)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h  2021-08-22 23:45:54 UTC (rev 281423)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.h     2021-08-23 00:03:10 UTC (rev 281424)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
</span><span class="cx"> 
</span><span class="cx"> #include "FormattingContext.h"
</span><ins>+#include "FormattingState.h"
</ins><span class="cx"> #include "InlineFormattingGeometry.h"
</span><span class="cx"> #include "InlineFormattingQuirks.h"
</span><span class="cx"> #include "InlineLineBuilder.h"
</span><span class="lines">@@ -61,6 +62,7 @@
</span><span class="cx">     IntrinsicWidthConstraints computedIntrinsicWidthConstraints() override;
</span><span class="cx"> 
</span><span class="cx">     void lineLayout(InlineItems&, LineBuilder::InlineItemRange, const ConstraintsForInFlowContent&);
</span><ins>+    void computeStaticPositionForOutOfFlowContent(const FormattingState::OutOfFlowBoxList&);
</ins><span class="cx"> 
</span><span class="cx">     void computeIntrinsicWidthForFormattingRoot(const Box&);
</span><span class="cx">     InlineLayoutUnit computedIntrinsicWidthForConstraint(InlineLayoutUnit availableWidth) const;
</span><span class="lines">@@ -69,7 +71,7 @@
</span><span class="cx">     void computeHeightAndMargin(const Box&, const HorizontalConstraints&);
</span><span class="cx">     void computeWidthAndMargin(const Box&, const HorizontalConstraints&);
</span><span class="cx"> 
</span><del>-    void collectInlineContentIfNeeded();
</del><ins>+    void collectContentIfNeeded();
</ins><span class="cx">     InlineRect computeGeometryForLineContent(const LineBuilder::LineContent&, const HorizontalConstraints&);
</span><span class="cx">     void invalidateFormattingState(const InvalidationState&);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>