Title: [253948] trunk/Source/WebCore
Revision
253948
Author
[email protected]
Date
2019-12-30 10:25:36 -0800 (Mon, 30 Dec 2019)

Log Message

[LFC][IFC] Fix imported/w3c/web-platform-tests/css/css-text/white-space/white-space-wrap-after-nowrap-001.html
https://bugs.webkit.org/show_bug.cgi?id=205633
<rdar://problem/58234239>

Reviewed by Antti Koivisto.

When the LineBreaker comes back with Action::Revert (meaning that the line
needs to be reverted back to an earlier line wrap opportunity), call LineBuilder::revert and
close the line.

* layout/inlineformatting/InlineLineBreaker.cpp:
(WebCore::Layout::LineBreaker::tryWrappingInlineContent const): Return push when the current content can be wrapped.
(WebCore::Layout::ContinousContent::ContinousContent):
(WebCore::Layout::ContinousContent::lastWrapOpportunityIndex const): Fix the last position logic.
* layout/inlineformatting/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::revert):
(WebCore::Layout::LineBuilder::collectHangingContent):
* layout/inlineformatting/InlineLineBuilder.h:
* layout/inlineformatting/LineLayoutContext.cpp:
(WebCore::Layout::endsWithSoftWrapOpportunity):
(WebCore::Layout::LineLayoutContext::layoutLine):
(WebCore::Layout::LineLayoutContext::tryAddingFloatItems):
(WebCore::Layout::LineLayoutContext::tryAddingInlineItems):
(WebCore::Layout::LineLayoutContext::addFloatItems): Deleted.
(WebCore::Layout::LineLayoutContext::checkForLineWrapAndCommit): Deleted.
* layout/inlineformatting/LineLayoutContext.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (253947 => 253948)


--- trunk/Source/WebCore/ChangeLog	2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/ChangeLog	2019-12-30 18:25:36 UTC (rev 253948)
@@ -1,3 +1,32 @@
+2019-12-30  Zalan Bujtas  <[email protected]>
+
+        [LFC][IFC] Fix imported/w3c/web-platform-tests/css/css-text/white-space/white-space-wrap-after-nowrap-001.html
+        https://bugs.webkit.org/show_bug.cgi?id=205633
+        <rdar://problem/58234239>
+
+        Reviewed by Antti Koivisto.
+
+        When the LineBreaker comes back with Action::Revert (meaning that the line
+        needs to be reverted back to an earlier line wrap opportunity), call LineBuilder::revert and
+        close the line.
+
+        * layout/inlineformatting/InlineLineBreaker.cpp:
+        (WebCore::Layout::LineBreaker::tryWrappingInlineContent const): Return push when the current content can be wrapped.
+        (WebCore::Layout::ContinousContent::ContinousContent):
+        (WebCore::Layout::ContinousContent::lastWrapOpportunityIndex const): Fix the last position logic.
+        * layout/inlineformatting/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineBuilder::revert):
+        (WebCore::Layout::LineBuilder::collectHangingContent):
+        * layout/inlineformatting/InlineLineBuilder.h:
+        * layout/inlineformatting/LineLayoutContext.cpp:
+        (WebCore::Layout::endsWithSoftWrapOpportunity):
+        (WebCore::Layout::LineLayoutContext::layoutLine):
+        (WebCore::Layout::LineLayoutContext::tryAddingFloatItems):
+        (WebCore::Layout::LineLayoutContext::tryAddingInlineItems):
+        (WebCore::Layout::LineLayoutContext::addFloatItems): Deleted.
+        (WebCore::Layout::LineLayoutContext::checkForLineWrapAndCommit): Deleted.
+        * layout/inlineformatting/LineLayoutContext.h:
+
 2019-12-30  youenn fablet  <[email protected]>
 
         Ignore URL host for schemes that are not using host information

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp (253947 => 253948)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp	2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBreaker.cpp	2019-12-30 18:25:36 UTC (rev 253948)
@@ -138,7 +138,7 @@
             return { Result::Action::Keep, IsEndOfLine };
         // Now check if we can trim the line too.
         if (lineStatus.lineHasFullyCollapsibleTrailingRun && candidateContent.isTrailingContentFullyCollapsible()) {
-            // If this new content is fully collapsible, it shoud surely fit.
+            // If this new content is fully collapsible, it should surely fit.
             return { Result::Action::Keep, IsEndOfLine };
         }
     } else if (lineStatus.collapsibleWidth && candidateContent.hasNonContentRunsOnly()) {
@@ -148,7 +148,7 @@
             return { Result::Action::Keep };
     }
     if (candidateContent.isVisuallyEmptyWhitespaceContentOnly() && shouldKeepEndOfLineWhitespace(candidateContent)) {
-        // This overflowing content apparently falls into the remove/hang end-of-line-spaces catergory.
+        // This overflowing content apparently falls into the remove/hang end-of-line-spaces category.
         // see https://www.w3.org/TR/css-text-3/#white-space-property matrix
         return { Result::Action::Keep };
     }
