Title: [284678] trunk/Source/WebCore
Revision
284678
Author
za...@apple.com
Date
2021-10-22 06:44:00 -0700 (Fri, 22 Oct 2021)

Log Message

[LFC][IFC] Add support for checking leading collapsible whitespace in InlineContentBreaker::processOverflowingContent
https://bugs.webkit.org/show_bug.cgi?id=232091

Reviewed by Antti Koivisto.

This patch ensures that the leading collapsible whitespace on the continuous run is taken
into account when checking if the otherwise overflowing content may fit the line.
e.g.
<span style="white-space: nowrap">no_wrap </span><span> yes_wrap</span>
The " yes_wrap" content has a collapsible leading whitespace here.
(This is also a preparation for fixing a regression and a WPT test.)

* layout/formattingContexts/inline/InlineContentBreaker.cpp:
(WebCore::Layout::isVisuallyEmptyWhitespaceContent):
(WebCore::Layout::InlineContentBreaker::processOverflowingContent const):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::append):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::reset):
* layout/formattingContexts/inline/InlineContentBreaker.h:
(WebCore::Layout::InlineContentBreaker::ContinuousContent::leadingCollapsibleWidth const):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::trailingCollapsibleWidth const):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::hasCollapsibleContent const):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::isFullyCollapsible const):
(WebCore::Layout::InlineContentBreaker::ContinuousContent::collapsibleLogicalWidth const): Deleted.
(WebCore::Layout::InlineContentBreaker::ContinuousContent::nonCollapsibleLogicalWidth const): Deleted.
(WebCore::Layout::InlineContentBreaker::ContinuousContent::hasTrailingCollapsibleContent const): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (284677 => 284678)


--- trunk/Source/WebCore/ChangeLog	2021-10-22 13:24:11 UTC (rev 284677)
+++ trunk/Source/WebCore/ChangeLog	2021-10-22 13:44:00 UTC (rev 284678)
@@ -1,5 +1,33 @@
 2021-10-22  Alan Bujtas  <za...@apple.com>
 
+        [LFC][IFC] Add support for checking leading collapsible whitespace in InlineContentBreaker::processOverflowingContent
+        https://bugs.webkit.org/show_bug.cgi?id=232091
+
+        Reviewed by Antti Koivisto.
+
+        This patch ensures that the leading collapsible whitespace on the continuous run is taken
+        into account when checking if the otherwise overflowing content may fit the line.
+        e.g.
+        <span style="white-space: nowrap">no_wrap </span><span> yes_wrap</span>
+        The " yes_wrap" content has a collapsible leading whitespace here.
+        (This is also a preparation for fixing a regression and a WPT test.)
+
+        * layout/formattingContexts/inline/InlineContentBreaker.cpp:
+        (WebCore::Layout::isVisuallyEmptyWhitespaceContent):
+        (WebCore::Layout::InlineContentBreaker::processOverflowingContent const):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::append):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::reset):
+        * layout/formattingContexts/inline/InlineContentBreaker.h:
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::leadingCollapsibleWidth const):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::trailingCollapsibleWidth const):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::hasCollapsibleContent const):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::isFullyCollapsible const):
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::collapsibleLogicalWidth const): Deleted.
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::nonCollapsibleLogicalWidth const): Deleted.
+        (WebCore::Layout::InlineContentBreaker::ContinuousContent::hasTrailingCollapsibleContent const): Deleted.
+
+2021-10-22  Alan Bujtas  <za...@apple.com>
+
         FontCascade::widthForSimpleText fails to produce matching measured width for monospace font
         https://bugs.webkit.org/show_bug.cgi?id=232104
         <rdar://83991027>

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp (284677 => 284678)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp	2021-10-22 13:24:11 UTC (rev 284677)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp	2021-10-22 13:44:00 UTC (rev 284678)
@@ -97,15 +97,19 @@
 {
     // [<span></span> ] [<span> </span>] [ <span style="padding: 0px;"></span>] are all considered visually empty whitespace content.
     // [<span style="border: 1px solid red"></span> ] while this is whitespace content only, it is not considered visually empty.
-    // Due to commit boundary rules, we just need to check the first non-typeless inline item (can't have both [img] and [text])
+    ASSERT(!continuousContent.runs().isEmpty());
+    auto hasWhitespace = false;
     for (auto& run : continuousContent.runs()) {
         auto& inlineItem = run.inlineItem;
-        // FIXME: check for padding border etc.
+        // FIXME: check if visual decoration makes a difference here e.g. padding border.
         if (inlineItem.isInlineBoxStart() || inlineItem.isInlineBoxEnd())
             continue;
-        return inlineItem.isText() && downcast<InlineTextItem>(inlineItem).isWhitespace();
+        auto isWhitespace = inlineItem.isText() && downcast<InlineTextItem>(inlineItem).isWhitespace();
+        if (!isWhitespace)
+            return false;
+        hasWhitespace = true;
     }
-    return false;
+    return hasWhitespace;
 }
 
 static inline bool isNonContentRunsOnly(const InlineContentBreaker::ContinuousContent& continuousContent)
@@ -173,16 +177,17 @@
     ASSERT(!continuousContent.runs().isEmpty());
 
     ASSERT(continuousContent.logicalWidth() > lineStatus.availableWidth);
