Title: [284323] trunk/Source/WebCore
Revision
284323
Author
za...@apple.com
Date
2021-10-16 14:14:57 -0700 (Sat, 16 Oct 2021)

Log Message

[LFC][IFC] Add "line spanning line box start items" to Line
https://bugs.webkit.org/show_bug.cgi?id=231551

Reviewed by Antti Koivisto.

This patch is in preparation for supporting box-decoration-break: clone, where the line spanning
inline boxes may take up space on the line (border/padding).
This patch moves the construction of the spanning inline boxes to an earlier step, from LineBox to Line.

* layout/formattingContexts/inline/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::initialize):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (284322 => 284323)


--- trunk/Source/WebCore/ChangeLog	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/ChangeLog	2021-10-16 21:14:57 UTC (rev 284323)
@@ -1,5 +1,19 @@
 2021-10-16  Alan Bujtas  <za...@apple.com>
 
+        [LFC][IFC] Add "line spanning line box start items" to Line
+        https://bugs.webkit.org/show_bug.cgi?id=231551
+
+        Reviewed by Antti Koivisto.
+
+        This patch is in preparation for supporting box-decoration-break: clone, where the line spanning
+        inline boxes may take up space on the line (border/padding).
+        This patch moves the construction of the spanning inline boxes to an earlier step, from LineBox to Line.
+
+        * layout/formattingContexts/inline/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineBuilder::initialize):
+
+2021-10-16  Alan Bujtas  <za...@apple.com>
+
         [LFC][IFC] Move overflowing content creation to LineBuilder::initialize
         https://bugs.webkit.org/show_bug.cgi?id=231540
 

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineDisplayContentBuilder.cpp	2021-10-16 21:14:57 UTC (rev 284323)
@@ -78,8 +78,7 @@
             return !lineIndex ? layoutBox.firstLineStyle() : layoutBox.style();
         }();
 
-        switch (lineRun.type()) {
-        case InlineItem::Type::Text: {
+        if (lineRun.isText()) {
             auto textRunRect = lineBox.logicalRectForTextRun(lineRun);
             textRunRect.moveBy(lineBoxLogicalTopLeft);
 
@@ -110,9 +109,9 @@
                 , inkOverflow()
                 , lineRun.expansion()
                 , InlineDisplay::Box::Text { text->start, text->length, content, adjustedContentToRender(), text->needsHyphen } });
-            break;
+            continue;
         }
-        case InlineItem::Type::SoftLineBreak: {
+        if (lineRun.isSoftLineBreak()) {
             auto softLineBreakRunRect = lineBox.logicalRectForTextRun(lineRun);
             softLineBreakRunRect.moveBy(lineBoxLogicalTopLeft);
 
@@ -127,7 +126,7 @@
                 , InlineDisplay::Box::Text { text->start, text->length, downcast<InlineTextBox>(layoutBox).content() } });
             break;
         }
