Title: [250490] trunk/Source/WebCore
Revision
250490
Author
za...@apple.com
Date
2019-09-29 08:08:41 -0700 (Sun, 29 Sep 2019)

Log Message

[LFC][IFC] Remove InlineLayout abstraction layer
https://bugs.webkit.org/show_bug.cgi?id=202352
<rdar://problem/55811532>

Reviewed by Antti Koivisto.

Move InlineLayout functions to InlineFormattingContext. Now inline layout has
1. InlineFormattingContext -high level layout and preferred width computation, collecting inline content, constructing display boxes
2. LineLayout -responsible for placing inline content on the current line (partial inline content handling, line breaking etc)
3. Line -represents an actual line, turns inline content into runs.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::layoutInFlowContent):
(WebCore::Layout::InlineFormattingContext::lineLayout):
(WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthConstraints):
(WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):
(WebCore::Layout::InlineFormattingContext::initialConstraintsForLine):
(WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
* layout/inlineformatting/InlineFormattingContext.h:
(WebCore::Layout::InlineFormattingContext::InlineLayout::layoutState const): Deleted.
(WebCore::Layout::InlineFormattingContext::InlineLayout::formattingContext const): Deleted.
(WebCore::Layout::InlineFormattingContext::InlineLayout::formattingRoot const): Deleted.
(WebCore::Layout::InlineFormattingContext::InlineLayout::formattingState): Deleted.
(WebCore::Layout::InlineFormattingContext::InlineLayout::widthConstraint const): Deleted.
* layout/inlineformatting/InlineFormattingContextLineLayout.cpp: Removed.
* layout/inlineformatting/InlineFormattingState.h:
(WebCore::Layout::InlineFormattingState::inlineItems const):
* layout/inlineformatting/InlineLineLayout.cpp: Added.
(WebCore::Layout::inlineItemWidth):
(WebCore::Layout::LineLayout::LineInput::LineInput):
(WebCore::Layout::LineLayout::UncommittedContent::add):
(WebCore::Layout::LineLayout::UncommittedContent::reset):
(WebCore::Layout::LineLayout::LineLayout):
(WebCore::Layout::LineLayout::commitPendingContent):
(WebCore::Layout::LineLayout::close):
(WebCore::Layout::LineLayout::placeInlineItem):
(WebCore::Layout::LineLayout::layout):
* layout/inlineformatting/InlineLineLayout.h: Added.
(WebCore::Layout::LineLayout::formattingContext const):
(WebCore::Layout::LineLayout::UncommittedContent::runs):
(WebCore::Layout::LineLayout::UncommittedContent::isEmpty const):
(WebCore::Layout::LineLayout::UncommittedContent::size const):
(WebCore::Layout::LineLayout::UncommittedContent::width const):

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (250489 => 250490)


--- trunk/Source/WebCore/ChangeLog	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/ChangeLog	2019-09-29 15:08:41 UTC (rev 250490)
@@ -1,3 +1,51 @@
+2019-09-29  Zalan Bujtas  <za...@apple.com>
+
+        [LFC][IFC] Remove InlineLayout abstraction layer
+        https://bugs.webkit.org/show_bug.cgi?id=202352
+        <rdar://problem/55811532>
+
+        Reviewed by Antti Koivisto.
+
+        Move InlineLayout functions to InlineFormattingContext. Now inline layout has
+        1. InlineFormattingContext -high level layout and preferred width computation, collecting inline content, constructing display boxes
+        2. LineLayout -responsible for placing inline content on the current line (partial inline content handling, line breaking etc)
+        3. Line -represents an actual line, turns inline content into runs.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::layoutInFlowContent):
+        (WebCore::Layout::InlineFormattingContext::lineLayout):
+        (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthConstraints):
+        (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):
+        (WebCore::Layout::InlineFormattingContext::initialConstraintsForLine):
+        (WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
+        * layout/inlineformatting/InlineFormattingContext.h:
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::layoutState const): Deleted.
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::formattingContext const): Deleted.
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::formattingRoot const): Deleted.
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::formattingState): Deleted.
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::widthConstraint const): Deleted.
+        * layout/inlineformatting/InlineFormattingContextLineLayout.cpp: Removed.
+        * layout/inlineformatting/InlineFormattingState.h:
+        (WebCore::Layout::InlineFormattingState::inlineItems const):
+        * layout/inlineformatting/InlineLineLayout.cpp: Added.
+        (WebCore::Layout::inlineItemWidth):
+        (WebCore::Layout::LineLayout::LineInput::LineInput):
+        (WebCore::Layout::LineLayout::UncommittedContent::add):
+        (WebCore::Layout::LineLayout::UncommittedContent::reset):
+        (WebCore::Layout::LineLayout::LineLayout):
+        (WebCore::Layout::LineLayout::commitPendingContent):
+        (WebCore::Layout::LineLayout::close):
+        (WebCore::Layout::LineLayout::placeInlineItem):
+        (WebCore::Layout::LineLayout::layout):
+        * layout/inlineformatting/InlineLineLayout.h: Added.
+        (WebCore::Layout::LineLayout::formattingContext const):
+        (WebCore::Layout::LineLayout::UncommittedContent::runs):
+        (WebCore::Layout::LineLayout::UncommittedContent::isEmpty const):
+        (WebCore::Layout::LineLayout::UncommittedContent::size const):
+        (WebCore::Layout::LineLayout::UncommittedContent::width const):
+
 2019-09-29  Zan Dobersek  <zdober...@igalia.com>
 
         [Nicosia] Add overflow, overflow proxy node implementations

Modified: trunk/Source/WebCore/Sources.txt (250489 => 250490)


--- trunk/Source/WebCore/Sources.txt	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/Sources.txt	2019-09-29 15:08:41 UTC (rev 250490)
@@ -1419,12 +1419,12 @@
 layout/floats/FloatingState.cpp
 layout/inlineformatting/InlineFormattingContext.cpp
 layout/inlineformatting/InlineFormattingContextGeometry.cpp
-layout/inlineformatting/InlineFormattingContextLineLayout.cpp
 layout/inlineformatting/InlineFormattingContextQuirks.cpp
 layout/inlineformatting/InlineFormattingState.cpp
 layout/inlineformatting/InlineInvalidation.cpp
 layout/inlineformatting/InlineLine.cpp
 layout/inlineformatting/InlineLineBreaker.cpp
+layout/inlineformatting/InlineLineLayout.cpp
 layout/inlineformatting/InlineTextItem.cpp
 layout/inlineformatting/text/TextUtil.cpp
 layout/layouttree/LayoutBox.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (250489 => 250490)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2019-09-29 15:08:41 UTC (rev 250490)
