Title: [266271] trunk/Source/WebCore
Revision
266271
Author
[email protected]
Date
2020-08-27 20:07:06 -0700 (Thu, 27 Aug 2020)

Log Message

[LFC][IFC] LineBuilder:Run should not have vertical geometry
https://bugs.webkit.org/show_bug.cgi?id=215068

Reviewed by Antti Koivisto.

Since LineBuilder only takes care of the horizontal ascpect of a run, LineBuilder::Run should only have logical left and width geometry.
The vertical geometry is computed as part of the content alignment phase in LineContentAligner (along with the final horizontal position
adjusted with the alignment).
This is still a transitional state (see InlineRunRectList m_runRectList) and all the line box related code will get moved to the LineBox class.
This patch also enables us to keep LineBuilder::Run const.

* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::LineContentAligner::inlineRectList const):
(WebCore::Layout::LineContentAligner::LineContentAligner):
(WebCore::Layout::LineContentAligner::alignHorizontally):
(WebCore::Layout::LineContentAligner::alignVertically):
(WebCore::Layout::LineContentAligner::adjustBaselineAndLineHeight):
(WebCore::Layout::InlineFormattingContext::lineLayout):
(WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
(WebCore::Layout::LineContentAligner::justifyRuns): Deleted.
(WebCore::Layout::LineContentAligner::runContentHeight const): Deleted.
* layout/inlineformatting/InlineFormattingContext.h:
* layout/inlineformatting/InlineLineBuilder.cpp:
(WebCore::Layout::LineBuilder::close):
(WebCore::Layout::LineBuilder::visuallyCollapsePreWrapOverflowContent):
(WebCore::Layout::LineBuilder::TrimmableTrailingContent::addFullyTrimmableContent):
(WebCore::Layout::LineBuilder::TrimmableTrailingContent::addPartiallyTrimmableContent):
(WebCore::Layout::LineBuilder::Run::Run):
(WebCore::Layout::LineBuilder::Run::expand):
(WebCore::Layout::LineBuilder::Run::removeTrailingWhitespace):
(WebCore::Layout::LineBuilder::Run::setHorizontalExpansion):
(WebCore::Layout::m_textContent): Deleted.
(WebCore::Layout::LineBuilder::Run::setComputedHorizontalExpansion): Deleted.
* layout/inlineformatting/InlineLineBuilder.h:
(WebCore::Layout::LineBuilder::Run::style const):
(WebCore::Layout::LineBuilder::Run::logicalWidth const):
(WebCore::Layout::LineBuilder::Run::logicalLeft const):
(WebCore::Layout::LineBuilder::Run::expansion const):
(WebCore::Layout::LineBuilder::Run::hasExpansionOpportunity const):
(WebCore::Layout::LineBuilder::Run::expansionOpportunityCount const):
(WebCore::Layout::LineBuilder::Run::hasTrailingWhitespace const):
(WebCore::Layout::LineBuilder::Run::trailingWhitespaceWidth const):
(WebCore::Layout::LineBuilder::Run::moveHorizontally):
(WebCore::Layout::LineBuilder::Run::shrinkHorizontally):
(WebCore::Layout::LineBuilder::Run::hasCollapsedTrailingWhitespace const):
(WebCore::Layout::LineBuilder::runs const):
(WebCore::Layout::LineBuilder::Run::logicalRect const): Deleted.
(WebCore::Layout::LineBuilder::Run::adjustLogicalTop): Deleted.
(WebCore::Layout::LineBuilder::Run::moveVertically): Deleted.
(WebCore::Layout::LineBuilder::Run::setLogicalHeight): Deleted.
(WebCore::Layout::LineBuilder::runs): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (266270 => 266271)


--- trunk/Source/WebCore/ChangeLog	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/ChangeLog	2020-08-28 03:07:06 UTC (rev 266271)
@@ -1,3 +1,57 @@
+2020-08-27  Zalan Bujtas  <[email protected]>
+
+        [LFC][IFC] LineBuilder:Run should not have vertical geometry
+        https://bugs.webkit.org/show_bug.cgi?id=215068
+
+        Reviewed by Antti Koivisto.
+
+        Since LineBuilder only takes care of the horizontal ascpect of a run, LineBuilder::Run should only have logical left and width geometry.
+        The vertical geometry is computed as part of the content alignment phase in LineContentAligner (along with the final horizontal position
+        adjusted with the alignment).
+        This is still a transitional state (see InlineRunRectList m_runRectList) and all the line box related code will get moved to the LineBox class.
+        This patch also enables us to keep LineBuilder::Run const.
+
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::LineContentAligner::inlineRectList const):
+        (WebCore::Layout::LineContentAligner::LineContentAligner):
+        (WebCore::Layout::LineContentAligner::alignHorizontally):
+        (WebCore::Layout::LineContentAligner::alignVertically):
+        (WebCore::Layout::LineContentAligner::adjustBaselineAndLineHeight):
+        (WebCore::Layout::InlineFormattingContext::lineLayout):
+        (WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
+        (WebCore::Layout::LineContentAligner::justifyRuns): Deleted.
+        (WebCore::Layout::LineContentAligner::runContentHeight const): Deleted.
+        * layout/inlineformatting/InlineFormattingContext.h:
+        * layout/inlineformatting/InlineLineBuilder.cpp:
+        (WebCore::Layout::LineBuilder::close):
+        (WebCore::Layout::LineBuilder::visuallyCollapsePreWrapOverflowContent):
+        (WebCore::Layout::LineBuilder::TrimmableTrailingContent::addFullyTrimmableContent):
+        (WebCore::Layout::LineBuilder::TrimmableTrailingContent::addPartiallyTrimmableContent):
+        (WebCore::Layout::LineBuilder::Run::Run):
+        (WebCore::Layout::LineBuilder::Run::expand):
+        (WebCore::Layout::LineBuilder::Run::removeTrailingWhitespace):
+        (WebCore::Layout::LineBuilder::Run::setHorizontalExpansion):
+        (WebCore::Layout::m_textContent): Deleted.
+        (WebCore::Layout::LineBuilder::Run::setComputedHorizontalExpansion): Deleted.
+        * layout/inlineformatting/InlineLineBuilder.h:
+        (WebCore::Layout::LineBuilder::Run::style const):
+        (WebCore::Layout::LineBuilder::Run::logicalWidth const):
+        (WebCore::Layout::LineBuilder::Run::logicalLeft const):
+        (WebCore::Layout::LineBuilder::Run::expansion const):
+        (WebCore::Layout::LineBuilder::Run::hasExpansionOpportunity const):
+        (WebCore::Layout::LineBuilder::Run::expansionOpportunityCount const):
+        (WebCore::Layout::LineBuilder::Run::hasTrailingWhitespace const):
+        (WebCore::Layout::LineBuilder::Run::trailingWhitespaceWidth const):
+        (WebCore::Layout::LineBuilder::Run::moveHorizontally):
+        (WebCore::Layout::LineBuilder::Run::shrinkHorizontally):
+        (WebCore::Layout::LineBuilder::Run::hasCollapsedTrailingWhitespace const):
+        (WebCore::Layout::LineBuilder::runs const):
+        (WebCore::Layout::LineBuilder::Run::logicalRect const): Deleted.
+        (WebCore::Layout::LineBuilder::Run::adjustLogicalTop): Deleted.
+        (WebCore::Layout::LineBuilder::Run::moveVertically): Deleted.
+        (WebCore::Layout::LineBuilder::Run::setLogicalHeight): Deleted.
+        (WebCore::Layout::LineBuilder::runs): Deleted.
+
 2020-08-27  Chris Dumez  <[email protected]>
 
         AudioParam's minValue / maxValue are ignored

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp (266270 => 266271)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp	2020-08-28 03:07:06 UTC (rev 266271)
@@ -99,7 +99,7 @@
 
 class LineContentAligner {
 public:
-    LineContentAligner(const InlineFormattingContext&, LineBox&, LineBuilder::RunList&, InlineLayoutUnit availableWidth);
+    LineContentAligner(const InlineFormattingContext&, LineBox&, const LineBuilder::RunList&, InlineLayoutUnit availableWidth);
 
     enum class IsLastLineWithInlineContent { No, Yes };
     void alignHorizontally(TextAlignMode, IsLastLineWithInlineContent);
@@ -106,10 +106,11 @@
     void alignVertically();
     void adjustBaselineAndLineHeight();
 
+    using InlineRunRectList = Vector<Display::InlineRect, 10>;
+    const InlineRunRectList& inlineRectList() const { return m_runRectList; }
+
 private:
-    void justifyRuns(InlineLayoutUnit availableWidth);
     HangingContent collectHangingContent(IsLastLineWithInlineContent) const;
-    InlineLayoutUnit runContentHeight(const LineBuilder::Run&) const;
 
     const InlineFormattingContext& formattingContext() const { return m_inlineFormattingContext; }
     LayoutState& layoutState() const { return formattingContext().layoutState(); }
@@ -116,16 +117,36 @@
 
     const InlineFormattingContext& m_inlineFormattingContext;
     LineBox& m_lineBox;
-    LineBuilder::RunList& m_runs;
+    const LineBuilder::RunList& m_runs;
+    InlineRunRectList m_runRectList;
     InlineLayoutUnit m_availableWidth;
 };
 
-LineContentAligner::LineContentAligner(const InlineFormattingContext& inlineFormattingContext, LineBox& lineBox, LineBuilder::RunList& runs, InlineLayoutUnit availableWidth)
+LineContentAligner::LineContentAligner(const InlineFormattingContext& inlineFormattingContext, LineBox& lineBox, const LineBuilder::RunList& runs, InlineLayoutUnit availableWidth)
     : m_inlineFormattingContext(inlineFormattingContext)
     , m_lineBox(lineBox)
     , m_runs(runs)
     , m_availableWidth(availableWidth)
 {
+    for (auto& run : m_runs) {
+        auto runHeight = [&]() -> InlineLayoutUnit {
+            auto& fontMetrics = run.style().fontMetrics();
+            if (run.isText() || run.isLineBreak())
+                return fontMetrics.height();
+
+            if (run.isContainerStart() || run.isContainerEnd())
+                return fontMetrics.height();
+
+            auto& layoutBox = run.layoutBox();
+            auto& boxGeometry = inlineFormattingContext.geometryForBox(layoutBox);
+            if (layoutBox.isReplacedBox() || layoutBox.isFloatingPositioned())
+                return boxGeometry.contentBoxHeight();
+
+            // Non-replaced inline box (e.g. inline-block). It looks a bit misleading but their margin box is considered the content height here.
+            return boxGeometry.marginBoxHeight();
+        };
+        m_runRectList.append({ 0, run.logicalLeft(), run.logicalWidth(), runHeight() });
+    }
 }
 
 void LineContentAligner::alignHorizontally(TextAlignMode horizontalAlignment, IsLastLineWithInlineContent isLastLine)
@@ -136,7 +157,14 @@
         return;
 
     if (horizontalAlignment == TextAlignMode::Justify) {
-        justifyRuns(availableWidth);
+        auto accumulatedExpansion = InlineLayoutUnit { };
+        for (size_t index = 0; index < m_runs.size(); ++index) {
+            m_runRectList[index].moveHorizontally(accumulatedExpansion);
+
+            auto horizontalExpansion = m_runs[index].expansion().horizontalExpansion;
+            m_runRectList[index].expandHorizontally(horizontalExpansion);
+            accumulatedExpansion += horizontalExpansion;
+        }
         return;
     }
 
@@ -161,22 +189,20 @@
         return { };
     };
 
