Title: [287809] trunk/Source/WebCore
Revision
287809
Author
za...@apple.com
Date
2022-01-08 06:27:39 -0800 (Sat, 08 Jan 2022)

Log Message

[LFC][IFC] Implement TextUtil::breakWord for the complex font codepath using ubrk_next
https://bugs.webkit.org/show_bug.cgi?id=234998

Reviewed by Antti Koivisto.

In order to use ubrk_preceding/ubrk_following with arbitrary position (binary search) inside a cluster with surrogate pairs we have to
implement some additional surrogate boundary checks (it would move the index to the beginning/end of the surrogate when it falls right
in the middle of it). In addition to that, ICU would still need to scan the content from the start to find the right index for
the boundary.
This new breakWord implementation simply iterates over the clusters by calling ubrk_next until the content overflows.

* layout/formattingContexts/inline/text/TextUtil.cpp:
(WebCore::Layout::TextUtil::breakWord):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (287808 => 287809)


--- trunk/Source/WebCore/ChangeLog	2022-01-08 06:23:50 UTC (rev 287808)
+++ trunk/Source/WebCore/ChangeLog	2022-01-08 14:27:39 UTC (rev 287809)
@@ -1,3 +1,19 @@
+2022-01-08  Alan Bujtas  <za...@apple.com>
+
+        [LFC][IFC] Implement TextUtil::breakWord for the complex font codepath using ubrk_next
+        https://bugs.webkit.org/show_bug.cgi?id=234998
+
+        Reviewed by Antti Koivisto.
+
+        In order to use ubrk_preceding/ubrk_following with arbitrary position (binary search) inside a cluster with surrogate pairs we have to
+        implement some additional surrogate boundary checks (it would move the index to the beginning/end of the surrogate when it falls right
+        in the middle of it). In addition to that, ICU would still need to scan the content from the start to find the right index for
+        the boundary.
+        This new breakWord implementation simply iterates over the clusters by calling ubrk_next until the content overflows.
+
+        * layout/formattingContexts/inline/text/TextUtil.cpp:
+        (WebCore::Layout::TextUtil::breakWord):
+
 2022-01-07  Jean-Yves Avenard  <j...@apple.com>
 
         Remove IPC::SharedBufferDataReference and use IPC::SharedBufferCopy instead

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp (287808 => 287809)


--- trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp	2022-01-08 06:23:50 UTC (rev 287808)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/text/TextUtil.cpp	2022-01-08 14:27:39 UTC (rev 287809)
@@ -153,69 +153,68 @@
     ASSERT(availableWidth >= 0);
     ASSERT(length);
     auto text = inlineTextBox.content();
-    auto contentUsesSimpleFontCodePath = inlineTextBox.canUseSimpleFontCodePath();
 
