Title: [284242] trunk
Revision
284242
Author
[email protected]
Date
2021-10-15 06:33:47 -0700 (Fri, 15 Oct 2021)

Log Message

[LFC][IFC] Do not break the word-wrap: break-word content on inline box boundary
https://bugs.webkit.org/show_bug.cgi?id=231761

Reviewed by Antti Koivisto.

Source/WebCore:

When the text content is breakable at arbitrary position and it is not the overflowing content (the overflowing content is not breakable)
we just return the text run as the trailing run as it surely fits e.g.

<span style="word-wrap: break-word">this_content_is_breakable</span>and_this_content_overflows

1. There's no soft wrapping opportunity between the two text runs (they form a continuous set)
2. The trailing run overflow but can't be split
we go backwards on the set to find a breakable one. In this case the first text run is breakable (see CSS property) and
since we know it fits the line we just simply declare the end of the run as the breaking position.
However we should try to keep the runs and their adjacent inline box boundary runs together and instead find the end of the </span> as
the breaking position. It's mostly noticeable when the inline box has some visual decoration e.g. border.

Test: fast/inline/wordbreak-at-inline-box-boundary.html

* layout/formattingContexts/inline/InlineContentBreaker.cpp:
(WebCore::Layout::InlineContentBreaker::tryBreakingTextRun const):
(WebCore::Layout::InlineContentBreaker::tryBreakingPreviousNonOverflowingRuns const):

LayoutTests:

* fast/inline/wordbreak-at-inline-box-boundary-expected.html: Added.
* fast/inline/wordbreak-at-inline-box-boundary.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (284241 => 284242)


--- trunk/LayoutTests/ChangeLog	2021-10-15 10:24:43 UTC (rev 284241)
+++ trunk/LayoutTests/ChangeLog	2021-10-15 13:33:47 UTC (rev 284242)
@@ -1,3 +1,13 @@
+2021-10-15  Alan Bujtas  <[email protected]>
+
+        [LFC][IFC] Do not break the word-wrap: break-word content on inline box boundary
+        https://bugs.webkit.org/show_bug.cgi?id=231761
+
+        Reviewed by Antti Koivisto.
+
+        * fast/inline/wordbreak-at-inline-box-boundary-expected.html: Added.
+        * fast/inline/wordbreak-at-inline-box-boundary.html: Added.
+
 2021-10-15  Robin Morisset  <[email protected]>
 
         Revert r284230, my last fixes to the watch build make it break tests

Added: trunk/LayoutTests/fast/inline/wordbreak-at-inline-box-boundary-expected.html (0 => 284242)


--- trunk/LayoutTests/fast/inline/wordbreak-at-inline-box-boundary-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/inline/wordbreak-at-inline-box-boundary-expected.html	2021-10-15 13:33:47 UTC (rev 284242)
@@ -0,0 +1,11 @@
+<style>
+div {
+  font-family: Monospace;
+  font-size: 20px;
+  width: 440px;
+}
+</style>
+<div>padding makes this content overflo<br>w</div>
+<div>padding makes this content overflo<br>w</div>
+<div>padding makes this content overflo<br>w</div>
+<div>padding makes this content overflo<br>w</div>

Added: trunk/LayoutTests/fast/inline/wordbreak-at-inline-box-boundary.html (0 => 284242)


--- trunk/LayoutTests/fast/inline/wordbreak-at-inline-box-boundary.html	                        (rev 0)
+++ trunk/LayoutTests/fast/inline/wordbreak-at-inline-box-boundary.html	2021-10-15 13:33:47 UTC (rev 284242)
@@ -0,0 +1,16 @@
+<style>
+div {
+  font-family: Monospace;
+  font-size: 20px;
+  width: 440px;
+}
+.span_with_content {
+  padding-right: 100px;
+  word-wrap: break-word;
+}
+</style>
+<!-- padding (and border as well) is an unbreakable part of the inline box content and we should not break the text content at the inline box boundary (e.g. between text and </span>) -->
+<div><span class=span_with_content>padding&nbspmakes&nbspthis&nbspcontent&nbspoverflow</span></div>
+<div><span class=span_with_content>padding&nbspmakes&nbspthis&nbspcontent&nbspoverflow<span></span></span></div>
+<div><span class=span_with_content>padding&nbspmakes&nbspthis&nbspcontent&nbspoverflow<span style="word-wrap: break-word;"></span></span></div>
+<div><span class=span_with_content>padding&nbspmakes&nbspthis&nbspcontent&nbspoverflow</span><span></span></div>

Modified: trunk/Source/WebCore/ChangeLog (284241 => 284242)