-        case InlineItem::Type::HardLineBreak: {
+        if (lineRun.isHardLineBreak()) {
             // Only hard linebreaks have associated layout boxes.
             auto lineBreakBoxRect = lineBox.logicalRectForLineBreakBox(layoutBox);
             lineBreakBoxRect.moveBy(lineBoxLogicalTopLeft);
@@ -136,9 +135,9 @@
             auto& boxGeometry = formattingState.boxGeometry(layoutBox);
             boxGeometry.setLogicalTopLeft(toLayoutPoint(lineBreakBoxRect.topLeft()));
             boxGeometry.setContentBoxHeight(toLayoutUnit(lineBreakBoxRect.height()));
-            break;
+            continue;
         }
-        case InlineItem::Type::Box: {
+        if (lineRun.isBox()) {
             ASSERT(layoutBox.isAtomicInlineLevelBox());
             auto& boxGeometry = formattingState.boxGeometry(layoutBox);
             auto logicalBorderBox = lineBox.logicalBorderBoxForAtomicInlineLevelBox(layoutBox, boxGeometry);
@@ -161,9 +160,9 @@
                 boxes[m_inlineBoxIndexMap.get(&parentInlineBox)].adjustInkOverflow(logicalBorderBox);
             };
             adjustParentInlineBoxInkOverflow();
-            break;
+            continue;
         }
-        case InlineItem::Type::InlineBoxStart: {
+        if (lineRun.isInlineBoxStart()) {
             // This inline box showed up first on this line.
             auto& boxGeometry = formattingState.boxGeometry(layoutBox);
             auto inlineBoxBorderBox = lineBox.logicalBorderBoxForInlineBox(layoutBox, boxGeometry);
@@ -185,12 +184,9 @@
             boxGeometry.setContentBoxHeight(contentBoxHeight);
             auto contentBoxWidth = logicalRect.width() - (boxGeometry.horizontalBorder() + boxGeometry.horizontalPadding().value_or(0_lu));
             boxGeometry.setContentBoxWidth(contentBoxWidth);
-            break;
+            continue;
         }
-        default:
-            ASSERT(lineRun.isInlineBoxEnd() || lineRun.isWordBreakOpportunity());
-            break;
-        }
+        ASSERT(lineRun.isInlineBoxEnd() || lineRun.isWordBreakOpportunity() || lineRun.isLineSpanningInlineBoxStart());
     }
 }
 

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


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineItem.h	2021-10-16 21:14:57 UTC (rev 284323)
@@ -35,7 +35,16 @@
 
 class InlineItem {
 public:
-    enum class Type : uint8_t { Text, HardLineBreak, SoftLineBreak, WordBreakOpportunity, Box, Float, InlineBoxStart, InlineBoxEnd };
+    enum class Type : uint8_t {
+        Text,
+        HardLineBreak,
+        SoftLineBreak,
+        WordBreakOpportunity,
+        Box,
+        InlineBoxStart,
+        InlineBoxEnd,
+        Float
+    };
     InlineItem(const Box& layoutBox, Type);
 
     Type type() const { return m_type; }

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.cpp	2021-10-16 21:14:57 UTC (rev 284323)
@@ -50,12 +50,17 @@
 {
 }
 
-void Line::initialize()
+void Line::initialize(const Vector<InlineItem>& lineSpanningInlineBoxes)
 {
     m_nonSpanningInlineLevelBoxCount = 0;
     m_contentLogicalWidth = { };
     m_runs.clear();
     resetTrailingContent();
+    auto appendLineSpanningInlineBoxes = [&] {
+        for (auto& inlineBoxStartItem : lineSpanningInlineBoxes)
+            m_runs.append({ inlineBoxStartItem });
+    };
+    appendLineSpanningInlineBoxes();
 }
 
 void Line::resetTrailingContent()
@@ -192,7 +197,7 @@
     for (auto& run : WTF::makeReversedRange(m_runs)) {
         if (!run.shouldTrailingWhitespaceHang())
             break;
-        auto visuallyCollapsibleInlineItem = run.isInlineBoxStart() || run.isInlineBoxEnd() || run.hasTrailingWhitespace();
+        auto visuallyCollapsibleInlineItem = run.isLineSpanningInlineBoxStart() || run.isInlineBoxStart() || run.isInlineBoxEnd() || run.hasTrailingWhitespace();
         if (!visuallyCollapsibleInlineItem)
             break;
         ASSERT(!run.hasCollapsibleTrailingWhitespace());
@@ -280,7 +285,7 @@
             // provided both spaces are within the same inline formatting context—is collapsed to have zero advance width.
             if (run.isText())
                 return run.hasCollapsibleTrailingWhitespace();
-            ASSERT(run.isInlineBoxStart() || run.isInlineBoxEnd() || run.isWordBreakOpportunity());
+            ASSERT(run.isLineSpanningInlineBoxStart() || run.isInlineBoxStart() || run.isInlineBoxEnd() || run.isWordBreakOpportunity());
         }
         // Leading whitespace.
         return true;
@@ -445,7 +450,7 @@
     // not produce a run since in ::appendText() we see it as a fully collapsible run.
     for (auto index = *m_firstTrimmableRunIndex + 1; index < m_runs.size(); ++index) {
         auto& run = m_runs[index];
-        ASSERT(run.isWordBreakOpportunity() || run.isInlineBoxStart() || run.isInlineBoxEnd() || run.isLineBreak());
+        ASSERT(run.isWordBreakOpportunity() || run.isLineSpanningInlineBoxStart() || run.isInlineBoxStart() || run.isInlineBoxEnd() || run.isLineBreak());
         run.moveHorizontally(-trimmableWidth);
     }
     if (!trimmableRun.textContent()->length) {
@@ -475,8 +480,27 @@
     m_length += trailingWhitespace.length();
 }
 
+inline static Line::Run::Type toLineRunType(InlineItem::Type inlineItemType)
+{
+    switch (inlineItemType) {
+    case InlineItem::Type::HardLineBreak:
+        return Line::Run::Type::HardLineBreak;
+    case InlineItem::Type::WordBreakOpportunity:
+        return Line::Run::Type::WordBreakOpportunity;
+    case InlineItem::Type::Box:
+        return Line::Run::Type::AtomicBox;
+    case InlineItem::Type::InlineBoxStart:
+        return Line::Run::Type::InlineBoxStart;
+    case InlineItem::Type::InlineBoxEnd:
+        return Line::Run::Type::InlineBoxEnd;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+    return { };
+}
+
 Line::Run::Run(const InlineItem& inlineItem, const RenderStyle& style, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth)
-    : m_type(inlineItem.type())
+    : m_type(toLineRunType(inlineItem.type()))
     , m_layoutBox(&inlineItem.layoutBox())
     , m_logicalLeft(logicalLeft)
     , m_logicalWidth(logicalWidth)
@@ -485,14 +509,21 @@
 }
 
 Line::Run::Run(const InlineItem& zeroWidhtInlineItem, InlineLayoutUnit logicalLeft)
-    : m_type(zeroWidhtInlineItem.type())
+    : m_type(toLineRunType(zeroWidhtInlineItem.type()))
     , m_layoutBox(&zeroWidhtInlineItem.layoutBox())
     , m_logicalLeft(logicalLeft)
 {
 }
 
+Line::Run::Run(const InlineItem& lineSpanningInlineBoxItem)
+    : m_type(Type::LineSpanningInlineBoxStart)
+    , m_layoutBox(&lineSpanningInlineBoxItem.layoutBox())
+{
+    ASSERT(lineSpanningInlineBoxItem.isInlineBoxStart());
+}
+
 Line::Run::Run(const InlineSoftLineBreakItem& softLineBreakItem, InlineLayoutUnit logicalLeft)
-    : m_type(softLineBreakItem.type())
+    : m_type(Type::SoftLineBreak)
     , m_layoutBox(&softLineBreakItem.layoutBox())
     , m_logicalLeft(logicalLeft)
     , m_textContent({ softLineBreakItem.position(), 1 })
@@ -500,7 +531,7 @@
 }
 
 Line::Run::Run(const InlineTextItem& inlineTextItem, const RenderStyle& style, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth)