@@ -175,14 +175,17 @@
             return { Result::Action::Split, IsEndOfLine::Yes, splitContent };
         }
     }
-    // If we are not allowed to break this content, we still need to decide whether keep it or push it to the next line.
+    // If we are not allowed to break this overflowing content, we still need to decide whether keep it or push it to the next line.
     if (lineStatus.lineIsEmpty) {
         ASSERT(!m_lastWrapOpportunity);
-        return { Result::Action::Keep, IsEndOfLine::Yes };
+        return { Result::Action::Keep, IsEndOfLine::No };
     }
+    // Now either wrap here or at an earlier position, or not wrap at all.
+    if (isContentWrappingAllowed(candidateContent))
+        return { Result::Action::Push, IsEndOfLine::Yes };
     if (m_lastWrapOpportunity)
         return { Result::Action::Revert, IsEndOfLine::Yes, { }, m_lastWrapOpportunity };
-    return { Result::Action::Keep, isContentWrappingAllowed(candidateContent) ? IsEndOfLine::Yes : IsEndOfLine::No };
+    return { Result::Action::Keep, IsEndOfLine::No };
 }
 
 bool LineBreaker::shouldWrapFloatBox(InlineLayoutUnit floatLogicalWidth, InlineLayoutUnit availableWidth, bool lineIsEmpty)
@@ -354,7 +357,7 @@
                 m_trailingCollapsibleContent.width += collapsibleWidth;
                 m_trailingCollapsibleContent.isFullyCollapsible = false;
             }
-            // End of whitspace content.
+            // End of whitespace content.
             break;
         }
     }
@@ -427,14 +430,13 @@
 
 Optional<size_t> ContinousContent::lastWrapOpportunityIndex() const
 {
-    // <span style="white-space: pre">no_wrap</span><span>yes_wrap</span><span style="white-space: pre">no_wrap</span>.
-    // [container start][no_wrap][container end][container start][yes_wrap][container end][container start][no_wrap][container end]
-    // Return #5 as the index where this content can wrap at last.
-    for (auto index = m_runs.size(); index--;) {
-        if (isWrappingAllowed(m_runs[index].inlineItem.style()))
-            return index;
-    }
-    return { };
+    // <span style="white-space: pre">no_wrap</span><span>yes wrap</span><span style="white-space: pre">no_wrap</span>.
+    // [container start][no_wrap][container end][container start][yes] <- continuous content
+    // [ ] <- continuous content
+    // [wrap][container end][container start][no_wrap][container end] <- continuous content
+    // Return #0 as the index where the second continuous content can wrap at.
+    auto lastItemIndex = m_runs.size() - 1;
+    return isWrappingAllowed(m_runs[lastItemIndex].inlineItem.style()) ? makeOptional(lastItemIndex) : WTF::nullopt;
 }
 
 void ContinousContent::TrailingCollapsibleContent::reset()

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (253947 => 253948)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2019-12-30 18:25:36 UTC (rev 253948)
@@ -263,14 +263,19 @@
     return runList;
 }
 
-void LineBuilder::revert(const InlineItem& revertTo)
+size_t LineBuilder::revert(const InlineItem& revertTo)
 {
+    if (m_inlineItemRuns.last() == revertTo) {
+        // Since the LineBreaker does not know what has been pushed on the current line
+        // in some cases revert() is called with the last item on the line.
+        return { };
+    }
     // 1. Remove and shrink the trailing content.
     // 2. Rebuild collapsible trailing whitespace content.
     ASSERT(!m_inlineItemRuns.isEmpty());
-    ASSERT(m_inlineItemRuns.last() != revertTo);
     auto revertedWidth = InlineLayoutUnit { };
-    int64_t index = static_cast<int64_t>(m_inlineItemRuns.size() - 1);
+    auto originalSize = m_inlineItemRuns.size();
+    int64_t index = static_cast<int64_t>(originalSize - 1);
     while (index >= 0 && m_inlineItemRuns[index] != revertTo)
         revertedWidth += m_inlineItemRuns[index--].logicalWidth();
     m_lineBox.shrinkHorizontally(revertedWidth);
@@ -310,7 +315,8 @@
             m_collapsibleContent.append(index);
         }
     }
-    // Consider alternative solutions if the (edge case)revert gets overly complicated.  
+    // Consider alternative solutions if the (edge case)revert gets overly complicated.
+    return originalSize - m_inlineItemRuns.size();
 }
 
 void LineBuilder::alignContentVertically(RunList& runList)
