Title: [266682] trunk/Source/WebCore
Revision
266682
Author
[email protected]
Date
2020-09-06 14:32:35 -0700 (Sun, 06 Sep 2020)

Log Message

[LFC][IFC] LineBox should contain all inline boxes
https://bugs.webkit.org/show_bug.cgi?id=216221

Reviewed by Antti Koivisto.

In this patch we decouple the line box and the line.

Previously the LineBox was pretty much representing the line.
It was responsible for both placing the inline boxes and sizing the line and position itself based on line-height/half leading.
Now the LineBox is only responsible for placing the inline boxes and sizing itself, it has no position geometry anymore neither
does it compute the line height.
The line size is computed later using the combination of line-height property/LineBox height/FontMetrics::lineSpacing/half leading.
This geometry is preserved in Display::LineBox (this needs to be renamed to Display::Line).

1. LineBuilder places the runs on the line after each other (at this point they only have horizontal geometry).
2. LineBreaker tells when to stop.
3. We start constructing inline boxes for the runs (root inline box etc) and place them inside an LineBox. This is when horizontal and vertical alignment happen.
4. We use the fully sized LineBox to compute the line geometry. Note that the line's geometry does not necessarily match the LineBox width/height (see below).
5. We construct a Display::LineBox for the line and Display::Runs for the runs inside the inline boxes.

LineBox:
- fully contains all the inline boxes, both horizontally and vertically.
- has only width and height geometry
- height is not constrained by the line-height property
- does not have the concept of overflow.

Line:
- contains the LineBox, but the LineBox can overflow the line, both horizontally and vertically.
- has position relative to the root block container.

Simple case.
<div>font went crazy with line spacing</div>
  ___________________________________________  line
|                    ^                       |
|                    | line spacing          |
|                    v                       |
| -------------------------------------------|---------  LineBox
||    ^                                      |         |
||    | line box height                      |         |
||----v--------------------------------------|-------- | alignment baseline
| -------------------------------------------|---------
|                    ^                       |   ^
|                    | line spacing          |   |
|____________________v_______________________|  scrollable overflow

 When glyphs in subsequent lines overflow:
 <div style="line-height: 5px; font-size: 20px;">line box overflows the line</div>
    ___________________________________________  LineBox
  |                          ^                 |
  |                          | line box height |
  |                          |                 |
 -|--------------------------|-----------------|-  Line
| |     ^                    |                 | |
| |     | line height        |                 | |
 -|-----v--------------------|-----------------|-
  |                          |                 |
  |--------------------------|-----------------| alignment baseline
  |                          |                 |
  |__________________________v_________________|

* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::createDisplayBoxesForLineContent):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (266681 => 266682)


--- trunk/Source/WebCore/ChangeLog	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/ChangeLog	2020-09-06 21:32:35 UTC (rev 266682)
@@ -1,3 +1,69 @@
+2020-09-06  Zalan Bujtas  <[email protected]>
+
+        [LFC][IFC] LineBox should contain all inline boxes
+        https://bugs.webkit.org/show_bug.cgi?id=216221
+
+        Reviewed by Antti Koivisto.
+
+        In this patch we decouple the line box and the line.
+
+        Previously the LineBox was pretty much representing the line.
+        It was responsible for both placing the inline boxes and sizing the line and position itself based on line-height/half leading.
+        Now the LineBox is only responsible for placing the inline boxes and sizing itself, it has no position geometry anymore neither
+        does it compute the line height.
+        The line size is computed later using the combination of line-height property/LineBox height/FontMetrics::lineSpacing/half leading.
+        This geometry is preserved in Display::LineBox (this needs to be renamed to Display::Line).
+
+        1. LineBuilder places the runs on the line after each other (at this point they only have horizontal geometry).
+        2. LineBreaker tells when to stop.
+        3. We start constructing inline boxes for the runs (root inline box etc) and place them inside an LineBox. This is when horizontal and vertical alignment happen.
+        4. We use the fully sized LineBox to compute the line geometry. Note that the line's geometry does not necessarily match the LineBox width/height (see below).
+        5. We construct a Display::LineBox for the line and Display::Runs for the runs inside the inline boxes.
+
+        LineBox:
+        - fully contains all the inline boxes, both horizontally and vertically.
+        - has only width and height geometry
+        - height is not constrained by the line-height property
+        - does not have the concept of overflow.
+
+        Line:
+        - contains the LineBox, but the LineBox can overflow the line, both horizontally and vertically.
+        - has position relative to the root block container.
+
+        Simple case.
+        <div>font went crazy with line spacing</div>
+          ___________________________________________  line
+        |                    ^                       |
+        |                    | line spacing          |
+        |                    v                       |
+        | -------------------------------------------|---------  LineBox
+        ||    ^                                      |         |
+        ||    | line box height                      |         |
+        ||----v--------------------------------------|-------- | alignment baseline
+        | -------------------------------------------|---------
+        |                    ^                       |   ^
+        |                    | line spacing          |   |
+        |____________________v_______________________|  scrollable overflow
+
+
+         When glyphs in subsequent lines overflow:
+         <div style="line-height: 5px; font-size: 20px;">line box overflows the line</div>
+            ___________________________________________  LineBox
+          |                          ^                 |
+          |                          | line box height |
+          |                          |                 |
+         -|--------------------------|-----------------|-  Line
+        | |     ^                    |                 | |
+        | |     | line height        |                 | |
+         -|-----v--------------------|-----------------|-
+          |                          |                 |
+          |--------------------------|-----------------| alignment baseline
+          |                          |                 |
+          |__________________________v_________________|
+
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::createDisplayBoxesForLineContent):
+
 2020-09-06  Darin Adler  <[email protected]>
 
         TextCodec refinements