-    auto adjustment = adjustmentForAlignment(availableWidth);
-    if (!adjustment)
-        return;
-    // Horizontal alignment means that we not only adjust the runs but also make sure
-    // that the line box is aligned as well
-    // e.g. <div style="text-align: center; width: 100px;">centered text</div> : the line box will also be centered
-    // as opposed to start at 0px all the way to [centered text] run's right edge.
-    m_lineBox.moveHorizontally(*adjustment);
-    for (auto& run : m_runs)
-        run.moveHorizontally(*adjustment);
+    if (auto adjustment = adjustmentForAlignment(availableWidth)) {
+        // FIXME: line box should not need to be moved, only the runs.
+        m_lineBox.moveHorizontally(*adjustment);
+        for (auto& runRect : m_runRectList)
+            runRect.moveHorizontally(*adjustment);
+    }
 }
 
 void LineContentAligner::alignVertically()
 {
     auto scrollableOverflowRect = m_lineBox.logicalRect();
-    for (auto& run : m_runs) {
+    for (size_t index = 0; index < m_runs.size(); ++index) {
+        auto& run = m_runs[index];
+        auto& runRect = m_runRectList[index];
         auto logicalTop = InlineLayoutUnit { };
         auto& layoutBox = run.layoutBox();
         auto verticalAlign = layoutBox.style().verticalAlign();
@@ -210,7 +236,7 @@
                 logicalTop = m_lineBox.alignmentBaseline() - baselineFromMarginBox;
             } else {
                 auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
-                logicalTop = m_lineBox.alignmentBaseline() - (boxGeometry.verticalBorder() + boxGeometry.verticalPadding().valueOr(0_lu) + run.logicalRect().height() + boxGeometry.marginAfter());
+                logicalTop = m_lineBox.alignmentBaseline() - (boxGeometry.verticalBorder() + boxGeometry.verticalPadding().valueOr(0_lu) + runRect.height() + boxGeometry.marginAfter());
             }
             break;
         case VerticalAlign::Top:
@@ -217,59 +243,22 @@
             logicalTop = 0_lu;
             break;
         case VerticalAlign::Bottom:
-            logicalTop = m_lineBox.logicalBottom() - run.logicalRect().height();
+            logicalTop = m_lineBox.logicalBottom() - runRect.height();
             break;
         default:
             ASSERT_NOT_IMPLEMENTED_YET();
             break;
         }
-        run.adjustLogicalTop(logicalTop);
+        runRect.setTop(logicalTop);
         // Adjust scrollable overflow if the run overflows the line.
-        scrollableOverflowRect.expandVerticallyToContain(run.logicalRect());
+        scrollableOverflowRect.expandVerticallyToContain(runRect);
         // Convert runs from relative to the line top/left to the formatting root's border box top/left.
-        run.moveVertically(m_lineBox.logicalTop());
-        run.moveHorizontally(m_lineBox.logicalLeft());
+        runRect.moveVertically(m_lineBox.logicalTop());
+        runRect.moveHorizontally(m_lineBox.logicalLeft());
     }
     m_lineBox.setScrollableOverflow(scrollableOverflowRect);
 }
 
