[LFC][IFC] Move some code from InlineFormattingContext::Line to InlineFormattingConte...
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 15:28:55 +0000 (15:28 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 15:28:55 +0000 (15:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191445

Reviewed by Antti Koivisto.

The idea here is that Line should not have to deal with all the post processig tasks like the runs final aligments.
(The line class would eventually turn into a collection of random things).

* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::closeLine const):
(WebCore::Layout::InlineFormattingContext::appendContentToLine const):
(WebCore::Layout::InlineFormattingContext::layoutInlineContent const):
* layout/inlineformatting/InlineFormattingContext.h:
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const):
(WebCore::Layout::InlineFormattingContext::Line::lastRunType const):
* layout/inlineformatting/InlineFormattingContextGeometry.cpp:
(WebCore::Layout::InlineFormattingContext::Geometry::adjustedLineLogicalLeft):
(WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns):
(WebCore::Layout::InlineFormattingContext::Geometry::computeExpansionOpportunities):
* layout/inlineformatting/Line.cpp:
(WebCore::Layout::InlineFormattingContext::Line::Line):
(WebCore::Layout::InlineFormattingContext::Line::init):
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight const):
(WebCore::Layout::InlineFormattingContext::Line::appendContent):
(WebCore::Layout::InlineFormattingContext::Line::close):
(WebCore::Layout::adjustedLineLogicalLeft): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::computeExpansionOpportunities): Deleted.
(WebCore::Layout::InlineFormattingContext::Line::justifyRuns): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238028 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
Source/WebCore/layout/inlineformatting/InlineFormattingContext.h
Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp
Source/WebCore/layout/inlineformatting/Line.cpp

index ecfa3ca..709aa91 100644 (file)
@@ -1,3 +1,35 @@
+2018-11-09  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Move some code from InlineFormattingContext::Line to InlineFormattingContext/Geometry
+        https://bugs.webkit.org/show_bug.cgi?id=191445
+
+        Reviewed by Antti Koivisto.
+
+        The idea here is that Line should not have to deal with all the post processig tasks like the runs final aligments.
+        (The line class would eventually turn into a collection of random things).
+
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::closeLine const):
+        (WebCore::Layout::InlineFormattingContext::appendContentToLine const):
+        (WebCore::Layout::InlineFormattingContext::layoutInlineContent const):
+        * layout/inlineformatting/InlineFormattingContext.h:
+        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalLeft const):
+        (WebCore::Layout::InlineFormattingContext::Line::lastRunType const):
+        * layout/inlineformatting/InlineFormattingContextGeometry.cpp:
+        (WebCore::Layout::InlineFormattingContext::Geometry::adjustedLineLogicalLeft):
+        (WebCore::Layout::InlineFormattingContext::Geometry::justifyRuns):
+        (WebCore::Layout::InlineFormattingContext::Geometry::computeExpansionOpportunities):
+        * layout/inlineformatting/Line.cpp:
+        (WebCore::Layout::InlineFormattingContext::Line::Line):
+        (WebCore::Layout::InlineFormattingContext::Line::init):
+        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight const):
+        (WebCore::Layout::InlineFormattingContext::Line::appendContent):
+        (WebCore::Layout::InlineFormattingContext::Line::close):
+        (WebCore::Layout::adjustedLineLogicalLeft): Deleted.
+        (WebCore::Layout::InlineFormattingContext::Line::contentLogicalRight): Deleted.
+        (WebCore::Layout::InlineFormattingContext::Line::computeExpansionOpportunities): Deleted.
+        (WebCore::Layout::InlineFormattingContext::Line::justifyRuns): Deleted.
+
 2018-11-09  Philippe Normand  <pnormand@igalia.com>
 
         Unreviewed, GStreamer build warning fix
index 2212071..832318f 100644 (file)
@@ -127,13 +127,33 @@ void InlineFormattingContext::initializeNewLine(Line& line) const
     line.init(logicalRect);
 }
 