Modified: trunk/Source/WebCore/layout/displaytree/DisplayInlineRect.h (266681 => 266682)


--- trunk/Source/WebCore/layout/displaytree/DisplayInlineRect.h	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/displaytree/DisplayInlineRect.h	2020-09-06 21:32:35 UTC (rev 266682)
@@ -37,6 +37,7 @@
     InlineRect() = default;
     InlineRect(InlineLayoutUnit top, InlineLayoutUnit left, InlineLayoutUnit width, InlineLayoutUnit height);
     InlineRect(const InlineLayoutPoint& topLeft, InlineLayoutUnit width, InlineLayoutUnit height);
+    InlineRect(const InlineLayoutPoint& topLeft, const InlineLayoutSize&);
     
     InlineLayoutUnit top() const;
     InlineLayoutUnit left() const;
@@ -108,6 +109,11 @@
 {
 }
 
+inline InlineRect::InlineRect(const InlineLayoutPoint& topLeft, const InlineLayoutSize& size)
+    : InlineRect(topLeft.y(), topLeft.x(), size.width(), size.height())
+{
+}
+
 #if ASSERT_ENABLED
 inline void InlineRect::invalidatePosition()
 {

Modified: trunk/Source/WebCore/layout/displaytree/DisplayRect.h (266681 => 266682)


--- trunk/Source/WebCore/layout/displaytree/DisplayRect.h	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/displaytree/DisplayRect.h	2020-09-06 21:32:35 UTC (rev 266682)
@@ -38,6 +38,7 @@
     Rect() = default;
     Rect(LayoutUnit top, LayoutUnit left, LayoutUnit width, LayoutUnit height);
     Rect(LayoutPoint topLeft, LayoutUnit width, LayoutUnit height);
+    Rect(const LayoutPoint& topLeft, const LayoutSize&);
     
     LayoutUnit top() const;
     LayoutUnit left() const;
@@ -113,6 +114,11 @@
 {
 }
 
+inline Rect::Rect(const LayoutPoint& topLeft, const LayoutSize& size)
+    : Rect(topLeft.y(), topLeft.x(), size.width(), size.height())
+{
+}
+
 #if ASSERT_ENABLED
 inline void Rect::invalidatePosition()
 {

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (266681 => 266682)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2020-09-06 21:32:35 UTC (rev 266682)
@@ -150,12 +150,13 @@
         auto partialLeadingContentLength = previousLine ? previousLine->overflowContentLength : WTF::nullopt;
         auto initialLineConstraints = ConstraintsForInFlowContent { constraints.horizontal, { lineLogicalTop, makeOptional(toLayoutUnit(quirks().initialLineHeight())) } };
         auto lineContent = lineBuilder.layoutInlineContent(needsLayoutRange, partialLeadingContentLength, initialLineConstraints, isFirstLine);
-        setDisplayBoxesForLine(lineContent, constraints.horizontal);
+        auto lineLogicalRect = createDisplayBoxesForLineContent(lineContent, constraints.horizontal);
+
         auto lineContentRange = lineContent.inlineItemRange;
         if (!lineContentRange.isEmpty()) {
             ASSERT(needsLayoutRange.start < lineContentRange.end);
             isFirstLine = false;
-            lineLogicalTop = lineContent.lineBox.logicalBottom();
+            lineLogicalTop = lineLogicalRect.bottom();
             // When the trailing content is partial, we need to reuse the last InlineTextItem.
             auto lastInlineItemNeedsPartialLayout = lineContent.partialContent.hasValue();
             if (lastInlineItemNeedsPartialLayout) {
@@ -178,7 +179,7 @@
         ASSERT(lineContent.runs.isEmpty());
         ASSERT(lineContent.hasIntrusiveFloat);
         // Move the next line below the intrusive float.
-        auto floatConstraints = floatingContext.constraints(lineLogicalTop, toLayoutUnit(lineContent.lineBox.logicalBottom()));
+        auto floatConstraints = floatingContext.constraints(lineLogicalTop, toLayoutUnit(lineLogicalRect.bottom()));
         ASSERT(floatConstraints.left || floatConstraints.right);
         static auto inifitePoint = PointInContextRoot::max();
         // In case of left and right constraints, we need to pick the one that's closer to the current line.
@@ -390,10 +391,54 @@
     }
 }
 
-void InlineFormattingContext::setDisplayBoxesForLine(const LineBuilder::LineContent& lineContent, const HorizontalConstraints& horizontalConstraints)
+InlineFormattingContext::LineRectAndLineBoxOffset InlineFormattingContext::computedLineLogicalRect(const LineBuilder::LineContent& lineContent) const
 {
+    // Compute the line height and the line box vertical offset.
+    // The line height is either the line-height value (negative value means line height is not set) or the font metrics's line spacing/line box height.
+    // The line box is then positioned using the half leading centering.
+    //   ___________________________________________  line
+    // |                    ^                       |
+    // |                    | line spacing          |
+    // |                    v                       |
+    // | -------------------------------------------|---------  LineBox
+    // ||    ^                                      |         |
+    // ||    | line box height                      |         |
+    // ||----v--------------------------------------|-------- | alignment baseline
+    // | -------------------------------------------|---------
+    // |                    ^                       |   ^
+    // |                    | line spacing          |   |
+    // |____________________v_______________________|  scrollable overflow
+    //
+    if (lineContent.runs.isEmpty() || lineContent.lineBox.isLineVisuallyEmpty())
+        return { { }, { lineContent.logicalTopLeft, lineContent.lineLogicalWidth, { } } };
+    auto& rootStyle = root().style();
+    auto& fontMetrics = rootStyle.fontMetrics();
+    InlineLayoutUnit lineSpacing = fontMetrics.lineSpacing();
+    auto& lineBox = lineContent.lineBox;
+    auto lineLogicalHeight = rootStyle.lineHeight().isNegative() ? std::max(lineBox.logicalHeight(), lineSpacing) : rootStyle.computedLineHeight();
+    auto logicalRect = Display::InlineRect { lineContent.logicalTopLeft, lineContent.lineLogicalWidth, lineLogicalHeight};
+
+    auto halfLeadingOffset = [&] {
+        InlineLayoutUnit ascent = fontMetrics.ascent();
+        InlineLayoutUnit descent = fontMetrics.descent();
+        // 10.8.1 Leading and half-leading
+        auto halfLeading = (lineLogicalHeight - (ascent + descent)) / 2;
+        // Inline tree height is all integer based.
+        return floorf(ascent + halfLeading);
+    }();
+    auto lineBoxOffset = logicalRect.height() == lineBox.logicalHeight() ? InlineLayoutUnit() : halfLeadingOffset - lineBox.alignmentBaseline();
+    return { lineBoxOffset, logicalRect };
+}
+
+Display::InlineRect InlineFormattingContext::createDisplayBoxesForLineContent(const LineBuilder::LineContent& lineContent, const HorizontalConstraints& horizontalConstraints)
+{
     auto& formattingState = this->formattingState();
     auto& lineBox = lineContent.lineBox;
+    auto lineRectAndLineBoxOffset = computedLineLogicalRect(lineContent);
+    auto lineLogicalRect = lineRectAndLineBoxOffset.logicalRect;
+    auto lineBoxVerticalOffset = lineRectAndLineBoxOffset.lineBoxVerticalOffset;
+    auto scrollableOverflow = Display::InlineRect { lineLogicalRect.topLeft(), std::max(lineLogicalRect.width(), lineBox.logicalWidth()), std::max(lineLogicalRect.height(), lineBoxVerticalOffset + lineBox.logicalHeight()) };
+
     if (!lineContent.floats.isEmpty()) {
         auto floatingContext = FloatingContext { root(), *this, formattingState.floatingState() };
         // Move floats to their final position.
@@ -401,8 +446,8 @@
             auto& floatBox = floatCandidate.item->layoutBox();
             auto& displayBox = formattingState.displayBox(floatBox);
             // Set static position first.
-            auto verticalStaticPosition = floatCandidate.isIntrusive ? lineBox.logicalTop() : lineBox.logicalBottom();
-            displayBox.setTopLeft({ lineBox.logicalLeft(), verticalStaticPosition });
+            auto verticalStaticPosition = floatCandidate.isIntrusive ? lineLogicalRect.top() : lineLogicalRect.bottom();
+            displayBox.setTopLeft({ lineLogicalRect.left(), verticalStaticPosition });
             // Float it.
             displayBox.setTopLeft(floatingContext.positionForFloat(floatBox, horizontalConstraints));
             floatingContext.append(floatBox);
@@ -417,7 +462,7 @@
         initialContaingBlockSize = geometryForBox(root().initialContainingBlock(), EscapeReason::StrokeOverflowNeedsViewportGeometry).contentBox().size();
     auto& inlineContent = formattingState.ensureDisplayInlineContent();
     auto lineIndex = inlineContent.lineBoxes.size();
-    auto lineInkOverflow = lineBox.scrollableOverflow();
+    auto lineInkOverflow = scrollableOverflow;
     // Compute final box geometry.
     for (auto& lineRun : lineContent.runs) {
         auto& layoutBox = lineRun.layoutBox();
@@ -443,7 +488,7 @@
             auto logicalRect = lineRun.isBox() ? lineBox.inlineBoxForLayoutBox(layoutBox).logicalRect() : lineBox.inlineRectForTextRun(lineRun);
             // Inline boxes are relative to the line box while final Display::Runs need to be relative to the parent Display:Box
             // FIXME: Shouldn't we just leave them be relative to the line box?
-            logicalRect.moveBy({ lineBox.logicalLeft(), lineBox.logicalTop() });
+            logicalRect.moveBy({ lineLogicalRect.left(), lineLogicalRect.top() + lineBoxVerticalOffset });
             auto inkOverflow = computedInkOverflow(logicalRect);
             lineInkOverflow.expandToContain(inkOverflow);
             inlineContent.runs.append({ lineIndex, layoutBox, logicalRect, inkOverflow, lineRun.expansion(), lineRun.textContent() });
@@ -456,6 +501,7 @@
             auto& displayBox = formattingState.displayBox(layoutBox);
             auto& inlineBox = lineBox.inlineBoxForLayoutBox(layoutBox);
             auto topLeft = inlineBox.logicalRect().topLeft();
+            topLeft.move({ }, lineBoxVerticalOffset);
             if (layoutBox.isInFlowPositioned())
                 topLeft += geometry().inFlowPositionedPositionOffset(layoutBox, horizontalConstraints);
             displayBox.setTopLeft(toLayoutPoint(topLeft));
@@ -468,17 +514,17 @@
             }
         }
     }
-    // FIXME: This is where the logical to physical translate should happen.
     auto constructDisplayLine = [&] {
-        // FIXME: Layout::LineBox should contain all inline boxes and it should not have neither top/left geometry nor overflow. 
-        auto lineRect = lineBox.logicalRect();
+        // FIXME: This is where the logical to physical translate should happen.
         if (auto horizontalAlignmentOffset = lineBox.horizontalAlignmentOffset()) {
             // Painting code (specifically TextRun's xPos) needs the aligned offset to be able to compute tab positions.
-            lineRect.moveHorizontally(*horizontalAlignmentOffset);
+            lineLogicalRect.moveHorizontally(*horizontalAlignmentOffset);
         }
-        inlineContent.lineBoxes.append({ lineRect, lineBox.scrollableOverflow(), lineInkOverflow, lineBox.alignmentBaseline() });
+        // FIXME: Display::LineBox should really be named Display::Line
+        inlineContent.lineBoxes.append({ lineLogicalRect, scrollableOverflow, lineInkOverflow, lineBoxVerticalOffset + lineBox.alignmentBaseline() });
     };
     constructDisplayLine();
+    return lineLogicalRect;
 }
 
 void InlineFormattingContext::invalidateFormattingState(const InvalidationState&)

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (266681 => 266682)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2020-09-06 21:32:35 UTC (rev 266682)
@@ -87,7 +87,12 @@
     void computeWidthAndMargin(const Box&, const HorizontalConstraints&);
 
     void collectInlineContentIfNeeded();
-    void setDisplayBoxesForLine(const LineBuilder::LineContent&, const HorizontalConstraints&);
+    Display::InlineRect createDisplayBoxesForLineContent(const LineBuilder::LineContent&, const HorizontalConstraints&);
+    struct LineRectAndLineBoxOffset {
+        InlineLayoutUnit lineBoxVerticalOffset;
+        Display::InlineRect logicalRect;
+    };
+    LineRectAndLineBoxOffset computedLineLogicalRect(const LineBuilder::LineContent&) const;
     void invalidateFormattingState(const InvalidationState&);
 
     const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp (266681 => 266682)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.cpp	2020-09-06 21:32:35 UTC (rev 266682)
@@ -31,13 +31,6 @@
 namespace WebCore {
 namespace Layout {
 
-struct AscentAndDescent {
-    InlineLayoutUnit height() const { return ascent + descent; }
-
-    InlineLayoutUnit ascent { 0 };
-    InlineLayoutUnit descent { 0 };
-};
-
 struct HangingContent {
 public:
     void reset();
@@ -124,16 +117,6 @@
     return { };
 }
 
-inline static AscentAndDescent halfLeadingMetrics(const FontMetrics& fontMetrics, InlineLayoutUnit lineLogicalHeight)
-{
-    InlineLayoutUnit ascent = fontMetrics.ascent();
-    InlineLayoutUnit descent = fontMetrics.descent();
-    // 10.8.1 Leading and half-leading
-    auto halfLeading = (lineLogicalHeight - (ascent + descent)) / 2;
-    // Inline tree height is all integer based.
-    return { floorf(ascent + halfLeading), ceilf(descent + halfLeading) };
-}
-
 LineBox::InlineBox::InlineBox(const Box& layoutBox, const Display::InlineRect& rect, InlineLayoutUnit baseline, InlineLayoutUnit descent, IsConsideredEmpty isConsideredEmpty)
     : m_layoutBox(makeWeakPtr(layoutBox))
     , m_logicalRect(rect)
@@ -143,21 +126,15 @@
 {
 }
 
-LineBox::LineBox(const InlineFormattingContext& inlineFormattingContext, const InlineLayoutPoint& topLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit contentLogicalWidth, const Line::RunList& runs, IsLineVisuallyEmpty isLineVisuallyEmpty, IsLastLineWithInlineContent isLastLineWithInlineContent)
-    : m_rect(topLeft, logicalWidth, { })
-    , m_contentLogicalWidth(contentLogicalWidth)
+LineBox::LineBox(const InlineFormattingContext& inlineFormattingContext, InlineLayoutUnit lineLogicalWidth, InlineLayoutUnit contentLogicalWidth, const Line::RunList& runs, IsLineVisuallyEmpty isLineVisuallyEmpty, IsLastLineWithInlineContent isLastLineWithInlineContent)
+    : m_logicalSize(contentLogicalWidth, { })
+    , m_isLineVisuallyEmpty(isLineVisuallyEmpty == IsLineVisuallyEmpty::Yes)
     , m_inlineFormattingContext(inlineFormattingContext)
 {
-    m_horizontalAlignmentOffset = Layout::horizontalAlignmentOffset(runs, root().style().textAlign(), logicalWidth, contentLogicalWidth, isLastLineWithInlineContent);
-    constructInlineBoxes(runs, isLineVisuallyEmpty);
+    m_horizontalAlignmentOffset = Layout::horizontalAlignmentOffset(runs, root().style().textAlign(), lineLogicalWidth, contentLogicalWidth, isLastLineWithInlineContent);
+    constructInlineBoxes(runs);
     computeInlineBoxesLogicalHeight();
-    alignInlineBoxesVerticallyAndComputeLineBoxHeight(isLineVisuallyEmpty);
-    // Compute scrollable overflow.
-    m_scrollableOverflow = Display::InlineRect { topLeft, std::max(logicalWidth, m_rootInlineBox.logicalWidth()), { } };
-    auto logicalBottom = InlineLayoutUnit { }; 
-    for (auto& inlineBoxEntry : m_inlineBoxRectMap)
-        logicalBottom = std::max(logicalBottom, inlineBoxEntry.value->logicalRect().bottom());
-    m_scrollableOverflow.expandVertically(logicalBottom);
+    alignInlineBoxesVerticallyAndComputeLineBoxHeight();
 }
 
 Display::InlineRect LineBox::inlineRectForTextRun(const Line::Run& run) const
@@ -168,18 +145,17 @@
     return { inlineBoxRect.top(), m_horizontalAlignmentOffset.valueOr(InlineLayoutUnit { }) + run.logicalLeft(), run.logicalWidth(), inlineBoxRect.height() };
 }
 
-void LineBox::constructInlineBoxes(const Line::RunList& runs, IsLineVisuallyEmpty isLineVisuallyEmpty)
+void LineBox::constructInlineBoxes(const Line::RunList& runs)
 {
     auto constructRootInlineBox = [&] {
         auto& fontMetrics = root().style().fontMetrics();
-        InlineLayoutUnit rootInlineBoxHeight = fontMetrics.height();
-        auto rootInlineBoxRect = Display::InlineRect { { }, m_horizontalAlignmentOffset.valueOr(InlineLayoutUnit { }), contentLogicalWidth(), rootInlineBoxHeight };
-        InlineLayoutUnit rootInlineBoxBaseline = fontMetrics.ascent();
-        auto rootInlineBoxDescent = rootInlineBoxHeight - rootInlineBoxBaseline;
+        InlineLayoutUnit logicalHeight = fontMetrics.height();
+        auto logicalRect = Display::InlineRect { { }, m_horizontalAlignmentOffset.valueOr(InlineLayoutUnit { }), logicalWidth(), logicalHeight };
+        InlineLayoutUnit baseline = fontMetrics.ascent();
+        auto descent = logicalHeight - baseline;
         auto lineHasImaginaryStrut = !layoutState().inQuirksMode();
-        auto rootInlineBoxIsConsideredEmpty = isLineVisuallyEmpty == IsLineVisuallyEmpty::No && lineHasImaginaryStrut ? InlineBox::IsConsideredEmpty::No : InlineBox::IsConsideredEmpty::Yes;
-
-        m_rootInlineBox = InlineBox { root(), rootInlineBoxRect, rootInlineBoxBaseline, rootInlineBoxDescent, rootInlineBoxIsConsideredEmpty };
+        auto isInitiallyConsideredEmpty =  !m_isLineVisuallyEmpty && lineHasImaginaryStrut ? InlineBox::IsConsideredEmpty::No : InlineBox::IsConsideredEmpty::Yes;
+        m_rootInlineBox = InlineBox { root(), logicalRect, baseline, descent, isInitiallyConsideredEmpty };
         m_inlineBoxRectMap.set(&root(), &m_rootInlineBox);
     };
     constructRootInlineBox();
@@ -219,8 +195,8 @@
                 m_inlineBoxList.append(WTFMove(inlineBox));
             }
         } else if (run.isContainerStart()) {
-            auto initialWidth = contentLogicalWidth() - run.logicalLeft();
             auto inlineBoxLogicalLeft = m_horizontalAlignmentOffset.valueOr(InlineLayoutUnit { }) + run.logicalLeft();
+            auto initialWidth = logicalWidth() - run.logicalLeft();
             ASSERT(initialWidth >= 0);
             auto& fontMetrics = layoutBox.style().fontMetrics();
             InlineLayoutUnit logicalHeight = fontMetrics.height();
@@ -306,20 +282,13 @@
     }
 }
 
