Title: [272416] trunk/Source/WebCore
Revision
272416
Author
[email protected]
Date
2021-02-05 08:38:48 -0800 (Fri, 05 Feb 2021)

Log Message

[LFC][IFC] Add support for "word separator" when the whitespace content has multiple characters
https://bugs.webkit.org/show_bug.cgi?id=221355

Reviewed by Antti Koivisto.

Keep track of word separator characters in whitespace content even when the whitespace content has multiple characters.
This fixes cases when "word-spacing" has a non-zero value in "space and tab preserve" content (e.g <pre style="word-spacing: 200px">This content has    spaces   and tabs</pre>)
(On trunk we fail to adjust the run position with the word-spacing value because the whitespace content is not marked as a word separator.)

* layout/inlineformatting/InlineTextItem.cpp:
(WebCore::Layout::moveToNextNonWhitespacePosition):
(WebCore::Layout::InlineTextItem::createAndAppendTextItems):
* layout/inlineformatting/InlineTextItem.h:
(WebCore::Layout::InlineTextItem::createNonWhitespaceItem):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (272415 => 272416)


--- trunk/Source/WebCore/ChangeLog	2021-02-05 16:19:08 UTC (rev 272415)
+++ trunk/Source/WebCore/ChangeLog	2021-02-05 16:38:48 UTC (rev 272416)
@@ -1,3 +1,20 @@
+2021-02-05  Zalan Bujtas  <[email protected]>
+
+        [LFC][IFC] Add support for "word separator" when the whitespace content has multiple characters
+        https://bugs.webkit.org/show_bug.cgi?id=221355
+
+        Reviewed by Antti Koivisto.
+
+        Keep track of word separator characters in whitespace content even when the whitespace content has multiple characters.
+        This fixes cases when "word-spacing" has a non-zero value in "space and tab preserve" content (e.g <pre style="word-spacing: 200px">This content has    spaces   and tabs</pre>)
+        (On trunk we fail to adjust the run position with the word-spacing value because the whitespace content is not marked as a word separator.)
+
+        * layout/inlineformatting/InlineTextItem.cpp:
+        (WebCore::Layout::moveToNextNonWhitespacePosition):
+        (WebCore::Layout::InlineTextItem::createAndAppendTextItems):
+        * layout/inlineformatting/InlineTextItem.h:
+        (WebCore::Layout::InlineTextItem::createNonWhitespaceItem):
+
 2021-02-05  Chris Dumez  <[email protected]>
 
         [GPUProcess][iOS] Audio is lost after media playback recovers from the GPUProcess crash

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp (272415 => 272416)


--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp	2021-02-05 16:19:08 UTC (rev 272415)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.cpp	2021-02-05 16:38:48 UTC (rev 272416)
@@ -38,16 +38,23 @@
 
 static_assert(sizeof(InlineItem) == sizeof(InlineTextItem), "");
 
-static size_t moveToNextNonWhitespacePosition(const StringView& textContent, size_t startPosition, bool preserveNewline)
+struct WhitespaceContent {
+    size_t length { 0 };
+    bool isWordSeparator { true };
+};
+static Optional<WhitespaceContent> moveToNextNonWhitespacePosition(const StringView& textContent, size_t startPosition, bool preserveNewline, bool preserveTab)
 {
+    auto hasWordSeparatorCharacter = false;
     auto isWhitespaceCharacter = [&](auto character) {
-        return character == space || character == tabCharacter || (character == newlineCharacter && !preserveNewline);
+        // 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);
+        hasWordSeparatorCharacter = hasWordSeparatorCharacter || isTreatedAsSpaceCharacter;
+        return isTreatedAsSpaceCharacter || character == tabCharacter;
     };
-
     auto nextNonWhiteSpacePosition = startPosition;
     while (nextNonWhiteSpacePosition < textContent.length() && isWhitespaceCharacter(textContent[nextNonWhiteSpacePosition]))
         ++nextNonWhiteSpacePosition;
-    return nextNonWhiteSpacePosition - startPosition;
+    return nextNonWhiteSpacePosition == startPosition ? WTF::nullopt : makeOptional(WhitespaceContent { nextNonWhiteSpacePosition - startPosition, hasWordSeparatorCharacter });
 }
 
 static unsigned moveToNextBreakablePosition(unsigned startPosition, LazyLineBreakIterator& lineBreakIterator, const RenderStyle& style)
