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)