@@ -2003,6 +2003,7 @@
 		6F0CD695229ED32700C5994E /* InlineLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F0CD694229ED32700C5994E /* InlineLine.h */; };
 		6F1CC1DE225F8B4900720AD2 /* InlineTextItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F1CC1DD225F8B4200720AD2 /* InlineTextItem.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		6F26BB6C23343E6F002F2BEA /* LayoutContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F26BB6B23343E5B002F2BEA /* LayoutContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		6F26EB48234004A5006906E2 /* InlineLineLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F26EB46234004A5006906E2 /* InlineLineLayout.h */; };
 		6F3E1F622136142000A65A08 /* FloatBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F3E1F612136141700A65A08 /* FloatBox.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		6F7CA3C6208C2957002F29AB /* LayoutState.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F7CA3C4208C2956002F29AB /* LayoutState.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		6F7CA3CA208C2B2E002F29AB /* InlineFormattingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F7CA3C8208C2B2E002F29AB /* InlineFormattingContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -9159,9 +9160,10 @@
 		6F1CC1DD225F8B4200720AD2 /* InlineTextItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InlineTextItem.h; sourceTree = "<group>"; };
 		6F222B741AB52D640094651A /* WebGLVertexArrayObjectBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebGLVertexArrayObjectBase.h; sourceTree = "<group>"; };
 		6F222B751AB52D8A0094651A /* WebGLVertexArrayObjectBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebGLVertexArrayObjectBase.cpp; sourceTree = "<group>"; };
-		6F25B200220A85AB0000011B /* InlineFormattingContextLineLayout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextLineLayout.cpp; sourceTree = "<group>"; };
+		6F25B200220A85AB0000011B /* InlineLineLayout.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = InlineLineLayout.cpp; sourceTree = "<group>"; };
 		6F26BB6923343E5A002F2BEA /* LayoutContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutContext.cpp; sourceTree = "<group>"; };
 		6F26BB6B23343E5B002F2BEA /* LayoutContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutContext.h; sourceTree = "<group>"; };
+		6F26EB46234004A5006906E2 /* InlineLineLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineLineLayout.h; sourceTree = "<group>"; };
 		6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFormattingContextGeometry.cpp; sourceTree = "<group>"; };
 		6F3E1F5F2136141700A65A08 /* FloatBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatBox.cpp; sourceTree = "<group>"; };
 		6F3E1F612136141700A65A08 /* FloatBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatBox.h; sourceTree = "<group>"; };
@@ -16482,7 +16484,6 @@
 				6F7CA3C9208C2B2E002F29AB /* InlineFormattingContext.cpp */,
 				6F7CA3C8208C2B2E002F29AB /* InlineFormattingContext.h */,
 				6F35EFAF2187CBD50044E0F4 /* InlineFormattingContextGeometry.cpp */,
-				6F25B200220A85AB0000011B /* InlineFormattingContextLineLayout.cpp */,
 				6F10B08622B8568D0090E69C /* InlineFormattingContextQuirks.cpp */,
 				115CFA7D208B8E10001E6991 /* InlineFormattingState.cpp */,
 				115CFA7C208B8E10001E6991 /* InlineFormattingState.h */,
@@ -16494,6 +16495,8 @@
 				6FB47E612277425A00C7BCB0 /* InlineLineBox.h */,
 				6FE198132178397B00446F08 /* InlineLineBreaker.cpp */,
 				6FE198152178397C00446F08 /* InlineLineBreaker.h */,
+				6F25B200220A85AB0000011B /* InlineLineLayout.cpp */,
+				6F26EB46234004A5006906E2 /* InlineLineLayout.h */,
 				6F1CC1DC225F8B4100720AD2 /* InlineTextItem.cpp */,
 				6F1CC1DD225F8B4200720AD2 /* InlineTextItem.h */,
 			);
@@ -28306,9 +28309,9 @@
 				FFB698CD1833F17600158A31 /* LineInfo.cpp */,
 				FFB698CE1833F17600158A31 /* LineInfo.h */,
 				FFEFAB2D183BCB6F00514534 /* LineInlineHeaders.h */,
+				FFEFAB2918380DA000514534 /* LineLayoutState.h */,
 				E484A33D23055303009ADE6A /* LineLayoutTraversal.cpp */,
 				E484A33B23055303009ADE6A /* LineLayoutTraversal.h */,
-				FFEFAB2918380DA000514534 /* LineLayoutState.h */,
 				FFDBC046183D27B700407109 /* LineWidth.cpp */,
 				FFDBC045183D27B700407109 /* LineWidth.h */,
 				FFAC30FD184FB145008C4F1E /* TrailingObjects.cpp */,
@@ -29749,6 +29752,7 @@
 				6F0CD695229ED32700C5994E /* InlineLine.h in Headers */,
 				6FB47E632277425A00C7BCB0 /* InlineLineBox.h in Headers */,
 				6FE198172178397C00446F08 /* InlineLineBreaker.h in Headers */,
+				6F26EB48234004A5006906E2 /* InlineLineLayout.h in Headers */,
 				AA4C3A770B2B1679002334A2 /* InlineStyleSheetOwner.h in Headers */,
 				BCEA485A097D93020094C9E4 /* InlineTextBox.h in Headers */,
 				1C010701192594DF008A4201 /* InlineTextBoxStyle.h in Headers */,
@@ -30744,8 +30748,8 @@
 				84730D911248F0B300D3A9C9 /* LightSource.h in Headers */,
 				B22279650D00BF220071B782 /* LinearGradientAttributes.h in Headers */,
 				AB31C91E10AE1B8E000C7B92 /* LineClampValue.h in Headers */,
+				FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
 				E484A33E23055325009ADE6A /* LineLayoutTraversal.h in Headers */,
-				FFEFAB2A18380DA000514534 /* LineLayoutState.h in Headers */,
 				FFDBC047183D27B700407109 /* LineWidth.h in Headers */,
 				CBA9DC0B1DF44DF40005675C /* LinkHeader.h in Headers */,
 				5143B2631DDD15200014FAC6 /* LinkIcon.h in Headers */,

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (250489 => 250490)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2019-09-29 15:08:41 UTC (rev 250490)
@@ -88,10 +88,41 @@
     formattingState().inlineRuns().clear();
 
     collectInlineContent();
-    InlineLayout(*this, usedHorizontalValues).layout(formattingState().inlineItems());
+    lineLayout(usedHorizontalValues);
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> inline formatting context -> formatting root(" << &root() << ")");
 }
 
+void InlineFormattingContext::lineLayout(UsedHorizontalValues usedHorizontalValues)
+{
+    auto& inlineItems = formattingState().inlineItems();
+    auto lineLogicalTop = geometryForBox(root()).contentBoxTop();
+    LineLayout::IndexAndRange currentInlineItem;
+    while (currentInlineItem.index < inlineItems.size()) {
+        auto lineConstraints = initialConstraintsForLine(usedHorizontalValues, lineLogicalTop);
+        auto lineInput = LineLayout::LineInput { lineConstraints, root().style().textAlign(), currentInlineItem, inlineItems };
+        auto lineLayout = LineLayout { *this, lineInput };
+
+        auto lineContent = lineLayout.layout();
+        setDisplayBoxesForLine(lineContent, usedHorizontalValues);
+
+        if (lineContent.lastCommitted) {
+            currentInlineItem = { lineContent.lastCommitted->index + 1, WTF::nullopt };
+            lineLogicalTop = lineContent.lineBox.logicalBottom();
+        } else {
+            // Floats prevented us placing any content on the line.
+            ASSERT(lineInput.initialConstraints.lineIsConstrainedByFloat);
+            // Move the next line below the intrusive float.
+            auto floatingContext = FloatingContext { root(), *this, formattingState().floatingState() };
+            auto floatConstraints = floatingContext.constraints({ lineLogicalTop });
+            ASSERT(floatConstraints.left || floatConstraints.right);
+            static auto inifitePoint = PointInContextRoot::max();
+            // In case of left and right constraints, we need to pick the one that's closer to the current line.
+            lineLogicalTop = std::min(floatConstraints.left.valueOr(inifitePoint).y, floatConstraints.right.valueOr(inifitePoint).y);
+            ASSERT(lineLogicalTop < inifitePoint.y);
+        }
+    }
+}
+
 void InlineFormattingContext::layoutFormattingContextRoot(const Box& formattingContextRoot, UsedHorizontalValues usedHorizontalValues, UsedVerticalValues usedVerticalValues)
 {
     ASSERT(formattingContextRoot.isFloatingPositioned() || formattingContextRoot.isInlineBlockBox());
@@ -183,7 +214,7 @@
             displayBox.setContentBoxWidth(contentWidth);
         }
         auto usedHorizontalValues = UsedHorizontalValues { UsedHorizontalValues::Constraints { { }, availableWidth } };
