Title: [286104] trunk/Source/WebCore
Revision
286104
Author
za...@apple.com
Date
2021-11-21 12:43:00 -0800 (Sun, 21 Nov 2021)

Log Message

[LFC][IFC] Add support for caching bidi InlineTextItem widths
https://bugs.webkit.org/show_bug.cgi?id=233402

Reviewed by Antti Koivisto.

Let's do a "text content measure" pass when the inline item boundaries are finalized (including bidi split).

* layout/formattingContexts/inline/InlineItem.h:
(WebCore::Layout::InlineItem::setWidth):
* layout/formattingContexts/inline/InlineItemsBuilder.cpp:
(WebCore::Layout::InlineItemsBuilder::build):
(WebCore::Layout::InlineItemsBuilder::computeInlineTextItemWidths):
(WebCore::Layout::InlineItemsBuilder::handleTextContent):
* layout/formattingContexts/inline/InlineItemsBuilder.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (286103 => 286104)


--- trunk/Source/WebCore/ChangeLog	2021-11-21 20:10:00 UTC (rev 286103)
+++ trunk/Source/WebCore/ChangeLog	2021-11-21 20:43:00 UTC (rev 286104)
@@ -1,5 +1,22 @@
 2021-11-21  Alan Bujtas  <za...@apple.com>
 
+        [LFC][IFC] Add support for caching bidi InlineTextItem widths
+        https://bugs.webkit.org/show_bug.cgi?id=233402
+
+        Reviewed by Antti Koivisto.
+
+        Let's do a "text content measure" pass when the inline item boundaries are finalized (including bidi split).
+
+        * layout/formattingContexts/inline/InlineItem.h:
+        (WebCore::Layout::InlineItem::setWidth):
+        * layout/formattingContexts/inline/InlineItemsBuilder.cpp:
+        (WebCore::Layout::InlineItemsBuilder::build):
+        (WebCore::Layout::InlineItemsBuilder::computeInlineTextItemWidths):
+        (WebCore::Layout::InlineItemsBuilder::handleTextContent):
+        * layout/formattingContexts/inline/InlineItemsBuilder.h:
+
+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
 

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h (286103 => 286104)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h	2021-11-21 20:10:00 UTC (rev 286103)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h	2021-11-21 20:43:00 UTC (rev 286104)
@@ -70,6 +70,7 @@
     friend class InlineItemsBuilder;
 
     void setBidiLevel(UBiDiLevel bidiLevel) { m_bidiLevel = bidiLevel; }
+    void setWidth(InlineLayoutUnit);
 
     const Box* m_layoutBox { nullptr };
     Type m_type { };
@@ -96,6 +97,12 @@
 {
 }
 
+inline void InlineItem::setWidth(InlineLayoutUnit width)
+{
+    m_width = width;
+    m_hasWidth = true;
+}
+
 #define SPECIALIZE_TYPE_TRAITS_INLINE_ITEM(ToValueTypeName, predicate) \
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Layout::ToValueTypeName) \
     static bool isType(const WebCore::Layout::InlineItem& inlineItem) { return inlineItem.predicate; } \

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp (286103 => 286104)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp	2021-11-21 20:10:00 UTC (rev 286103)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp	2021-11-21 20:43:00 UTC (rev 286104)
@@ -88,6 +88,7 @@
     collectInlineItems(inlineItems);
     if (hasSeenBidiContent())
         breakAndComputeBidiLevels(inlineItems);
+    computeInlineTextItemWidths(inlineItems);
     return inlineItems;
 }
 
@@ -367,6 +368,32 @@
     return true;
 }
 