+void InlineFormattingContext::closeLine(Line& line, IsLastLine isLastLine) const
+{
+    auto runRange = line.close();
+    ASSERT(!runRange.firstRunIndex || runRange.lastRunIndex);
+
+    if (!runRange.firstRunIndex)
+        return;
+
+    Geometry::alignRuns(downcast<InlineFormattingState>(formattingState()), root().style().textAlign(), line, runRange, isLastLine);
+}
+
+void InlineFormattingContext::appendContentToLine(Line& line, const InlineLineBreaker::Run& run) const
+{
+    auto lastRunType = line.lastRunType();
+    line.appendContent(run);
+
+    if (root().style().textAlign() == TextAlignMode::Justify)
+        Geometry::computeExpansionOpportunities(downcast<InlineFormattingState>(formattingState()), run.content, lastRunType.value_or(InlineRunProvider::Run::Type::NonWhitespace));
+}
+
 void InlineFormattingContext::layoutInlineContent(const InlineRunProvider& inlineRunProvider) const
 {
     auto& layoutState = this->layoutState();
     auto& inlineFormattingState = downcast<InlineFormattingState>(formattingState());
     auto floatingContext = FloatingContext { inlineFormattingState.floatingState() };
 
-    Line line(inlineFormattingState, root());
+    Line line(inlineFormattingState);
     initializeNewLine(line);
 
     InlineLineBreaker lineBreaker(layoutState, inlineFormattingState.inlineContent(), inlineRunProvider.runs());
@@ -168,19 +188,19 @@ void InlineFormattingContext::layoutInlineContent(const InlineRunProvider& inlin
             if (line.hasContent()) {
                 // Previous run ended up being at the line end. Adjust the line accordingly.
                 if (!line.isClosed())
-                    line.close(Line::LastLine::No);
+                    closeLine(line, IsLastLine::No);
                 initializeNewLine(line);
             }
          }
 
         if (generatesInlineRun)
-             line.appendContent(*run);
+            appendContentToLine(line, *run);
 
         if (isLastRun)
-            line.close(Line::LastLine::No);
+            closeLine(line, IsLastLine::No);
     }
 
-    line.close(Line::LastLine::Yes);
+    closeLine(line, IsLastLine::Yes);
 }
 
 void InlineFormattingContext::computeWidthAndMargin(const Box& layoutBox) const
index fa90aa4..724792a 100644 (file)
@@ -50,60 +50,67 @@ public:
 private:
     class Line {
     public:
-        Line(InlineFormattingState&, const Box& formattingRoot);
+        Line(InlineFormattingState&);
 
         void init(const Display::Box::Rect&);
+        struct RunRange {
+            std::optional<unsigned> firstRunIndex;
+            std::optional<unsigned> lastRunIndex;
+        };
+        RunRange close();
 
         void appendContent(const InlineLineBreaker::Run&);
 
         void adjustLogicalLeft(LayoutUnit delta);
         void adjustLogicalRight(LayoutUnit delta);
 
-        enum class LastLine { No, Yes };
-        void close(LastLine = LastLine::No);
-
         bool hasContent() const { return m_firstRunIndex.has_value(); }
         bool isClosed() const { return m_closed; }
         bool isFirstLine() const { return m_isFirstLine; }
-        LayoutUnit contentLogicalRight();
+        LayoutUnit contentLogicalRight() const;
+        LayoutUnit contentLogicalLeft() const { return m_logicalRect.left(); }
         LayoutUnit availableWidth() const { return m_availableWidth; }
+        std::optional<InlineRunProvider::Run::Type> lastRunType() const { return m_lastRunType; }
 
         LayoutUnit logicalTop() const { return m_logicalRect.top(); }
         LayoutUnit logicalBottom() const { return m_logicalRect.bottom(); }
 
     private:
-        void justifyRuns();
-        void computeExpansionOpportunities(const InlineLineBreaker::Run&);
-
         struct TrailingTrimmableContent {
             LayoutUnit width;
             unsigned length;
         };
         std::optional<TrailingTrimmableContent> m_trailingTrimmableContent;
-        bool m_lastRunIsWhitespace { false };
+        std::optional<InlineRunProvider::Run::Type> m_lastRunType;
         bool m_lastRunCanExpand { false };
 
         InlineFormattingState& m_formattingState;
-        const Box& m_formattingRoot;
 
         Display::Box::Rect m_logicalRect;
         LayoutUnit m_availableWidth;
 
         std::optional<unsigned> m_firstRunIndex;
-        bool m_alignmentIsJustify { false };
         bool m_isFirstLine { true };
         bool m_closed { true };
     };