-        return InlineLayout(*this, usedHorizontalValues).computedIntrinsicWidth(formattingState().inlineItems());
+        return computedIntrinsicWidthForConstraint(usedHorizontalValues);
     };
 
     auto constraints = geometry().constrainByMinMaxWidth(root(), { maximumLineWidth(0), maximumLineWidth(LayoutUnit::max()) });
@@ -191,6 +222,27 @@
     return constraints;
 }
 
+LayoutUnit InlineFormattingContext::computedIntrinsicWidthForConstraint(UsedHorizontalValues usedHorizontalValues) const
+{
+    auto& inlineItems = formattingState().inlineItems();
+    LayoutUnit maximumLineWidth;
+    LineLayout::IndexAndRange currentInlineItem;
+    while (currentInlineItem.index < inlineItems.size()) {
+        // Only the horiztonal available width is constrained when computing intrinsic width.
+        auto initialLineConstraints = Line::InitialConstraints { { }, usedHorizontalValues.constraints.width, false, { } };
+        auto lineInput = LineLayout::LineInput { initialLineConstraints, currentInlineItem, inlineItems };
+
+        auto lineContent = LineLayout(*this, lineInput).layout();
+
+        currentInlineItem = { lineContent.lastCommitted->index + 1, { } };
+        LayoutUnit floatsWidth;
+        for (auto& floatItem : lineContent.floats)
+            floatsWidth += geometryForBox(floatItem->layoutBox()).marginBoxWidth();
+        maximumLineWidth = std::max(maximumLineWidth, floatsWidth + lineContent.lineBox.logicalWidth());
+    }
+    return maximumLineWidth;
+}
+
 void InlineFormattingContext::computeIntrinsicWidthForFormattingRoot(const Box& formattingRoot, UsedHorizontalValues usedHorizontalValues)
 {
     ASSERT(formattingRoot.establishesFormattingContext());
@@ -311,7 +363,139 @@
     }
 }
 
+Line::InitialConstraints InlineFormattingContext::initialConstraintsForLine(UsedHorizontalValues usedHorizontalValues, const LayoutUnit lineLogicalTop)
+{
+    auto lineLogicalLeft = geometryForBox(root()).contentBoxLeft();
+    auto availableWidth = usedHorizontalValues.constraints.width;
+    auto lineIsConstrainedByFloat = false;
+
+    auto floatingContext = FloatingContext { root(), *this, formattingState().floatingState() };
+    // Check for intruding floats and adjust logical left/available width for this line accordingly.
+    if (!floatingContext.isEmpty()) {
+        auto floatConstraints = floatingContext.constraints({ lineLogicalTop });
+        // Check if these constraints actually put limitation on the line.
+        if (floatConstraints.left && floatConstraints.left->x <= lineLogicalLeft)
+            floatConstraints.left = { };
+
+        auto lineLogicalRight = geometryForBox(root()).contentBoxRight();
+        if (floatConstraints.right && floatConstraints.right->x >= lineLogicalRight)
+            floatConstraints.right = { };
+
+        lineIsConstrainedByFloat = floatConstraints.left || floatConstraints.right;
+
+        if (floatConstraints.left && floatConstraints.right) {
+            ASSERT(floatConstraints.left->x <= floatConstraints.right->x);
+            availableWidth = floatConstraints.right->x - floatConstraints.left->x;
+            lineLogicalLeft = floatConstraints.left->x;
+        } else if (floatConstraints.left) {
+            ASSERT(floatConstraints.left->x >= lineLogicalLeft);
+            availableWidth -= (floatConstraints.left->x - lineLogicalLeft);
+            lineLogicalLeft = floatConstraints.left->x;
+        } else if (floatConstraints.right) {
+            ASSERT(floatConstraints.right->x >= lineLogicalLeft);
+            availableWidth = floatConstraints.right->x - lineLogicalLeft;
+        }
+    }
+    return Line::InitialConstraints { { lineLogicalLeft, lineLogicalTop }, availableWidth, lineIsConstrainedByFloat, quirks().lineHeightConstraints(root()) };
 }
+
+void InlineFormattingContext::setDisplayBoxesForLine(const LineLayout::LineContent& lineContent, UsedHorizontalValues usedHorizontalValues)
+{
+    auto& formattingState = this->formattingState();
+
+    if (!lineContent.floats.isEmpty()) {
+        auto floatingContext = FloatingContext { root(), *this, formattingState.floatingState() };
+        // Move floats to their final position.
+        for (const auto& floatItem : lineContent.floats) {
+            auto& floatBox = floatItem->layoutBox();
+            auto& displayBox = formattingState.displayBox(floatBox);
+            // Set static position first.
+            auto& lineBox = lineContent.lineBox;
+            displayBox.setTopLeft({ lineBox.logicalLeft(), lineBox.logicalTop() });
+            // Float it.
+            displayBox.setTopLeft(floatingContext.positionForFloat(floatBox));
+            floatingContext.append(floatBox);
+        }
+    }
+
+    // Add final display runs to state.
+    for (auto& lineRun : lineContent.runList) {
+        // Inline level containers (<span>) don't generate inline runs.
+        if (lineRun->isContainerStart() || lineRun->isContainerEnd())
+            continue;
+        // Collapsed line runs don't generate display runs.
+        if (lineRun->isVisuallyEmpty())
+            continue;
+        formattingState.addInlineRun(lineRun->displayRun());
+    }
+
+    // Compute box final geometry.
+    auto& lineRuns = lineContent.runList;
+    for (unsigned index = 0; index < lineRuns.size(); ++index) {
+        auto& lineRun = lineRuns.at(index);
+        auto& logicalRect = lineRun->logicalRect();
+        auto& layoutBox = lineRun->layoutBox();
+        auto& displayBox = formattingState.displayBox(layoutBox);
+
+        if (lineRun->isLineBreak()) {
+            displayBox.setTopLeft(logicalRect.topLeft());
+            displayBox.setContentBoxWidth(logicalRect.width());
+            displayBox.setContentBoxHeight(logicalRect.height());
+            continue;
+        }
+
+        // Inline level box (replaced or inline-block)
+        if (lineRun->isBox()) {
+            auto topLeft = logicalRect.topLeft();
+            if (layoutBox.isInFlowPositioned())
+                topLeft += geometry().inFlowPositionedPositionOffset(layoutBox, usedHorizontalValues);
+            displayBox.setTopLeft(topLeft);
+            continue;
+        }
+
+        // Inline level container start (<span>)
+        if (lineRun->isContainerStart()) {
+            displayBox.setTopLeft(logicalRect.topLeft());
+            continue;
+        }
+
+        // Inline level container end (</span>)
+        if (lineRun->isContainerEnd()) {
+            if (layoutBox.isInFlowPositioned()) {
+                auto inflowOffset = geometry().inFlowPositionedPositionOffset(layoutBox, usedHorizontalValues);
+                displayBox.moveHorizontally(inflowOffset.width());
+                displayBox.moveVertically(inflowOffset.height());
+            }
+            auto marginBoxWidth = logicalRect.left() - displayBox.left();
+            auto contentBoxWidth = marginBoxWidth - (displayBox.marginStart() + displayBox.borderLeft() + displayBox.paddingLeft().valueOr(0));
+            // FIXME fix it for multiline.
+            displayBox.setContentBoxWidth(contentBoxWidth);
+            displayBox.setContentBoxHeight(logicalRect.height());
+            continue;
+        }
+
+        if (lineRun->isText()) {
+            const Line::Run* previousLineRun = !index ? nullptr : lineRuns[index - 1].get();
+            // FIXME take content breaking into account when part of the layout box is on the previous line.
+            auto firstInlineRunForLayoutBox = !previousLineRun || &previousLineRun->layoutBox() != &layoutBox;
+            auto logicalWidth = lineRun->isVisuallyEmpty() ? LayoutUnit() : logicalRect.width();
+            if (firstInlineRunForLayoutBox) {
+                // Setup display box for the associated layout box.
+                displayBox.setTopLeft(logicalRect.topLeft());
+                displayBox.setContentBoxWidth(logicalWidth);
+                displayBox.setContentBoxHeight(logicalRect.height());
+            } else {
+                // FIXME fix it for multirun/multiline.
+                displayBox.setContentBoxWidth(displayBox.contentBoxWidth() + logicalWidth);
+            }
+            continue;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    formattingState.addLineBox(lineContent.lineBox);
 }
 
+}
+}
+
 #endif

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (250489 => 250490)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2019-09-29 15:08:41 UTC (rev 250490)
@@ -31,6 +31,7 @@
 #include "FormattingContext.h"
 #include "InlineFormattingState.h"
 #include "InlineLine.h"