-void LineBox::alignInlineBoxesVerticallyAndComputeLineBoxHeight(IsLineVisuallyEmpty isLineVisuallyEmpty)
+void LineBox::alignInlineBoxesVerticallyAndComputeLineBoxHeight()
 {
     // Inline boxes are in the coordinate system of the line box (and not in the coordinate system of their parents).
     // Starting with the root inline box, position the ancestors first so that the descendant line boxes see absolute vertical positions.
-    auto& rootStyle = root().style();
-    auto contentLogicalBottom = InlineLayoutUnit { };
+    auto contentLogicalHeight = InlineLayoutUnit { };
     auto alignRootInlineBox = [&] {
-        auto usedLineHeight = InlineLayoutUnit { };
-        if (isLineVisuallyEmpty == IsLineVisuallyEmpty::No)
-            usedLineHeight = rootStyle.computedLineHeight();
-        auto alignmentBaseline = halfLeadingMetrics(rootStyle.fontMetrics(), usedLineHeight).ascent;
-        auto rootInlineBoxTopPosition = alignmentBaseline - m_rootInlineBox.baseline();
-        m_rootInlineBox.setLogicalTop(rootInlineBoxTopPosition);
-        contentLogicalBottom = m_rootInlineBox.logicalHeight();
+        contentLogicalHeight = m_rootInlineBox.logicalHeight();
         for (auto& inlineBox : m_inlineBoxList) {
             auto verticalAlign = inlineBox->layoutBox().style().verticalAlign();
             if (verticalAlign == VerticalAlign::Bottom) {
@@ -326,9 +295,9 @@
                 // bottom align always pushes the root inline box downwards.
                 auto overflow = std::max(0.0f, inlineBox->logicalBottom() - m_rootInlineBox.logicalBottom());
                 m_rootInlineBox.setLogicalTop(m_rootInlineBox.logicalTop() + overflow);
-                contentLogicalBottom += overflow;
+                contentLogicalHeight += overflow;
             } else if (verticalAlign == VerticalAlign::Top)
-                contentLogicalBottom = std::max(contentLogicalBottom, inlineBox->logicalHeight());
+                contentLogicalHeight = std::max(contentLogicalHeight, inlineBox->logicalHeight());
         }
     };
     alignRootInlineBox();
@@ -359,7 +328,7 @@
             inlineBoxLogicalTop = InlineLayoutUnit { };
             break;
         case VerticalAlign::Bottom:
-            inlineBoxLogicalTop = contentLogicalBottom - inlineBox->logicalHeight();
+            inlineBoxLogicalTop = contentLogicalHeight - inlineBox->logicalHeight();
             break;
         case VerticalAlign::Middle: {
             auto& parentLayoutBox = layoutBox.parent();
@@ -377,7 +346,7 @@
     auto adjustContentBottomIfNeeded = [&] {
         if (!m_rootInlineBox.isEmpty())
             return;
-        auto collapsedContentLogicalTop = contentLogicalBottom;
+        auto collapsedContentLogicalTop = contentLogicalHeight;
         auto collapsedContentLogicalBottom = InlineLayoutUnit { };
         for (auto& inlineBox : m_inlineBoxList) {
             auto verticalAlign = inlineBox->layoutBox().style().verticalAlign();
@@ -389,24 +358,19 @@
             collapsedContentLogicalTop = std::min(collapsedContentLogicalTop, inlineBox->logicalTop());
             collapsedContentLogicalBottom = std::max(collapsedContentLogicalBottom, inlineBox->logicalBottom());
         }
-        if (collapsedContentLogicalTop <= 0) {
-            contentLogicalBottom = collapsedContentLogicalBottom;
+        if (!collapsedContentLogicalTop) {
+            contentLogicalHeight = collapsedContentLogicalBottom;
             return;
         }
-        contentLogicalBottom = InlineLayoutUnit { };
+        contentLogicalHeight = InlineLayoutUnit { };
         for (auto& inlineBox : m_inlineBoxList) {
             inlineBox->setLogicalTop(inlineBox->logicalTop() - collapsedContentLogicalTop);
-            contentLogicalBottom = std::max(contentLogicalBottom, inlineBox->logicalBottom());
+            contentLogicalHeight = std::max(contentLogicalHeight, inlineBox->logicalBottom());
         }
     };
     adjustContentBottomIfNeeded();
-    // Compute the line box height. It's either the line-height value (negative value means line height it not set) or
-    // maximum of the root inline box's bottom and the top aligned content height.
-    if (isLineVisuallyEmpty == IsLineVisuallyEmpty::No) {
-        InlineLayoutUnit lineSpacing = rootStyle.fontMetrics().lineSpacing();
-        auto lineBoxLogicalHeight = !rootStyle.lineHeight().isNegative() ? rootStyle.computedLineHeight() : std::max(lineSpacing, contentLogicalBottom);
-        m_rect.setHeight(lineBoxLogicalHeight);
-    }
+    if (!m_isLineVisuallyEmpty)
+        m_logicalSize.setHeight(contentLogicalHeight);
 }
 
 const InlineFormattingContext& LineBox::formattingContext() const

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h (266681 => 266682)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBox.h	2020-09-06 21:32:35 UTC (rev 266682)
@@ -38,6 +38,21 @@
 
 class InlineFormattingContext;
 
+// LineBox contains all the inline boxes both horizontally and vertically. It only has width and height geometry.
+//
+//   ____________________________________________________________ Line Box
+// |                                    --------------
+// |                                   |              |
+// | ----------------------------------|--------------|---------- Root Inline Box
+// ||   _____    ___      ___          |              |
+// ||  |        /   \    /   \         |  Inline Box  |
+// ||  |_____  |     |  |     |        |              |    ascent
+// ||  |       |     |  |     |        |              |
+// ||__|________\___/____\___/_________|______________|_______ alignment_baseline
+// ||
+// ||                                                      descent
+// ||_______________________________________________________________
+// |________________________________________________________________
 class LineBox {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -80,57 +95,34 @@
 
     enum class IsLastLineWithInlineContent { No, Yes };
     enum class IsLineVisuallyEmpty { No, Yes };
-    LineBox(const InlineFormattingContext&, const InlineLayoutPoint& topLeft, InlineLayoutUnit logicalWidth, InlineLayoutUnit contentLogicalWidth, const Line::RunList&, IsLineVisuallyEmpty, IsLastLineWithInlineContent);
+    LineBox(const InlineFormattingContext&, InlineLayoutUnit lineLogicalWidth, InlineLayoutUnit contentLogicalWidth, const Line::RunList&, IsLineVisuallyEmpty, IsLastLineWithInlineContent);
 
-    InlineLayoutUnit logicalLeft() const { return m_rect.left(); }
-    InlineLayoutUnit logicalRight() const { return m_rect.right(); }
-    InlineLayoutUnit logicalTop() const { return m_rect.top(); }
-    InlineLayoutUnit logicalBottom() const { return m_rect.bottom(); }
-    InlineLayoutUnit logicalWidth() const { return m_rect.width(); }
-    InlineLayoutUnit logicalHeight() const { return m_rect.height(); }
+    InlineLayoutUnit logicalWidth() const { return m_logicalSize.width(); }
+    InlineLayoutUnit logicalHeight() const { return m_logicalSize.height(); }
+    InlineLayoutSize logicalSize() const { return m_logicalSize; }
 
-    const Display::InlineRect& logicalRect() const { return m_rect; }
-    const Display::InlineRect& scrollableOverflow() const { return m_scrollableOverflow; }
-
     Optional<InlineLayoutUnit> horizontalAlignmentOffset() const { return m_horizontalAlignmentOffset; }
+    bool isLineVisuallyEmpty() const { return m_isLineVisuallyEmpty; }
 
     const InlineBox& inlineBoxForLayoutBox(const Box& layoutBox) const { return *m_inlineBoxRectMap.get(&layoutBox); }
     Display::InlineRect inlineRectForTextRun(const Line::Run&) const;
 
-    // _____________________________________________________ line box logical top
-    //                      ^
-    //                      |
-    //   ____________________________________ root inline box
-    //   ^                  |
-    //   |                  |
-    //   | root line ascent |
-    //   |                  |
-    //   v                  v
-    //   ___________________________________________________ alignment baseline
-    //   ^
-    //   | root line descent
-    //   v
-    //   ___________________________________
-    // _____________________________________________________ line box logical bottom
     InlineLayoutUnit alignmentBaseline() const { return m_rootInlineBox.logicalTop() + m_rootInlineBox.baseline(); }
 
 private:
-    void constructInlineBoxes(const Line::RunList&, IsLineVisuallyEmpty);
+    void constructInlineBoxes(const Line::RunList&);
     void computeInlineBoxesLogicalHeight();
-    void alignInlineBoxesVerticallyAndComputeLineBoxHeight(IsLineVisuallyEmpty);
+    void alignInlineBoxesVerticallyAndComputeLineBoxHeight();
 
     InlineBox& inlineBoxForLayoutBox(const Box& layoutBox) { return *m_inlineBoxRectMap.get(&layoutBox); }
 
-    InlineLayoutUnit contentLogicalWidth() const { return m_contentLogicalWidth; }
-
     const InlineFormattingContext& formattingContext() const;
     const Box& root() const;
     LayoutState& layoutState() const;
 
 private:
-    Display::InlineRect m_rect;
-    Display::InlineRect m_scrollableOverflow;
-    InlineLayoutUnit m_contentLogicalWidth { 0 };
+    InlineLayoutSize m_logicalSize;
+    bool m_isLineVisuallyEmpty { true };
 
     InlineBox m_rootInlineBox;
 

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (266681 => 266682)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2020-09-06 21:32:35 UTC (rev 266682)
@@ -302,7 +302,9 @@
     auto isLastLine = isLastLineWithInlineContent(committedRange, needsLayoutRange.end, committedContent.partialTrailingContent.hasValue());
     auto lineIsVisuallyEmpty = m_line.isVisuallyEmpty() ? LineBox::IsLineVisuallyEmpty::Yes : LineBox::IsLineVisuallyEmpty::No;
     return LineContent { committedContent.partialTrailingContent, committedRange, m_floats, m_line.hasIntrusiveFloat()
-        , LineBox { formattingContext(), lineLogicalTopLeft, m_line.lineLogicalWidth(), m_line.contentLogicalWidth(), m_line.runs(), lineIsVisuallyEmpty
+        , lineLogicalTopLeft
+        , m_line.lineLogicalWidth()
+        , LineBox { formattingContext(), m_line.lineLogicalWidth(), m_line.contentLogicalWidth(), m_line.runs(), lineIsVisuallyEmpty
         , isLastLine ? LineBox::IsLastLineWithInlineContent::Yes : LineBox::IsLastLineWithInlineContent::No }
         , m_line.runs() };
 }

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (266681 => 266682)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2020-09-06 19:10:11 UTC (rev 266681)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2020-09-06 21:32:35 UTC (rev 266682)
@@ -61,6 +61,8 @@
         using FloatList = Vector<Float>;
         const FloatList& floats;
         bool hasIntrusiveFloat { false };
+        InlineLayoutPoint logicalTopLeft;
+        InlineLayoutUnit lineLogicalWidth;
         const LineBox lineBox;
         const Line::RunList& runs;
     };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to