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

Changeset 286801 in webkit


Ignore:
Timestamp:
Dec 9, 2021, 1:28:22 PM (5 years ago)
Author:
Alan Bujtas
Message:

[LFC][IFC] Try not to include non-content type of inline boxes in the visual reordering
https://bugs.webkit.org/show_bug.cgi?id=234033

Reviewed by Antti Koivisto.

In InlineItemsBuilder::setBidiLevelForOpaqueInlineItems we try to figure out the bidi
level for inline box markers (<span> and </span>) mostly to be able to position
empty inline boxes (specifically with decorations). In some cases though the guessed
bidi level breaks the continuation between the content before and after the marker (e.g. before</span>after)
In this patch we try to limit the number of items associated with this guessed bidi level.

  • layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp:

(WebCore::Layout::InlineDisplayContentBuilder::processBidiContent):

  • layout/formattingContexts/inline/InlineItem.h:
  • layout/formattingContexts/inline/InlineItemsBuilder.cpp:

(WebCore::Layout::InlineItemsBuilder::breakAndComputeBidiLevels):

  • layout/formattingContexts/inline/InlineLineBuilder.cpp:

(WebCore::Layout::LineBuilder::layoutInlineContent): we may only submit a subset of runs to the reordering
algorithm. It also means we may end up with gaps between the visual index values and the real run item indexes.
The runIndexOffsetMap ensures that the indexes are always consistent with the content in the lineRuns vector.

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286799 r286801  
     12021-12-09  Alan Bujtas  <zalan@apple.com>
     2
     3        [LFC][IFC] Try not to include non-content type of inline boxes in the visual reordering
     4        https://bugs.webkit.org/show_bug.cgi?id=234033
     5
     6        Reviewed by Antti Koivisto.
     7
     8        In InlineItemsBuilder::setBidiLevelForOpaqueInlineItems we try to figure out the bidi
     9        level for inline box markers (<span> and </span>) mostly to be able to position
     10        empty inline boxes (specifically with decorations). In some cases though the guessed
     11        bidi level breaks the continuation between the content before and after the marker (e.g.  before</span>after)
     12        In this patch we try to limit the number of items associated with this guessed bidi level.
     13
     14        * layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp:
     15        (WebCore::Layout::InlineDisplayContentBuilder::processBidiContent):
     16        * layout/formattingContexts/inline/InlineItem.h:
     17        * layout/formattingContexts/inline/InlineItemsBuilder.cpp:
     18        (WebCore::Layout::InlineItemsBuilder::breakAndComputeBidiLevels):
     19        * layout/formattingContexts/inline/InlineLineBuilder.cpp:
     20        (WebCore::Layout::LineBuilder::layoutInlineContent): we may only submit a subset of runs to the reordering
     21        algorithm. It also means we may end up with gaps between the visual index values and the real run item indexes.
     22        The runIndexOffsetMap ensures that the indexes are always consistent with the content in the lineRuns vector.
     23
    1242021-12-08  BJ Burg  <bburg@apple.com>
    225
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp

    r286789 r286801  
    461461void InlineDisplayContentBuilder::processBidiContent(const LineBuilder::LineContent& lineContent, const LineBox& lineBox, const InlineLayoutPoint& lineBoxLogicalTopLeft, DisplayBoxes& boxes)
    462462{
    463     ASSERT(lineContent.visualOrderList.size() == lineContent.runs.size());
     463    ASSERT(lineContent.visualOrderList.size() <= lineContent.runs.size());
    464464
    465465    AncestorStack ancestorStack;
     
    480480        auto contentRightInVisualOrder = contentStartInVisualOrder;
    481481        auto& runs = lineContent.runs;
    482         for (size_t i = 0; i < runs.size(); ++i) {
    483             auto visualIndex = lineContent.visualOrderList[i];
    484             auto& lineRun = runs[visualIndex];
     482        for (auto visualOrder : lineContent.visualOrderList) {
     483            ASSERT(runs[visualOrder].bidiLevel() != InlineItem::opaqueBidiLevel);
     484
     485            auto& lineRun = runs[visualOrder];
    485486            auto& layoutBox = lineRun.layoutBox();
    486487
    487             auto needsDisplayBox = !lineRun.isInlineBoxEnd() && !lineRun.isWordBreakOpportunity();
     488            auto needsDisplayBox = !lineRun.isWordBreakOpportunity();
    488489            if (!needsDisplayBox)
    489490                continue;
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h

    r286104 r286801  
    5252
    5353    Type type() const { return m_type; }
     54    static constexpr UBiDiLevel opaqueBidiLevel = 0xff;
    5455    UBiDiLevel bidiLevel() const { return m_bidiLevel; }
    5556    const Box& layoutBox() const { return *m_layoutBox; }
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineItemsBuilder.cpp

    r286104 r286801  
    334334            }
    335335            if (inlineItems[index].isInlineBoxEnd()) {
    336                 // Inline box end (e.g. </span>) also uses the content bidi level, but in this case it's the previous content.
    337                 auto previousBidiLevel = [&]() -> std::optional<UBiDiLevel> {
    338                     for (auto i = index; i--;) {
    339                         if (inlineItemOffsets[i])
    340                             return inlineItems[i].bidiLevel();
    341                     }
    342                     return { };
    343                 }();
    344                 inlineItems[index].setBidiLevel(previousBidiLevel.value_or(rootBidiLevel));
     336                // Let's not confuse ubidi with non-content entries. Opaque runs are excluded from the visual list.
     337                inlineItems[index].setBidiLevel(InlineItem::opaqueBidiLevel);
    345338                continue;
    346339            }
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp

    r285999 r286801  
    301301            return { };
    302302
    303         Vector<UBiDiLevel> runLevels(lineRuns.size());
    304         // FIXME: We may cache these values in Line, if it turns out to be a perf hit.
    305         for (size_t i = 0; i < lineRuns.size(); ++i)
    306             runLevels[i] = lineRuns[i].bidiLevel();
    307 
    308         Vector<int32_t> visualOrderList(lineRuns.size());
     303        Vector<UBiDiLevel> runLevels;
     304        runLevels.reserveInitialCapacity(lineRuns.size());
     305
     306        Vector<size_t> runIndexOffsetMap;
     307        runIndexOffsetMap.reserveInitialCapacity(lineRuns.size());
     308        auto hasOpaqueRun = false;
     309        for (size_t i = 0, accumulatedOffset = 0; i < lineRuns.size(); ++i) {
     310            if (lineRuns[i].bidiLevel() == InlineItem::opaqueBidiLevel) {
     311                ++accumulatedOffset;
     312                hasOpaqueRun = true;
     313                continue;
     314            }
     315            runLevels.append(lineRuns[i].bidiLevel());
     316            runIndexOffsetMap.append(accumulatedOffset);
     317        }
     318
     319        Vector<int32_t> visualOrderList(runLevels.size());
    309320        ubidi_reorderVisual(runLevels.data(), runLevels.size(), visualOrderList.data());
     321        if (hasOpaqueRun) {
     322            ASSERT(visualOrderList.size() == runIndexOffsetMap.size());
     323            for (size_t i = 0; i < runIndexOffsetMap.size(); ++i)
     324                visualOrderList[i] += runIndexOffsetMap[visualOrderList[i]];
     325        }
    310326        return visualOrderList;
    311327    };
Note: See TracChangeset for help on using the changeset viewer.