Title: [281575] trunk/Source/WebCore
Revision
281575
Author
[email protected]
Date
2021-08-25 12:50:35 -0700 (Wed, 25 Aug 2021)

Log Message

[LFC][IFC] Line spanning inline boxes should also be in the run list
https://bugs.webkit.org/show_bug.cgi?id=228059
<rdar://problem/81077420>

Reviewed by Antti Koivisto.

Consider the following case:
  <div><span>first line text<br>second line text<br>third line text</span></div>

Here is the list of runs we generate for the content above:

  [inline box][first line text][hard linebreak][second line text][hard linebreak][third line text]

This list does not include the spanning inline boxes, i.e. the missing inline box on the second and the third line.
The integration code then looks inside the LineBox to find these spanning inline boxes (see createDisplayNonRootInlineBoxes)

In this patch we start including such spanning inline boxes in the run list.
  [inline box][first line text][hard linebreak][inline box][second line text][hard linebreak][inline box][third line text]

This is also in preparation for making LineBox completely internal to the layout code.

* layout/formattingContexts/inline/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::computeGeometryForLineContent):
* layout/formattingContexts/inline/InlineLineRun.h:
(WebCore::Layout::LineRun::isText const):
(WebCore::Layout::LineRun::isLineBreak const):
(WebCore::Layout::LineRun::isAtomicInlineLevelBox const):
(WebCore::Layout::LineRun::isInlineBox const):
(WebCore::Layout::LineRun::isRootInlineBox const):
(WebCore::Layout::LineRun::type const):
(WebCore::Layout::LineRun::hasContent const):
(WebCore::Layout::LineRun::isLineSpanning const):
(WebCore::Layout::LineRun::LineRun):
* layout/integration/LayoutIntegrationInlineContentBuilder.cpp:
(WebCore::LayoutIntegration::InlineContentBuilder::build const):
(WebCore::LayoutIntegration::InlineContentBuilder::createDisplayLineRuns const):
(WebCore::LayoutIntegration::InlineContentBuilder::createDisplayNonRootInlineBoxes const): Deleted.
* layout/integration/LayoutIntegrationInlineContentBuilder.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (281574 => 281575)


--- trunk/Source/WebCore/ChangeLog	2021-08-25 19:40:21 UTC (rev 281574)
+++ trunk/Source/WebCore/ChangeLog	2021-08-25 19:50:35 UTC (rev 281575)
@@ -1,3 +1,44 @@
+2021-08-25  Alan Bujtas  <[email protected]>
+
+        [LFC][IFC] Line spanning inline boxes should also be in the run list
+        https://bugs.webkit.org/show_bug.cgi?id=228059
+        <rdar://problem/81077420>
+
+        Reviewed by Antti Koivisto.
+
+        Consider the following case:
+          <div><span>first line text<br>second line text<br>third line text</span></div>
+
+        Here is the list of runs we generate for the content above:
+
+          [inline box][first line text][hard linebreak][second line text][hard linebreak][third line text]
+
+        This list does not include the spanning inline boxes, i.e. the missing inline box on the second and the third line.
+        The integration code then looks inside the LineBox to find these spanning inline boxes (see createDisplayNonRootInlineBoxes)
+
+        In this patch we start including such spanning inline boxes in the run list.
+          [inline box][first line text][hard linebreak][inline box][second line text][hard linebreak][inline box][third line text]
+
+        This is also in preparation for making LineBox completely internal to the layout code. 
+
+        * layout/formattingContexts/inline/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::computeGeometryForLineContent):
+        * layout/formattingContexts/inline/InlineLineRun.h:
+        (WebCore::Layout::LineRun::isText const):
+        (WebCore::Layout::LineRun::isLineBreak const):
+        (WebCore::Layout::LineRun::isAtomicInlineLevelBox const):
+        (WebCore::Layout::LineRun::isInlineBox const):
+        (WebCore::Layout::LineRun::isRootInlineBox const):
+        (WebCore::Layout::LineRun::type const):
+        (WebCore::Layout::LineRun::hasContent const):
+        (WebCore::Layout::LineRun::isLineSpanning const):
+        (WebCore::Layout::LineRun::LineRun):
+        * layout/integration/LayoutIntegrationInlineContentBuilder.cpp:
+        (WebCore::LayoutIntegration::InlineContentBuilder::build const):
+        (WebCore::LayoutIntegration::InlineContentBuilder::createDisplayLineRuns const):
+        (WebCore::LayoutIntegration::InlineContentBuilder::createDisplayNonRootInlineBoxes const): Deleted.
+        * layout/integration/LayoutIntegrationInlineContentBuilder.h:
+
 2021-08-25  Sonia Singla  <[email protected]>
 
         Add onsecuritypolicyviolation on GlobalEventHandlers

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp (281574 => 281575)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp	2021-08-25 19:40:21 UTC (rev 281574)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineFormattingContext.cpp	2021-08-25 19:50:35 UTC (rev 281575)
@@ -605,6 +605,9 @@
         return lineBoxLogicalRect;
     }
 