+    enum class IsLastLine { No, Yes };
 
-    // This class implements positioning and sizing for boxes participating in a block formatting context.
     class Geometry : public FormattingContext::Geometry {
     public:
         static HeightAndMargin inlineBlockHeightAndMargin(const LayoutState&, const Box&);
         static WidthAndMargin inlineBlockWidthAndMargin(LayoutState&, const Box&);
+        static void alignRuns(InlineFormattingState&, TextAlignMode, Line&, Line::RunRange, IsLastLine);
+        static void computeExpansionOpportunities(InlineFormattingState&, const InlineRunProvider::Run&, InlineRunProvider::Run::Type lastRunType);
+
+    private:
+        static void justifyRuns(InlineFormattingState&, Line&, Line::RunRange);
     };
 
     void layoutInlineContent(const InlineRunProvider&) const;
+
     void initializeNewLine(Line&) const;
+    void closeLine(Line&, IsLastLine) const;
+    void appendContentToLine(Line&, const InlineLineBreaker::Run&) const;
 
     void layoutFormattingContextRoot(const Box&) const;
     void computeWidthAndHeightForReplacedInlineBox(const Box&) const;
index 7c9e29e..cd8289f 100644 (file)
@@ -77,6 +77,108 @@ HeightAndMargin InlineFormattingContext::Geometry::inlineBlockHeightAndMargin(co
     return complicatedCases(layoutState, layoutBox);
 }
 