-    : m_type(InlineItem::Type::Text)
+    : m_type(Type::Text)
     , m_layoutBox(&inlineTextItem.layoutBox())
     , m_logicalLeft(logicalLeft)
     , m_logicalWidth(logicalWidth)

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLine.h	2021-10-16 21:14:57 UTC (rev 284323)
@@ -42,10 +42,12 @@
     Line(const InlineFormattingContext&);
     ~Line();
 
-    void initialize();
+    void initialize(const Vector<InlineItem>& lineSpanningInlineBoxes);
 
     void append(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalWidth);
 
+    bool hasContent() const { return !m_runs.isEmpty() && !m_runs.last().isLineSpanningInlineBoxStart(); }
+
     InlineLayoutUnit contentLogicalWidth() const { return m_contentLogicalWidth; }
     InlineLayoutUnit contentLogicalRight() const { return m_runs.isEmpty() ? 0.0f : m_runs.last().logicalRight(); }
     size_t nonSpanningInlineLevelBoxCount() const { return m_nonSpanningInlineLevelBoxCount; }
@@ -62,15 +64,26 @@
     void applyRunExpansion(InlineLayoutUnit horizontalAvailableSpace);
 
     struct Run {
-        bool isText() const { return m_type == InlineItem::Type::Text; }
-        bool isBox() const { return m_type == InlineItem::Type::Box; }
+        enum class Type : uint8_t {
+            Text,
+            HardLineBreak,
+            SoftLineBreak,
+            WordBreakOpportunity,
+            AtomicBox,
+            InlineBoxStart,
+            InlineBoxEnd,
+            LineSpanningInlineBoxStart
+        };
+
+        bool isText() const { return m_type == Type::Text; }
+        bool isBox() const { return m_type == Type::AtomicBox; }
         bool isLineBreak() const { return isHardLineBreak() || isSoftLineBreak(); }
-        bool isSoftLineBreak() const  { return m_type == InlineItem::Type::SoftLineBreak; }
-        bool isHardLineBreak() const { return m_type == InlineItem::Type::HardLineBreak; }
-        bool isWordBreakOpportunity() const { return m_type == InlineItem::Type::WordBreakOpportunity; }
-        bool isInlineBoxStart() const { return m_type == InlineItem::Type::InlineBoxStart; }
-        bool isInlineBoxEnd() const { return m_type == InlineItem::Type::InlineBoxEnd; }
-        auto type() const { return m_type; }
+        bool isSoftLineBreak() const  { return m_type == Type::SoftLineBreak; }
+        bool isHardLineBreak() const { return m_type == Type::HardLineBreak; }
+        bool isWordBreakOpportunity() const { return m_type == Type::WordBreakOpportunity; }
+        bool isInlineBoxStart() const { return m_type == Type::InlineBoxStart; }
+        bool isLineSpanningInlineBoxStart() const { return m_type == Type::LineSpanningInlineBoxStart; }
+        bool isInlineBoxEnd() const { return m_type == Type::InlineBoxEnd; }
 
         const Box& layoutBox() const { return *m_layoutBox; }
         struct Text {
@@ -101,6 +114,7 @@
         Run(const InlineSoftLineBreakItem&, InlineLayoutUnit logicalLeft);
         Run(const InlineItem&, const RenderStyle&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth);
         Run(const InlineItem&, InlineLayoutUnit logicalLeft);
+        Run(const InlineItem& lineSpanningInlineBoxItem);
 
         void expand(const InlineTextItem&, InlineLayoutUnit logicalWidth);
         void moveHorizontally(InlineLayoutUnit offset) { m_logicalLeft += offset; }
@@ -124,7 +138,7 @@
         InlineLayoutUnit trailingLetterSpacing() const;
         void removeTrailingLetterSpacing();
 
-        InlineItem::Type m_type { InlineItem::Type::Text };
+        Type m_type { Type::Text };
         const Box* m_layoutBox { nullptr };
         InlineLayoutUnit m_logicalLeft { 0 };
         InlineLayoutUnit m_logicalWidth { 0 };

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.cpp	2021-10-16 21:14:57 UTC (rev 284323)
@@ -254,43 +254,6 @@
         return !lineIndex ? layoutBox.firstLineStyle() : layoutBox.style();
     };
 
-    auto createLineSpanningInlineBoxes = [&] {
-        if (runs.isEmpty())
-            return;
-        // An inline box may not necessarily start on the current line:
-        // <span id=outer>line break<br>this content's parent inline box('outer') <span id=inner>starts on the previous line</span></span>
-        // We need to make sure that there's an InlineLevelBox for every inline box that's present on the current line.
-        // In nesting case we need to create InlineLevelBoxes for the inline box ancestors.
-        // We only have to do it on the first run as any subsequent inline content is either at the same/higher nesting level or
-        // nested with a [inline box start] run.
-        auto& firstRun = runs[0];
-        auto& firstRunParentLayoutBox = firstRun.layoutBox().parent();
-        // If the parent is the formatting root, we can stop here. This is root inline box content, there's no nesting inline box from the previous line(s)
-        // unless the inline box closing is forced over to the current line.
-        // e.g.
-        // <span>normally the inline box closing forms a continuous content</span>
-        // <span>unless it's forced to the next line<br></span>
-        auto firstRunNeedsInlineBox = firstRun.isInlineBoxEnd();
-        if (!firstRunNeedsInlineBox && isRootLayoutBox(firstRunParentLayoutBox))
-            return;
-        Vector<const Box*> layoutBoxesWithoutInlineBoxes;
-        if (firstRunNeedsInlineBox)
-            layoutBoxesWithoutInlineBoxes.append(&firstRun.layoutBox());
-        auto* ancestor = &firstRunParentLayoutBox;
-        while (!isRootLayoutBox(*ancestor)) {
-            layoutBoxesWithoutInlineBoxes.append(ancestor);
-            ancestor = &ancestor->parent();
-        }
-        // Construct the missing LineBox::InlineBoxes starting with the topmost layout box.
-        for (auto* layoutBox : WTF::makeReversedRange(layoutBoxesWithoutInlineBoxes)) {
-            auto inlineBox = InlineLevelBox::createInlineBox(*layoutBox, styleToUse(*layoutBox), rootInlineBox.logicalLeft(), rootInlineBox.logicalWidth(), InlineLevelBox::LineSpanningInlineBox::Yes);
-            setInitialVerticalGeometryForInlineBox(inlineBox);
-            updateCanUseSimplifiedAlignment(inlineBox);
-            lineBox.addInlineLevelBox(WTFMove(inlineBox));
-        }
-    };
-    createLineSpanningInlineBoxes();
-
     auto lineHasContent = false;
     for (auto& run : runs) {
         auto& layoutBox = run.layoutBox();
@@ -299,6 +262,10 @@
             ASSERT(!lineHasContent);
             if (run.isText() || run.isBox() || run.isSoftLineBreak() || run.isHardLineBreak())
                 return true;
+            if (run.isLineSpanningInlineBoxStart())
+                return false;
+            if (run.isWordBreakOpportunity())
+                return false;
             auto& inlineBoxGeometry = formattingContext().geometryForBox(layoutBox);
             // Even negative horizontal margin makes the line "contentful".
             if (run.isInlineBoxStart())
@@ -305,8 +272,6 @@
                 return inlineBoxGeometry.marginStart() || inlineBoxGeometry.borderLeft() || inlineBoxGeometry.paddingLeft().value_or(0_lu);
             if (run.isInlineBoxEnd())
                 return inlineBoxGeometry.marginEnd() || inlineBoxGeometry.borderRight() || inlineBoxGeometry.paddingRight().value_or(0_lu);
-            if (run.isWordBreakOpportunity())
-                return false;
             ASSERT_NOT_REACHED();
             return true;
         };
@@ -344,6 +309,13 @@
             lineBox.addInlineLevelBox(WTFMove(atomicInlineLevelBox));
             continue;
         }