+    // Spanning inline boxes start at the very beginning of the line.
+    // FIXME: Offset it with the run for the root inline box, when we start constructing runs for them.
+    auto lineSpanningInlineBoxIndex = formattingState.lineRuns().size();
     HashSet<const Box*> inlineBoxStartSet;
     auto constructLineRunsAndUpdateBoxGeometry = [&] {
         // Create the inline runs on the current line. This is mostly text and atomic inline runs.
@@ -612,7 +615,7 @@
             // FIXME: We should not need to construct a line run for <br>.
             auto& layoutBox = lineRun.layoutBox();
             if (lineRun.isText()) {
-                formattingState.addLineRun({ lineIndex, layoutBox, lineBox.logicalRectForTextRun(lineRun), lineRun.expansion(), lineRun.textContent() });
+                formattingState.addLineRun({ lineIndex, LineRun::Type::Text, layoutBox, lineBox.logicalRectForTextRun(lineRun), lineRun.expansion(), lineRun.textContent() });
                 continue;
             }
             if (lineRun.isLineBreak()) {
@@ -619,7 +622,7 @@
                 if (layoutBox.isLineBreakBox()) {
                     // Only hard linebreaks have associated layout boxes.
                     auto lineBreakBoxRect = lineBox.logicalRectForLineBreakBox(layoutBox);
-                    formattingState.addLineRun({ lineIndex, layoutBox, lineBreakBoxRect, lineRun.expansion(), { } });
+                    formattingState.addLineRun({ lineIndex, LineRun::Type::LineBreak, layoutBox, lineBreakBoxRect, lineRun.expansion(), { } });
 
                     auto& boxGeometry = formattingState.boxGeometry(layoutBox);
                     lineBreakBoxRect.moveBy(lineBoxLogicalRect.topLeft());
@@ -626,7 +629,7 @@
                     boxGeometry.setLogicalTopLeft(toLayoutPoint(lineBreakBoxRect.topLeft()));
                     boxGeometry.setContentBoxHeight(toLayoutUnit(lineBreakBoxRect.height()));
                 } else 
-                    formattingState.addLineRun({ lineIndex, layoutBox, lineBox.logicalRectForTextRun(lineRun), lineRun.expansion(), lineRun.textContent() });
+                    formattingState.addLineRun({ lineIndex, LineRun::Type::LineBreak, layoutBox, lineBox.logicalRectForTextRun(lineRun), lineRun.expansion(), lineRun.textContent() });
                 continue;
             }
             if (lineRun.isBox()) {
@@ -633,7 +636,7 @@
                 ASSERT(layoutBox.isAtomicInlineLevelBox());
                 auto& boxGeometry = formattingState.boxGeometry(layoutBox);
                 auto logicalBorderBox = lineBox.logicalBorderBoxForAtomicInlineLevelBox(layoutBox, boxGeometry);
-                formattingState.addLineRun({ lineIndex, layoutBox, logicalBorderBox, lineRun.expansion(), { } });
+                formattingState.addLineRun({ lineIndex, LineRun::Type::AtomicInlineLevelBox, layoutBox, logicalBorderBox, lineRun.expansion(), { } });
 
                 auto borderBoxLogicalTopLeft = logicalBorderBox.topLeft();
                 // Note that inline boxes are relative to the line and their top position can be negative.
@@ -647,7 +650,7 @@
             if (lineRun.isInlineBoxStart()) {
                 auto& boxGeometry = formattingState.boxGeometry(layoutBox);
                 auto inlineBoxLogicalRect = lineBox.logicalBorderBoxForInlineBox(layoutBox, boxGeometry);
-                formattingState.addLineRun({ lineIndex, layoutBox, inlineBoxLogicalRect, lineRun.expansion(), { } });
+                formattingState.addLineRun({ lineIndex, LineRun::Type::InlineBox, layoutBox, inlineBoxLogicalRect, lineRun.expansion(), { }, lineBox.inlineLevelBoxForLayoutBox(layoutBox).hasContent() });
                 inlineBoxStartSet.add(&layoutBox);
                 continue;
             }
@@ -682,6 +685,8 @@
                 continue;
             }
             // Middle or end of the inline box. Let's stretch the box as needed.
+            formattingState.lineRuns().insert(lineSpanningInlineBoxIndex++, { lineIndex, LineRun::Type::InlineBox, layoutBox, inlineBoxBorderBox, { }, { }, inlineLevelBox.hasContent(), true });
+
             auto enclosingBorderBoxRect = BoxGeometry::borderBoxRect(boxGeometry);
             enclosingBorderBoxRect.expandToContain(logicalRect);
             boxGeometry.setLogicalLeft(enclosingBorderBoxRect.left());

Modified: trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineRun.h (281574 => 281575)


--- trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineRun.h	2021-08-25 19:40:21 UTC (rev 281574)
+++ trunk/Source/WebCore/layout/formattingContexts/inline/InlineLineRun.h	2021-08-25 19:50:35 UTC (rev 281575)
@@ -59,9 +59,27 @@
         String m_contentString;
     };
 