-    if (continuousContent.hasTrailingCollapsibleContent()) {
-        ASSERT(hasTrailingTextContent(overflowContent));
-        // First check if the content fits without the trailing collapsible part.
-        if (continuousContent.nonCollapsibleLogicalWidth() <= lineStatus.availableWidth)
-            return { Result::Action::Keep, IsEndOfLine::No };
-        // Now check if we can trim the line too.
-        if (lineStatus.hasFullyCollapsibleTrailingRun && continuousContent.isFullyCollapsible()) {
+    if (continuousContent.hasCollapsibleContent()) {
+        if (lineStatus.hasFullyCollapsibleTrailingContent && continuousContent.isFullyCollapsible()) {
             // If this new content is fully collapsible, it should surely fit.
             return { Result::Action::Keep, IsEndOfLine::No };
         }
+        // Check if the content fits if we collapsed it.
+        auto spaceRequired = continuousContent.logicalWidth() - continuousContent.trailingCollapsibleWidth();
+        if (lineStatus.hasFullyCollapsibleTrailingContent)
+            spaceRequired -= continuousContent.leadingCollapsibleWidth();
+        if (spaceRequired <= lineStatus.availableWidth)
+            return { Result::Action::Keep, IsEndOfLine::No };
     } else if (lineStatus.collapsibleWidth && isNonContentRunsOnly(continuousContent)) {
         // Let's see if the non-content runs fit when the line has trailing collapsible content.
         // "text content <span style="padding: 1px"></span>" <- the <span></span> runs could fit after collapsing the trailing whitespace.
@@ -649,29 +654,30 @@
 void InlineContentBreaker::ContinuousContent::append(const InlineItem& inlineItem, const RenderStyle& style, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth)
 {
     ASSERT(inlineItem.isText() || inlineItem.isBox() || inlineItem.isInlineBoxStart() || inlineItem.isInlineBoxEnd());
+    auto isLeadingCollapsible = collapsibleWidth && (m_runs.isEmpty() || isFullyCollapsible());
     m_runs.append({ inlineItem, style, logicalWidth });
     m_logicalWidth = clampTo<InlineLayoutUnit>(m_logicalWidth + logicalWidth);
     if (!collapsibleWidth) {
         if (inlineItem.isText() || inlineItem.isBox()) {
             // Inline boxes do not prevent the trailing content from getting collapsed.
-            m_collapsibleLogicalWidth = { };
+            m_trailingCollapsibleWidth = { };
         }
         return;
     }
     ASSERT(*collapsibleWidth <= logicalWidth);
-    if (*collapsibleWidth == logicalWidth) {
-        // Fully collapsible run.
-        m_collapsibleLogicalWidth += logicalWidth;
+    if (isLeadingCollapsible) {
+        ASSERT(!m_trailingCollapsibleWidth);
+        m_leadingCollapsibleWidth += *collapsibleWidth;
         return;
     }
-    // Partially collapsible run.
-    m_collapsibleLogicalWidth = *collapsibleWidth;
+    m_trailingCollapsibleWidth = *collapsibleWidth == logicalWidth ? m_trailingCollapsibleWidth + logicalWidth : *collapsibleWidth;
 }
 
 void InlineContentBreaker::ContinuousContent::reset()
 {
     m_logicalWidth = { };
-    m_collapsibleLogicalWidth = { };
+    m_leadingCollapsibleWidth = { };
+    m_trailingCollapsibleWidth = { };
     m_runs.clear();
 }
 }

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h (284677 => 284678)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h	2021-10-22 13:24:11 UTC (rev 284677)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h	2021-10-22 13:44:00 UTC (rev 284678)
@@ -77,12 +77,12 @@
     // see https://drafts.csswg.org/css-text-3/#line-break-details
     struct ContinuousContent {
         InlineLayoutUnit logicalWidth() const { return m_logicalWidth; }
-        InlineLayoutUnit collapsibleLogicalWidth() const { return m_collapsibleLogicalWidth; }
-        InlineLayoutUnit nonCollapsibleLogicalWidth() const { return logicalWidth() - collapsibleLogicalWidth(); }
-        bool hasTrailingCollapsibleContent() const { return !!collapsibleLogicalWidth(); }
-        bool isFullyCollapsible() const { return logicalWidth() == collapsibleLogicalWidth(); }
+        InlineLayoutUnit leadingCollapsibleWidth() const { return m_leadingCollapsibleWidth; }
+        InlineLayoutUnit trailingCollapsibleWidth() const { return m_trailingCollapsibleWidth; }
+        bool hasCollapsibleContent() const { return trailingCollapsibleWidth() > 0 || leadingCollapsibleWidth() > 0; }
+        bool isFullyCollapsible() const { return logicalWidth() == trailingCollapsibleWidth() + leadingCollapsibleWidth(); }
 
-        void append(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth);
+        void append(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalWidth, std::optional<InlineLayoutUnit> collapsibleWidth = std::nullopt);
         void reset();
 
         struct Run {
@@ -100,7 +100,8 @@
     private:
         RunList m_runs;
         InlineLayoutUnit m_logicalWidth { 0 };
-        InlineLayoutUnit m_collapsibleLogicalWidth { 0 };
+        InlineLayoutUnit m_leadingCollapsibleWidth { 0 };
+        InlineLayoutUnit m_trailingCollapsibleWidth { 0 };
     };
 
     struct LineStatus {
@@ -108,7 +109,7 @@
         InlineLayoutUnit availableWidth { 0 };
         InlineLayoutUnit collapsibleWidth { 0 };
         std::optional<InlineLayoutUnit> trailingSoftHyphenWidth;
-        bool hasFullyCollapsibleTrailingRun { false };
+        bool hasFullyCollapsibleTrailingContent { false };
         bool hasContent { false };
         bool hasWrapOpportunityAtPreviousPosition { false };
     };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to