+        if (run.isLineSpanningInlineBoxStart()) {
+            auto inlineBox = InlineLevelBox::createInlineBox(layoutBox, style, logicalLeft, rootInlineBox.logicalWidth(), InlineLevelBox::LineSpanningInlineBox::Yes);
+            setInitialVerticalGeometryForInlineBox(inlineBox);
+            updateCanUseSimplifiedAlignment(inlineBox);
+            lineBox.addInlineLevelBox(WTFMove(inlineBox));
+            continue;
+        }
         if (run.isInlineBoxStart()) {
             // At this point we don't know yet how wide this inline box is. Let's assume it's as long as the line is
             // and adjust it later if we come across an inlineBoxEnd run (see below).

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.h (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.h	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBoxBuilder.h	2021-10-16 21:14:57 UTC (rev 284323)
@@ -60,8 +60,6 @@
     const Box& rootBox() const { return formattingContext().root(); }
     LayoutState& layoutState() const { return formattingContext().layoutState(); }
 
-    bool isRootLayoutBox(const ContainerBox& containerBox) const { return &containerBox == &rootBox(); }
-
 private:
     const InlineFormattingContext& m_inlineFormattingContext;
 };

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp	2021-10-16 21:14:57 UTC (rev 284323)
@@ -292,19 +292,50 @@
     return { committedRange, m_line.contentLogicalWidth(), m_floats };
 }
 