+#include "InlineLineLayout.h"
 #include <wtf/IsoMalloc.h>
 
 namespace WebCore {
@@ -51,29 +52,6 @@
 private:
     IntrinsicWidthConstraints computedIntrinsicWidthConstraints() override;
 
-    class InlineLayout {
-    public:
-        InlineLayout(InlineFormattingContext&, UsedHorizontalValues);
-        void layout(const InlineItems&);
-        LayoutUnit computedIntrinsicWidth(const InlineItems&) const;
-
-    private:
-        Line::InitialConstraints initialConstraintsForLine(const LayoutUnit lineLogicalTop);
-
-        LayoutState& layoutState() const { return m_inlineFormattingContext.layoutState(); }
-        InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
-        const Container& formattingRoot() const { return m_inlineFormattingContext.root(); }
-        InlineFormattingState& formattingState() { return m_inlineFormattingContext.formattingState(); }
-        LayoutUnit widthConstraint() const { return m_usedHorizontalValues.constraints.width; }
-
-        LineContent placeInlineItems(const LineInput&) const;
-        void setupDisplayBoxes(const LineContent&);
-
-    private:
-        InlineFormattingContext& m_inlineFormattingContext;
-        UsedHorizontalValues m_usedHorizontalValues;
-    };
-
     class Quirks : public FormattingContext::Quirks {
     public:
         bool lineDescentNeedsCollapsing(const Line::RunList&) const;
@@ -102,11 +80,13 @@
     };
     InlineFormattingContext::Geometry geometry() const { return Geometry(*this); }
 
+    void lineLayout(UsedHorizontalValues);
     void layoutFormattingContextRoot(const Box&, UsedHorizontalValues, UsedVerticalValues);
     void computeHorizontalAndVerticalGeometry(const Box&, UsedHorizontalValues, UsedVerticalValues);
 
     void computeIntrinsicWidthForFormattingRoot(const Box&, UsedHorizontalValues);
     void computeWidthAndHeightForReplacedInlineBox(const Box&, UsedHorizontalValues, UsedVerticalValues);
+    LayoutUnit computedIntrinsicWidthForConstraint(UsedHorizontalValues) const;
 
     void computeHorizontalMargin(const Box&, UsedHorizontalValues);
     void computeHeightAndMargin(const Box&, UsedHorizontalValues, UsedVerticalValues);
@@ -113,12 +93,13 @@
     void computeWidthAndMargin(const Box&, UsedHorizontalValues);
 
     void collectInlineContent();
+    Line::InitialConstraints initialConstraintsForLine(UsedHorizontalValues, const LayoutUnit lineLogicalTop);
+    void setDisplayBoxesForLine(const LineLayout::LineContent&, UsedHorizontalValues);
 
     const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
     InlineFormattingState& formattingState() { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
     // FIXME: Come up with a structure that requires no friending.
     friend class Line;
-    friend class InlineLayout;
 };
 
 inline InlineFormattingContext::Geometry::Geometry(const InlineFormattingContext& inlineFormattingContext)

Deleted: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp (250489 => 250490)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp	2019-09-29 15:08:41 UTC (rev 250490)
@@ -1,471 +0,0 @@
-/*
- * 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.
- */
-
-#include "config.h"
-#include "InlineFormattingContext.h"
-
-#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
-
-#include "FloatingContext.h"
-#include "FloatingState.h"
-#include "InlineFormattingState.h"
-#include "InlineLine.h"
-#include "InlineLineBreaker.h"
-#include "LayoutBox.h"
-#include "LayoutContainer.h"
-#include "LayoutState.h"
-#include "TextUtil.h"
-
-namespace WebCore {
-namespace Layout {
-
-static LayoutUnit inlineItemWidth(const FormattingContext& formattingContext, const InlineItem& inlineItem, LayoutUnit contentLogicalLeft)
-{
-    if (inlineItem.isLineBreak())
-        return 0;
-
-    if (is<InlineTextItem>(inlineItem)) {
-        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
-        auto end = inlineTextItem.isCollapsed() ? inlineTextItem.start() + 1 : inlineTextItem.end();
-        return TextUtil::width(inlineTextItem.layoutBox(), inlineTextItem.start(), end, contentLogicalLeft);
-    }
-
-    auto& layoutBox = inlineItem.layoutBox();
-    auto& boxGeometry = formattingContext.geometryForBox(layoutBox);
-
-    if (layoutBox.isFloatingPositioned())
-        return boxGeometry.marginBoxWidth();
-
-    if (layoutBox.replaced())
-        return boxGeometry.width();
-
-    if (inlineItem.isContainerStart())
-        return boxGeometry.marginStart() + boxGeometry.borderLeft() + boxGeometry.paddingLeft().valueOr(0);
-
-    if (inlineItem.isContainerEnd())
-        return boxGeometry.marginEnd() + boxGeometry.borderRight() + boxGeometry.paddingRight().valueOr(0);
-
-    // Non-replaced inline box (e.g. inline-block)
-    return boxGeometry.width();
-}
-
-struct IndexAndRange {
-    unsigned index { 0 };
-    struct Range {
-        unsigned start { 0 };
-        unsigned length { 0 };
-    };
-    Optional<Range> partialContext;
-};
-
-struct LineInput {
-    LineInput(const Line::InitialConstraints&, TextAlignMode, IndexAndRange firstToProcess, const InlineItems&);
-    LineInput(const Line::InitialConstraints&, IndexAndRange firstToProcess, const InlineItems&);
-
-    Line::InitialConstraints initialConstraints;
-    TextAlignMode horizontalAlignment;
-    // FIXME Alternatively we could just have a second pass with vertical positioning (preferred width computation opts out) 
-    Line::SkipAlignment skipAlignment { Line::SkipAlignment::No };
-    IndexAndRange firstInlineItem;
-    const InlineItems& inlineItems;
-    Optional<LayoutUnit> floatMinimumLogicalBottom;
-};
-
-LineInput::LineInput(const Line::InitialConstraints& initialLineConstraints, TextAlignMode horizontalAlignment, IndexAndRange firstToProcess, const InlineItems& inlineItems)
-    : initialConstraints(initialLineConstraints)
-    , horizontalAlignment(horizontalAlignment)
-    , firstInlineItem(firstToProcess)
-    , inlineItems(inlineItems)
-{
-}
-
-LineInput::LineInput(const Line::InitialConstraints& initialLineConstraints, IndexAndRange firstToProcess, const InlineItems& inlineItems)
-    : initialConstraints(initialLineConstraints)
-    , skipAlignment(Line::SkipAlignment::Yes)
-    , firstInlineItem(firstToProcess)
-    , inlineItems(inlineItems)
-{
-}
-
-struct LineContent {
-    Optional<IndexAndRange> lastCommitted;
-    Vector<WeakPtr<InlineItem>> floats;
-    const Line::RunList runList;
-    const LineBox lineBox;
-};
-
-class LineLayout {
-public:
-    LineLayout(const InlineFormattingContext&, const LineInput&);
-
-    LineContent layout();
-
-private:
-    const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
-    enum class IsEndOfLine { No, Yes };
-    IsEndOfLine placeInlineItem(const InlineItem&);
-    void commitPendingContent();
-    LineContent close();
-    
-    struct UncommittedContent {
-        struct Run {
-            const InlineItem& inlineItem;
-            LayoutUnit logicalWidth;
-        };
-        void add(const InlineItem&, LayoutUnit logicalWidth);
-        void reset();
-
-        Vector<Run> runs() { return m_uncommittedRuns; }
-        bool isEmpty() const { return m_uncommittedRuns.isEmpty(); }
-        unsigned size() const { return m_uncommittedRuns.size(); }
-        LayoutUnit width() const { return m_width; }
-
-    private:
-        Vector<Run> m_uncommittedRuns;
-        LayoutUnit m_width;
-    };
-
-    const InlineFormattingContext& m_inlineFormattingContext;
-    const LineInput& m_lineInput;
-    Line m_line;
-    LineBreaker m_lineBreaker;
-    bool m_lineHasIntrusiveFloat { false };
-    UncommittedContent m_uncommittedContent;
-    unsigned m_committedInlineItemCount { 0 };
-    Vector<WeakPtr<InlineItem>> m_floats;
-    std::unique_ptr<InlineTextItem> m_leadingPartialInlineTextItem;
-    std::unique_ptr<InlineTextItem> m_trailingPartialInlineTextItem;
-};
-
-void LineLayout::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth)
-{
-    m_uncommittedRuns.append({ inlineItem, logicalWidth });
-    m_width += logicalWidth;
-}
-
-void LineLayout::UncommittedContent::reset()
-{
-    m_uncommittedRuns.clear();
-    m_width = 0;
-}
-
-LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const LineInput& lineInput)
-    : m_inlineFormattingContext(inlineFormattingContext)
-    , m_lineInput(lineInput)
-    , m_line(inlineFormattingContext, lineInput.initialConstraints, lineInput.horizontalAlignment, lineInput.skipAlignment)
-    , m_lineHasIntrusiveFloat(lineInput.initialConstraints.lineIsConstrainedByFloat)
-{
-}
-
-void LineLayout::commitPendingContent()
-{
-    if (m_uncommittedContent.isEmpty())
-        return;
-    m_committedInlineItemCount += m_uncommittedContent.size();
-    for (auto& uncommittedRun : m_uncommittedContent.runs())
-        m_line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
-    m_uncommittedContent.reset();
-}
-
-LineContent LineLayout::close()
-{
-    ASSERT(m_committedInlineItemCount || m_lineHasIntrusiveFloat);
-    if (!m_committedInlineItemCount)
-        return LineContent { WTF::nullopt, WTFMove(m_floats), m_line.close(), m_line.lineBox() };
-
-    auto lastInlineItemIndex = m_lineInput.firstInlineItem.index + m_committedInlineItemCount - 1;
-    Optional<IndexAndRange::Range> partialContext;
-    if (m_trailingPartialInlineTextItem)
-        partialContext = IndexAndRange::Range { m_trailingPartialInlineTextItem->start(), m_trailingPartialInlineTextItem->length() };
-
-    auto lastCommitedItem = IndexAndRange { lastInlineItemIndex, partialContext };
-    return LineContent { lastCommitedItem, WTFMove(m_floats), m_line.close(), m_line.lineBox() };
-}
-
-LineLayout::IsEndOfLine LineLayout::placeInlineItem(const InlineItem& inlineItem)
-{
-    auto availableWidth = m_line.availableWidth() - m_uncommittedContent.width();
-    auto currentLogicalRight = m_line.lineBox().logicalRight() + m_uncommittedContent.width();
-    auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight);
-
-    // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed.
-    auto lineIsConsideredEmpty = !m_line.hasContent() && !m_lineHasIntrusiveFloat;
-    auto breakingContext = m_lineBreaker.breakingContext(inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, m_line.trailingTrimmableWidth(), lineIsConsideredEmpty });
-    if (breakingContext.isAtBreakingOpportunity)
-        commitPendingContent();
-
-    // Content does not fit the current line.
-    if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)
-        return IsEndOfLine::Yes;
-
-    // Partial content stays on the current line.
-    if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Split) {
-        ASSERT(inlineItem.isText());
-        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
-        auto splitData = TextUtil::split(inlineTextItem.layoutBox(), inlineTextItem.start(), inlineTextItem.length(), itemLogicalWidth, availableWidth, currentLogicalRight);
-        // Construct a partial trailing inline item.
-        ASSERT(!m_trailingPartialInlineTextItem);
-        m_trailingPartialInlineTextItem = inlineTextItem.split(splitData.start, splitData.length);
-        m_uncommittedContent.add(*m_trailingPartialInlineTextItem, splitData.logicalWidth);
-        commitPendingContent();
-        return IsEndOfLine::Yes;
-    }
-
-    ASSERT(breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Keep);
-    if (inlineItem.isFloat()) {
-        auto& floatBox = inlineItem.layoutBox();
-        // Shrink available space for current line and move existing inline runs.
-        auto floatBoxWidth = formattingContext().geometryForBox(floatBox).marginBoxWidth();
-        floatBox.isLeftFloatingPositioned() ? m_line.moveLogicalLeft(floatBoxWidth) : m_line.moveLogicalRight(floatBoxWidth);
-        m_floats.append(makeWeakPtr(inlineItem));
-        ++m_committedInlineItemCount;
-        m_lineHasIntrusiveFloat = true;
-        return IsEndOfLine::No;
-    }
-
-    m_uncommittedContent.add(inlineItem, itemLogicalWidth);
-    if (breakingContext.isAtBreakingOpportunity)
-        commitPendingContent();
-
-    return inlineItem.isHardLineBreak() ? IsEndOfLine::Yes : IsEndOfLine::No;
-}
-
-LineContent LineLayout::layout()
-{
-    // Iterate through the inline content and place the inline boxes on the current line.
-    // Start with the partial text from the previous line.
-    auto firstInlineItem = m_lineInput.firstInlineItem;
-    unsigned firstNonPartialIndex = firstInlineItem.index;
-    if (firstInlineItem.partialContext) {
-        // Handle partial inline item (split text from the previous line).
-        auto& originalTextItem = m_lineInput.inlineItems[firstInlineItem.index];
-        RELEASE_ASSERT(originalTextItem->isText());
-
-        auto textRange = *firstInlineItem.partialContext;
-        // Construct a partial leading inline item.
-        ASSERT(!m_leadingPartialInlineTextItem);
-        m_leadingPartialInlineTextItem = downcast<InlineTextItem>(*originalTextItem).split(textRange.start, textRange.length);
-        if (placeInlineItem(*m_leadingPartialInlineTextItem) == IsEndOfLine::Yes)
-            return close();
-        ++firstNonPartialIndex;
-    }
-
-    for (auto inlineItemIndex = firstNonPartialIndex; inlineItemIndex < m_lineInput.inlineItems.size(); ++inlineItemIndex) {
-        if (placeInlineItem(*m_lineInput.inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
-            return close();
-    }
-    commitPendingContent();
-    return close();
-}
-
-InlineFormattingContext::InlineLayout::InlineLayout(InlineFormattingContext& inlineFormattingContext, UsedHorizontalValues usedHorizontalValues)
-    : m_inlineFormattingContext(inlineFormattingContext)
-    , m_usedHorizontalValues(usedHorizontalValues)
-{
-}
-
-void InlineFormattingContext::InlineLayout::layout(const InlineItems& inlineItems)
-{
-    auto lineLogicalTop = formattingContext().geometryForBox(formattingRoot()).contentBoxTop();
-    IndexAndRange currentInlineItem;
-    while (currentInlineItem.index < inlineItems.size()) {
-        auto lineInput = LineInput { initialConstraintsForLine(lineLogicalTop), formattingRoot().style().textAlign(), currentInlineItem, inlineItems };
-        auto lineLayout = LineLayout { formattingContext(), lineInput };
-
-        auto lineContent = lineLayout.layout();
-        setupDisplayBoxes(lineContent);
-
-        if (lineContent.lastCommitted) {
-            currentInlineItem = { lineContent.lastCommitted->index + 1, WTF::nullopt };
-            lineLogicalTop = lineContent.lineBox.logicalBottom();
-        } else {
-            // Floats prevented us placing any content on the line.
-            ASSERT(lineInput.initialConstraints.lineIsConstrainedByFloat);
-            // Move the next line below the intrusive float.
-            auto floatingContext = FloatingContext { formattingRoot(), formattingContext(), formattingState().floatingState() };
-            auto floatConstraints = floatingContext.constraints({ lineLogicalTop });
-            ASSERT(floatConstraints.left || floatConstraints.right);
-            static auto inifitePoint = PointInContextRoot::max();
-            // In case of left and right constraints, we need to pick the one that's closer to the current line.
-            lineLogicalTop = std::min(floatConstraints.left.valueOr(inifitePoint).y, floatConstraints.right.valueOr(inifitePoint).y);
-            ASSERT(lineLogicalTop < inifitePoint.y);
-        }
-    }
-}
-
-Line::InitialConstraints InlineFormattingContext::InlineLayout::initialConstraintsForLine(const LayoutUnit lineLogicalTop)
-{
-    auto lineLogicalLeft = formattingContext().geometryForBox(formattingRoot()).contentBoxLeft();
-    auto availableWidth = widthConstraint();
-    auto lineIsConstrainedByFloat = false;
-
-    auto floatingContext = FloatingContext { formattingRoot(), formattingContext(), formattingState().floatingState() };
-    // Check for intruding floats and adjust logical left/available width for this line accordingly.
-    if (!floatingContext.isEmpty()) {
-        auto floatConstraints = floatingContext.constraints({ lineLogicalTop });
-        // Check if these constraints actually put limitation on the line.
-        if (floatConstraints.left && floatConstraints.left->x <= lineLogicalLeft)
-            floatConstraints.left = { };
-
-        auto lineLogicalRight = formattingContext().geometryForBox(formattingRoot()).contentBoxRight();
-        if (floatConstraints.right && floatConstraints.right->x >= lineLogicalRight)
-            floatConstraints.right = { };
-
-        lineIsConstrainedByFloat = floatConstraints.left || floatConstraints.right;
-
-        if (floatConstraints.left && floatConstraints.right) {
-            ASSERT(floatConstraints.left->x <= floatConstraints.right->x);
-            availableWidth = floatConstraints.right->x - floatConstraints.left->x;
-            lineLogicalLeft = floatConstraints.left->x;
-        } else if (floatConstraints.left) {
-            ASSERT(floatConstraints.left->x >= lineLogicalLeft);
-            availableWidth -= (floatConstraints.left->x - lineLogicalLeft);
-            lineLogicalLeft = floatConstraints.left->x;
-        } else if (floatConstraints.right) {
-            ASSERT(floatConstraints.right->x >= lineLogicalLeft);
-            availableWidth = floatConstraints.right->x - lineLogicalLeft;
-        }
-    }
-    return Line::InitialConstraints { { lineLogicalLeft, lineLogicalTop }, availableWidth, lineIsConstrainedByFloat, formattingContext().quirks().lineHeightConstraints(formattingRoot()) };
-}
-
-LayoutUnit InlineFormattingContext::InlineLayout::computedIntrinsicWidth(const InlineItems& inlineItems) const
-{
-    auto& formattingContext = this->formattingContext();
-    LayoutUnit maximumLineWidth;
-    IndexAndRange currentInlineItem;
-    while (currentInlineItem.index < inlineItems.size()) {
-        // Only the horiztonal available width is constrained when computing intrinsic width.
-        auto initialLineConstraints = Line::InitialConstraints { { }, widthConstraint(), false, { } };
-        auto lineInput = LineInput { initialLineConstraints, currentInlineItem, inlineItems };
-
-        auto lineContent = LineLayout(formattingContext, lineInput).layout();
-
-        currentInlineItem = { lineContent.lastCommitted->index + 1, { } };
-        LayoutUnit floatsWidth;
-        for (auto& floatItem : lineContent.floats)
-            floatsWidth += formattingContext.geometryForBox(floatItem->layoutBox()).marginBoxWidth();
-        maximumLineWidth = std::max(maximumLineWidth, floatsWidth + lineContent.lineBox.logicalWidth());
-    }
-    return maximumLineWidth;
-}
-
-void InlineFormattingContext::InlineLayout::setupDisplayBoxes(const LineContent& lineContent)
-{
-    auto& formattingContext = this->formattingContext();
-    auto& formattingState = this->formattingState();
-    auto floatingContext = FloatingContext { formattingRoot(), formattingContext, formattingState.floatingState() };
-
-    // Move floats to their final position.
-    for (const auto& floatItem : lineContent.floats) {
-        auto& floatBox = floatItem->layoutBox();
-        auto& displayBox = formattingState.displayBox(floatBox);
-        // Set static position first.
-        auto& lineBox = lineContent.lineBox;
-        displayBox.setTopLeft({ lineBox.logicalLeft(), lineBox.logicalTop() });
-        // Float it.
-        displayBox.setTopLeft(floatingContext.positionForFloat(floatBox));
-        floatingContext.append(floatBox);
-    }
-
-    // Add final display runs to state.
-    for (auto& lineRun : lineContent.runList) {
-        // Inline level containers (<span>) don't generate inline runs.
-        if (lineRun->isContainerStart() || lineRun->isContainerEnd())
-            continue;
-        formattingState.addInlineRun(lineRun->displayRun());
-    }
-
-    // Compute box final geometry.
-    auto geometry = formattingContext.geometry();
-    auto& lineRuns = lineContent.runList;
-    for (unsigned index = 0; index < lineRuns.size(); ++index) {
-        auto& lineRun = lineRuns.at(index);
-        auto& logicalRect = lineRun->logicalRect();
-        auto& layoutBox = lineRun->layoutBox();
-        auto& displayBox = formattingState.displayBox(layoutBox);
-
-        if (lineRun->isLineBreak()) {
-            displayBox.setTopLeft(logicalRect.topLeft());
-            displayBox.setContentBoxWidth(logicalRect.width());
-            displayBox.setContentBoxHeight(logicalRect.height());
-            continue;
-        }
-
-        // Inline level box (replaced or inline-block)
-        if (lineRun->isBox()) {
-            auto topLeft = logicalRect.topLeft();
-            if (layoutBox.isInFlowPositioned())
-                topLeft += geometry.inFlowPositionedPositionOffset(layoutBox, m_usedHorizontalValues);
-            displayBox.setTopLeft(topLeft);
-            continue;
-        }
-
-        // Inline level container start (<span>)
-        if (lineRun->isContainerStart()) {
-            displayBox.setTopLeft(logicalRect.topLeft());
-            continue;
-        }
-
-        // Inline level container end (</span>)
-        if (lineRun->isContainerEnd()) {
-            if (layoutBox.isInFlowPositioned()) {
-                auto inflowOffset = geometry.inFlowPositionedPositionOffset(layoutBox, m_usedHorizontalValues);
-                displayBox.moveHorizontally(inflowOffset.width());
-                displayBox.moveVertically(inflowOffset.height());
-            }
-            auto marginBoxWidth = logicalRect.left() - displayBox.left();
-            auto contentBoxWidth = marginBoxWidth - (displayBox.marginStart() + displayBox.borderLeft() + displayBox.paddingLeft().valueOr(0));
-            // FIXME fix it for multiline.
-            displayBox.setContentBoxWidth(contentBoxWidth);
-            displayBox.setContentBoxHeight(logicalRect.height());
-            continue;
-        }
-
-        if (lineRun->isText()) {
-            const Line::Run* previousLineRun = !index ? nullptr : lineRuns[index - 1].get();
-            // FIXME take content breaking into account when part of the layout box is on the previous line.
-            auto firstInlineRunForLayoutBox = !previousLineRun || &previousLineRun->layoutBox() != &layoutBox;
-            auto logicalWidth = lineRun->isVisuallyEmpty() ? LayoutUnit() : logicalRect.width();
-            if (firstInlineRunForLayoutBox) {
-                // Setup display box for the associated layout box.
-                displayBox.setTopLeft(logicalRect.topLeft());
-                displayBox.setContentBoxWidth(logicalWidth);
-                displayBox.setContentBoxHeight(logicalRect.height());
-            } else {
-                // FIXME fix it for multirun/multiline.
-                displayBox.setContentBoxWidth(displayBox.contentBoxWidth() + logicalWidth);
-            }
-            continue;
-        }
-        ASSERT_NOT_REACHED();
-    }
-    formattingState.addLineBox(lineContent.lineBox);
-}
-
-}
-}
-
-#endif

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h (250489 => 250490)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h	2019-09-29 08:56:34 UTC (rev 250489)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h	2019-09-29 15:08:41 UTC (rev 250490)
@@ -49,6 +49,7 @@
     virtual ~InlineFormattingState();
 
     InlineItems& inlineItems() { return m_inlineItems; }