-    auto graphemeClustersIterator = std::optional<NonSharedCharacterBreakIterator> { };
-    if (!contentUsesSimpleFontCodePath)
-        graphemeClustersIterator.emplace(text);
+    if (inlineTextBox.canUseSimpleFontCodePath()) {
 
-    auto userPerceivedCharacterBoundaryAlignedIndex = [&] (auto index) -> size_t {
-        if (text.is8Bit())
-            return index;
-        if (contentUsesSimpleFontCodePath) {
-            auto alignedStartIndex = index;
-            U16_SET_CP_START(text, startPosition, alignedStartIndex);
-            ASSERT(alignedStartIndex >= startPosition);
-            return alignedStartIndex;
-        }
-        ASSERT(graphemeClustersIterator.has_value());
-        if (ubrk_isBoundary(*graphemeClustersIterator, index))
-            return index;
-        auto boundaryIndex = ubrk_preceding(*graphemeClustersIterator, index);
-        return boundaryIndex == UBRK_DONE ? startPosition : boundaryIndex;
-    };
+        auto findBreakingPositionInSimpleText = [&] {
+            auto userPerceivedCharacterBoundaryAlignedIndex = [&] (auto index) -> size_t {
+                if (text.is8Bit())
+                    return index;
+                auto alignedStartIndex = index;
+                U16_SET_CP_START(text, startPosition, alignedStartIndex);
+                ASSERT(alignedStartIndex >= startPosition);
+                return alignedStartIndex;
+            };
 
-    auto nextUserPerceivedCharacterIndex = [&] (auto index) -> size_t {
-        if (text.is8Bit())
-            return index + 1;
-        if (contentUsesSimpleFontCodePath) {
-            U16_FWD_1(text, index, length);
-            return index;
-        }
-        ASSERT(graphemeClustersIterator.has_value());
-        auto nextPosition = ubrk_following(*graphemeClustersIterator, index);
-        return nextPosition == UBRK_DONE ? startPosition + length - 1 : nextPosition;
-    };
+            auto nextUserPerceivedCharacterIndex = [&] (auto index) -> size_t {
+                if (text.is8Bit())
+                    return index + 1;
+                U16_FWD_1(text, index, length);
+                return index;
+            };
 
-    auto left = startPosition;
-    auto right = left + length - 1;
-    if (contentUsesSimpleFontCodePath) {
-        // Pathological case of (extremely)long string and narrow lines.
-        // Adjust the range so that we can pick a reasonable midpoint.
-        auto averageCharacterWidth = InlineLayoutUnit { textWidth / length };
-        size_t startOffset = 2 * availableWidth / averageCharacterWidth;
-        right = userPerceivedCharacterBoundaryAlignedIndex(std::min(left + startOffset, right));
+            auto left = startPosition;
+            auto right = left + length - 1;
+            // Pathological case of (extremely)long string and narrow lines.
+            // Adjust the range so that we can pick a reasonable midpoint.
+            auto averageCharacterWidth = InlineLayoutUnit { textWidth / length };
+            size_t startOffset = 2 * availableWidth / averageCharacterWidth;
+            right = userPerceivedCharacterBoundaryAlignedIndex(std::min(left + startOffset, right));
+            // Preserve the left width for the final split position so that we don't need to remeasure the left side again.
+            auto leftSideWidth = InlineLayoutUnit { 0 };
+            while (left < right) {
+                auto middle = userPerceivedCharacterBoundaryAlignedIndex((left + right) / 2);
+                ASSERT(middle >= left && middle < right);
+                auto endOfMiddleCharacter = nextUserPerceivedCharacterIndex(middle);
+                auto width = TextUtil::width(inlineTextBox, fontCascade, startPosition, endOfMiddleCharacter, contentLogicalLeft);
+                if (width < availableWidth) {
+                    left = endOfMiddleCharacter;
+                    leftSideWidth = width;
+                } else if (width > availableWidth)
+                    right = middle;
+                else {
+                    right = endOfMiddleCharacter;
+                    leftSideWidth = width;
+                    break;
+                }
+            }
+            RELEASE_ASSERT(right >= startPosition);
+            return TextUtil::WordBreakLeft { right - startPosition, leftSideWidth };
+        };
+        return findBreakingPositionInSimpleText();
     }
-    // Preserve the left width for the final split position so that we don't need to remeasure the left side again.
-    auto leftSideWidth = InlineLayoutUnit { 0 };
-    while (left < right) {
-        auto middle = userPerceivedCharacterBoundaryAlignedIndex((left + right) / 2);
-        ASSERT(middle >= left && middle < right);
-        auto endOfMiddleCharacter = nextUserPerceivedCharacterIndex(middle);
-        auto width = TextUtil::width(inlineTextBox, fontCascade, startPosition, endOfMiddleCharacter, contentLogicalLeft);
-        if (width < availableWidth) {
-            left = endOfMiddleCharacter;
-            leftSideWidth = width;
-        } else if (width > availableWidth)
-            right = middle;
-        else {
-            right = endOfMiddleCharacter;
-            leftSideWidth = width;
-            break;
-        }
+
+    auto graphemeClusterIterator = NonSharedCharacterBreakIterator { StringView { text }.substring(startPosition, length) };
+    auto leftSide = TextUtil::WordBreakLeft { };
+    for (auto clusterStartPosition = ubrk_next(graphemeClusterIterator); clusterStartPosition != UBRK_DONE; clusterStartPosition = ubrk_next(graphemeClusterIterator)) {
+        auto width = TextUtil::width(inlineTextBox, fontCascade, startPosition, startPosition + clusterStartPosition, contentLogicalLeft);
+        if (width > availableWidth)
+            return leftSide;
+        leftSide = { static_cast<size_t>(clusterStartPosition), width };
     }
-    RELEASE_ASSERT(right >= startPosition);
-    return { right - startPosition, leftSideWidth };
+    // This content is not supposed to fit availableWidth.
+    ASSERT_NOT_REACHED();
+    return { };
 }
 
 unsigned TextUtil::findNextBreakablePosition(LazyLineBreakIterator& lineBreakIterator, unsigned startPosition, const RenderStyle& style)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to