Title: [246483] trunk/Source/WebCore
Revision
246483
Author
[email protected]
Date
2019-06-16 13:19:24 -0700 (Sun, 16 Jun 2019)

Log Message

[LFC][IFC] Intruding float may prevent adding any inline box
https://bugs.webkit.org/show_bug.cgi?id=198891
<rdar://problem/51779956>

Reviewed by Antti Koivisto.

Take the intruding left/right float pair and find the vertical position where the next line might go
if these floats prevent us from adding even one inline box to the current line.

* layout/FormattingContext.cpp:
(WebCore::Layout::FormattingContext::mapPointToAncestor):
(WebCore::Layout::FormattingContext::mapPointToDescendent):
* layout/FormattingContext.h:
* layout/LayoutUnits.h:
(WebCore::Layout::Point::max):
* layout/inlineformatting/InlineFormattingContext.h:
* layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
(WebCore::Layout::InlineFormattingContext::LineLayout::placeInlineItems const):
(WebCore::Layout::InlineFormattingContext::LineLayout::layout const):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (246482 => 246483)


--- trunk/Source/WebCore/ChangeLog	2019-06-16 20:15:02 UTC (rev 246482)
+++ trunk/Source/WebCore/ChangeLog	2019-06-16 20:19:24 UTC (rev 246483)
@@ -1,5 +1,27 @@
 2019-06-16  Zalan Bujtas  <[email protected]>
 
+        [LFC][IFC] Intruding float may prevent adding any inline box
+        https://bugs.webkit.org/show_bug.cgi?id=198891
+        <rdar://problem/51779956>
+
+        Reviewed by Antti Koivisto.
+
+        Take the intruding left/right float pair and find the vertical position where the next line might go
+        if these floats prevent us from adding even one inline box to the current line.
+
+        * layout/FormattingContext.cpp:
+        (WebCore::Layout::FormattingContext::mapPointToAncestor):
+        (WebCore::Layout::FormattingContext::mapPointToDescendent):
+        * layout/FormattingContext.h:
+        * layout/LayoutUnits.h:
+        (WebCore::Layout::Point::max):
+        * layout/inlineformatting/InlineFormattingContext.h:
+        * layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
+        (WebCore::Layout::InlineFormattingContext::LineLayout::placeInlineItems const):
+        (WebCore::Layout::InlineFormattingContext::LineLayout::layout const):
+
+2019-06-16  Zalan Bujtas  <[email protected]>
+
         [LFC][Floats] Add bottom value to FloatingState::Constraints
         https://bugs.webkit.org/show_bug.cgi?id=198889
         <rdar://problem/51776730>

Modified: trunk/Source/WebCore/layout/FormattingContext.cpp (246482 => 246483)


--- trunk/Source/WebCore/layout/FormattingContext.cpp	2019-06-16 20:15:02 UTC (rev 246482)
+++ trunk/Source/WebCore/layout/FormattingContext.cpp	2019-06-16 20:19:24 UTC (rev 246483)
@@ -211,17 +211,28 @@
     return top;
 }
 
-Point FormattingContext::mapPointToAncestor(const LayoutState& layoutState, Point position, const Container& containingBlock, const Container& ancestor)
+Point FormattingContext::mapPointToAncestor(const LayoutState& layoutState, Point position, const Container& from, const Container& to)
 {
-    if (&containingBlock == &ancestor)
+    if (&from == &to)
         return position;
-    ASSERT(containingBlock.isContainingBlockDescendantOf(ancestor));
+    ASSERT(from.isContainingBlockDescendantOf(to));
     auto mappedPosition = position;
-    for (auto* container = &containingBlock; container && container != &ancestor; container = container->containingBlock())
+    for (auto* container = &from; container && container != &to; container = container->containingBlock())
         mappedPosition.moveBy(layoutState.displayBoxForLayoutBox(*container).topLeft());
     return mappedPosition;
 }
 