-void LineContentAligner::justifyRuns(InlineLayoutUnit availableWidth)
-{
-    ASSERT(availableWidth > 0);
-    // Collect the expansion opportunity numbers and find the last run with content.
-    auto expansionOpportunityCount = 0;
-    LineBuilder::Run* lastRunWithContent = nullptr;
-    for (auto& run : m_runs) {
-        expansionOpportunityCount += run.expansionOpportunityCount();
-        if (run.isText() || run.isBox())
-            lastRunWithContent = &run;
-    }
-    // Need to fix up the last run's trailing expansion.
-    if (lastRunWithContent && lastRunWithContent->hasExpansionOpportunity()) {
-        // Turn off the trailing bits first and add the forbid trailing expansion.
-        auto leftExpansion = lastRunWithContent->expansionBehavior() & LeftExpansionMask;
-        lastRunWithContent->setExpansionBehavior(leftExpansion | ForbidRightExpansion);
-    }
-    // Nothing to distribute?
-    if (!expansionOpportunityCount)
-        return;
-    // Distribute the extra space.
-    auto expansionToDistribute = availableWidth / expansionOpportunityCount;
-    InlineLayoutUnit accumulatedExpansion = 0;
-    for (auto& run : m_runs) {
-        // Expand and moves runs by the accumulated expansion.
-        if (!run.hasExpansionOpportunity()) {
-            run.moveHorizontally(accumulatedExpansion);
-            continue;
-        }
-        ASSERT(run.expansionOpportunityCount());
-        auto computedExpansion = expansionToDistribute * run.expansionOpportunityCount();
-        run.setComputedHorizontalExpansion(computedExpansion);
-        run.moveHorizontally(accumulatedExpansion);
-        accumulatedExpansion += computedExpansion;
-    }
-}
-
 void LineContentAligner::adjustBaselineAndLineHeight()
 {
     unsigned inlineContainerNestingLevel = 0;
@@ -277,9 +266,6 @@
     for (auto& run : m_runs) {
         auto& layoutBox = run.layoutBox();
         auto& style = layoutBox.style();
-
-        run.setLogicalHeight(runContentHeight(run));
-
         if (run.isText() || run.isLineBreak()) {
             if (inlineContainerNestingLevel) {
                 // We've already adjusted the line height/baseline through the parent inline container. 
@@ -385,24 +371,6 @@
     return hangingContent;
 }
 
-InlineLayoutUnit LineContentAligner::runContentHeight(const LineBuilder::Run& run) const
-{
-    auto& fontMetrics = run.style().fontMetrics();
-    if (run.isText() || run.isLineBreak())
-        return fontMetrics.height();
-
-    if (run.isContainerStart() || run.isContainerEnd())
-        return fontMetrics.height();
-
-    auto& layoutBox = run.layoutBox();
-    auto& boxGeometry = formattingContext().geometryForBox(layoutBox);
-    if (layoutBox.isReplacedBox() || layoutBox.isFloatingPositioned())
-        return boxGeometry.contentBoxHeight();
-
-    // Non-replaced inline box (e.g. inline-block). It looks a bit misleading but their margin box is considered the content height here.
-    return boxGeometry.marginBoxHeight();
-}
-
 void InlineFormattingContext::layoutInFlowContent(InvalidationState& invalidationState, const ConstraintsForInFlowContent& constraints)
 {
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[Start] -> inline formatting context -> formatting root(" << &root() << ")");
@@ -477,13 +445,28 @@
         // "sp[<-line break->]lit_content" -> overflow length: 11 -> leading partial content length: 11.
         auto partialLeadingContentLength = previousLine ? previousLine->overflowContentLength : WTF::nullopt;
         auto lineContent = lineLayoutContext.layoutInlineContent(line, needsLayoutRange, partialLeadingContentLength);
-
         auto lineContentRange = lineContent.inlineItemRange;
-        auto lineBox = LineBox { Display::InlineRect { lineConstraints.logicalTopLeft, line.contentLogicalWidth(), lineConstraints.lineHeight }, LineBox::halfLeadingMetrics(root().style().fontMetrics(), lineConstraints.lineHeight) };
 
         // FIXME: This is temporary and will eventually get merged to LineBox.
+        auto isLastLineWithInlineContent = [&] {
+            if (lineContentRange.end == needsLayoutRange.end)
+                return LineContentAligner::IsLastLineWithInlineContent::Yes;
+            if (lineContent.partialContent)
+                return LineContentAligner::IsLastLineWithInlineContent::No;
+            // Omit floats to see if this is the last line with inline content.
+            for (auto i = needsLayoutRange.end; i--;) {
+                if (!inlineItems[i].isFloat())
+                    return i == lineContentRange.end - 1 ? LineContentAligner::IsLastLineWithInlineContent::Yes : LineContentAligner::IsLastLineWithInlineContent::No;
+            }
+            // There has to be at least one non-float item.
+            ASSERT_NOT_REACHED();
+            return LineContentAligner::IsLastLineWithInlineContent::No;
+        }();
+        line.close(isLastLineWithInlineContent == LineContentAligner::IsLastLineWithInlineContent::Yes);
+
+        auto lineBox = LineBox { Display::InlineRect { lineConstraints.logicalTopLeft, line.contentLogicalWidth(), lineConstraints.lineHeight }, LineBox::halfLeadingMetrics(root().style().fontMetrics(), lineConstraints.lineHeight) };
+        auto contentAligner = LineContentAligner { *this, lineBox, line.runs(), line.availableWidth() };
         auto alignLineContent = [&] {
-            auto contentAligner = LineContentAligner { *this, lineBox, line.runs(), line.availableWidth() };
             contentAligner.adjustBaselineAndLineHeight();
             if (line.isVisuallyEmpty()) {
                 lineBox.resetAlignmentBaseline();
@@ -496,21 +479,6 @@
             }
             contentAligner.alignVertically();
 
-            auto isLastLineWithInlineContent = [&] {
-                if (lineContentRange.end == needsLayoutRange.end)
-                    return LineContentAligner::IsLastLineWithInlineContent::Yes;
-                if (lineContent.partialContent)
-                    return LineContentAligner::IsLastLineWithInlineContent::No;
-                // Omit floats to see if this is the last line with inline content.
-                for (auto i = needsLayoutRange.end; i--;) {
-                    if (!inlineItems[i].isFloat())
-                        return i == lineContentRange.end - 1 ? LineContentAligner::IsLastLineWithInlineContent::Yes : LineContentAligner::IsLastLineWithInlineContent::No;
-                }
-                // There has to be at least one non-float item.
-                ASSERT_NOT_REACHED();
-                return LineContentAligner::IsLastLineWithInlineContent::No;
-            }();
-
             auto computedHorizontalAlignment = [&] {
                 if (root().style().textAlign() != TextAlignMode::Justify)
                     return root().style().textAlign();
@@ -525,7 +493,7 @@
         };
 
         alignLineContent();
-        setDisplayBoxesForLine(line, lineBox, lineContent, constraints.horizontal);
+        setDisplayBoxesForLine(line, contentAligner.inlineRectList(), lineBox, lineContent, constraints.horizontal);
 
         if (!lineContentRange.isEmpty()) {
             ASSERT(needsLayoutRange.start < lineContentRange.end);
@@ -631,6 +599,8 @@
         // Only the horiztonal available width is constrained when computing intrinsic width.
         line.open(availableWidth);
         auto lineContent = lineLayoutContext.layoutInlineContent(line, layoutRange, { });
+        // FIXME: Find out if min/max needs to set the isLastLine bit.
+        line.close(false);
         layoutRange.start = lineContent.inlineItemRange.end;
         // FIXME: Use line logical left and right to take floats into account.
         maximumLineWidth = std::max(maximumLineWidth, line.contentLogicalWidth());
@@ -837,7 +807,7 @@
     return LineConstraints { { lineLogicalLeft, lineLogicalTop }, lineLogicalRight - lineLogicalLeft, initialLineHeight, lineIsConstrainedByFloat };
 }
 
-void InlineFormattingContext::setDisplayBoxesForLine(const LineBuilder& line, const LineBox& lineBox,  const LineLayoutContext::LineContent& lineContent, const HorizontalConstraints& horizontalConstraints)
+void InlineFormattingContext::setDisplayBoxesForLine(const LineBuilder& line, const LineContentAligner::InlineRunRectList& runRectList, const LineBox& lineBox, const LineLayoutContext::LineContent& lineContent, const HorizontalConstraints& horizontalConstraints)
 {
     auto& formattingState = this->formattingState();
 
@@ -867,9 +837,9 @@
     auto lineInkOverflow = lineBox.scrollableOverflow();
     // Compute box final geometry.
     auto& lineRuns = line.runs();
-    for (unsigned index = 0; index < lineRuns.size(); ++index) {
+    for (size_t index = 0; index < lineRuns.size(); ++index) {
         auto& lineRun = lineRuns.at(index);
-        auto& logicalRect = lineRun.logicalRect();
+        auto logicalRect = runRectList[index];
         auto& layoutBox = lineRun.layoutBox();
 
         // Add final display runs to state first.

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h (266270 => 266271)


--- trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.h	2020-08-28 03:07:06 UTC (rev 266271)
@@ -94,7 +94,7 @@
         bool lineIsConstrainedByFloat { false };
     };
     LineConstraints constraintsForLine(const HorizontalConstraints&, InlineLayoutUnit lineLogicalTop);
-    void setDisplayBoxesForLine(const LineBuilder&, const LineBox&, const LineLayoutContext::LineContent&, const HorizontalConstraints&);
+    void setDisplayBoxesForLine(const LineBuilder&, const Vector<Display::InlineRect, 10>&, const LineBox&, const LineLayoutContext::LineContent&, const HorizontalConstraints&);
     void invalidateFormattingState(const InvalidationState&);
 
     const InlineFormattingState& formattingState() const { return downcast<InlineFormattingState>(FormattingContext::formattingState()); }

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp (266270 => 266271)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp	2020-08-28 03:07:06 UTC (rev 266271)
@@ -31,6 +31,7 @@
 #include "InlineFormattingContext.h"
 #include "InlineSoftLineBreakItem.h"
 #include "RuntimeEnabledFeatures.h"
+#include "TextFlags.h"
 #include "TextUtil.h"
 #include <wtf/IsoMallocInlines.h>
 
@@ -72,7 +73,7 @@
     m_lineIsVisuallyEmptyBeforeTrimmableTrailingContent = { };
 }
 
-void LineBuilder::close()
+void LineBuilder::close(bool isLastLineWithInlineContent)
 {
 #if ASSERT_ENABLED
     m_isClosed = true;
@@ -79,6 +80,44 @@
 #endif
     removeTrailingTrimmableContent();
     visuallyCollapsePreWrapOverflowContent();
+
+    auto computeExpansionForRunsIfNeeded = [&] {
+        if (formattingContext().root().style().textAlign() != TextAlignMode::Justify)
+            return;
+        // Text is justified according to the method specified by the text-justify property,
+        // in order to exactly fill the line box. Unless otherwise specified by text-align-last,
+        // the last line before a forced break or the end of the block is start-aligned.
+        if (isLastLineWithInlineContent)
+            return;
+        if (m_runs.isEmpty() || m_runs.last().isLineBreak())
+            return;
+
+        auto expansionOpportunityCount = 0;
+        Run* lastRunWithContent = nullptr;
+        // Collect and distribute the expansion opportunities.
+        for (auto& run : m_runs) {
+            expansionOpportunityCount += run.expansionOpportunityCount();
+            if (run.isText() || run.isBox())
+                lastRunWithContent = &run;
+        }
+        // Need to fix up the last run's trailing expansion.
+        if (lastRunWithContent && lastRunWithContent->hasExpansionOpportunity()) {
+            // Turn off the trailing bits first and add the forbid trailing expansion.
+            auto leadingExpansion = lastRunWithContent->expansionBehavior() & LeftExpansionMask;
+            lastRunWithContent->setExpansionBehavior(leadingExpansion | ForbidRightExpansion);
+        }
+        // Anything to distribute?
+        if (expansionOpportunityCount && availableWidth()) {
+            // Distribute the extra space.
+            auto expansionToDistribute = availableWidth() / expansionOpportunityCount;
+            for (auto& run : m_runs) {
+                // Expand and moves runs by the accumulated expansion.
+                if (run.hasExpansionOpportunity())
+                    run.setHorizontalExpansion(expansionToDistribute * run.expansionOpportunityCount());
+            }
+        }
+    };
+    computeExpansionForRunsIfNeeded();
 }
 
 void LineBuilder::removeTrailingTrimmableContent()
@@ -143,7 +182,7 @@
         InlineLayoutUnit trimmableWidth = { };
         if (run.isText()) {
             // FIXME: We should always collapse the run at a glyph boundary as the spec indicates: "collapse the character advance widths of any that would otherwise overflow"
-            // and the trimmed width should be capped at std::min(run.trailingWhitespaceWidth(), overflowWidth) for texgt runs. Both FF and Chrome agree.
+            // and the trimmed width should be capped at std::min(run.trailingWhitespaceWidth(), overflowWidth) for text runs. Both FF and Chrome agree.
             trimmableWidth = run.trailingWhitespaceWidth();
             run.visuallyCollapseTrailingWhitespace();
         } else {
@@ -359,7 +398,7 @@
     // Any subsequent trimmable whitespace should collapse to zero advanced width and ignored at ::appendTextContent().
     ASSERT(!m_hasFullyTrimmableContent);
     m_fullyTrimmableWidth = trimmableWidth;
-    // Note that just becasue the trimmable width is 0 (font-size: 0px), it does not mean we don't have a trimmable trailing content.
+    // Note that just because the trimmable width is 0 (font-size: 0px), it does not mean we don't have a trimmable trailing content.
     m_hasFullyTrimmableContent = true;
     m_firstRunIndex = m_firstRunIndex.valueOr(runIndex);
 }
@@ -366,7 +405,7 @@
 
 void LineBuilder::TrimmableTrailingContent::addPartiallyTrimmableContent(size_t runIndex, InlineLayoutUnit trimmableWidth)
 {
-    // Do not add trimmable letter spacing after a fully trimmable whitesapce.
+    // Do not add trimmable letter spacing after a fully trimmable whitespace.
     ASSERT(!m_firstRunIndex);
     ASSERT(!m_hasFullyTrimmableContent);
     ASSERT(!m_partiallyTrimmableWidth);
@@ -411,7 +450,8 @@
 LineBuilder::Run::Run(const InlineItem& inlineItem, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth)
     : m_type(inlineItem.type())
     , m_layoutBox(&inlineItem.layoutBox())
-    , m_logicalRect({ 0, logicalLeft, logicalWidth, 0 })
+    , m_logicalLeft(logicalLeft)
+    , m_logicalWidth(logicalWidth)
 {
 }
 
@@ -418,7 +458,7 @@
 LineBuilder::Run::Run(const InlineSoftLineBreakItem& softLineBreakItem, InlineLayoutUnit logicalLeft)
     : m_type(softLineBreakItem.type())
     , m_layoutBox(&softLineBreakItem.layoutBox())
-    , m_logicalRect({ 0, logicalLeft, 0, 0 })
+    , m_logicalLeft(logicalLeft)
     , m_textContent({ softLineBreakItem.position(), 1, softLineBreakItem.inlineTextBox().content(), false })
 {
 }
@@ -426,7 +466,8 @@
 LineBuilder::Run::Run(const InlineTextItem& inlineTextItem, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, bool needsHyphen)
     : m_type(InlineItem::Type::Text)
     , m_layoutBox(&inlineTextItem.layoutBox())
-    , m_logicalRect({ 0, logicalLeft, logicalWidth, 0 })
+    , m_logicalLeft(logicalLeft)
+    , m_logicalWidth(logicalWidth)
     , m_trailingWhitespaceType(trailingWhitespaceType(inlineTextItem))
     , m_textContent({ inlineTextItem.start(), m_trailingWhitespaceType == TrailingWhitespace::Collapsed ? 1 : inlineTextItem.length(), inlineTextItem.inlineTextBox().content(), needsHyphen })
 {
@@ -444,7 +485,7 @@
     ASSERT(isText() && inlineTextItem.isText());
     ASSERT(m_layoutBox == &inlineTextItem.layoutBox());
 
-    m_logicalRect.expandHorizontally(logicalWidth);
+    m_logicalWidth += logicalWidth;
     m_trailingWhitespaceType = trailingWhitespaceType(inlineTextItem);
 
     if (m_trailingWhitespaceType == TrailingWhitespace::None) {
@@ -485,7 +526,7 @@
 void LineBuilder::Run::removeTrailingWhitespace()
 {
     // According to https://www.w3.org/TR/css-text-3/#white-space-property matrix
-    // Trimmable whitespace is always collapsable so the length of the trailing trimmable whitespace is always 1 (or non-existent).
+    // Trimmable whitespace is always collapsible so the length of the trailing trimmable whitespace is always 1 (or non-existent).
     ASSERT(m_textContent->length());
     constexpr size_t trailingTrimmableContentLength = 1;
     m_textContent->shrink(trailingTrimmableContentLength);
@@ -518,11 +559,10 @@
     return m_expansion.behavior;
 }
 
-void LineBuilder::Run::setComputedHorizontalExpansion(InlineLayoutUnit logicalExpansion)
+void LineBuilder::Run::setHorizontalExpansion(InlineLayoutUnit logicalExpansion)
 {
     ASSERT(isText());
     ASSERT(hasExpansionOpportunity());
-    m_logicalRect.expandHorizontally(logicalExpansion);
     m_expansion.horizontalExpansion = logicalExpansion;
 }
 

Modified: trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h (266270 => 266271)


--- trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.h	2020-08-28 03:07:06 UTC (rev 266271)
@@ -45,7 +45,7 @@
     ~LineBuilder();
 
     void open(InlineLayoutUnit availableLogicalWidth);
-    void close();
+    void close(bool isLastLineWithInlineContent);
     void clearContent();
 
     void setHasIntrusiveFloat(bool hasIntrusiveFloat) { m_hasIntrusiveFloat = hasIntrusiveFloat; }
@@ -74,16 +74,21 @@
 
         const Box& layoutBox() const { return *m_layoutBox; }
         const RenderStyle& style() const { return m_layoutBox->style(); }
-        const Display::InlineRect& logicalRect() const { return m_logicalRect; }
-        Display::Run::Expansion expansion() const { return m_expansion; }
         const Optional<Display::Run::TextContent>& textContent() const { return m_textContent; }
 
-        Run(Run&&) = default;
-        Run& operator=(Run&& other) = default;
+        InlineLayoutUnit logicalWidth() const { return m_logicalWidth; }
+        InlineLayoutUnit logicalLeft() const { return m_logicalLeft; }
 
+        const Display::Run::Expansion& expansion() const { return m_expansion; }
+        bool hasExpansionOpportunity() const { return m_expansionOpportunityCount; }
+        ExpansionBehavior expansionBehavior() const;
+        unsigned expansionOpportunityCount() const { return m_expansionOpportunityCount; }
+
+        bool hasTrailingWhitespace() const { return m_trailingWhitespaceType != TrailingWhitespace::None; }
+        InlineLayoutUnit trailingWhitespaceWidth() const { return m_trailingWhitespaceWidth; }
+
     private:
         friend class LineBuilder;
-        friend class LineContentAligner;
 
         Run(const InlineTextItem&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth, bool needsHypen);
         Run(const InlineSoftLineBreakItem&, InlineLayoutUnit logicalLeft);
@@ -90,22 +95,10 @@
         Run(const InlineItem&, InlineLayoutUnit logicalLeft, InlineLayoutUnit logicalWidth);
 
         void expand(const InlineTextItem&, InlineLayoutUnit logicalWidth);
-
-        InlineLayoutUnit logicalWidth() const { return m_logicalRect.width(); }
-
-        void moveHorizontally(InlineLayoutUnit offset) { m_logicalRect.moveHorizontally(offset); }
-        void shrinkHorizontally(InlineLayoutUnit width) { m_logicalRect.expandHorizontally(-width); }
-
-        void adjustLogicalTop(InlineLayoutUnit logicalTop) { m_logicalRect.setTop(logicalTop); }
-        void moveVertically(InlineLayoutUnit offset) { m_logicalRect.moveVertically(offset); }
-        void setLogicalHeight(InlineLayoutUnit logicalHeight) { m_logicalRect.setHeight(logicalHeight); }
-
-        bool hasExpansionOpportunity() const { return m_expansionOpportunityCount; }
-        ExpansionBehavior expansionBehavior() const;
-        unsigned expansionOpportunityCount() const { return m_expansionOpportunityCount; }
-        void setComputedHorizontalExpansion(InlineLayoutUnit logicalExpansion);
+        void moveHorizontally(InlineLayoutUnit offset) { m_logicalLeft += offset; }
+        void shrinkHorizontally(InlineLayoutUnit width) { m_logicalWidth -= width; }
         void setExpansionBehavior(ExpansionBehavior);
-
+        void setHorizontalExpansion(InlineLayoutUnit logicalExpansion);
         void setNeedsHyphen() { m_textContent->setNeedsHyphen(); }
 
         enum class TrailingWhitespace {
@@ -114,10 +107,8 @@
             Collapsible,
             Collapsed
         };
-        bool hasTrailingWhitespace() const { return m_trailingWhitespaceType != TrailingWhitespace::None; }
         bool hasCollapsibleTrailingWhitespace() const { return m_trailingWhitespaceType == TrailingWhitespace::Collapsible || hasCollapsedTrailingWhitespace(); }
         bool hasCollapsedTrailingWhitespace() const { return m_trailingWhitespaceType == TrailingWhitespace::Collapsed; }
-        InlineLayoutUnit trailingWhitespaceWidth() const { return m_trailingWhitespaceWidth; }
         TrailingWhitespace trailingWhitespaceType(const InlineTextItem&) const;
         void removeTrailingWhitespace();
         void visuallyCollapseTrailingWhitespace();
@@ -128,7 +119,8 @@
 
         InlineItem::Type m_type { InlineItem::Type::Text };
         const Box* m_layoutBox { nullptr };
-        Display::InlineRect m_logicalRect;
+        InlineLayoutUnit m_logicalLeft { 0 };
+        InlineLayoutUnit m_logicalWidth { 0 };
         TrailingWhitespace m_trailingWhitespaceType { TrailingWhitespace::None };
         InlineLayoutUnit m_trailingWhitespaceWidth { 0 };
         Optional<Display::Run::TextContent> m_textContent;
@@ -137,7 +129,6 @@
     };
     using RunList = Vector<Run, 10>;
     const RunList& runs() const { return m_runs; }
-    RunList& runs() { return m_runs; }
 
 private:
     InlineLayoutUnit contentLogicalRight() const { return m_lineLogicalLeft + m_contentLogicalWidth; }

Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp (266270 => 266271)


--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.cpp	2020-08-28 03:07:06 UTC (rev 266271)
@@ -325,14 +325,13 @@
     return close(line, layoutRange, committedInlineItemCount, { });
 }
 
-LineLayoutContext::LineContent LineLayoutContext::close(LineBuilder& line, const InlineItemRange& layoutRange, unsigned committedInlineItemCount, Optional<LineContent::PartialContent> partialContent)
+LineLayoutContext::LineContent LineLayoutContext::close(const LineBuilder& line, const InlineItemRange& layoutRange, unsigned committedInlineItemCount, Optional<LineContent::PartialContent> partialContent)
 {
-    ASSERT(committedInlineItemCount || !m_floats.isEmpty() || line.hasIntrusiveFloat());
+    ASSERT_UNUSED(line, committedInlineItemCount || !m_floats.isEmpty() || line.hasIntrusiveFloat());
     auto numberOfCommittedItems = committedInlineItemCount + m_floats.size();
     auto trailingInlineItemIndex = layoutRange.start + numberOfCommittedItems - 1;
     auto lineRange = InlineItemRange { layoutRange.start, trailingInlineItemIndex + 1 };
     ASSERT(lineRange.end <= layoutRange.end);
-    line.close();
     // Adjust hyphenated line count.
     m_successiveHyphenatedLineCount = partialContent && partialContent->trailingContentHasHyphen ? m_successiveHyphenatedLineCount + 1 : 0;
     return LineContent { partialContent, lineRange, WTFMove(m_floats) };

Modified: trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h (266270 => 266271)


--- trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h	2020-08-28 02:56:46 UTC (rev 266270)
+++ trunk/Source/WebCore/layout/inlineformatting/LineLayoutContext.h	2020-08-28 03:07:06 UTC (rev 266271)
@@ -77,7 +77,7 @@
     Result handleFloatsAndInlineContent(LineBreaker&, LineBuilder&, const InlineItemRange& layoutRange, const LineCandidate&);
     size_t rebuildLine(LineBuilder&, const InlineItemRange& layoutRange);
     void commitPartialContent(LineBuilder&, const LineBreaker::RunList&, const LineBreaker::Result::PartialTrailingContent&);
-    LineContent close(LineBuilder&, const InlineItemRange& layoutRange, unsigned committedInlineItemCount, Optional<LineContent::PartialContent>);
+    LineContent close(const LineBuilder&, const InlineItemRange& layoutRange, unsigned committedInlineItemCount, Optional<LineContent::PartialContent>);
 
     InlineLayoutUnit inlineItemWidth(const InlineItem&, InlineLayoutUnit contentLogicalLeft) const;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to