+static LayoutUnit adjustedLineLogicalLeft(TextAlignMode align, LayoutUnit lineLogicalLeft, LayoutUnit remainingWidth)
+{
+    switch (align) {
+    case TextAlignMode::Left:
+    case TextAlignMode::WebKitLeft:
+    case TextAlignMode::Start:
+        return lineLogicalLeft;
+    case TextAlignMode::Right:
+    case TextAlignMode::WebKitRight:
+    case TextAlignMode::End:
+        return lineLogicalLeft + std::max(remainingWidth, LayoutUnit());
+    case TextAlignMode::Center:
+    case TextAlignMode::WebKitCenter:
+        return lineLogicalLeft + std::max(remainingWidth / 2, LayoutUnit());
+    case TextAlignMode::Justify:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return lineLogicalLeft;
+}
+
+void InlineFormattingContext::Geometry::justifyRuns(InlineFormattingState& formattingState, Line& line, Line::RunRange runRange)
+{
+    auto& inlineRuns = formattingState.inlineRuns();
+    auto& lastInlineRun = inlineRuns.last();
+
+    // Adjust (forbid) trailing expansion for the last text run on line.
+    auto expansionBehavior = lastInlineRun.expansionOpportunity().behavior;
+    // Remove allow and add forbid.
+    expansionBehavior ^= AllowTrailingExpansion;
+    expansionBehavior |= ForbidTrailingExpansion;
+    lastInlineRun.expansionOpportunity().behavior = expansionBehavior;
+
+    // Collect expansion opportunities and justify the runs.
+    auto widthToDistribute = line.availableWidth();
+    if (widthToDistribute <= 0)
+        return;
+
+    auto expansionOpportunities = 0;
+    ASSERT(*runRange.lastRunIndex < inlineRuns.size());
+    for (auto runIndex = *runRange.firstRunIndex; runIndex <= *runRange.lastRunIndex; ++runIndex)
+        expansionOpportunities += inlineRuns[runIndex].expansionOpportunity().count;
+
+    if (!expansionOpportunities)
+        return;
+
+    float expansion = widthToDistribute.toFloat() / expansionOpportunities;
+    LayoutUnit accumulatedExpansion = 0;
+    for (auto runIndex = *runRange.firstRunIndex; runIndex <= *runRange.lastRunIndex; ++runIndex) {
+        auto& inlineRun = inlineRuns[runIndex];
+        auto expansionForRun = inlineRun.expansionOpportunity().count * expansion;
+
+        inlineRun.expansionOpportunity().expansion = expansionForRun;
+        inlineRun.setLogicalLeft(inlineRun.logicalLeft() + accumulatedExpansion);
+        inlineRun.setWidth(inlineRun.width() + expansionForRun);
+        accumulatedExpansion += expansionForRun;
+    }
+}
+
+void InlineFormattingContext::Geometry::computeExpansionOpportunities(InlineFormattingState& formattingState, const InlineRunProvider::Run& run, InlineRunProvider::Run::Type lastRunType)
+{
+    auto isExpansionOpportunity = [](auto currentRunIsWhitespace, auto lastRunIsWhitespace) {
+        return currentRunIsWhitespace || (!currentRunIsWhitespace && !lastRunIsWhitespace);
+    };
+
+    auto expansionBehavior = [](auto isAtExpansionOpportunity) {
+        ExpansionBehavior expansionBehavior = AllowTrailingExpansion;
+        expansionBehavior |= isAtExpansionOpportunity ? ForbidLeadingExpansion : AllowLeadingExpansion;
+        return expansionBehavior;
+    };
+
+    auto isAtExpansionOpportunity = isExpansionOpportunity(run.isWhitespace(), lastRunType == InlineRunProvider::Run::Type::Whitespace);
+
+    auto& currentInlineRun = formattingState.inlineRuns().last();
+    auto& expansionOpportunity = currentInlineRun.expansionOpportunity();
+    if (isAtExpansionOpportunity)
+        ++expansionOpportunity.count;
+
+    expansionOpportunity.behavior = expansionBehavior(isAtExpansionOpportunity);
+}
+
+void InlineFormattingContext::Geometry::alignRuns(InlineFormattingState& inlineFormattingState, TextAlignMode textAlign, Line& line, Line::RunRange runRange, IsLastLine isLastLine)
+{
+    auto adjutedTextAlignment = textAlign != TextAlignMode::Justify ? textAlign : isLastLine == IsLastLine::No ? TextAlignMode::Justify : TextAlignMode::Left;
+    if (adjutedTextAlignment == TextAlignMode::Justify) {
+        justifyRuns(inlineFormattingState, line, runRange);
+        return;
+    }
+
+    auto lineLogicalLeft = line.contentLogicalLeft();
+    auto adjustedLogicalLeft = adjustedLineLogicalLeft(adjutedTextAlignment, lineLogicalLeft, line.availableWidth());
+    if (adjustedLogicalLeft == lineLogicalLeft)
+        return;
+
+    auto& inlineRuns = inlineFormattingState.inlineRuns();
+    auto delta = adjustedLogicalLeft - lineLogicalLeft;
+    ASSERT(*runRange.lastRunIndex < inlineRuns.size());
+    for (auto runIndex = *runRange.firstRunIndex; runIndex <= *runRange.lastRunIndex; ++runIndex)
+        inlineRuns[runIndex].setLogicalLeft(inlineRuns[runIndex].logicalLeft() + delta);
+}
+
 }
 }
 
