Title: [284127] trunk
Revision
284127
Author
[email protected]
Date
2021-10-13 14:40:32 -0700 (Wed, 13 Oct 2021)

Log Message

[LFC][IFC] Preserved tab is not a word separator
https://bugs.webkit.org/show_bug.cgi?id=231687

Reviewed by Antti Koivisto.

Source/WebCore:

The 'tab' character is not considered a word separator in the word-spacing sense. When the preserved whitespace sequence
has the mix of word separators (regular space) and non-separators, we use incorrect 'x' position to compute the width of the 'tab' character (tab width is position sensitive).
This patch fixes it by splitting the whitespace sequence at word-separator boundary (e.g [space][space][tab] will produce 2 individual InlineTextItems [space][space] and [tab]).

Test: fast/text/preserved-white-space-with-word-spacing.html

* layout/formattingContexts/inline/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::candidateContentForLine):
* layout/formattingContexts/inline/InlineTextItem.cpp:
(WebCore::Layout::moveToNextNonWhitespacePosition):
(WebCore::Layout::InlineTextItem::createAndAppendTextItems):

LayoutTests:

* fast/text/preserved-white-space-with-word-spacing-expected.html: Added.
* fast/text/preserved-white-space-with-word-spacing.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (284126 => 284127)


--- trunk/LayoutTests/ChangeLog	2021-10-13 21:37:15 UTC (rev 284126)
+++ trunk/LayoutTests/ChangeLog	2021-10-13 21:40:32 UTC (rev 284127)
@@ -1,3 +1,13 @@
+2021-10-13  Alan Bujtas  <[email protected]>
+
+        [LFC][IFC] Preserved tab is not a word separator
+        https://bugs.webkit.org/show_bug.cgi?id=231687
+
+        Reviewed by Antti Koivisto.
+
+        * fast/text/preserved-white-space-with-word-spacing-expected.html: Added.
+        * fast/text/preserved-white-space-with-word-spacing.html: Added.
+
 2021-10-13  Jean-Yves Avenard  <[email protected]>
 
         Add mp3 and aac web audio test

Added: trunk/LayoutTests/fast/text/preserved-white-space-with-word-spacing-expected.html (0 => 284127)


--- trunk/LayoutTests/fast/text/preserved-white-space-with-word-spacing-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/preserved-white-space-with-word-spacing-expected.html	2021-10-13 21:40:32 UTC (rev 284127)
@@ -0,0 +1,10 @@
+<style>
+ body {
+   margin: 0px;
+ }
+ div {
+   font-family: Ahem;
+   font-size: 50px;
+ }
+</style>
+<div>XX</div>

Added: trunk/LayoutTests/fast/text/preserved-white-space-with-word-spacing.html (0 => 284127)


--- trunk/LayoutTests/fast/text/preserved-white-space-with-word-spacing.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/preserved-white-space-with-word-spacing.html	2021-10-13 21:40:32 UTC (rev 284127)
@@ -0,0 +1,16 @@
+<style>
+ body {
+   margin: 0px;
+ }
+ div {
+   white-space: pre;
+   font-family: Ahem;
+   font-size: 50px;
+   margin-left: -400px;
+ }
+ span {
+   word-spacing: 100px;
+ }
+</style>
+<!-- The preserved tab is not a word separator and should not trigger word-spacing -->
+<div>X<span> 	X</span>X</div>

Modified: trunk/Source/WebCore/ChangeLog (284126 => 284127)


--- trunk/Source/WebCore/ChangeLog	2021-10-13 21:37:15 UTC (rev 284126)
+++ trunk/Source/WebCore/ChangeLog	2021-10-13 21:40:32 UTC (rev 284127)
@@ -1,3 +1,22 @@
+2021-10-13  Alan Bujtas  <[email protected]>
+
+        [LFC][IFC] Preserved tab is not a word separator
+        https://bugs.webkit.org/show_bug.cgi?id=231687
+
+        Reviewed by Antti Koivisto.
+
+        The 'tab' character is not considered a word separator in the word-spacing sense. When the preserved whitespace sequence
+        has the mix of word separators (regular space) and non-separators, we use incorrect 'x' position to compute the width of the 'tab' character (tab width is position sensitive).
+        This patch fixes it by splitting the whitespace sequence at word-separator boundary (e.g [space][space][tab] will produce 2 individual InlineTextItems [space][space] and [tab]). 
+
+        Test: fast/text/preserved-white-space-with-word-spacing.html
+
+        * layout/formattingContexts/inline/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineBuilder::candidateContentForLine):
+        * layout/formattingContexts/inline/InlineTextItem.cpp:
+        (WebCore::Layout::moveToNextNonWhitespacePosition):
+        (WebCore::Layout::InlineTextItem::createAndAppendTextItems):
+
 2021-10-13  Sihui Liu  <[email protected]>
 
         Implement FileSystemHandle move()

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp (284126 => 284127)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp	2021-10-13 21:37:15 UTC (rev 284126)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp	2021-10-13 21:40:32 UTC (rev 284127)
@@ -509,6 +509,10 @@
             auto logicalWidth = leadingLogicalWidth ? *std::exchange(leadingLogicalWidth, std::nullopt) : inlineItemWidth(inlineItem, currentLogicalRight);
             lineCandidate.inlineContent.appendInlineItem(inlineItem, style, logicalWidth);
             currentLogicalRight += logicalWidth;