--- trunk/Source/WebCore/ChangeLog	2021-10-15 10:24:43 UTC (rev 284241)
+++ trunk/Source/WebCore/ChangeLog	2021-10-15 13:33:47 UTC (rev 284242)
@@ -1,3 +1,28 @@
+2021-10-15  Alan Bujtas  <[email protected]>
+
+        [LFC][IFC] Do not break the word-wrap: break-word content on inline box boundary
+        https://bugs.webkit.org/show_bug.cgi?id=231761
+
+        Reviewed by Antti Koivisto.
+
+        When the text content is breakable at arbitrary position and it is not the overflowing content (the overflowing content is not breakable)
+        we just return the text run as the trailing run as it surely fits e.g.
+
+        <span style="word-wrap: break-word">this_content_is_breakable</span>and_this_content_overflows
+
+        1. There's no soft wrapping opportunity between the two text runs (they form a continuous set)
+        2. The trailing run overflow but can't be split
+        we go backwards on the set to find a breakable one. In this case the first text run is breakable (see CSS property) and
+        since we know it fits the line we just simply declare the end of the run as the breaking position.
+        However we should try to keep the runs and their adjacent inline box boundary runs together and instead find the end of the </span> as
+        the breaking position. It's mostly noticeable when the inline box has some visual decoration e.g. border.
+
+        Test: fast/inline/wordbreak-at-inline-box-boundary.html
+
+        * layout/formattingContexts/inline/InlineContentBreaker.cpp:
+        (WebCore::Layout::InlineContentBreaker::tryBreakingTextRun const):
+        (WebCore::Layout::InlineContentBreaker::tryBreakingPreviousNonOverflowingRuns const):
+
 2021-10-15  Alexey Shvayka  <[email protected]>
 
         [WebIDL] JSDOMBuiltinConstructor instances should support subclassing

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


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp	2021-10-15 10:24:43 UTC (rev 284241)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp	2021-10-15 13:33:47 UTC (rev 284242)
@@ -414,9 +414,17 @@
             }
             if (!candidateTextRun.isOverflowingRun) {
                 // When the run can be split at arbitrary position let's just return the entire run when it is intended to fit on the line.
+                // However the breaking properties only set rules for text content, so let's check if this run is adjacent to another text run.
                 ASSERT(inlineTextItem.length());
-                auto trailingPartialRunWidth = TextUtil::width(inlineTextItem, fontCascade, candidateTextRun.logicalLeft);
-                return { inlineTextItem.length(), trailingPartialRunWidth };
+                // FIXME: We may need to check if the "next" text run is visually adjacent to this non-overflowing run too (e.g. A<span style="border: 100px solid green;"></span>B)
+                if (nextTextRunIndex(runs, candidateTextRun.index)) {
+                    // We are in-between text runs. It's okay to return the entire run triggering split at the very right edge.
+                    auto trailingPartialRunWidth = TextUtil::width(inlineTextItem, fontCascade, candidateTextRun.logicalLeft);
+                    return { inlineTextItem.length(), trailingPartialRunWidth };
+                }
+                auto startPosition = inlineTextItem.start() + 1;
+                auto endPosition = inlineTextItem.end();
+                return { inlineTextItem.length() - 1, TextUtil::width(inlineTextItem, fontCascade, startPosition, endPosition, candidateTextRun.logicalLeft) };
             }
             if (!lineHasRoomForContent) {
                 // Fast path for cases when there's no room at all. The content is breakable but we don't have space for it.
@@ -467,7 +475,26 @@
             // since it's either at hyphen position or the entire run is returned.
             ASSERT(partialRun->length);
             auto runIsFullyAccommodated = partialRun->length == downcast<InlineTextItem>(run.inlineItem).length();
-            return OverflowingTextContent::BreakingPosition { index, OverflowingTextContent::BreakingPosition::TrailingContent { false, runIsFullyAccommodated ? std::nullopt : partialRun } };
+            if (runIsFullyAccommodated) {
+                auto trailingRunIndex = [&] {
+                    // Try not break content at inline box boundary.
+                    // e.g. <span style="word-wrap: break-word">fits_and_we_break_at_the_right_edge</span><span>overflows</span>
+                    // we should forward the breaking index to the closing inline box.
+                    // FIXME: We may wanna skip over the visually empty inline boxes only e.g. <span style="word-wrap: break-word">fits_and_we_break_at_the_right_edge</span><span></span><span>overflows</span>
+                    auto trailingInlineBoxEndIndex = std::optional<size_t> { };
+                    for (auto candidateIndex = index + 1; candidateIndex < overflowingRunIndex; ++candidateIndex) {
+                        auto& trailingInlineItem = runs[candidateIndex].inlineItem;
+                        if (trailingInlineItem.isInlineBoxEnd())
+                            trailingInlineBoxEndIndex = candidateIndex;
+                        if (!trailingInlineItem.isInlineBoxStart() && !trailingInlineItem.isInlineBoxEnd())
+                            break;
+                    }
+                    ASSERT(!trailingInlineBoxEndIndex || *trailingInlineBoxEndIndex < overflowingRunIndex);
+                    return trailingInlineBoxEndIndex.value_or(index);
+                };
+                return OverflowingTextContent::BreakingPosition { trailingRunIndex(), OverflowingTextContent::BreakingPosition::TrailingContent { false, std::nullopt } };
+            }
+            return OverflowingTextContent::BreakingPosition { index, OverflowingTextContent::BreakingPosition::TrailingContent { false, partialRun } };
         }
     }
     return { };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to