+    const InlineItems& inlineItems() const { return m_inlineItems; }
     void addInlineItem(std::unique_ptr<InlineItem>&& inlineItem) { m_inlineItems.append(WTFMove(inlineItem)); }
 
     InlineRuns& inlineRuns() { return m_inlineRuns; }

Added: trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp (0 => 250490)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp	                        (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.cpp	2019-09-29 15:08:41 UTC (rev 250490)
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "InlineLineLayout.h"
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "FloatingContext.h"
+#include "FloatingState.h"
+#include "InlineFormattingState.h"
+#include "LayoutBox.h"
+#include "TextUtil.h"
+
+namespace WebCore {
+namespace Layout {
+
+static LayoutUnit inlineItemWidth(const FormattingContext& formattingContext, const InlineItem& inlineItem, LayoutUnit contentLogicalLeft)
+{
+    if (inlineItem.isLineBreak())
+        return 0;
+
+    if (is<InlineTextItem>(inlineItem)) {
+        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
+        auto end = inlineTextItem.isCollapsed() ? inlineTextItem.start() + 1 : inlineTextItem.end();
+        return TextUtil::width(inlineTextItem.layoutBox(), inlineTextItem.start(), end, contentLogicalLeft);
+    }
+
+    auto& layoutBox = inlineItem.layoutBox();
+    auto& boxGeometry = formattingContext.geometryForBox(layoutBox);
+
+    if (layoutBox.isFloatingPositioned())
+        return boxGeometry.marginBoxWidth();
+
+    if (layoutBox.replaced())
+        return boxGeometry.width();
+
+    if (inlineItem.isContainerStart())
+        return boxGeometry.marginStart() + boxGeometry.borderLeft() + boxGeometry.paddingLeft().valueOr(0);
+
+    if (inlineItem.isContainerEnd())
+        return boxGeometry.marginEnd() + boxGeometry.borderRight() + boxGeometry.paddingRight().valueOr(0);
+
+    // Non-replaced inline box (e.g. inline-block)
+    return boxGeometry.width();
+}
+
+LineLayout::LineInput::LineInput(const Line::InitialConstraints& initialLineConstraints, TextAlignMode horizontalAlignment, IndexAndRange firstToProcess, const InlineItems& inlineItems)
+    : initialConstraints(initialLineConstraints)
+    , horizontalAlignment(horizontalAlignment)
+    , firstInlineItem(firstToProcess)
+    , inlineItems(inlineItems)
+{
+}
+
+LineLayout::LineInput::LineInput(const Line::InitialConstraints& initialLineConstraints, IndexAndRange firstToProcess, const InlineItems& inlineItems)
+    : initialConstraints(initialLineConstraints)
+    , skipAlignment(Line::SkipAlignment::Yes)
+    , firstInlineItem(firstToProcess)
+    , inlineItems(inlineItems)
+{
+}
+
+void LineLayout::UncommittedContent::add(const InlineItem& inlineItem, LayoutUnit logicalWidth)
+{
+    m_uncommittedRuns.append({ inlineItem, logicalWidth });
+    m_width += logicalWidth;
+}
+
+void LineLayout::UncommittedContent::reset()
+{
+    m_uncommittedRuns.clear();
+    m_width = 0;
+}
+
+LineLayout::LineLayout(const InlineFormattingContext& inlineFormattingContext, const LineInput& lineInput)
+    : m_inlineFormattingContext(inlineFormattingContext)
+    , m_lineInput(lineInput)
+    , m_line(inlineFormattingContext, lineInput.initialConstraints, lineInput.horizontalAlignment, lineInput.skipAlignment)
+    , m_lineHasIntrusiveFloat(lineInput.initialConstraints.lineIsConstrainedByFloat)
+{
+}
+
+LineLayout::LineContent LineLayout::layout()
+{
+    // Iterate through the inline content and place the inline boxes on the current line.
+    // Start with the partial text from the previous line.
+    auto firstInlineItem = m_lineInput.firstInlineItem;
+    unsigned firstNonPartialIndex = firstInlineItem.index;
+    if (firstInlineItem.partialContext) {
+        // Handle partial inline item (split text from the previous line).
+        auto& originalTextItem = m_lineInput.inlineItems[firstInlineItem.index];
+        RELEASE_ASSERT(originalTextItem->isText());
+
+        auto textRange = *firstInlineItem.partialContext;
+        // Construct a partial leading inline item.
+        ASSERT(!m_leadingPartialInlineTextItem);
+        m_leadingPartialInlineTextItem = downcast<InlineTextItem>(*originalTextItem).split(textRange.start, textRange.length);
+        if (placeInlineItem(*m_leadingPartialInlineTextItem) == IsEndOfLine::Yes)
+            return close();
+        ++firstNonPartialIndex;
+    }
+
+    for (auto inlineItemIndex = firstNonPartialIndex; inlineItemIndex < m_lineInput.inlineItems.size(); ++inlineItemIndex) {
+        if (placeInlineItem(*m_lineInput.inlineItems[inlineItemIndex]) == IsEndOfLine::Yes)
+            return close();
+    }
+    commitPendingContent();
+    return close();
+}
+
+void LineLayout::commitPendingContent()
+{
+    if (m_uncommittedContent.isEmpty())
+        return;
+    m_committedInlineItemCount += m_uncommittedContent.size();
+    for (auto& uncommittedRun : m_uncommittedContent.runs())
+        m_line.append(uncommittedRun.inlineItem, uncommittedRun.logicalWidth);
+    m_uncommittedContent.reset();
+}
+
+LineLayout::LineContent LineLayout::close()
+{
+    ASSERT(m_committedInlineItemCount || m_lineHasIntrusiveFloat);
+    if (!m_committedInlineItemCount)
+        return LineContent { WTF::nullopt, WTFMove(m_floats), m_line.close(), m_line.lineBox() };
+
+    auto lastInlineItemIndex = m_lineInput.firstInlineItem.index + m_committedInlineItemCount - 1;
+    Optional<IndexAndRange::Range> partialContext;
+    if (m_trailingPartialInlineTextItem)
+        partialContext = IndexAndRange::Range { m_trailingPartialInlineTextItem->start(), m_trailingPartialInlineTextItem->length() };
+
+    auto lastCommitedItem = IndexAndRange { lastInlineItemIndex, partialContext };
+    return LineContent { lastCommitedItem, WTFMove(m_floats), m_line.close(), m_line.lineBox() };
+}
+
+LineLayout::IsEndOfLine LineLayout::placeInlineItem(const InlineItem& inlineItem)
+{
+    auto availableWidth = m_line.availableWidth() - m_uncommittedContent.width();
+    auto currentLogicalRight = m_line.lineBox().logicalRight() + m_uncommittedContent.width();
+    auto itemLogicalWidth = inlineItemWidth(formattingContext(), inlineItem, currentLogicalRight);
+
+    // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed.
+    auto lineIsConsideredEmpty = !m_line.hasContent() && !m_lineHasIntrusiveFloat;
+    auto breakingContext = m_lineBreaker.breakingContext(inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, m_line.trailingTrimmableWidth(), lineIsConsideredEmpty });
+    if (breakingContext.isAtBreakingOpportunity)
+        commitPendingContent();
+
+    // Content does not fit the current line.
+    if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Wrap)
+        return IsEndOfLine::Yes;
+
+    // Partial content stays on the current line.
+    if (breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Split) {
+        ASSERT(inlineItem.isText());
+        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
+        auto splitData = TextUtil::split(inlineTextItem.layoutBox(), inlineTextItem.start(), inlineTextItem.length(), itemLogicalWidth, availableWidth, currentLogicalRight);
+        // Construct a partial trailing inline item.
+        ASSERT(!m_trailingPartialInlineTextItem);
+        m_trailingPartialInlineTextItem = inlineTextItem.split(splitData.start, splitData.length);
+        m_uncommittedContent.add(*m_trailingPartialInlineTextItem, splitData.logicalWidth);
+        commitPendingContent();
+        return IsEndOfLine::Yes;
+    }
+
+    ASSERT(breakingContext.breakingBehavior == LineBreaker::BreakingBehavior::Keep);
+    if (inlineItem.isFloat()) {
+        auto& floatBox = inlineItem.layoutBox();
+        // Shrink available space for current line and move existing inline runs.
+        auto floatBoxWidth = formattingContext().geometryForBox(floatBox).marginBoxWidth();
+        floatBox.isLeftFloatingPositioned() ? m_line.moveLogicalLeft(floatBoxWidth) : m_line.moveLogicalRight(floatBoxWidth);
+        m_floats.append(makeWeakPtr(inlineItem));
+        ++m_committedInlineItemCount;
+        m_lineHasIntrusiveFloat = true;
+        return IsEndOfLine::No;
+    }
+
+    m_uncommittedContent.add(inlineItem, itemLogicalWidth);
+    if (breakingContext.isAtBreakingOpportunity)
+        commitPendingContent();
+
+    return inlineItem.isHardLineBreak() ? IsEndOfLine::Yes : IsEndOfLine::No;
+}
+
+}
+}
+
+#endif