index c1daa3f..31cfe0a 100644 (file)
 namespace WebCore {
 namespace Layout {
 
-InlineFormattingContext::Line::Line(InlineFormattingState& formattingState, const Box& formattingRoot)
+InlineFormattingContext::Line::Line(InlineFormattingState& formattingState)
     : m_formattingState(formattingState)
-    , m_formattingRoot(formattingRoot)
-    , m_alignmentIsJustify(m_formattingRoot.style().textAlign() == TextAlignMode::Justify)
 {
 }
 
@@ -46,7 +44,7 @@ void InlineFormattingContext::Line::init(const Display::Box::Rect& logicalRect)
     m_availableWidth = logicalRect.width();
 
     m_firstRunIndex = { };
-    m_lastRunIsWhitespace = false;
+    m_lastRunType = { };
     m_lastRunCanExpand = false;
     m_trailingTrimmableContent = { };
     m_closed = false;
@@ -75,34 +73,12 @@ void InlineFormattingContext::Line::adjustLogicalRight(LayoutUnit delta)
     m_logicalRect.shiftRightTo(m_logicalRect.right() - delta);
 }
 
-static LayoutUnit adjustedLineLogicalLeft(TextAlignMode align, LayoutUnit lineLogicalLeft, LayoutUnit remainingWidth)
-{
-    switch (align) {
-    case TextAlignMode::Left:
-    case TextAlignMode::WebKitLeft:
-    case TextAlignMode::Start:
-        return lineLogicalLeft;
-    case TextAlignMode::Right:
-    case TextAlignMode::WebKitRight:
-    case TextAlignMode::End:
-        return lineLogicalLeft + std::max(remainingWidth, LayoutUnit());
-    case TextAlignMode::Center:
-    case TextAlignMode::WebKitCenter:
-        return lineLogicalLeft + std::max(remainingWidth / 2, LayoutUnit());
-    case TextAlignMode::Justify:
-        ASSERT_NOT_REACHED();
-        break;
-    }
-    ASSERT_NOT_REACHED();
-    return lineLogicalLeft;
-}
-
 static bool isTrimmableContent(const InlineRunProvider::Run& inlineRun)
 {
     return inlineRun.isWhitespace() && inlineRun.style().collapseWhiteSpace();
 }
 
-LayoutUnit InlineFormattingContext::Line::contentLogicalRight()
+LayoutUnit InlineFormattingContext::Line::contentLogicalRight() const
 {
     if (!m_firstRunIndex.has_value())
         return m_logicalRect.left();
@@ -110,31 +86,6 @@ LayoutUnit InlineFormattingContext::Line::contentLogicalRight()
     return m_formattingState.inlineRuns().last().logicalRight();
 }
 
-void InlineFormattingContext::Line::computeExpansionOpportunities(const InlineLineBreaker::Run& run)
-{
-    if (!m_alignmentIsJustify)
-        return;
-
-    auto isExpansionOpportunity = [](auto currentRunIsWhitespace, auto lastRunIsWhitespace) {
-        return currentRunIsWhitespace || (!currentRunIsWhitespace && !lastRunIsWhitespace);
-    };
-
-    auto expansionBehavior = [](auto isAtExpansionOpportunity) {
-        ExpansionBehavior expansionBehavior = AllowTrailingExpansion;
-        expansionBehavior |= isAtExpansionOpportunity ? ForbidLeadingExpansion : AllowLeadingExpansion;
-        return expansionBehavior;
-    };
-
-    auto isAtExpansionOpportunity = isExpansionOpportunity(run.content.isWhitespace(), m_lastRunIsWhitespace);
-
-    auto& currentInlineRun = m_formattingState.inlineRuns().last();
-    auto& expansionOpportunity = currentInlineRun.expansionOpportunity();
-    if (isAtExpansionOpportunity)
-        ++expansionOpportunity.count;
-
-    expansionOpportunity.behavior = expansionBehavior(isAtExpansionOpportunity);
-}
-
 void InlineFormattingContext::Line::appendContent(const InlineLineBreaker::Run& run)
 {
     ASSERT(!isClosed());
@@ -164,10 +115,8 @@ void InlineFormattingContext::Line::appendContent(const InlineLineBreaker::Run&
         inlineRun.textContext()->setLength(inlineRun.textContext()->length() + textRun->length());
     }
 
-    computeExpansionOpportunities(run);
-
     m_availableWidth -= run.width;
-    m_lastRunIsWhitespace = content.isWhitespace();
+    m_lastRunType = content.type();
     m_lastRunCanExpand = content.isText() && !content.textContext()->isCollapsed();
     m_firstRunIndex = m_firstRunIndex.value_or(m_formattingState.inlineRuns().size() - 1);
     m_trailingTrimmableContent = { };
@@ -175,47 +124,7 @@ void InlineFormattingContext::Line::appendContent(const InlineLineBreaker::Run&
         m_trailingTrimmableContent = TrailingTrimmableContent { run.width, textRun->length() };
 }
 
-void InlineFormattingContext::Line::justifyRuns()
-{
-    if (!hasContent())
-        return;
-
-    auto& inlineRuns = m_formattingState.inlineRuns();
-    auto& lastInlineRun = inlineRuns.last();
-
-    // Adjust (forbid) trailing expansion for the last text run on line.
-    auto expansionBehavior = lastInlineRun.expansionOpportunity().behavior;
-    // Remove allow and add forbid.
-    expansionBehavior ^= AllowTrailingExpansion;
-    expansionBehavior |= ForbidTrailingExpansion;
-    lastInlineRun.expansionOpportunity().behavior = expansionBehavior;
-
-    // Collect expansion opportunities and justify the runs.
-    auto widthToDistribute = availableWidth();
-    if (widthToDistribute <= 0)
-        return;
-
-    auto expansionOpportunities = 0;
-    for (auto runIndex = *m_firstRunIndex; runIndex < inlineRuns.size(); ++runIndex)
-        expansionOpportunities += inlineRuns[runIndex].expansionOpportunity().count;
-
-    if (!expansionOpportunities)
-        return;
-
-    float expansion = widthToDistribute.toFloat() / expansionOpportunities;
-    LayoutUnit accumulatedExpansion = 0;
-    for (auto runIndex = *m_firstRunIndex; runIndex < inlineRuns.size(); ++runIndex) {
-        auto& inlineRun = inlineRuns[runIndex];
-        auto expansionForRun = inlineRun.expansionOpportunity().count * expansion;
-
-        inlineRun.expansionOpportunity().expansion = expansionForRun;
-        inlineRun.setLogicalLeft(inlineRun.logicalLeft() + accumulatedExpansion);
-        inlineRun.setWidth(inlineRun.width() + expansionForRun);
-        accumulatedExpansion += expansionForRun;
-    }
-}
-
-void InlineFormattingContext::Line::close(LastLine isLastLine)
+InlineFormattingContext::Line::RunRange InlineFormattingContext::Line::close()
 {
     auto trimTrailingContent = [&]{
 
@@ -235,35 +144,16 @@ void InlineFormattingContext::Line::close(LastLine isLastLine)
         m_trailingTrimmableContent = { };
     };
 
-    auto alignRuns = [&]{
-
-        if (!hasContent())
-            return;
-
-        auto textAlignment = !m_alignmentIsJustify ? m_formattingRoot.style().textAlign() : isLastLine == LastLine::No ? TextAlignMode::Justify : TextAlignMode::Left;
-        if (textAlignment == TextAlignMode::Justify) {
-            justifyRuns();
-            return;
-        }
-
-        auto adjustedLogicalLeft = adjustedLineLogicalLeft(textAlignment, m_logicalRect.left(), m_availableWidth);
-        if (m_logicalRect.left() == adjustedLogicalLeft)
-            return;
-
-        auto& inlineRuns = m_formattingState.inlineRuns();
-        auto delta = adjustedLogicalLeft - m_logicalRect.left();
-        for (auto runIndex = *m_firstRunIndex; runIndex < inlineRuns.size(); ++runIndex)
-            inlineRuns[runIndex].setLogicalLeft(inlineRuns[runIndex].logicalLeft() + delta);
-    };
-
     if (!hasContent())
-        return;
+        return { };
 
     trimTrailingContent();
-    alignRuns();
-
     m_isFirstLine = false;
     m_closed = true;
+
+    if (!m_firstRunIndex)
+        return { };
+    return { m_firstRunIndex, m_formattingState.inlineRuns().size() - 1 };
 }
 
 }