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

Changeset 286541 in webkit


Ignore:
Timestamp:
Dec 6, 2021, 12:13:26 AM (5 years ago)
Author:
Antti Koivisto
Message:

[LFC][Integration] Use end bits in text box iterator
https://bugs.webkit.org/show_bug.cgi?id=233858

Reviewed by Alan Bujtas.

Make text box traversal work correctly in bidi context where encountering a different
layout box does not necessarily mean there are no further text boxes for the layout box.

  • layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp:

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

Set the bits for all box types.

  • layout/formattingContexts/inline/display/InlineDisplayBox.h:

(WebCore::InlineDisplay::Box::Box):
(WebCore::InlineDisplay::Box::isTextOrSoftLineBreak const):
(WebCore::InlineDisplay::Box::isFirstForLayoutBox const):
(WebCore::InlineDisplay::Box::isLastForLayoutBox const):
(WebCore::InlineDisplay::Box::setIsFirstForLayoutBox):
(WebCore::InlineDisplay::Box::setIsLastForLayoutBox):
(WebCore::InlineDisplay::Box::isFirstBox const): Deleted.
(WebCore::InlineDisplay::Box::isLastBox const): Deleted.
(WebCore::InlineDisplay::Box::setIsLastBox): Deleted.
(WebCore::InlineDisplay::Box::setIsFirstBox): Deleted.

Renamed for clarity and correctness.

  • layout/integration/InlineIteratorBoxModernPath.h:

(WebCore::InlineIterator::BoxModernPath::isText const):
(WebCore::InlineIterator::BoxModernPath::traverseNextTextBox):

Use the isLastForLayoutBox bit to end the traversal.

(WebCore::InlineIterator::BoxModernPath::traverseNextInlineBox):
(WebCore::InlineIterator::BoxModernPath::traversePreviousInlineBox):
(WebCore::InlineIterator::BoxModernPath::traverseNextWithSameLayoutBox):
(WebCore::InlineIterator::BoxModernPath::traversePreviousWithSameLayoutBox):