+            if (is<InlineTextItem>(inlineItem) && downcast<InlineTextItem>(inlineItem).isWordSeparator()) {
+                // Word spacing does not make the run longer, but it produces an offset instead. See Line::appendTextContent as well.
+                currentLogicalRight += style.fontCascade().wordSpacing();
+            }
             continue;
         }
         if (inlineItem.isBox()) {

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineTextItem.cpp (284126 => 284127)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineTextItem.cpp	2021-10-13 21:37:15 UTC (rev 284126)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineTextItem.cpp	2021-10-13 21:40:32 UTC (rev 284127)
@@ -42,18 +42,23 @@
     size_t length { 0 };
     bool isWordSeparator { true };
 };
-static std::optional<WhitespaceContent> moveToNextNonWhitespacePosition(StringView textContent, size_t startPosition, bool preserveNewline, bool preserveTab, bool treatNonBreakingSpaceAsRegularSpace)
+static std::optional<WhitespaceContent> moveToNextNonWhitespacePosition(StringView textContent, size_t startPosition, bool preserveNewline, bool preserveTab, bool treatNonBreakingSpaceAsRegularSpace, bool stopAtWordSeparatorBoundary)
 {
     auto hasWordSeparatorCharacter = false;
+    auto isWordSeparatorCharacter = false;
     auto isWhitespaceCharacter = [&](auto character) {
         // white space processing in CSS affects only the document white space characters: spaces (U+0020), tabs (U+0009), and segment breaks.
         auto isTreatedAsSpaceCharacter = character == space || (character == newlineCharacter && !preserveNewline) || (character == tabCharacter && !preserveTab) || (character == noBreakSpace && treatNonBreakingSpaceAsRegularSpace);
-        hasWordSeparatorCharacter = hasWordSeparatorCharacter || isTreatedAsSpaceCharacter;
+        isWordSeparatorCharacter = isTreatedAsSpaceCharacter;
+        hasWordSeparatorCharacter = hasWordSeparatorCharacter || isWordSeparatorCharacter;
         return isTreatedAsSpaceCharacter || character == tabCharacter;
     };
     auto nextNonWhiteSpacePosition = startPosition;
-    while (nextNonWhiteSpacePosition < textContent.length() && isWhitespaceCharacter(textContent[nextNonWhiteSpacePosition]))
+    while (nextNonWhiteSpacePosition < textContent.length() && isWhitespaceCharacter(textContent[nextNonWhiteSpacePosition])) {
+        if (UNLIKELY(stopAtWordSeparatorBoundary && hasWordSeparatorCharacter && !isWordSeparatorCharacter))
+            break;
         ++nextNonWhiteSpacePosition;
+    }
     return nextNonWhiteSpacePosition == startPosition ? std::nullopt : std::make_optional(WhitespaceContent { nextNonWhiteSpacePosition - startPosition, hasWordSeparatorCharacter });
 }
 
@@ -79,7 +84,8 @@
 
     auto& style = inlineTextBox.style();
     auto& fontCascade = style.fontCascade();
-    auto whitespaceContentIsTreatedAsSingleSpace = !TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox);
+    auto shouldPreserveSpacesAndTabs = TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox);
+    auto whitespaceContentIsTreatedAsSingleSpace = !shouldPreserveSpacesAndTabs;
     auto shouldPreserveNewline = TextUtil::shouldPreserveNewline(inlineTextBox);
     auto shouldTreatNonBreakingSpaceAsRegularSpace = style.nbspMode() == NBSPMode::Space;
     auto lineBreakIterator = LazyLineBreakIterator { text, style.computedLocale(), TextUtil::lineBreakIteratorMode(style.lineBreak()) };
@@ -104,7 +110,8 @@
             continue;
         }
 
-        if (auto whitespaceContent = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreserveNewline, !whitespaceContentIsTreatedAsSingleSpace, shouldTreatNonBreakingSpaceAsRegularSpace)) {
+        auto stopAtWordSeparatorBoundary = shouldPreserveSpacesAndTabs && fontCascade.wordSpacing();
+        if (auto whitespaceContent = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreserveNewline, shouldPreserveSpacesAndTabs, shouldTreatNonBreakingSpaceAsRegularSpace, stopAtWordSeparatorBoundary)) {
             ASSERT(whitespaceContent->length);
             auto appendWhitespaceItem = [&] (auto startPosition, auto itemLength) {
                 auto simpleSingleWhitespaceContent = inlineTextBox.canUseSimplifiedContentMeasuring() && (itemLength == 1 || whitespaceContentIsTreatedAsSingleSpace);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to