+    enum class Type {
+        Text,
+        LineBreak,
+        AtomicInlineLevelBox,
+        InlineBox,
+        RootInlineBox,
+        GenericInlineLevelBox
+    };
     struct Expansion;
-    LineRun(size_t lineIndex, const Box&, const InlineRect&, Expansion, std::optional<Text> = std::nullopt);
+    LineRun(size_t lineIndex, Type, const Box&, const InlineRect&, Expansion, std::optional<Text> = std::nullopt, bool hasContent = true, bool isLineSpanning = false);
 
+    bool isText() const { return m_type == Type::Text; }
+    bool isLineBreak() const { return m_type == Type::LineBreak; }
+    bool isAtomicInlineLevelBox() const { return m_type == Type::AtomicInlineLevelBox; }
+    bool isInlineBox() const { return m_type == Type::InlineBox || isRootInlineBox(); }
+    bool isRootInlineBox() const { return m_type == Type::RootInlineBox; }
+    Type type() const { return m_type; }
+
+    bool hasContent() const { return m_hasContent; }
+    bool isLineSpanning() const { return m_isLineSpanning; }
+
     const InlineRect& logicalRect() const { return m_logicalRect; }
 
     InlineLayoutUnit logicalTop() const { return logicalRect().top(); }
@@ -87,16 +105,23 @@
 
 private:
     const size_t m_lineIndex;
+    const Type m_type;
     WeakPtr<const Layout::Box> m_layoutBox;
     InlineRect m_logicalRect;
+    bool m_hasContent { true };
+    // FIXME: This is temporary until after iterators can skip over line spanning/root inline boxes.
+    bool m_isLineSpanning { false };
     Expansion m_expansion;
     std::optional<Text> m_text;
 };
 
-inline LineRun::LineRun(size_t lineIndex, const Layout::Box& layoutBox, const InlineRect& logicalRect, Expansion expansion, std::optional<Text> text)
+inline LineRun::LineRun(size_t lineIndex, Type type, const Layout::Box& layoutBox, const InlineRect& logicalRect, Expansion expansion, std::optional<Text> text, bool hasContent, bool isLineSpanning)
     : m_lineIndex(lineIndex)
+    , m_type(type)
     , m_layoutBox(makeWeakPtr(layoutBox))
     , m_logicalRect(logicalRect)
