⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286104 in webkit


Ignore:
Timestamp:
Nov 21, 2021, 12:43:00 PM (5 years ago)
Author:
Alan Bujtas
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:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286101 r286104  
     12021-11-21  Alan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Add support for caching bidi InlineTextItem widths
     4        https://bugs.webkit.org/show_bug.cgi?id=233402
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Let's do a "text content measure" pass when the inline item boundaries are finalized (including bidi split).
     9
     10        * layout/formattingContexts/inline/InlineItem.h:
     11        (WebCore::Layout::InlineItem::setWidth):
     12        * layout/formattingContexts/inline/InlineItemsBuilder.cpp:
     13        (WebCore::Layout::InlineItemsBuilder::build):
     14        (WebCore::Layout::InlineItemsBuilder::computeInlineTextItemWidths):
     15        (WebCore::Layout::InlineItemsBuilder::handleTextContent):
     16        * layout/formattingContexts/inline/InlineItemsBuilder.h:
     17
    1182021-11-21  Alan Bujtas  <zalan@apple.com>
    219
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h

    r285119 r286104  
    7171
    7272    void setBidiLevel(UBiDiLevel bidiLevel) { m_bidiLevel = bidiLevel; }
     73    void setWidth(InlineLayoutUnit);
    7374
    7475    const Box* m_layoutBox { nullptr };
     
    9798}
    9899
     100inline void InlineItem::setWidth(InlineLayoutUnit width)
     101{
     102    m_width = width;
     103    m_hasWidth = true;
     104}
     105
    99106#define SPECIALIZE_TYPE_TRAITS_INLINE_ITEM(ToValueTypeName, predicate) \
    100107SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::Layout::ToValueTypeName) \
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp

    r286101 r286104  
    8989    if (hasSeenBidiContent())
    9090        breakAndComputeBidiLevels(inlineItems);
     91    computeInlineTextItemWidths(inlineItems);
    9192    return inlineItems;
    9293}
     
    368369}
    369370
     371void InlineItemsBuilder::computeInlineTextItemWidths(InlineItems& inlineItems)
     372{
     373    for (auto& inlineItem : inlineItems) {
     374        if (!inlineItem.isText())
     375            continue;
     376
     377        auto& inlineTextItem = downcast<InlineTextItem>(inlineItem);
     378        auto& inlineTextBox = inlineTextItem.inlineTextBox();
     379        auto start = inlineTextItem.start();
     380        auto length = inlineTextItem.length();
     381        if (!canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, start, length, inlineTextItem.isWhitespace()))
     382            continue;
     383
     384        auto width = [&]() -> std::optional<InlineLayoutUnit> {
     385            auto singleWhiteSpace = inlineTextItem.isWhitespace() && (!TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox) || (length == 1 && inlineTextBox.canUseSimplifiedContentMeasuring()));
     386            if (singleWhiteSpace)
     387                return inlineTextItem.style().fontCascade().spaceWidth();
     388            if (length && !inlineTextItem.isZeroWidthSpaceSeparator())
     389                return TextUtil::width(inlineTextBox, inlineTextItem.style().fontCascade(), start, start + length, { });
     390            return { };
     391        }();
     392        if (width)
     393            inlineTextItem.setWidth(*width);
     394    }
     395}
     396
    370397void InlineItemsBuilder::handleTextContent(const InlineTextBox& inlineTextBox, InlineItems& inlineItems)
    371398{
     
    379406
    380407    auto& style = inlineTextBox.style();
    381     auto& fontCascade = style.fontCascade();
    382     auto whiteSpaceWidth = std::optional<InlineLayoutUnit> { fontCascade.spaceWidth() };
    383408    auto shouldPreserveSpacesAndTabs = TextUtil::shouldPreserveSpacesAndTabs(inlineTextBox);
    384     auto whitespaceContentIsTreatedAsSingleSpace = !shouldPreserveSpacesAndTabs;
    385409    auto shouldPreserveNewline = TextUtil::shouldPreserveNewline(inlineTextBox);
    386410    auto shouldTreatNonBreakingSpaceAsRegularSpace = style.nbspMode() == NBSPMode::Space;
     
    401425
    402426        auto handleWhitespace = [&] {
    403             auto stopAtWordSeparatorBoundary = shouldPreserveSpacesAndTabs && fontCascade.wordSpacing();
     427            auto stopAtWordSeparatorBoundary = shouldPreserveSpacesAndTabs && style.fontCascade().wordSpacing();
    404428            auto whitespaceContent = moveToNextNonWhitespacePosition(text, currentPosition, shouldPreserveNewline, shouldPreserveSpacesAndTabs, shouldTreatNonBreakingSpaceAsRegularSpace, stopAtWordSeparatorBoundary);
    405429            if (!whitespaceContent)
     
    407431
    408432            ASSERT(whitespaceContent->length);
    409             auto appendWhitespaceItem = [&] (auto startPosition, auto itemLength) {
    410                 auto width = [&]() -> std::optional<InlineLayoutUnit> {
    411                     if (!canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, startPosition, itemLength, true))
    412                         return { };
    413                     if (whitespaceContentIsTreatedAsSingleSpace || (itemLength == 1 && inlineTextBox.canUseSimplifiedContentMeasuring()))
    414                         return whiteSpaceWidth;
    415                     return TextUtil::width(inlineTextBox, fontCascade, startPosition, startPosition + itemLength, { });
    416                 }();
    417                 inlineItems.append(InlineTextItem::createWhitespaceItem(inlineTextBox, startPosition, itemLength, UBIDI_DEFAULT_LTR, whitespaceContent->isWordSeparator, width));
    418             };
    419433            if (style.whiteSpace() == WhiteSpace::BreakSpaces) {
    420434                // https://www.w3.org/TR/css-text-3/#white-space-phase-1
     
    422436                // 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.
    423437                for (size_t i = 0; i < whitespaceContent->length; ++i)
    424                     appendWhitespaceItem(currentPosition + i, 1);
     438                    inlineItems.append(InlineTextItem::createWhitespaceItem(inlineTextBox, currentPosition + i, 1, UBIDI_DEFAULT_LTR, whitespaceContent->isWordSeparator, { }));
    425439            } else
    426                 appendWhitespaceItem(currentPosition, whitespaceContent->length);
     440                inlineItems.append(InlineTextItem::createWhitespaceItem(inlineTextBox, currentPosition, whitespaceContent->length, UBIDI_DEFAULT_LTR, whitespaceContent->isWordSeparator, { }));
    427441            currentPosition += whitespaceContent->length;
    428442            return true;
     
    447461            }
    448462            ASSERT_IMPLIES(style.hyphens() == Hyphens::None, !hasTrailingSoftHyphen);
    449             auto length = endPosition - startPosition;
    450             auto textWidth = [&]() -> std::optional<InlineLayoutUnit> {
    451                 // Delay non-whitespace content measuring until after bidi split.
    452                 if (hasSeenBidiContent() || !canCacheMeasuredWidthOnInlineTextItem(inlineTextBox, startPosition, length, false))
    453                     return { };
    454                 return TextUtil::width(inlineTextBox, fontCascade, startPosition, endPosition, { });
    455             }();
    456             inlineItems.append(InlineTextItem::createNonWhitespaceItem(inlineTextBox, startPosition, length, UBIDI_DEFAULT_LTR, hasTrailingSoftHyphen, textWidth));
     463            inlineItems.append(InlineTextItem::createNonWhitespaceItem(inlineTextBox, startPosition, endPosition - startPosition, UBIDI_DEFAULT_LTR, hasTrailingSoftHyphen, { }));
    457464            currentPosition = endPosition;
    458465            return true;
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.h

    r285369 r286104  
    4444    void collectInlineItems(InlineItems&);
    4545    void breakAndComputeBidiLevels(InlineItems&);
     46    void computeInlineTextItemWidths(InlineItems&);
    4647
    4748    void handleTextContent(const InlineTextBox&, InlineItems&);
Note: See TracChangeset for help on using the changeset viewer.