Title: [270429] trunk/Source/WebCore
Revision
270429
Author
[email protected]
Date
2020-12-04 05:48:09 -0800 (Fri, 04 Dec 2020)

Log Message

[LFC][IFC] Float positioning needs to happen while building the line
https://bugs.webkit.org/show_bug.cgi?id=219523

Reviewed by Antti Koivisto.

This patch is in preparation for cases when the float may fit the line and we assume it's intrusive but due to e.g. "clear"
it is not intersecting the line at all.
In order to figure out whether the float boxes intersect the current line, we need to compute their position as we find them.
In this patch the float positioning logic is moved over to LineBuilder (from the line post-processing) and floats are added
to the FloatingState as we encounter them while building the line.

* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::lineLayout):
(WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):
(WebCore::Layout::InlineFormattingContext::computeGeometryForLineContent):
* layout/inlineformatting/InlineFormattingContext.h:
* layout/inlineformatting/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::LineBuilder):
(WebCore::Layout::LineBuilder::layoutInlineContent):
(WebCore::Layout::LineBuilder::computedIntrinsicWidth):
(WebCore::Layout::LineBuilder::initialize):
(WebCore::Layout::LineBuilder::constraintsForLine):
(WebCore::Layout::LineBuilder::handleFloatContent):
* layout/inlineformatting/InlineLineBuilder.h:
(WebCore::Layout::LineBuilder::formattingState):
(WebCore::Layout::LineBuilder::floatingState):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (270428 => 270429)


--- trunk/Source/WebCore/ChangeLog	2020-12-04 13:35:23 UTC (rev 270428)
+++ trunk/Source/WebCore/ChangeLog	2020-12-04 13:48:09 UTC (rev 270429)
@@ -1,5 +1,34 @@
 2020-12-04  Zalan Bujtas  <[email protected]>
 
+        [LFC][IFC] Float positioning needs to happen while building the line
+        https://bugs.webkit.org/show_bug.cgi?id=219523
+
+        Reviewed by Antti Koivisto.
+
+        This patch is in preparation for cases when the float may fit the line and we assume it's intrusive but due to e.g. "clear"
+        it is not intersecting the line at all.
+        In order to figure out whether the float boxes intersect the current line, we need to compute their position as we find them.
+        In this patch the float positioning logic is moved over to LineBuilder (from the line post-processing) and floats are added
+        to the FloatingState as we encounter them while building the line.
+
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::lineLayout):
+        (WebCore::Layout::InlineFormattingContext::computedIntrinsicWidthForConstraint const):
+        (WebCore::Layout::InlineFormattingContext::computeGeometryForLineContent):
+        * layout/inlineformatting/InlineFormattingContext.h:
+        * layout/inlineformatting/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineBuilder::LineBuilder):
+        (WebCore::Layout::LineBuilder::layoutInlineContent):
+        (WebCore::Layout::LineBuilder::computedIntrinsicWidth):
+        (WebCore::Layout::LineBuilder::initialize):
+        (WebCore::Layout::LineBuilder::constraintsForLine):
+        (WebCore::Layout::LineBuilder::handleFloatContent):
+        * layout/inlineformatting/InlineLineBuilder.h:
+        (WebCore::Layout::LineBuilder::formattingState):
+        (WebCore::Layout::LineBuilder::floatingState):
+
+2020-12-04  Zalan Bujtas  <[email protected]>
+
         Web process assert when loading slack
         https://bugs.webkit.org/show_bug.cgi?id=219079
         <rdar://problem/71814675>

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (270428 => 270429)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2020-12-04 13:35:23 UTC (rev 270428)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2020-12-04 13:48:09 UTC (rev 270429)
@@ -149,10 +149,11 @@
         size_t overflowContentLength { 0 };
     };
     Optional<PreviousLine> previousLine;
-    auto floatingContext = FloatingContext { *this, formattingState().floatingState() };
+    auto& floatingState = formattingState().floatingState();
+    auto floatingContext = FloatingContext { *this, floatingState };
     auto isFirstLine = formattingState().lines().isEmpty();
 