+void InlineItemsBuilder::computeInlineTextItemWidths(InlineItems& inlineItems)
+{
+    for (auto& inlineItem : inlineItems) {
+        if (!inlineItem.isText())
+            continue;
+
+        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
+        auto& inlineTextBox = inlineTextItem.inlineTextBox();
+        auto start = inlineTextItem.start();
+        auto length = inlineTextItem.length();
+        if (!canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, start, length, inlineTextItem.isWhitespace()))
+            continue;
+
+        auto width = [&]() -> std::optional<InlineLayoutUnit> {
+            auto singleWhiteSpace = inlineTextItem.isWhitespace() && (!TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox) || (length == 1 && inlineTextBox.canUseSimplifiedContentMeasuring()));
+            if (singleWhiteSpace)
+                return inlineTextItem.style().fontCascade().spaceWidth();
+            if (length && !inlineTextItem.isZeroWidthSpaceSeparator())
+                return TextUtil::width(inlineTextBox, inlineTextItem.style().fontCascade(), start, start + length, { });
+            return { };
+        }();
+        if (width)
+            inlineTextItem.setWidth(*width);
+    }
+}
+
 void InlineItemsBuilder::handleTextContent(const InlineTextBox& inlineTextBox, InlineItems& inlineItems)
 {
     auto text = inlineTextBox.content();
@@ -378,10 +405,7 @@
         m_hasSeenBidiContent = true;
 
     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);
     auto shouldTreatNonBreakingSpaceAsRegularSpace = style.nbspMode() == NBSPMode::Space;
     auto lineBreakIterator = LazyLineBreakIterator { text, style.computedLocale(), TextUtil::lineBreakIteratorMode(style.lineBreak()) };
@@ -400,30 +424,20 @@
             continue;
 
         auto handleWhitespace = [&] {
-            auto stopAtWordSeparatorBoundary = shouldPreserveSpacesAndTabs && fontCascade.wordSpacing();
+            auto stopAtWordSeparatorBoundary = shouldPreserveSpacesAndTabs && style.fontCascade().wordSpacing();
             auto whitespaceContent = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreserveNewline, shouldPreserveSpacesAndTabs, shouldTreatNonBreakingSpaceAsRegularSpace, stopAtWordSeparatorBoundary);
             if (!whitespaceContent)
                 return false;
 
             ASSERT(whitespaceContent->length);
-            auto appendWhitespaceItem = [&] (auto startPosition, auto 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) {
                 // 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 < whitespaceContent->length; ++i)
-                    appendWhitespaceItem(currentPosition + i, 1);
+                    inlineItems.append(InlineTextItem::createWhitespaceItem(inlineTextBox, currentPosition + i, 1, UBIDI_DEFAULT_LTR, whitespaceContent->isWordSeparator, { }));
             } else
-                appendWhitespaceItem(currentPosition, whitespaceContent->length);
+                inlineItems.append(InlineTextItem::createWhitespaceItem(inlineTextBox, currentPosition, whitespaceContent->length, UBIDI_DEFAULT_LTR, whitespaceContent->isWordSeparator, { }));
             currentPosition += whitespaceContent->length;
             return true;
         };
@@ -446,14 +460,7 @@
                 hasTrailingSoftHyphen = text[endPosition - 1] == softHyphen;
             }
             ASSERT_IMPLIES(style.hyphens() == Hyphens::None, !hasTrailingSoftHyphen);
-            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));
+            inlineItems.append(InlineTextItem::createNonWhitespaceItem(inlineTextBox, startPosition, endPosition - startPosition, UBIDI_DEFAULT_LTR, hasTrailingSoftHyphen, { }));
             currentPosition = endPosition;
             return true;
         };

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.h (286103 => 286104)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.h	2021-11-21 20:10:00 UTC (rev 286103)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.h	2021-11-21 20:43:00 UTC (rev 286104)
@@ -43,6 +43,7 @@
 private:
     void collectInlineItems(InlineItems&);
     void breakAndComputeBidiLevels(InlineItems&);
+    void computeInlineTextItemWidths(InlineItems&);
 
     void handleTextContent(const InlineTextBox&, InlineItems&);
     void handleInlineBoxStart(const Box&, InlineItems&);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to