Changeset 286782 in webkit

Timestamp:
Dec 9, 2021, 9:10:03 AM (3 years ago)
Author:
Alan Bujtas
Message:

[LFC][IFC] Make collectInkOverflowForInlineBoxes propagate ink overflow using the display box list
https://bugs.webkit.org/show_bug.cgi?id=233950

Reviewed by Antti Koivisto.

This is in preparation for supporting ink overflow across bidi boundaries.

The current HashMap<const Box*, size_t> approach does not work when a layout box could
produce multiple inline box type of display boxes on the same line (at bidi boundaries).
Instead let's propagate ink overflow by traversing the display box list starting
at the end and bubble up the inflated ink overflow rect to the parent inline boxes.

  • layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp:

(WebCore::Layout::InlineDisplayContentBuilder::build):
(WebCore::Layout::computeBoxShadowInkOverflow):
(WebCore::Layout::InlineDisplayContentBuilder::appendAtomicInlineLevelDisplayBox):
(WebCore::Layout::InlineDisplayContentBuilder::appendInlineBoxDisplayBox):
(WebCore::Layout::InlineDisplayContentBuilder::appendSpanningInlineBoxDisplayBox):
(WebCore::Layout::InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes):
(WebCore::Layout::addBoxShadowInkOverflow): Deleted.

  • layout/formattingContexts/inline/InlineDisplayContentBuilder.h:
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286780 r286782  
     1
     2
     3
     4
     5
     6
     7
     8
     9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
    1252021-12-09  Tyler Wilcock  <tyler_w@apple.com>
    226
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp

    r286541 r286782  
    7575        processNonBidiContent(lineContent, lineBox, lineBoxLogicalRect.topLeft(), boxes);
    7676    processOverflownRunsForEllipsis(boxes, lineBoxLogicalRect.right());
    77     collectInkOverflowForInlineBoxes(lineBox, boxes);
     77    collectInkOverflowForInlineBoxes(boxes);
    7878    return boxes;
    7979}
    8080
    81 static inline void addBoxShadowInkOverflow(const RenderStyle& style, InlineRect& inkOverflow)
     81static inline BoxShadowInkOverflow(const RenderStyle& style, InlineRect& inkOverflow)
    8282{
    8383    auto topBoxShadow = LayoutUnit { };
     
    8888    auto rightBoxShadow = LayoutUnit { };
    8989    style.getBoxShadowInlineDirectionExtent(leftBoxShadow, rightBoxShadow);
     90
     91
    9092    inkOverflow.inflate(InlineLayoutUnit { topBoxShadow }, InlineLayoutUnit { rightBoxShadow }, InlineLayoutUnit { bottomBoxShadow }, InlineLayoutUnit { leftBoxShadow });
     93
    9194}
    9295
     
    169172
    170173    auto& layoutBox = lineRun.layoutBox();
    171     // FIXME: Add ink overflow support for atomic inline level boxes (e.g. box shadow).
     174    auto inkOverflow = [&] {
     175        auto inkOverflow = borderBoxRect;
     176        computeBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow);
     177        // Atomic inline box contribute to their inline box parents ink overflow at all times (e.g. <span><img></span>).
     178        m_contentHasInkOverflow = m_contentHasInkOverflow || &layoutBox.parent() != &root();
     179        return inkOverflow;
     180    };
    172181    boxes.append({ m_lineIndex
    173182        , InlineDisplay::Box::Type::AtomicInlineLevelBox
     
    175184        , lineRun.bidiLevel()
    176185        , borderBoxRect
    177         , borderBoxRect
     186        ,
    178187        , lineRun.expansion()
    179188        , { } });
    180 
    181189    // Note that inline boxes are relative to the line and their top position can be negative.
    182190    // Atomic inline boxes are all set. Their margin/border/content box geometries are already computed. We just have to position them here.
    183     auto& boxGeometry = formattingState().boxGeometry(layoutBox);
    184     boxGeometry.setLogicalTopLeft(toLayoutPoint(borderBoxRect.topLeft()));
    185 
    186     auto adjustParentInlineBoxInkOverflow = [&] {
    187         auto& parentInlineBox = layoutBox.parent();
    188         if (&parentInlineBox == &root()) {
    189             // We don't collect ink overflow for the root inline box.
    190             return;
    191         }
    192         RELEASE_ASSERT(m_inlineBoxIndexMap.contains(&parentInlineBox));
    193 
    194         auto boxInkOverflow = borderBoxRect;
    195         addBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), boxInkOverflow);
    196         boxes[m_inlineBoxIndexMap.get(&parentInlineBox)].adjustInkOverflow(boxInkOverflow);
    197     };
    198     adjustParentInlineBoxInkOverflow();
     191    formattingState().boxGeometry(layoutBox).setLogicalTopLeft(toLayoutPoint(borderBoxRect.topLeft()));
    199192}
    200193
     
    221214
    222215    auto& layoutBox = lineRun.layoutBox();
    223     if (linehasContent) {
    224         auto inkOverflow = [&] {
    225             auto inkOverflow = inlineBoxBorderBox;
    226             addBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow);
    227             return inkOverflow;
    228         };
     216
     217    if (!linehasContent) {
    229218        // FIXME: It's expected to not have any boxes on empty lines. We should reconsider this.
    230         m_inlineBoxIndexMap.add(&layoutBox, boxes.size());
    231 
    232         ASSERT(inlineBox.isInlineBox());
    233         ASSERT(inlineBox.isFirstBox());
    234         boxes.append({ m_lineIndex
    235             , InlineDisplay::Box::Type::NonRootInlineBox
    236             , layoutBox
    237             , lineRun.bidiLevel()
    238             , inlineBoxBorderBox
    239             , inkOverflow()
    240             , { }
    241             , { }
    242             , inlineBox.hasContent()
    243             , isFirstLastBox(inlineBox) });
     219        setInlineBoxGeometry(layoutBox, inlineBoxBorderBox, true);
     220        return;
    244221    }
    245222
     223
     224
     225
     226
     227
     228
     229
     230
     231
     232
     233
     234
     235
     236
     237
     238
     239
    246240    // This inline box showed up first on this line.
    247241    setInlineBoxGeometry(layoutBox, inlineBoxBorderBox, true);
     
    253247
    254248    auto& layoutBox = lineRun.layoutBox();
    255     m_inlineBoxIndexMap.add(&layoutBox, boxes.size());
    256 
    257249    auto inkOverflow = [&] {
    258250        auto inkOverflow = inlineBoxBorderBox;
    259         addBoxShadowInkOverflow(!m_lineIndex ? layoutBox.firstLineStyle() : layoutBox.style(), inkOverflow);
     251        ;
    260252        return inkOverflow;
    261253    };
     
    271263        , inlineBox.hasContent()
    272264        , isFirstLastBox(inlineBox) });
    273 
    274265    // Middle or end of the inline box. Let's stretch the box as needed.
    275266    setInlineBoxGeometry(layoutBox, inlineBoxBorderBox, false);
     
    628619}
    629620
    630 void InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes(const LineBox& lineBox, DisplayBoxes& boxes)
    631 {
    632     if (m_inlineBoxIndexMap.isEmpty() || !lineBox.hasContent()) {
    633         // This line has no inline box (only root, but we don't collect ink overflow for the root inline box atm)
     621void InlineDisplayContentBuilder::collectInkOverflowForInlineBoxes(DisplayBoxes& boxes)
     622{
     623    if (!m_contentHasInkOverflow)
    634624        return;
    635     }
    636 
    637     auto& nonRootInlineLevelBoxes = lineBox.nonRootInlineLevelBoxes();
    638625    // Visit the inline boxes and propagate ink overflow to their parents -except to the root inline box.
    639626    // (e.g. <span style="font-size: 10px;">Small font size<span style="font-size: 300px;">Larger font size. This overflows the top most span.</span></span>).
    640     for (size_t index = nonRootInlineLevelBoxes.size(); index--;) {
    641         if (!nonRootInlineLevelBoxes[index].isInlineBox())
    642             continue;
    643         auto& inlineBox = nonRootInlineLevelBoxes[index].layoutBox();
    644         auto& parentInlineBox = inlineBox.parent();
    645         if (&parentInlineBox == &root())
    646             continue;
    647         RELEASE_ASSERT(m_inlineBoxIndexMap.contains(&inlineBox) && m_inlineBoxIndexMap.contains(&parentInlineBox));
    648         auto& inkOverflow = boxes[m_inlineBoxIndexMap.get(&inlineBox)].inkOverflow();
    649         auto& parentDisplayBox = boxes[m_inlineBoxIndexMap.get(&parentInlineBox)];
    650         parentDisplayBox.adjustInkOverflow(inkOverflow);
     627    auto accumulatedInkOverflowRect = InlineRect { { }, { } };
     628    for (size_t index = boxes.size(); index--;) {
     629        auto& displayBox = boxes[index];
     630
     631        auto mayHaveInkOverflow = displayBox.isAtomicInlineLevelBox() || displayBox.isGenericInlineLevelBox() || displayBox.isNonRootInlineBox();
     632        if (!mayHaveInkOverflow)
     633            continue;
     634        if (displayBox.isNonRootInlineBox() && !accumulatedInkOverflowRect.isEmpty())
     635            displayBox.adjustInkOverflow(accumulatedInkOverflowRect);
     636
     637        // We stop collecting ink overflow for at root inline box (i.e. don't inflate the root inline box with the inline content here).
     638        auto parentBoxIsRoot = &displayBox.layoutBox().parent() == &root();
     639        if (parentBoxIsRoot)
     640            accumulatedInkOverflowRect = InlineRect { { }, { } };
     641        else if (accumulatedInkOverflowRect.isEmpty())
     642            accumulatedInkOverflowRect = displayBox.inkOverflow();
     643        else
     644            accumulatedInkOverflowRect.expandToContain(displayBox.inkOverflow());
    651645    }
    652646}
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.h

    r286534 r286782  
    5050    void processBidiContent(const LineBuilder::LineContent&, const LineBox&, const InlineLayoutPoint& lineBoxLogicalTopLeft, DisplayBoxes&);
    5151    void processOverflownRunsForEllipsis(DisplayBoxes&, InlineLayoutUnit lineBoxLogicalRight);
    52     void collectInkOverflowForInlineBoxes(const LineBox&, DisplayBoxes&);
     52    void collectInkOverflowForInlineBoxes(DisplayBoxes&);
    5353
    5454    void appendTextDisplayBox(const Line::Run&, const InlineRect&, DisplayBoxes&);
     
    6868    const ContainerBox& m_formattingContextRoot;
    6969    InlineFormattingState& m_formattingState;
    70     HashMap<const Box*, size_t> m_inlineBoxIndexMap;
    7170    size_t m_lineIndex { 0 };
     71
    7272};
    7373
  • trunk/Source/WebCore/layout/formattingContexts/inline/InlineRect.h

    r286178 r286782  
    7272    void inflate(InlineLayoutUnit top, InlineLayoutUnit right, InlineLayoutUnit bottom, InlineLayoutUnit left);
    7373
     74
     75
    7476    operator InlineLayoutRect() const;
    7577
     
    309311}
    310312
     313
     314
     315
     316
     317
     318
    311319inline InlineRect::operator InlineLayoutRect() const
    312320{
Note: See TracChangeset for help on using the changeset viewer.