+Point FormattingContext::mapPointToDescendent(const LayoutState& layoutState, Point point, const Container& from, const Container& to)
+{
+    // "point" is in the coordinate system of the "from" container.
+    if (&from == &to)
+        return point;
+    ASSERT(to.isContainingBlockDescendantOf(from));
+    for (auto* container = &to; container && container != &from; container = container->containingBlock())
+        point.moveBy(-layoutState.displayBoxForLayoutBox(*container).topLeft());
+    return point;
+}
+
 #ifndef NDEBUG
 void FormattingContext::validateGeometryConstraintsAfterLayout() const
 {

Modified: trunk/Source/WebCore/layout/FormattingContext.h (246482 => 246483)


--- trunk/Source/WebCore/layout/FormattingContext.h	2019-06-16 20:15:02 UTC (rev 246482)
+++ trunk/Source/WebCore/layout/FormattingContext.h	2019-06-16 20:19:24 UTC (rev 246483)
@@ -62,7 +62,8 @@
     static LayoutUnit mapTopToAncestor(const LayoutState&, const Box&, const Container& ancestor);
     static LayoutUnit mapLeftToAncestor(const LayoutState&, const Box&, const Container& ancestor);
     static LayoutUnit mapRightToAncestor(const LayoutState&, const Box&, const Container& ancestor);
-    static Point mapPointToAncestor(const LayoutState&, Point, const Container& containingBlock, const Container& ancestor);
+    static Point mapPointToAncestor(const LayoutState&, Point, const Container& from, const Container& to);
+    static Point mapPointToDescendent(const LayoutState&, Point, const Container& from, const Container& to);
 
 protected:
     using LayoutQueue = Vector<const Box*>;

Modified: trunk/Source/WebCore/layout/LayoutUnits.h (246482 => 246483)


--- trunk/Source/WebCore/layout/LayoutUnits.h	2019-06-16 20:15:02 UTC (rev 246482)
+++ trunk/Source/WebCore/layout/LayoutUnits.h	2019-06-16 20:19:24 UTC (rev 246483)
@@ -59,6 +59,8 @@
     Point() = default;
     Point(LayoutUnit, LayoutUnit);
     Point(LayoutPoint);
+    static Point max() { return { LayoutUnit::max(), LayoutUnit::max() }; }
+
     void move(LayoutSize);
     void moveBy(LayoutPoint);
     operator LayoutPoint() const { return { x, y }; }

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (246482 => 246483)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2019-06-16 20:15:02 UTC (rev 246482)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2019-06-16 20:19:24 UTC (rev 246483)
@@ -79,6 +79,7 @@
             SkipVerticalAligment skipVerticalAligment;
             unsigned firstInlineItemIndex { 0 };
             const InlineItems& inlineItems;
+            Optional<LayoutUnit> floatMinimumLogicalBottom;
         };
         LineContent placeInlineItems(const LineInput&) const;
         void createDisplayRuns(const Line::Content&, const Vector<WeakPtr<InlineItem>>& floats, LayoutUnit widthConstraint) const;

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp (246482 => 246483)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp	2019-06-16 20:15:02 UTC (rev 246482)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp	2019-06-16 20:19:24 UTC (rev 246483)
@@ -161,10 +161,11 @@
         uncommittedContent.reset();
     };
 
+    auto lineHasFloatBox = lineInput.floatMinimumLogicalBottom.hasValue();
     auto closeLine = [&] {
-        // This might change at some point.
-        ASSERT(committedInlineItemCount);
-        return LineContent { lineInput.firstInlineItemIndex + (committedInlineItemCount - 1), WTFMove(floats), line->close() };
+        ASSERT(committedInlineItemCount || lineHasFloatBox);
+        auto lastCommittedIndex = committedInlineItemCount ? Optional<unsigned> { lineInput.firstInlineItemIndex + (committedInlineItemCount - 1) } : WTF::nullopt;
+        return LineContent { lastCommittedIndex, WTFMove(floats), line->close() };
     };
     LineBreaker lineBreaker;
     // Iterate through the inline content and place the inline boxes on the current line.
@@ -175,7 +176,8 @@
         auto itemLogicalWidth = inlineItemWidth(layoutState(), *inlineItem, currentLogicalRight);
 
         // FIXME: Ensure LineContext::trimmableWidth includes uncommitted content if needed.
-        auto breakingContext = lineBreaker.breakingContext(*inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, line->trailingTrimmableWidth(), !line->hasContent() });
+        auto lineIsConsideredEmpty = !line->hasContent() && !lineHasFloatBox;
+        auto breakingContext = lineBreaker.breakingContext(*inlineItem, itemLogicalWidth, { availableWidth, currentLogicalRight, line->trailingTrimmableWidth(), lineIsConsideredEmpty });
         if (breakingContext.isAtBreakingOpportunity)
             commitPendingContent();
 
@@ -200,6 +202,7 @@
             floatBox.isLeftFloatingPositioned() ? line->moveLogicalLeft(floatBoxWidth) : line->moveLogicalRight(floatBoxWidth);
             floats.append(makeWeakPtr(*inlineItem));
             ++committedInlineItemCount;