Added: trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h (0 => 250490)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h	                        (rev 0)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineLayout.h	2019-09-29 15:08:41 UTC (rev 250490)
@@ -0,0 +1,113 @@
+/*
+ * 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
+
+#if ENABLE(LAYOUT_FORMATTING_CONTEXT)
+
+#include "InlineLine.h"
+#include "InlineLineBreaker.h"
+#include <wtf/IsoMalloc.h>
+
+namespace WebCore {
+namespace Layout {
+
+class LineLayout {
+public:
+    struct LineInput;
+    LineLayout(const InlineFormattingContext&, const LineInput&);
+
+    struct LineContent;
+    LineContent layout();
+
+    struct IndexAndRange {
+        unsigned index { 0 };
+        struct Range {
+            unsigned start { 0 };
+            unsigned length { 0 };
+        };
+        Optional<Range> partialContext;
+    };
+
+    struct LineInput {
+        LineInput(const Line::InitialConstraints&, TextAlignMode, IndexAndRange firstToProcess, const InlineItems&);
+        LineInput(const Line::InitialConstraints&, IndexAndRange firstToProcess, const InlineItems&);
+
+        Line::InitialConstraints initialConstraints;
+        TextAlignMode horizontalAlignment;
+        // FIXME Alternatively we could just have a second pass with vertical positioning (preferred width computation opts out) 
+        Line::SkipAlignment skipAlignment { Line::SkipAlignment::No };
+        IndexAndRange firstInlineItem;
+        const InlineItems& inlineItems;
+        Optional<LayoutUnit> floatMinimumLogicalBottom;
+    };
+
+    struct LineContent {
+        Optional<IndexAndRange> lastCommitted;
+        Vector<WeakPtr<InlineItem>> floats;
+        const Line::RunList runList;
+        const LineBox lineBox;
+    };
+
+private:
+    const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
+    enum class IsEndOfLine { No, Yes };
+    IsEndOfLine placeInlineItem(const InlineItem&);
+    void commitPendingContent();
+    LineContent close();
+    
+    struct UncommittedContent {
+        struct Run {
+            const InlineItem& inlineItem;
+            LayoutUnit logicalWidth;
+        };
+        void add(const InlineItem&, LayoutUnit logicalWidth);
+        void reset();
+
+        Vector<Run> runs() { return m_uncommittedRuns; }
+        bool isEmpty() const { return m_uncommittedRuns.isEmpty(); }
+        unsigned size() const { return m_uncommittedRuns.size(); }
+        LayoutUnit width() const { return m_width; }
+
+    private:
+        Vector<Run> m_uncommittedRuns;
+        LayoutUnit m_width;
+    };
+
+    const InlineFormattingContext& m_inlineFormattingContext;
+    const LineInput& m_lineInput;
+    Line m_line;
+    LineBreaker m_lineBreaker;
+    bool m_lineHasIntrusiveFloat { false };
+    UncommittedContent m_uncommittedContent;
+    unsigned m_committedInlineItemCount { 0 };
+    Vector<WeakPtr<InlineItem>> m_floats;
+    std::unique_ptr<InlineTextItem> m_leadingPartialInlineTextItem;
+    std::unique_ptr<InlineTextItem> m_trailingPartialInlineTextItem;
+};
+
+}
+}
+#endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to