Skip to content

Commit 1543357

Browse files
committed
[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): Canonical link: https://commits.webkit.org/233740@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@272416 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent a68ee25 commit 1543357

3 files changed

Lines changed: 35 additions & 24 deletions

File tree

Source/WebCore/ChangeLog

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
2021-02-05 Zalan Bujtas <zalan@apple.com>
2+
3+
[LFC][IFC] Add support for "word separator" when the whitespace content has multiple characters
4+
https://bugs.webkit.org/show_bug.cgi?id=221355
5+
6+
Reviewed by Antti Koivisto.
7+
8+
Keep track of word separator characters in whitespace content even when the whitespace content has multiple characters.
9+
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>)
10+
(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.)
11+
12+
* layout/inlineformatting/InlineTextItem.cpp:
13+
(WebCore::Layout::moveToNextNonWhitespacePosition):
14+
(WebCore::Layout::InlineTextItem::createAndAppendTextItems):
15+
* layout/inlineformatting/InlineTextItem.h:
16+
(WebCore::Layout::InlineTextItem::createNonWhitespaceItem):
17+
118
2021-02-05 Chris Dumez <cdumez@apple.com>
219

320
[GPUProcess][iOS] Audio is lost after media playback recovers from the GPUProcess crash

Source/WebCore/layout/inlineformatting/InlineTextItem.cpp

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,23 @@ namespace Layout {
3838

3939
static_assert(sizeof(InlineItem) == sizeof(InlineTextItem), "");
4040

41-
static size_t moveToNextNonWhitespacePosition(const StringView& textContent, size_t startPosition, bool preserveNewline)
41+
struct WhitespaceContent {
42+
size_t length { 0 };
43+
bool isWordSeparator { true };
44+
};
45+
static Optional<WhitespaceContent> moveToNextNonWhitespacePosition(const StringView& textContent, size_t startPosition, bool preserveNewline, bool preserveTab)
4246
{
47+
auto hasWordSeparatorCharacter = false;
4348
auto isWhitespaceCharacter = [&](auto character) {
44-
return character == space || character == tabCharacter || (character == newlineCharacter && !preserveNewline);
49+
// white space processing in CSS affects only the document white space characters: spaces (U+0020), tabs (U+0009), and segment breaks.
50+
auto isTreatedAsSpaceCharacter = character == space || (character == newlineCharacter && !preserveNewline) || (character == tabCharacter && !preserveTab);
51+
hasWordSeparatorCharacter = hasWordSeparatorCharacter || isTreatedAsSpaceCharacter;
52+
return isTreatedAsSpaceCharacter || character == tabCharacter;
4553
};
46-
4754
auto nextNonWhiteSpacePosition = startPosition;
4855
while (nextNonWhiteSpacePosition < textContent.length() && isWhitespaceCharacter(textContent[nextNonWhiteSpacePosition]))
4956
++nextNonWhiteSpacePosition;
50-
return nextNonWhiteSpacePosition - startPosition;
57+
return nextNonWhiteSpacePosition == startPosition ? WTF::nullopt : makeOptional(WhitespaceContent { nextNonWhiteSpacePosition - startPosition, hasWordSeparatorCharacter });
5158
}
5259

5360
static unsigned moveToNextBreakablePosition(unsigned startPosition, LazyLineBreakIterator& lineBreakIterator, const RenderStyle& style)
@@ -95,36 +102,22 @@ void InlineTextItem::createAndAppendTextItems(InlineItems& inlineContent, const
95102
continue;
96103
}
97104

98-
if (auto length = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreseveNewline)) {
105+
if (auto whitespaceContent = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreseveNewline, !whitespaceContentIsTreatedAsSingleSpace)) {
106+
ASSERT(whitespaceContent->length);
99107
auto appendWhitespaceItem = [&] (auto startPosition, auto itemLength) {
100108
auto simpleSingleWhitespaceContent = inlineTextBox.canUseSimplifiedContentMeasuring() && (itemLength == 1 || whitespaceContentIsTreatedAsSingleSpace);
101109
auto width = simpleSingleWhitespaceContent ? makeOptional(InlineLayoutUnit { font.spaceWidth() }) : inlineItemWidth(startPosition, itemLength);
102-
auto isWordSeparator = [&] {
103-
if (whitespaceContentIsTreatedAsSingleSpace)
104-
return true;
105-
if (itemLength != 1) {
106-
// FIXME: Add support for cases where the whitespace content contains different type of characters (e.g "\t \t \t").
107-
return false;
108-
}
109-
auto whitespaceCharacter = text[startPosition];
110-
return whitespaceCharacter == space
111-
|| whitespaceCharacter == noBreakSpace
112-
|| whitespaceCharacter == ethiopicWordspace
113-
|| whitespaceCharacter == aegeanWordSeparatorLine
114-
|| whitespaceCharacter == aegeanWordSeparatorDot
115-
|| whitespaceCharacter == ugariticWordDivider;
116-
}();
117-
inlineContent.append(InlineTextItem::createWhitespaceItem(inlineTextBox, startPosition, itemLength, isWordSeparator, width));
110+
inlineContent.append(InlineTextItem::createWhitespaceItem(inlineTextBox, startPosition, itemLength, whitespaceContent->isWordSeparator, width));
118111
};
119112
if (style.whiteSpace() == WhiteSpace::BreakSpaces) {
120113
// https://www.w3.org/TR/css-text-3/#white-space-phase-1
121114
// For break-spaces, a soft wrap opportunity exists after every space and every tab.
122115
// 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.
123-
for (size_t i = 0; i < length; ++i)
116+
for (size_t i = 0; i < whitespaceContent->length; ++i)
124117
appendWhitespaceItem(currentPosition + i, 1);
125118
} else
126-
appendWhitespaceItem(currentPosition, length);
127-
currentPosition += length;
119+
appendWhitespaceItem(currentPosition, whitespaceContent->length);
120+
currentPosition += whitespaceContent->length;
128121
continue;
129122
}
130123

Source/WebCore/layout/inlineformatting/InlineTextItem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ inline InlineTextItem InlineTextItem::createWhitespaceItem(const InlineTextBox&
7474

7575
inline InlineTextItem InlineTextItem::createNonWhitespaceItem(const InlineTextBox& inlineTextBox, unsigned start, unsigned length, bool hasTrailingSoftHyphen, Optional<InlineLayoutUnit> width)
7676
{
77+
// FIXME: Use the following list of non-whitespace characters to set the "isWordSeparator" bit: noBreakSpace, ethiopicWordspace, aegeanWordSeparatorLine aegeanWordSeparatorDot ugariticWordDivider.
7778
return { inlineTextBox, start, length, hasTrailingSoftHyphen, false, width, TextItemType::NonWhitespace };
7879
}
7980

0 commit comments

Comments
 (0)