@@ -95,36 +102,22 @@
             continue;
         }
 
-        if (auto length = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreseveNewline)) {
+        if (auto whitespaceContent = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreseveNewline, !whitespaceContentIsTreatedAsSingleSpace)) {
+            ASSERT(whitespaceContent->length);
             auto appendWhitespaceItem = [&] (auto startPosition, auto itemLength) {
                 auto simpleSingleWhitespaceContent = inlineTextBox.canUseSimplifiedContentMeasuring() && (itemLength == 1 || whitespaceContentIsTreatedAsSingleSpace);
                 auto width = simpleSingleWhitespaceContent ? makeOptional(InlineLayoutUnit { font.spaceWidth() }) : inlineItemWidth(startPosition, itemLength);
-                auto isWordSeparator = [&] {
-                    if (whitespaceContentIsTreatedAsSingleSpace)
-                        return true;
-                    if (itemLength != 1) {
-                        // FIXME: Add support for cases where the whitespace content contains different type of characters (e.g  "\t  \t  \t").
-                        return false;
-                    }
-                    auto whitespaceCharacter = text[startPosition];
-                    return whitespaceCharacter == space
-                        || whitespaceCharacter == noBreakSpace
-                        || whitespaceCharacter == ethiopicWordspace
-                        || whitespaceCharacter == aegeanWordSeparatorLine
-                        || whitespaceCharacter == aegeanWordSeparatorDot
-                        || whitespaceCharacter == ugariticWordDivider;
-                }();
-                inlineContent.append(InlineTextItem::createWhitespaceItem(inlineTextBox, startPosition, itemLength, isWordSeparator, width));
+                inlineContent.append(InlineTextItem::createWhitespaceItem(inlineTextBox, startPosition, itemLength, whitespaceContent->isWordSeparator, width));
             };
             if (style.whiteSpace() == WhiteSpace::BreakSpaces) {
                 // https://www.w3.org/TR/css-text-3/#white-space-phase-1
                 // For break-spaces, a soft wrap opportunity exists after every space and every tab.
                 // FIXME: if this turns out to be a perf hit with too many individual whitespace inline items, we should transition this logic to line breaking.
-                for (size_t i = 0; i < length; ++i)
+                for (size_t i = 0; i < whitespaceContent->length; ++i)
                     appendWhitespaceItem(currentPosition + i, 1);
             } else
-                appendWhitespaceItem(currentPosition, length);
-            currentPosition += length;
+                appendWhitespaceItem(currentPosition, whitespaceContent->length);
+            currentPosition += whitespaceContent->length;
             continue;
         }
 

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h (272415 => 272416)


--- trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h	2021-02-05 16:19:08 UTC (rev 272415)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineTextItem.h	2021-02-05 16:38:48 UTC (rev 272416)
@@ -74,6 +74,7 @@
 
 inline InlineTextItem InlineTextItem::createNonWhitespaceItem(const InlineTextBox& inlineTextBox, unsigned start, unsigned length, bool hasTrailingSoftHyphen, Optional<InlineLayoutUnit> width)
 {
+    // FIXME: Use the following list of non-whitespace characters to set the "isWordSeparator" bit: noBreakSpace, ethiopicWordspace, aegeanWordSeparatorLine aegeanWordSeparatorDot ugariticWordDivider.
     return { inlineTextBox, start, length, hasTrailingSoftHyphen, false, width, TextItemType::NonWhitespace };
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to