Modified: trunk/Source/WebCore/ChangeLog (286100 => 286101)
--- trunk/Source/WebCore/ChangeLog 2021-11-21 18:22:01 UTC (rev 286100)
+++ trunk/Source/WebCore/ChangeLog 2021-11-21 18:33:06 UTC (rev 286101)
@@ -1,3 +1,19 @@
+2021-11-21 Alan Bujtas <za...@apple.com>
+
+ [LFC][IFC] Cache measured width even if canUseSimplifiedTextMeasuring is false
+ https://bugs.webkit.org/show_bug.cgi?id=233404
+
+ Reviewed by Antti Koivisto.
+
+ Just because some content goes through the non-simplified text measuring codepath, it does not
+ necessary mean we can't cache the measured value on the inline item (actually, we can cache these values just fine in most cases).
+
+ This is in preparation for being able to cache bidi content measured widths.
+
+ * layout/formattingContexts/inline/InlineItemsBuilder.cpp:
+ (WebCore::Layout::canCacheMeasuredWidthOnInlineTextItem):
+ (WebCore::Layout::InlineItemsBuilder::handleTextContent):
+
2021-11-21 Ziran Sun <z...@igalia.com>
[css-grid] svg image as grid items should use the overriding logical width/height when defined to compute the logical height/width
Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp (286100 => 286101)
--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp 2021-11-21 18:22:01 UTC (rev 286100)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp 2021-11-21 18:33:06 UTC (rev 286101)
@@ -349,12 +349,22 @@
setBidiLevelForOpaqueInlineItems();
}
-static inline bool canCacheMeasuredWidthOnInlineTextItem(const InlineTextBox& inlineTextBox)
+static inline bool canCacheMeasuredWidthOnInlineTextItem(const InlineTextBox& inlineTextBox, size_t start, size_t length, bool isWhitespace)
{
- // FIXME: Disable width caching for position dependent content only.
- if (!inlineTextBox.canUseSimplifiedContentMeasuring())
+ // Do not cache when:
+ // 1. first-line style's unique font properties may produce non-matching width values.
+ // 2. position dependent content is present (preserved tab character atm).
+ if (inlineTextBox.style().fontCascade() != inlineTextBox.firstLineStyle().fontCascade())
return false;
- return inlineTextBox.style().fontCascade() == inlineTextBox.firstLineStyle().fontCascade();
+ if (!isWhitespace || !TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox))
+ return true;
+ // FIXME: Currently we opt out of caching only when we see a preserved \t character (position dependent measured width).
+ auto textContent = inlineTextBox.content();
+ for (auto index = start; index < start + length; ++index) {
+ if (textContent[index] == tabCharacter)
+ return false;
+ }
+ return true;
}
void InlineItemsBuilder::handleTextContent(const InlineTextBox& inlineTextBox, InlineItems& inlineItems)
@@ -369,6 +379,7 @@
auto& style = inlineTextBox.style();
auto& fontCascade = style.fontCascade();
+ auto whiteSpaceWidth = std::optional<InlineLayoutUnit> { fontCascade.spaceWidth() };
auto shouldPreserveSpacesAndTabs = TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox);
auto whitespaceContentIsTreatedAsSingleSpace = !shouldPreserveSpacesAndTabs;
auto shouldPreserveNewline = TextUtil::shouldPreserveNewline(inlineTextBox);
@@ -376,13 +387,6 @@
auto lineBreakIterator = LazyLineBreakIterator { text, style.computedLocale(), TextUtil::lineBreakIteratorMode(style.lineBreak()) };
unsigned currentPosition = 0;
- auto textWidth = [&](auto startPosition, auto length) -> std::optional<InlineLayoutUnit> {
- // Delay content measuring until after bidi split.
- if (hasSeenBidiContent() || !canCacheMeasuredWidthOnInlineTextItem(inlineTextBox))
- return { };
- return TextUtil::width(inlineTextBox, fontCascade, startPosition, startPosition + length, { });
- };
-
while (currentPosition < contentLength) {
auto handleSegmentBreak = [&] {
// Segment breaks with preserve new line style (white-space: pre, pre-wrap, break-spaces and pre-line) compute to forced line break.
@@ -403,8 +407,13 @@
ASSERT(whitespaceContent->length);
auto appendWhitespaceItem = [&] (auto startPosition, auto itemLength) {
- auto simpleSingleWhitespaceContent = inlineTextBox.canUseSimplifiedContentMeasuring() && (itemLength == 1 || whitespaceContentIsTreatedAsSingleSpace);
- auto width = simpleSingleWhitespaceContent ? std::make_optional(InlineLayoutUnit { fontCascade.spaceWidth() }) : textWidth(startPosition, itemLength);
+ auto width = [&]() -> std::optional<InlineLayoutUnit> {
+ if (!canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, startPosition, itemLength, true))
+ return { };
+ if (whitespaceContentIsTreatedAsSingleSpace || (itemLength == 1 && inlineTextBox.canUseSimplifiedContentMeasuring()))
+ return whiteSpaceWidth;
+ return TextUtil::width(inlineTextBox, fontCascade, startPosition, startPosition + itemLength, { });
+ }();
inlineItems.append(InlineTextItem::createWhitespaceItem(inlineTextBox, startPosition, itemLength, UBIDI_DEFAULT_LTR, whitespaceContent->isWordSeparator, width));
};
if (style.whiteSpace() == WhiteSpace::BreakSpaces) {
@@ -437,10 +446,15 @@
hasTrailingSoftHyphen = text[endPosition - 1] == softHyphen;
}
ASSERT_IMPLIES(style.hyphens() == Hyphens::None, !hasTrailingSoftHyphen);
- auto inlineItemLength = endPosition - startPosition;
- inlineItems.append(InlineTextItem::createNonWhitespaceItem(inlineTextBox, startPosition, inlineItemLength, UBIDI_DEFAULT_LTR, hasTrailingSoftHyphen, textWidth(startPosition, inlineItemLength)));
+ auto length = endPosition - startPosition;
+ auto textWidth = [&]() -> std::optional<InlineLayoutUnit> {
+ // Delay non-whitespace content measuring until after bidi split.
+ if (hasSeenBidiContent() || !canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, startPosition, length, false))
+ return { };
+ return TextUtil::width(inlineTextBox, fontCascade, startPosition, endPosition, { });
+ }();
+ inlineItems.append(InlineTextItem::createNonWhitespaceItem(inlineTextBox, startPosition, length, UBIDI_DEFAULT_LTR, hasTrailingSoftHyphen, textWidth));
currentPosition = endPosition;
-
return true;
};
if (handleNonWhitespace())