-    auto lineBuilder = LineBuilder { *this, floatingContext, inlineItems };
+    auto lineBuilder = LineBuilder { *this, floatingState, constraints.horizontal, inlineItems };
     while (!needsLayoutRange.isEmpty()) {
         // Turn previous line's overflow content length into the next line's leading content partial length.
         // "sp[<-line break->]lit_content" -> overflow length: 11 -> leading partial content length: 11.
@@ -261,19 +262,19 @@
 InlineLayoutUnit InlineFormattingContext::computedIntrinsicWidthForConstraint(InlineLayoutUnit availableWidth) const
 {
     auto& inlineItems = formattingState().inlineItems();
-    // Preferred width computation is not constrained by floats. 
-    auto floatingState = FloatingState::create(layoutState(), root());
-    auto floatingContext = FloatingContext { *this, floatingState };
-    auto lineBuilder = LineBuilder { *this, floatingContext, inlineItems };
+    auto lineBuilder = LineBuilder { *this, inlineItems };
     auto layoutRange = LineBuilder::InlineItemRange { 0 , inlineItems.size() };
     auto maximumLineWidth = InlineLayoutUnit { };
+    auto maximumFloatWidth = LayoutUnit { };
     while (!layoutRange.isEmpty()) {
         auto intrinsicContent = lineBuilder.computedIntrinsicWidth(layoutRange, availableWidth);
         layoutRange.start = intrinsicContent.inlineItemRange.end;
-        // FIXME: Use line logical left and right to take floats into account.
         maximumLineWidth = std::max(maximumLineWidth, intrinsicContent.logicalWidth);
+        // FIXME: Add support for clear.
+        for (auto* floatBox : intrinsicContent.floats)
+            maximumFloatWidth += geometryForBox(*floatBox).marginBoxWidth();
     }
-    return maximumLineWidth;
+    return maximumLineWidth + maximumFloatWidth;
 }
 
 void InlineFormattingContext::computeIntrinsicWidthForFormattingRoot(const Box& formattingRoot)
@@ -414,23 +415,6 @@
     const auto& lineBox = formattingState.lineBoxes().last();
     auto& lineBoxLogicalRect = lineBox.logicalRect();
 
-    auto updateFloatGeometry = [&] {
-        if (lineContent.floats.isEmpty())
-            return;
-        auto& floatingState = formattingState.floatingState();
-        auto floatingContext = FloatingContext { *this, floatingState };
-        // Move floats to their final position.
-        for (auto* floatBox : lineContent.floats) {
-            auto& boxGeometry = formattingState.boxGeometry(*floatBox);
-            // Set static position first.
-            boxGeometry.setLogicalTopLeft({ lineBoxLogicalRect.left(), lineBoxLogicalRect.top() });
-            // Float it.
-            boxGeometry.setLogicalTopLeft(floatingContext.positionForFloat(*floatBox, horizontalConstraints));
-            floatingState.append(floatingContext.toFloatItem(*floatBox));
-        }
-    };
-    updateFloatGeometry();
-
     auto constructLineRuns = [&] {
         auto lineIndex = formattingState.lines().size();
         // Create the inline runs on the current line. This is mostly text and atomic inline runs.

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (270428 => 270429)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2020-12-04 13:35:23 UTC (rev 270428)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2020-12-04 13:48:09 UTC (rev 270429)
@@ -61,6 +61,9 @@
     };
     InlineFormattingContext::Quirks quirks() const { return Quirks(*this); }
 
+    const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
+    InlineFormattingState& formattingState() { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
+
 private:
     IntrinsicWidthConstraints computedIntrinsicWidthConstraints() override;
 
@@ -93,9 +96,6 @@
     void collectInlineContentIfNeeded();
     InlineRect computeGeometryForLineContent(const LineBuilder::LineContent&, const HorizontalConstraints&);
     void invalidateFormattingState(const InvalidationState&);
-
-    const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
-    InlineFormattingState& formattingState() { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }
 };
 
 inline InlineFormattingContext::Geometry::Geometry(const InlineFormattingContext& inlineFormattingContext)

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (270428 => 270429)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2020-12-04 13:35:23 UTC (rev 270428)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2020-12-04 13:48:09 UTC (rev 270429)
@@ -230,14 +230,23 @@
     return boxGeometry.marginBoxWidth();
 }
 
-LineBuilder::LineBuilder(const InlineFormattingContext& inlineFormattingContext, const FloatingContext& floatingContext, const InlineItems& inlineItems)
+LineBuilder::LineBuilder(InlineFormattingContext& inlineFormattingContext, FloatingState& floatingState, HorizontalConstraints rootHorizontalConstraints, const InlineItems& inlineItems)
     : m_inlineFormattingContext(inlineFormattingContext)
-    , m_floatingContext(floatingContext)
+    , m_inlineFormattingState(&inlineFormattingContext.formattingState())
+    , m_floatingState(&floatingState)
+    , m_rootHorizontalConstraints(rootHorizontalConstraints)
     , m_line(inlineFormattingContext)
     , m_inlineItems(inlineItems)
 {
 }
 