@@ -482,7 +488,7 @@
 HangingContent LineBuilder::collectHangingContent(IsLastLineWithInlineContent isLastLineWithInlineContent)
 {
     auto hangingContent = HangingContent { };
-    // Can't setup hanging content with removable trailing whitspaces.
+    // Can't setup hanging content with removable trailing whitespace.
     ASSERT(m_collapsibleContent.isEmpty());
     if (isLastLineWithInlineContent == IsLastLineWithInlineContent::Yes)
         hangingContent.setIsConditional();

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (253947 => 253948)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2019-12-30 18:25:36 UTC (rev 253948)
@@ -115,7 +115,7 @@
     using RunList = Vector<Run, 50>;
     enum class IsLastLineWithInlineContent { No, Yes };
     RunList close(IsLastLineWithInlineContent = IsLastLineWithInlineContent::No);
-    void revert(const InlineItem& revertTo);
+    size_t revert(const InlineItem& revertTo);
 
     static Display::LineBox::Baseline halfLeadingMetrics(const FontMetrics&, InlineLayoutUnit lineLogicalHeight);
 

Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp (253947 => 253948)


--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp	2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp	2019-12-30 18:25:36 UTC (rev 253948)
@@ -44,7 +44,7 @@
     // they are split at a soft breaking opportunity. See InlineTextItem::moveToNextBreakablePosition.
     if (&currentTextItem.layoutBox() == &nextInlineTextItem.layoutBox())
         return true;
-    // Now we need to collect at least 3 adjacent characters to be able to make a descision whether the previous text item ends with breaking opportunity.
+    // Now we need to collect at least 3 adjacent characters to be able to make a decision whether the previous text item ends with breaking opportunity.
     // [ex-][ample] <- second to last[x] last[-] current[a]
     // We need at least 1 character in the current inline text item and 2 more from previous inline items.
     auto previousContent = currentTextItem.layoutBox().textContext()->content;
@@ -269,9 +269,9 @@
         }
         if (candidateContent.hasIntrusiveFloats()) {
             // Add floats first because they shrink the available horizontal space for the rest of the content.
-            auto floatContent = addFloatItems(line, candidateContent.floats());
-            committedInlineItemCount += floatContent.count;
-            if (floatContent.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
+            auto result = tryAddingFloatItems(line, candidateContent.floats());
+            committedInlineItemCount += result.committedCount;
+            if (result.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
                 // Floats take up all the horizontal space.
                 return close(line, leadingInlineItemIndex, committedInlineItemCount, { });
             }
@@ -278,11 +278,17 @@
         }
         if (!candidateContent.runs().isEmpty()) {
             // Now check if we can put this content on the current line.
-            auto committedContent = checkForLineWrapAndCommit(lineBreaker, line, candidateContent.runs());
-            committedInlineItemCount += committedContent.count;
-            if (committedContent.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
+            auto result = tryAddingInlineItems(lineBreaker, line, candidateContent.runs());
+            if (result.revertTo) {
+                ASSERT(!result.committedCount);
+                ASSERT(result.isEndOfLine == LineBreaker::IsEndOfLine::Yes);
+                // An earlier line wrapping opportunity turned out to be the final breaking position.
+                committedInlineItemCount -= line.revert(*result.revertTo);
+            }
+            committedInlineItemCount += result.committedCount;
+            if (result.isEndOfLine == LineBreaker::IsEndOfLine::Yes) {
                 // We can't place any more items on the current line.
-                return close(line, leadingInlineItemIndex, committedInlineItemCount, committedContent.partialContent);
+                return close(line, leadingInlineItemIndex, committedInlineItemCount, result.partialContent);
             }
         }
         currentItemIndex = leadingInlineItemIndex + committedInlineItemCount;
@@ -366,7 +372,7 @@
     return candidateContent;
 }
 
-LineLayoutContext::CommittedContent LineLayoutContext::addFloatItems(LineBuilder& line, const FloatList& floats)
+LineLayoutContext::Result LineLayoutContext::tryAddingFloatItems(LineBuilder& line, const FloatList& floats)
 {
     size_t committedFloatItemCount = 0;
     for (auto& floatItem : floats) {
@@ -374,7 +380,7 @@
 
         auto lineIsConsideredEmpty = line.isVisuallyEmpty() && !line.hasIntrusiveFloat();
         if (LineBreaker().shouldWrapFloatBox(logicalWidth, line.availableWidth() + line.trailingCollapsibleWidth(), lineIsConsideredEmpty))
-            return { LineBreaker::IsEndOfLine::Yes, committedFloatItemCount, { } };
+            return { LineBreaker::IsEndOfLine::Yes, committedFloatItemCount };
         // This float can sit on the current line.
         ++committedFloatItemCount;
         auto& floatBox = floatItem->layoutBox();
@@ -386,10 +392,10 @@
             line.moveLogicalRight(logicalWidth);
         m_floats.append(floatItem);
     }
-    return { LineBreaker::IsEndOfLine::No, committedFloatItemCount, { } };
+    return { LineBreaker::IsEndOfLine::No, committedFloatItemCount };
 }
 
-LineLayoutContext::CommittedContent LineLayoutContext::checkForLineWrapAndCommit(LineBreaker& lineBreaker, LineBuilder& line, const LineBreaker::RunList& candidateRuns)
+LineLayoutContext::Result LineLayoutContext::tryAddingInlineItems(LineBreaker& lineBreaker, LineBuilder& line, const LineBreaker::RunList& candidateRuns)
 {
     auto shouldDisableHyphenation = [&] {
         auto& style = root().style();
@@ -406,15 +412,15 @@
     if (result.action == LineBreaker::Result::Action::Keep) {
         // This continuous content can be fully placed on the current line.
         commitContent(line, candidateRuns, { });
-        return { result.isEndOfLine, candidateRuns.size(), { } };
+        return { result.isEndOfLine, candidateRuns.size() };
     }
     if (result.action == LineBreaker::Result::Action::Push) {
         // This continuous content can't be placed on the current line. Nothing to commit at this time.
-        return { result.isEndOfLine, 0, { } };
+        return { result.isEndOfLine };
     }
     if (result.action == LineBreaker::Result::Action::Revert) {
-        ASSERT_NOT_IMPLEMENTED_YET();
-        return { result.isEndOfLine, 0, { } };
+        // Not only this content can't be placed on the current line, but we even need to revert the line back to an earlier position.
+        return { result.isEndOfLine, 0, { }, result.revertTo };
     }
     if (result.action == LineBreaker::Result::Action::Split) {
         // Commit the combination of full and partial content on the current line.
@@ -425,7 +431,7 @@
         auto trailingRunIndex = result.partialTrailingContent->trailingRunIndex;
         auto committedInlineItemCount = trailingRunIndex + 1;
         if (!result.partialTrailingContent->partialRun)
-            return { result.isEndOfLine, committedInlineItemCount, { } };
+            return { result.isEndOfLine, committedInlineItemCount };
 
         auto partialRun = *result.partialTrailingContent->partialRun;
         auto& trailingInlineTextItem = downcast<InlineTextItem>(candidateRuns[trailingRunIndex].inlineItem);
@@ -433,7 +439,7 @@
         return { result.isEndOfLine, committedInlineItemCount, LineContent::PartialContent { partialRun.needsHyphen, overflowLength } };
     }
     ASSERT_NOT_REACHED();
-    return { LineBreaker::IsEndOfLine::No, 0, { } };
+    return { LineBreaker::IsEndOfLine::No };
 }
 
 void LineLayoutContext::commitContent(LineBuilder& line, const LineBreaker::RunList& runs, Optional<LineBreaker::Result::PartialTrailingContent> partialTrailingContent)

Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h (253947 => 253948)


--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h	2019-12-30 17:17:00 UTC (rev 253947)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h	2019-12-30 18:25:36 UTC (rev 253948)
@@ -54,14 +54,15 @@
     using FloatList = Vector<WeakPtr<InlineItem>>;
 
 private:
-    struct CommittedContent {
+    LineCandidateContent nextContentForLine(unsigned inlineItemIndex, Optional<unsigned> overflowLength, InlineLayoutUnit currentLogicalRight);
+    struct Result {
         LineBreaker::IsEndOfLine isEndOfLine { LineBreaker::IsEndOfLine::No };
-        size_t count { 0 };
-        Optional <LineContent::PartialContent> partialContent;
+        size_t committedCount { 0 };
+        Optional <LineContent::PartialContent> partialContent { };
+        const InlineItem* revertTo { nullptr };
     };
-    LineCandidateContent nextContentForLine(unsigned inlineItemIndex, Optional<unsigned> overflowLength, InlineLayoutUnit currentLogicalRight);
-    CommittedContent addFloatItems(LineBuilder&, const FloatList&);
-    CommittedContent checkForLineWrapAndCommit(LineBreaker&, LineBuilder&, const LineBreaker::RunList&);
+    Result tryAddingFloatItems(LineBuilder&, const FloatList&);
+    Result tryAddingInlineItems(LineBreaker&, LineBuilder&, const LineBreaker::RunList&);
     void commitContent(LineBuilder&, const LineBreaker::RunList&, Optional<LineBreaker::Result::PartialTrailingContent>);
     LineContent close(LineBuilder&, unsigned leadingInlineItemIndex, unsigned committedInlineItemCount, Optional<LineContent::PartialContent>);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to