-void LineBuilder::initialize(const UsedConstraints& lineConstraints, bool isFirstLine, size_t leadingInlineTextItemIndex, size_t partialLeadingContentLength, std::optional<InlineLayoutUnit> overflowingLogicalWidth)
+void LineBuilder::initialize(const UsedConstraints& lineConstraints, bool isFirstLine, size_t leadingInlineItemIndex, size_t partialLeadingContentLength, std::optional<InlineLayoutUnit> overflowingLogicalWidth)
 {
     m_isFirstLine = isFirstLine;
     m_floats.clear();
+    m_lineSpanningInlineBoxes.clear();
     m_wrapOpportunityList.clear();
 
-    m_line.initialize();
+    auto createLineSpanningInlineBoxes = [&] {
+        auto isRootLayoutBox = [&](auto& containerBox) {
+            return &containerBox == &root();
+        };
+        // An inline box may not necessarily start on the current line:
+        // <span>first line<br>second line<span>with some more embedding<br> forth line</span></span>
+        // We need to make sure that there's an [InlineBoxStart] for every inline box that's present on the current line.
+        // We only have to do it on the first run as any subsequent inline content is either at the same/higher nesting level.
+        auto& firstInlineItem = m_inlineItems[leadingInlineItemIndex];
+        // If the parent is the formatting root, we can stop here. This is root inline box content, there's no nesting inline box from the previous line(s)
+        // unless the inline box closing is forced over to the current line.
+        // e.g.
+        // <span>normally the inline box closing forms a continuous content</span>
+        // <span>unless it's forced to the next line<br></span>
+        auto firstInlineItemIsLineSpanning = firstInlineItem.isInlineBoxEnd();
+        if (!firstInlineItemIsLineSpanning && isRootLayoutBox(firstInlineItem.layoutBox().parent()))
+            return;
+        Vector<const Box*> spanningLayoutBoxList;
+        if (firstInlineItemIsLineSpanning)
+            spanningLayoutBoxList.append(&firstInlineItem.layoutBox());
+        auto* ancestor = &firstInlineItem.layoutBox().parent();
+        while (!isRootLayoutBox(*ancestor)) {
+            spanningLayoutBoxList.append(ancestor);
+            ancestor = &ancestor->parent();
+        }
+        for (auto* spanningInlineBox : WTF::makeReversedRange(spanningLayoutBoxList))
+            m_lineSpanningInlineBoxes.append({ *spanningInlineBox, InlineItem::Type::InlineBoxStart });
+    };
+    createLineSpanningInlineBoxes();
+    m_line.initialize(m_lineSpanningInlineBoxes);
+
     m_lineLogicalRect = lineConstraints.logicalRect;
     m_contentIsConstrainedByFloat = lineConstraints.isConstrainedByFloat;
 
     if (partialLeadingContentLength) {
         ASSERT(!isFirstLine);
-        m_partialLeadingTextItem = downcast<InlineTextItem>(m_inlineItems[leadingInlineTextItemIndex]).right(partialLeadingContentLength, overflowingLogicalWidth);
+        m_partialLeadingTextItem = downcast<InlineTextItem>(m_inlineItems[leadingInlineItemIndex]).right(partialLeadingContentLength, overflowingLogicalWidth);
         m_overflowingLogicalWidth = { };
     } else {
         m_partialLeadingTextItem = { };
@@ -386,7 +417,7 @@
     if (runsExpandHorizontally)
         m_line.applyRunExpansion(horizontalAvailableSpace);
     auto lineEndsWithHyphen = false;
-    if (!m_line.runs().isEmpty()) {
+    if (m_line.hasContent()) {
         auto& lastTextContent = m_line.runs().last().textContent();
         lineEndsWithHyphen = lastTextContent && lastTextContent->needsHyphen;
     }
@@ -707,7 +738,7 @@
         return std::isnan(availableWidthForContent) ? maxInlineLayoutUnit() : availableWidthForContent;
     }();
     // While the floats are not considered to be on the line, they make the line contentful for line breaking.
-    auto lineHasContent = !m_line.runs().isEmpty() || m_contentIsConstrainedByFloat;
+    auto lineHasContent = m_line.hasContent() || m_contentIsConstrainedByFloat;
     auto lineStatus = InlineContentBreaker::LineStatus { m_line.contentLogicalRight(), availableWidth, m_line.trimmableTrailingWidth(), m_line.trailingSoftHyphenWidth(), m_line.isTrailingRunFullyTrimmable(), lineHasContent, !m_wrapOpportunityList.isEmpty() };
     auto result = inlineContentBreaker.processInlineContent(continuousInlineContent, lineStatus);
     auto& candidateRuns = continuousInlineContent.runs();
@@ -721,7 +752,7 @@
             auto& trailingRun = candidateRuns.last();
             // FIXME: There must be a way to decide if the trailing run actually ended up on the line.
             // Let's just deal with collapsed leading whitespace for now.
-            if (!m_line.runs().isEmpty() && TextUtil::isWrappingAllowed(trailingRun.style))
+            if (m_line.hasContent() && TextUtil::isWrappingAllowed(trailingRun.style))
                 m_wrapOpportunityList.append(&trailingRun.inlineItem);
         }
         return { result.isEndOfLine, { candidateRuns.size(), false } };
@@ -826,7 +857,7 @@
     ASSERT(!m_wrapOpportunityList.isEmpty());
     // We might already have added floats. They shrink the available horizontal space for the line.
     // Let's just reuse what the line has at this point.
-    m_line.initialize();
+    m_line.initialize(m_lineSpanningInlineBoxes);
     auto currentItemIndex = layoutRange.start;
     if (m_partialLeadingTextItem) {
         m_line.append(*m_partialLeadingTextItem, m_partialLeadingTextItem->style(), inlineItemWidth(*m_partialLeadingTextItem, { }));

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h (284322 => 284323)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h	2021-10-16 20:32:52 UTC (rev 284322)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.h	2021-10-16 21:14:57 UTC (rev 284323)
@@ -131,6 +131,7 @@
     std::optional<InlineTextItem> m_partialLeadingTextItem;
     std::optional<InlineLayoutUnit> m_overflowingLogicalWidth;
     Vector<const InlineItem*> m_wrapOpportunityList;
+    Vector<InlineItem> m_lineSpanningInlineBoxes;
     unsigned m_successiveHyphenatedLineCount { 0 };
     bool m_contentIsConstrainedByFloat { false };
 };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to