+LineBuilder::LineBuilder(const InlineFormattingContext& inlineFormattingContext, const InlineItems& inlineItems)
+    : m_inlineFormattingContext(inlineFormattingContext)
+    , m_line(inlineFormattingContext)
+    , m_inlineItems(inlineItems)
+{
+}
+
 LineBuilder::LineContent LineBuilder::layoutInlineContent(const InlineItemRange& needsLayoutRange, size_t partialLeadingContentLength, const InlineRect& initialConstraintsForLine, bool isFirstLine)
 {
     auto usedConstraints = constraintsForLine(initialConstraintsForLine, isFirstLine);
@@ -246,7 +255,7 @@
     auto committedContent = placeInlineContent(needsLayoutRange, partialLeadingContentLength);
     auto committedRange = close(needsLayoutRange, committedContent);
 
-    auto lineLogicalTopLeft = InlineLayoutPoint { usedConstraints.logicalLeft, initialConstraintsForLine.top() };
+    auto lineLogicalTopLeft = usedConstraints.logicalTopLeft;
     auto isLastLine = isLastLineWithInlineContent(committedRange, needsLayoutRange.end, committedContent.partialTrailingContentLength);
     return LineContent { committedRange, committedContent.partialTrailingContentLength, m_floats, m_contentIsConstrainedByFloat
         , lineLogicalTopLeft
@@ -262,7 +271,7 @@
     initialize({ { }, availableWidth, false });
     auto committedContent = placeInlineContent(needsLayoutRange, { });
     auto committedRange = close(needsLayoutRange, committedContent);
-    return { committedRange, m_line.contentLogicalWidth() };
+    return { committedRange, m_line.contentLogicalWidth(), m_floats };
 }
 
 void LineBuilder::initialize(const UsedConstraints& lineConstraints)
@@ -274,6 +283,7 @@
     m_line.initialize();
     m_contentIsConstrainedByFloat = lineConstraints.isConstrainedByFloat;
     m_horizontalSpaceForLine = lineConstraints.logicalWidth; 
+    m_lineLogicalTopLeft = lineConstraints.logicalTopLeft;
 }
 
 LineBuilder::CommittedContent LineBuilder::placeInlineContent(const InlineItemRange& needsLayoutRange, size_t partialLeadingContentLength)
@@ -360,28 +370,31 @@
     auto lineIsConstrainedByFloat = false;
 
     // Check for intruding floats and adjust logical left/available width for this line accordingly.
-    if (!m_floatingContext.isEmpty()) {
-        // FIXME: Add support for variable line height, where the floats should be probed as the line height grows.
-        auto floatConstraints = m_floatingContext.constraints(toLayoutUnit(lineLogicalTop), toLayoutUnit(lineLogicalTop + lineLogicalConstraints.height()));
-        // Check if these values actually constrain the line.
-        if (floatConstraints.left && floatConstraints.left->x <= lineLogicalLeft)
-            floatConstraints.left = { };
+    if (auto* floatingState = this->floatingState()) {
+        auto floatingContext = FloatingContext { formattingContext(), *floatingState };
+        if (!floatingContext.isEmpty()) {
+            // FIXME: Add support for variable line height, where the floats should be probed as the line height grows.
+            auto floatConstraints = floatingContext.constraints(toLayoutUnit(lineLogicalTop), toLayoutUnit(lineLogicalTop + lineLogicalConstraints.height()));
+            // Check if these values actually constrain the line.
+            if (floatConstraints.left && floatConstraints.left->x <= lineLogicalLeft)
+                floatConstraints.left = { };
 
-        if (floatConstraints.right && floatConstraints.right->x >= lineLogicalRight)
-            floatConstraints.right = { };
+            if (floatConstraints.right && floatConstraints.right->x >= lineLogicalRight)
+                floatConstraints.right = { };
 
-        lineIsConstrainedByFloat = floatConstraints.left || floatConstraints.right;
+            lineIsConstrainedByFloat = floatConstraints.left || floatConstraints.right;
 
-        if (floatConstraints.left && floatConstraints.right) {
-            ASSERT(floatConstraints.left->x <= floatConstraints.right->x);
-            lineLogicalRight = floatConstraints.right->x;
-            lineLogicalLeft = floatConstraints.left->x;
-        } else if (floatConstraints.left) {
-            ASSERT(floatConstraints.left->x >= lineLogicalLeft);
-            lineLogicalLeft = floatConstraints.left->x;
-        } else if (floatConstraints.right) {
-            // Right float boxes may overflow the containing block on the left.
-            lineLogicalRight = std::max<InlineLayoutUnit>(lineLogicalLeft, floatConstraints.right->x);
+            if (floatConstraints.left && floatConstraints.right) {
+                ASSERT(floatConstraints.left->x <= floatConstraints.right->x);
+                lineLogicalRight = floatConstraints.right->x;
+                lineLogicalLeft = floatConstraints.left->x;
+            } else if (floatConstraints.left) {
+                ASSERT(floatConstraints.left->x >= lineLogicalLeft);
+                lineLogicalLeft = floatConstraints.left->x;
+            } else if (floatConstraints.right) {
+                // Right float boxes may overflow the containing block on the left.
+                lineLogicalRight = std::max<InlineLayoutUnit>(lineLogicalLeft, floatConstraints.right->x);
+            }
         }
     }
 
@@ -423,7 +436,7 @@
         return { minimumValueForLength(textIndent, lineLogicalConstraints.width()) };
     };
     lineLogicalLeft += computedTextIndent();
-    return UsedConstraints { lineLogicalLeft, lineLogicalRight - lineLogicalLeft, lineIsConstrainedByFloat };
+    return UsedConstraints { { lineLogicalLeft, lineLogicalTop }, lineLogicalRight - lineLogicalLeft, lineIsConstrainedByFloat };
 }
 
 void LineBuilder::candidateContentForLine(LineCandidate& lineCandidate, size_t currentInlineItemIndex, const InlineItemRange& layoutRange, size_t partialLeadingContentLength, InlineLayoutUnit currentLogicalRight)