+            lineHasFloatBox = true;
             continue;
         }
 
@@ -222,12 +225,12 @@
     auto lineLogicalTop = formattingRootDisplayBox.contentBoxTop();
     auto lineLogicalLeft = formattingRootDisplayBox.contentBoxLeft();
 
-    auto applyFloatConstraint = [&](auto& lineHorizontalConstraint) {
+    auto applyFloatConstraint = [&](auto& lineInput) {
         // Check for intruding floats and adjust logical left/available width for this line accordingly.
         if (m_floatingState.isEmpty())
             return;
-        auto availableWidth = lineHorizontalConstraint.availableLogicalWidth;
-        auto lineLogicalLeft = lineHorizontalConstraint.logicalTopLeft.x();
+        auto availableWidth = lineInput.horizontalConstraint.availableLogicalWidth;
+        auto lineLogicalLeft = lineInput.horizontalConstraint.logicalTopLeft.x();
         auto floatConstraints = m_floatingState.constraints({ lineLogicalTop }, m_formattingRoot);
         // Check if these constraints actually put limitation on the line.
         if (floatConstraints.left && floatConstraints.left->x <= formattingRootDisplayBox.contentBoxLeft())
@@ -236,20 +239,26 @@
         if (floatConstraints.right && floatConstraints.right->x >= formattingRootDisplayBox.contentBoxRight())
             floatConstraints.right = { };
 
+        // Set the minimum float bottom value as a hint for the next line if needed.
+        static auto inifitePoint = PointInContextRoot::max();
+        auto floatMinimumLogicalBottom = std::min(floatConstraints.left.valueOr(inifitePoint).y, floatConstraints.right.valueOr(inifitePoint).y);
+        if (floatMinimumLogicalBottom != inifitePoint.y)
+            lineInput.floatMinimumLogicalBottom = floatMinimumLogicalBottom;
+
         if (floatConstraints.left && floatConstraints.right) {
-            ASSERT(floatConstraints.left->x < floatConstraints.right->x);
+            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);
+            ASSERT(floatConstraints.left->x >= lineLogicalLeft);
             availableWidth -= (floatConstraints.left->x - lineLogicalLeft);
             lineLogicalLeft = floatConstraints.left->x;
         } else if (floatConstraints.right) {
-            ASSERT(floatConstraints.right->x > lineLogicalLeft);
+            ASSERT(floatConstraints.right->x >= lineLogicalLeft);
             availableWidth = floatConstraints.right->x - lineLogicalLeft;
         }
-        lineHorizontalConstraint.availableLogicalWidth = availableWidth;
-        lineHorizontalConstraint.logicalTopLeft.setX(lineLogicalLeft);
+        lineInput.horizontalConstraint.availableLogicalWidth = availableWidth;
+        lineInput.horizontalConstraint.logicalTopLeft.setX(lineLogicalLeft);
     };
 
     auto& inlineItems = m_formattingState.inlineItems();
@@ -256,13 +265,18 @@
     unsigned currentInlineItemIndex = 0;
     while (currentInlineItemIndex < inlineItems.size()) {
         auto lineInput = LineInput { { lineLogicalLeft, lineLogicalTop }, widthConstraint, LineInput::SkipVerticalAligment::No, currentInlineItemIndex, inlineItems };
-        applyFloatConstraint(lineInput.horizontalConstraint);
+        applyFloatConstraint(lineInput);
         auto lineContent = placeInlineItems(lineInput);
         createDisplayRuns(*lineContent.runs, lineContent.floats, widthConstraint);
-        // We should always put at least one run on the line atm. This might change later on though.
-        ASSERT(lineContent.lastInlineItemIndex);
-        currentInlineItemIndex = *lineContent.lastInlineItemIndex + 1;
-        lineLogicalTop = lineContent.runs->logicalBottom();
+        if (!lineContent.lastInlineItemIndex) {
+            // Floats prevented us putting any content on the line.
+            ASSERT(lineInput.floatMinimumLogicalBottom);
+            ASSERT(lineContent.runs->isEmpty());
+            lineLogicalTop = *lineInput.floatMinimumLogicalBottom;
+        } else {
+            currentInlineItemIndex = *lineContent.lastInlineItemIndex + 1;
+            lineLogicalTop = lineContent.runs->logicalBottom();
+        }
     }
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to