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 };
}