@@ -539,6 +552,20 @@
     auto& floatBox = floatItem.layoutBox();
     m_floats.append(&floatBox);
     m_contentIsConstrainedByFloat = true;
+
+    if (auto* floatingState = this->floatingState()) {
+        ASSERT(formattingState());
+        auto& boxGeometry = formattingState()->boxGeometry(floatBox);
+        // Set static position first.
+        boxGeometry.setLogicalTopLeft(LayoutPoint { m_lineLogicalTopLeft });
+        // Float it.
+        ASSERT(m_rootHorizontalConstraints);
+        auto floatingContext = FloatingContext { formattingContext(), *floatingState };
+        auto floatingPosition = floatingContext.positionForFloat(floatBox, *m_rootHorizontalConstraints);
+        boxGeometry.setLogicalTopLeft(floatingPosition);
+        floatingState->append(floatingContext.toFloatItem(floatBox));
+    }
+
     if (floatBox.isLeftFloatingPositioned())
         m_line.moveLogicalLeft(floatBoxWidth);
     m_horizontalSpaceForLine -= floatBoxWidth;

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (270428 => 270429)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2020-12-04 13:35:23 UTC (rev 270428)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2020-12-04 13:48:09 UTC (rev 270429)
@@ -39,7 +39,8 @@
 
 class LineBuilder {
 public:
-    LineBuilder(const InlineFormattingContext&, const FloatingContext&, const InlineItems&);
+    LineBuilder(InlineFormattingContext&, FloatingState&, HorizontalConstraints rootHorizontalConstraints, const InlineItems&);
+    LineBuilder(const InlineFormattingContext&, const InlineItems&);
 
     struct InlineItemRange {
         bool isEmpty() const { return start == end; }
@@ -47,10 +48,10 @@
         size_t start { 0 };
         size_t end { 0 };
     };
+    using FloatList = Vector<const Box*>;
     struct LineContent {
         InlineItemRange inlineItemRange;
         size_t partialTrailingContentLength { 0 };
-        using FloatList = Vector<const Box*>;
         const FloatList& floats;
         bool hasIntrusiveFloat { false };
         InlineLayoutPoint logicalTopLeft;
@@ -65,6 +66,7 @@
     struct IntrinsicContent {
         InlineItemRange inlineItemRange;
         InlineLayoutUnit logicalWidth { 0 };
+        const FloatList& floats;
     };
     IntrinsicContent computedIntrinsicWidth(const InlineItemRange&, InlineLayoutUnit availableWidth);
 
@@ -82,7 +84,7 @@
         size_t partialTrailingContentLength { 0 };
     };
     struct UsedConstraints {
-        InlineLayoutUnit logicalLeft { 0 };
+        InlineLayoutPoint logicalTopLeft;
         InlineLayoutUnit logicalWidth { 0 };
         bool isConstrainedByFloat { false };
     };
@@ -104,15 +106,21 @@
     bool isLastLineWithInlineContent(const InlineItemRange& lineRange, size_t lastInlineItemIndex, bool hasPartialTrailingContent) const;
 
     const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
+    InlineFormattingState* formattingState() { return m_inlineFormattingState; }
+    FloatingState* floatingState() { return m_floatingState; }
     const ContainerBox& root() const;
     const LayoutState& layoutState() const;
 
     const InlineFormattingContext& m_inlineFormattingContext;
-    const FloatingContext& m_floatingContext;
+    InlineFormattingState* m_inlineFormattingState { nullptr };
+    FloatingState* m_floatingState { nullptr };
+    Optional<HorizontalConstraints> m_rootHorizontalConstraints;
+
     Line m_line;
+    InlineLayoutPoint m_lineLogicalTopLeft;
     InlineLayoutUnit m_horizontalSpaceForLine { 0 };
     const InlineItems& m_inlineItems;
-    LineContent::FloatList m_floats;
+    FloatList m_floats;
     Optional<InlineTextItem> m_partialLeadingTextItem;
     Vector<const InlineItem*> m_wrapOpportunityList;
     unsigned m_successiveHyphenatedLineCount { 0 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to