+    , m_hasContent(hasContent)
+    , m_isLineSpanning(isLineSpanning)
     , m_expansion(expansion)
     , m_text(text)
 {

Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp (281574 => 281575)


--- trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp	2021-08-25 19:40:21 UTC (rev 281574)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.cpp	2021-08-25 19:50:35 UTC (rev 281575)
@@ -166,7 +166,6 @@
 {
     auto lineLevelVisualAdjustmentsForRuns = computeLineLevelVisualAdjustmentsForRuns(inlineFormattingState);
     createDisplayLineRuns(inlineFormattingState.lines(), inlineFormattingState.lineRuns(), inlineContent, lineLevelVisualAdjustmentsForRuns);
-    createDisplayNonRootInlineBoxes(inlineFormattingState, inlineContent);
     createDisplayLines(inlineFormattingState.lines(), inlineContent, lineLevelVisualAdjustmentsForRuns);
 }
 
@@ -245,7 +244,20 @@
             runRect.setY(roundToInt(runRect.y()));
         // FIXME: Add support for non-text ink overflow.
         // FIXME: Add support for cases when the run is after ellipsis.
-        inlineContent.runs.append({ lineIndex, layoutBox, runRect, runRect, { }, { } });
+        if (lineRun.isInlineBox()) {
+            auto lineRunRect = lineRun.logicalRect();
+            lineRunRect.moveBy(lineBoxLogicalRect.topLeft());
+            auto hasScrollableContent = [&] {
+                // In standards mode, inline boxes always start with an imaginary strut.
+                return m_layoutState.inStandardsMode() || lineRun.hasContent() || geometry.horizontalBorder() || (geometry.horizontalPadding() && geometry.horizontalPadding().value());
+            };
+            inlineContent.nonRootInlineBoxes.append({ lineIndex, layoutBox, lineRunRect, hasScrollableContent() });
+            if (!lineRun.isLineSpanning()) {
+                // FIXME: Run iterators with (text)runs spanning over multiple lines expect no "in-between" runs (e.g. line spanning or root inline boxes).
+                inlineContent.runs.append({ lineIndex, layoutBox, runRect, runRect, { }, { } });
+            }
+        } else
+            inlineContent.runs.append({ lineIndex, layoutBox, runRect, runRect, { }, { } });
     };
 
     auto createDisplayTextRunForRange = [&](auto& lineRun, auto startOffset, auto endOffset) {
@@ -368,32 +380,7 @@
     }
 }
 
-void InlineContentBuilder::createDisplayNonRootInlineBoxes(const Layout::InlineFormattingState& inlineFormattingState, InlineContent& inlineContent) const
-{
-    for (size_t lineIndex = 0; lineIndex < inlineFormattingState.lineBoxes().size(); ++lineIndex) {
-        auto& lineBox = inlineFormattingState.lineBoxes()[lineIndex];
-        if (!lineBox.hasInlineBox())
-            continue;
-
-        auto lineBoxLogicalRect = inlineFormattingState.lines()[lineIndex].lineBoxLogicalRect();
-        for (auto& inlineLevelBox : lineBox.nonRootInlineLevelBoxes()) {
-            if (!inlineLevelBox.isInlineBox())
-                continue;
-            auto& layoutBox = inlineLevelBox.layoutBox();
-            auto& boxGeometry = m_layoutState.geometryForBox(layoutBox);
-            auto inlineBoxRect = lineBox.logicalBorderBoxForInlineBox(layoutBox, boxGeometry);
-            inlineBoxRect.moveBy(lineBoxLogicalRect.topLeft());
-
-            auto hasScrollableContent = [&] {
-                // In standards mode, inline boxes always start with an imaginary strut.
-                return m_layoutState.inStandardsMode() || inlineLevelBox.hasContent() || boxGeometry.horizontalBorder() || (boxGeometry.horizontalPadding() && boxGeometry.horizontalPadding().value());
-            };
-            inlineContent.nonRootInlineBoxes.append({ lineIndex, layoutBox, inlineBoxRect, hasScrollableContent() });
-        }
-    }
 }
-
 }
-}
 
 #endif

Modified: trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.h (281574 => 281575)


--- trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.h	2021-08-25 19:40:21 UTC (rev 281574)
+++ trunk/Source/WebCore/layout/integration/LayoutIntegrationInlineContentBuilder.h	2021-08-25 19:50:35 UTC (rev 281575)
@@ -52,7 +52,6 @@
     LineLevelVisualAdjustmentsForRunsList computeLineLevelVisualAdjustmentsForRuns(const Layout::InlineFormattingState&) const;
     void createDisplayLineRuns(const Layout::InlineLines&, const Layout::InlineLineRuns&, InlineContent&, const LineLevelVisualAdjustmentsForRunsList&) const;
     void createDisplayLines(const Layout::InlineLines&, InlineContent&, const LineLevelVisualAdjustmentsForRunsList&) const;
-    void createDisplayNonRootInlineBoxes(const Layout::InlineFormattingState&, InlineContent&) const;
 
     const Layout::LayoutState& m_layoutState;
     const RenderBlockFlow& m_blockFlow;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to