Factor into helpers.

  • layout/integration/InlineIteratorTextBox.h:
Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286538 r286541  
     12021-12-06  Antti Koivisto  <antti@apple.com>
     2
     3        [LFC][Integration] Use end bits in text box iterator
     4        https://bugs.webkit.org/show_bug.cgi?id=233858
     5
     6        Reviewed by Alan Bujtas.
     7
     8        Make text box traversal work correctly in bidi context where encountering a different
     9        layout box does not necessarily mean there are no further text boxes for the layout box.
     10
     11        * layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp:
     12        (WebCore::Layout::InlineDisplayContentBuilder::processBidiContent):
     13        (WebCore::Layout::InlineDisplayContentBuilder::computeIsFirstIsLastBoxForInlineContent):
     14
     15        Set the bits for all box types.
     16
     17        * layout/formattingContexts/inline/display/InlineDisplayBox.h:
     18        (WebCore::InlineDisplay::Box::Box):
     19        (WebCore::InlineDisplay::Box::isTextOrSoftLineBreak const):
     20        (WebCore::InlineDisplay::Box::isFirstForLayoutBox const):
     21        (WebCore::InlineDisplay::Box::isLastForLayoutBox const):
     22        (WebCore::InlineDisplay::Box::setIsFirstForLayoutBox):
     23        (WebCore::InlineDisplay::Box::setIsLastForLayoutBox):
     24        (WebCore::InlineDisplay::Box::isFirstBox const): Deleted.
     25        (WebCore::InlineDisplay::Box::isLastBox const): Deleted.
     26        (WebCore::InlineDisplay::Box::setIsLastBox): Deleted.
     27        (WebCore::InlineDisplay::Box::setIsFirstBox): Deleted.
     28
     29        Renamed for clarity and correctness.
     30
     31        * layout/integration/InlineIteratorBoxModernPath.h:
     32        (WebCore::InlineIterator::BoxModernPath::isText const):
     33        (WebCore::InlineIterator::BoxModernPath::traverseNextTextBox):
     34
     35        Use the isLastForLayoutBox bit to end the traversal.
     36
     37        (WebCore::InlineIterator::BoxModernPath::traverseNextInlineBox):
     38        (WebCore::InlineIterator::BoxModernPath::traversePreviousInlineBox):
     39        (WebCore::InlineIterator::BoxModernPath::traverseNextWithSameLayoutBox):
     40        (WebCore::InlineIterator::BoxModernPath::traversePreviousWithSameLayoutBox):
     41
     42        Factor into helpers.
     43
     44        * layout/integration/InlineIteratorTextBox.h:
     45
    1462021-12-05  Said Abou-Hallawa  <said@apple.com>
    247
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp

    r286534 r286541  
    479479                            auto isFirstFragment = !lastDisplayBoxForInlineBoxIndex;
    480480                            if (!isFirstFragment)
    481                                 boxes[lastDisplayBoxForInlineBoxIndex].setIsLastBox(false);
     481                                boxes[lastDisplayBoxForInlineBoxIndex].setIsLastForLayoutBox(false);
    482482                            inlineBoxDisplayBoxMap.set(inlineBox, index);
    483483
     
    535535                auto& boxGeometry = formattingState().boxGeometry(inlineBoxDisplayBox.layoutBox());
    536536                auto contentRight = displayBox.logicalRight();
    537                 if (inlineBoxDisplayBox.isLastBox()) {
     537                if (inlineBoxDisplayBox.isLastForLayoutBox()) {
    538538                    accumulatedOffset += boxGeometry.borderAndPaddingEnd() + boxGeometry.marginEnd();
    539539                    inlineBoxDisplayBox.setLogicalRight(contentRight + boxGeometry.borderAndPaddingEnd());
     
    541541                    inlineBoxDisplayBox.setLogicalRight(contentRight);
    542542            }
    543             if (displayBox.isNonRootInlineBox() && displayBox.isFirstBox()) {
     543            if (displayBox.isNonRootInlineBox() && displayBox.isFirstForLayoutBox()) {
    544544                auto& layoutBox = displayBox.layoutBox();
    545545                auto& boxGeometry = formattingState().boxGeometry(layoutBox);
     
    557557        for (auto& inlineBoxRange : inlineBoxRangeList) {
    558558            auto& inlineBoxDisplayBox = boxes[inlineBoxRange.begin()];
    559             setInlineBoxGeometry(inlineBoxDisplayBox.layoutBox(), inlineBoxDisplayBox.logicalRect(), inlineBoxDisplayBox.isFirstBox());
     559            setInlineBoxGeometry(inlineBoxDisplayBox.layoutBox(), inlineBoxDisplayBox.logicalRect(), inlineBoxDisplayBox.isFirstForLayoutBox());
    560560        }
    561561    };
     
    654654void InlineDisplayContentBuilder::computeIsFirstIsLastBoxForInlineContent(DisplayBoxes& boxes)
    655655{
    656     HashMap<const Box*, size_t> lastDisplayBoxForInlineTextBoxIndexes;
     656    HashMap<const Box*, size_t> lastDisplayBoxForLayoutBoxIndexes;
     657
    657658    ASSERT(boxes[0].isRootInlineBox());
     659    boxes[0].setIsFirstForLayoutBox(true);
     660    size_t lastRootInlineBoxIndex = 0;
     661
    658662    for (size_t index = 1; index < boxes.size(); ++index) {
    659663        auto& displayBox = boxes[index];
    660         // FIXME: Transition the inline box isFirst/isLast computation here as well.
    661         if (!displayBox.isText())
    662             continue;
     664        if (displayBox.isRootInlineBox()) {
     665            lastRootInlineBoxIndex = index;
     666            continue;
     667        }
    663668        auto& layoutBox = displayBox.layoutBox();
    664         if (!lastDisplayBoxForInlineTextBoxIndexes.contains(&layoutBox))
    665             displayBox.setIsFirstBox(true);
    666         lastDisplayBoxForInlineTextBoxIndexes.set(&layoutBox, index);
    667     }
    668     for (auto lastDisplayBoxForInlineTextBoxIndex : lastDisplayBoxForInlineTextBoxIndexes)
    669         boxes[lastDisplayBoxForInlineTextBoxIndex.value].setIsLastBox(true);
     669        if (lastDisplayBoxForLayoutBoxIndexes.set(&layoutBox, index).isNewEntry)
     670            displayBox.setIsFirstForLayoutBox(true);
     671    }
     672    for (auto index : lastDisplayBoxForLayoutBoxIndexes.values())
     673        boxes[index].setIsLastForLayoutBox(true);
     674
     675    boxes[lastRootInlineBoxIndex].setIsLastForLayoutBox(true);
    670676}
    671677
  • trunk/Source/WebCore/layout/formattingContexts/inline/display/InlineDisplayBox.h

    r286534 r286541  
    7575        Last  = 1 << 1
    7676    };
    77     Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const Layout::InlineRect&, const Layout::InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, OptionSet<PositionWithinInlineLevelBox> = { PositionWithinInlineLevelBox::First, PositionWithinInlineLevelBox::Last });
     77    Box(size_t lineIndex, Type, const Layout::Box&, UBiDiLevel, const Layout::InlineRect&, const Layout::InlineRect& inkOverflow, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, OptionSet<PositionWithinInlineLevelBox> = { });
    7878
    7979    bool isText() const { return m_type == Type::Text; }
    8080    bool isEllipsis() const { return m_type == Type::Ellipsis; }
    8181    bool isSoftLineBreak() const { return m_type == Type::SoftLineBreak; }
     82    bool isTextOrSoftLineBreak() const { return isText() || isSoftLineBreak(); }
    8283    bool isLineBreakBox() const { return m_type == Type::LineBreakBox; }
    8384    bool isLineBreak() const { return isSoftLineBreak() || isLineBreakBox(); }
     
    106107    Layout::InlineLayoutUnit logicalHeight() const { return logicalRect().height(); }
    107108
    108     void moveVertically(Layout::InlineLayoutUnit offset) { m_logicalRect.moveVertically(offset); }
    109     void moveHorizontally(Layout::InlineLayoutUnit offset) { m_logicalRect.moveHorizontally(offset); }
     109    void moveVertically(Layout::InlineLayoutUnit offset)
     110    {
     111        m_logicalRect.moveVertically(offset);
     112        m_inkOverflow.moveVertically(offset);
     113    }
     114    void moveHorizontally(Layout::InlineLayoutUnit offset)
     115    {
     116        m_logicalRect.moveHorizontally(offset);
     117        m_inkOverflow.moveHorizontally(offset);
     118    }
    110119    void adjustInkOverflow(const Layout::InlineRect& childBorderBox) { return m_inkOverflow.expandToContain(childBorderBox); }
    111120    void truncate(Layout::InlineLayoutUnit truncatedwidth = 0.f);
     
    127136    // These functions tell you whether this display box is the first/last for the associated inline level box (Layout::Box) and not whether it's the first/last box on the line.
    128137    // (e.g. always true for atomic boxes, but inline boxes spanning over multiple lines can produce individual first/last boxes).
    129     bool isFirstBox() const { return m_isFirstWithinInlineLevelBox; }
    130     bool isLastBox() const { return m_isLastWithinInlineLevelBox; }
     138    bool isFirstForLayoutBox() const { return m_isFirstForLayoutBox; }
     139    bool isLastForLayoutBox() const { return m_isLastForLayoutBox; }
    131140
    132     void setIsLastBox(bool isLastBox) { m_isLastWithinInlineLevelBox = isLastBox; }
    133     void setIsFirstBox(bool isFirstBox) { m_isFirstWithinInlineLevelBox = isFirstBox; }
     141    void setIsFirstForLayoutBox(bool isFirstBox) { m_isFirstForLayoutBox = isFirstBox; }
     142    void setIsLastForLayoutBox(bool isLastBox) { m_isLastForLayoutBox = isLastBox; }
    134143
    135144private:
     
    141150    Layout::InlineRect m_inkOverflow;
    142151    bool m_hasContent : 1;
    143     bool m_isFirstWithinInlineLevelBox : 1;
    144     bool m_isLastWithinInlineLevelBox : 1;
     152    bool m_isFirstForLayoutBox : 1;
     153    bool m_isLastForLayoutBox : 1;
    145154    Expansion m_expansion;
    146155    std::optional<Text> m_text;
     
    155164    , m_inkOverflow(inkOverflow)
    156165    , m_hasContent(hasContent)
    157     , m_isFirstWithinInlineLevelBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::First))
    158     , m_isLastWithinInlineLevelBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::Last))
     166    , m_isFirstForLayoutBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::First))
     167    , m_isLastForLayoutBox(positionWithinInlineLevelBox.contains(PositionWithinInlineLevelBox::Last))
    159168    , m_expansion(expansion)
    160169    , m_text(text)
  • trunk/Source/WebCore/layout/integration/InlineIteratorBoxModernPath.h

    r286113 r286541  
    4949    }
    5050
    51     bool isText() const { return !!box().text(); }
     51    bool isText() const { return box().isTextOrSoftLineBreak(); }
    5252    bool isInlineBox() const { return box().isInlineBox(); }
    5353    bool isRootInlineBox() const { return box().isRootInlineBox(); }
     
    107107    {
    108108        ASSERT(!atEnd());
    109         ASSERT(box().text());
    110 
    111         auto& layoutBox = box().layoutBox();
     109        ASSERT(box().isTextOrSoftLineBreak());
     110
     111        if (box().isLastForLayoutBox()) {
     112            setAtEnd();
     113            return;
     114        }
     115
     116        traverseNextWithSameLayoutBox();
     117
     118        ASSERT(box().isTextOrSoftLineBreak());
     119    }
     120
     121    void traverseNextOnLine()
     122    {
     123        ASSERT(!atEnd());
     124
     125        auto oldLineIndex = box().lineIndex();
    112126
    113127        traverseNextLeaf();
    114128
    115         if (!atEnd() && &layoutBox != &box().layoutBox())
    116             setAtEnd();
    117 
    118         ASSERT(atEnd() || box().text());
    119     }
    120 
    121     void traverseNextOnLine()
     129        if (!atEnd() && oldLineIndex != box().lineIndex())
     130            setAtEnd();
     131    }
     132
     133    void traversePreviousOnLine()
    122134    {
    123135        ASSERT(!atEnd());
     
    125137        auto oldLineIndex = box().lineIndex();
    126138
    127         traverseNextLeaf();
     139        traversePreviousLeaf();
    128140
    129141        if (!atEnd() && oldLineIndex != box().lineIndex())
     
    131143    }
    132144
    133     void traversePreviousOnLine()
    134     {
    135         ASSERT(!atEnd());
    136 
    137         auto oldLineIndex = box().lineIndex();
    138 
    139         traversePreviousLeaf();
    140 
    141         if (!atEnd() && oldLineIndex != box().lineIndex())
    142             setAtEnd();
    143     }
    144 
    145145    void traverseNextInlineBox()
    146146    {
    147         ASSERT(box().isInlineBox());
    148 
    149         if (box().isLastBox()) {
     147        ASSERT(!atEnd());
     148        ASSERT(box().isInlineBox());
     149
     150        if (box().isLastForLayoutBox()) {
    150151            setAtEnd();
    151152            return;
    152153        }
    153154
    154         auto& layoutBox = box().layoutBox();
    155         do {
    156             traverseNextBox();
    157         } while (!atEnd() && &box().layoutBox() != &layoutBox);
    158 
    159         ASSERT(atEnd() || box().isInlineBox());
     155        traverseNextWithSameLayoutBox();
     156
     157        ASSERT(box().isInlineBox());
    160158    }
    161159
    162160    void traversePreviousInlineBox()
    163161    {
    164         ASSERT(box().isInlineBox());
    165 
    166         if (box().isFirstBox()) {
     162        ASSERT(!atEnd());
     163        ASSERT(box().isInlineBox());
     164
     165        if (box().isFirstForLayoutBox()) {
    167166            setAtEnd();
    168167            return;
    169168        }
    170169
    171         auto& layoutBox = box().layoutBox();
    172         do {
    173             traversePreviousBox();
    174         } while (!atEnd() && &box().layoutBox() != &layoutBox);
    175 
    176         ASSERT(atEnd() || box().isInlineBox());
     170        traversePreviousWithSameLayoutBox();
     171
     172        ASSERT(box().isInlineBox());
    177173    }
    178174
     
    250246    }
    251247
     248    void traverseNextWithSameLayoutBox()
     249    {
     250        auto& layoutBox = box().layoutBox();
     251        do {
     252            traverseNextBox();
     253        } while (!atEnd() && &box().layoutBox() != &layoutBox);
     254    }
     255
     256    void traversePreviousWithSameLayoutBox()
     257    {
     258        auto& layoutBox = box().layoutBox();
     259        do {
     260            traversePreviousBox();
     261        } while (!atEnd() && &box().layoutBox() != &layoutBox);
     262    }
     263
    252264    void setAtEnd() { m_boxIndex = boxes().size(); }
    253265
  • trunk/Source/WebCore/layout/integration/InlineIteratorTextBox.h

    r285938 r286541  
    6060    const LegacyInlineTextBox* legacyInlineBox() const { return downcast<LegacyInlineTextBox>(Box::legacyInlineBox()); }
    6161
     62    // This returns the next text box generated for the same RenderText/Layout::InlineTextBox.
    6263    TextBoxIterator nextTextBox() const;
    63     TextBoxIterator previousTextBox() const;
    6464};
    6565
     
    7575    const TextBox* operator->() const { return &get(); }
    7676
     77    // This traverses to the next text box generated for the same RenderText/Layout::InlineTextBox.
    7778    TextBoxIterator& traverseNextTextBox();
    7879
  • trunk/Source/WebCore/layout/integration/LayoutIntegrationPagination.cpp

    r285083 r286541  
    143143    auto adjustedBox = [&](const InlineDisplay::Box& box, float offset)
    144144    {
    145         return InlineDisplay::Box {
    146             box.lineIndex(),
    147             box.type(),
    148             box.layoutBox(),
    149             box.bidiLevel(),
    150             moveVertically(box.logicalRect(), offset),
    151             moveVertically(box.inkOverflow(), offset),
    152             box.expansion(),
    153             box.text()
    154         };
     145        auto adjustedBox = box;
     146        adjustedBox.moveVertically(offset);
     147        return adjustedBox;
    155148    };
    156149
Note: See TracChangeset for help on using the changeset viewer.