[LFC][IFC] Line::close should merge the text runs.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Sep 2019 19:25:53 +0000 (19:25 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Sep 2019 19:25:53 +0000 (19:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=202319
<rdar://problem/55785949>

Reviewed by Antti Koivisto.

Now Line::close returns the final Display::Run list.

* layout/displaytree/DisplayRect.h:
(WebCore::Display::Rect::expandHorizontally):
(WebCore::Display::Rect::expandVertically):
(WebCore::Display::Rect::expand):
* layout/displaytree/DisplayRun.h:
(WebCore::Display::Run::expandVertically):
(WebCore::Display::Run::expandHorizontally):
* layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
(WebCore::Layout::InlineFormattingContext::InlineLayout::createDisplayRuns):
* layout/inlineformatting/InlineLine.cpp:
(WebCore::Layout::Line::close):
* layout/inlineformatting/InlineLine.h:
(WebCore::Layout::Line::Run::displayRun):

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

Source/WebCore/ChangeLog
Source/WebCore/layout/displaytree/DisplayRect.h
Source/WebCore/layout/displaytree/DisplayRun.h
Source/WebCore/layout/inlineformatting/InlineFormattingContext.h
Source/WebCore/layout/inlineformatting/InlineFormattingContextLineLayout.cpp
Source/WebCore/layout/inlineformatting/InlineLine.cpp
Source/WebCore/layout/inlineformatting/InlineLine.h

index c6628bf..2c52543 100644 (file)
@@ -1,3 +1,27 @@
+2019-09-27  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Line::close should merge the text runs.
+        https://bugs.webkit.org/show_bug.cgi?id=202319
+        <rdar://problem/55785949>
+
+        Reviewed by Antti Koivisto.
+
+        Now Line::close returns the final Display::Run list.
+
+        * layout/displaytree/DisplayRect.h:
+        (WebCore::Display::Rect::expandHorizontally):
+        (WebCore::Display::Rect::expandVertically):
+        (WebCore::Display::Rect::expand):
+        * layout/displaytree/DisplayRun.h:
+        (WebCore::Display::Run::expandVertically):
+        (WebCore::Display::Run::expandHorizontally):
+        * layout/inlineformatting/InlineFormattingContextLineLayout.cpp:
+        (WebCore::Layout::InlineFormattingContext::InlineLayout::createDisplayRuns):
+        * layout/inlineformatting/InlineLine.cpp:
+        (WebCore::Layout::Line::close):
+        * layout/inlineformatting/InlineLine.h:
+        (WebCore::Layout::Line::Run::displayRun):
+
 2019-09-27  Chris Dumez  <cdumez@apple.com>
 
         Allow pages served over HTTPS with `Cache-Control: no-store` header to enter the back/forward cache
index bd2d79a..77e5920 100644 (file)
@@ -68,9 +68,9 @@ public:
     void moveHorizontally(LayoutUnit);
     void moveVertically(LayoutUnit);
 
-    void expand(LayoutUnit, LayoutUnit);
-    void expandHorizontally(LayoutUnit delta) { expand(delta, 0); }
-    void expandVertically(LayoutUnit delta) { expand(0, delta); }
+    void expand(Optional<LayoutUnit>, Optional<LayoutUnit>);
+    void expandHorizontally(LayoutUnit delta) { expand(delta, { }); }
+    void expandVertically(LayoutUnit delta) { expand({ }, delta); }
     bool intersects(const Rect& rect) const { return m_rect.intersects(rect); }
 
     Rect clone() const;
@@ -273,10 +273,11 @@ inline void Rect::moveVertically(LayoutUnit offset)
     m_rect.move(LayoutSize { 0, offset });
 }
 
-inline void Rect::expand(LayoutUnit width, LayoutUnit height)
+inline void Rect::expand(Optional<LayoutUnit> width, Optional<LayoutUnit> height)
 {
-    ASSERT(hasValidGeometry());
-    m_rect.expand(width, height);
+    ASSERT(!width || m_hasValidWidth);
+    ASSERT(!height || m_hasValidHeight);
+    m_rect.expand(width.valueOr(0), height.valueOr(0));
 }
 
 inline Rect Rect::clone() const
index 2da71dc..ef0c04f 100644 (file)
@@ -74,8 +74,8 @@ struct Run {
     void setLogicalRight(LayoutUnit logicalRight) { m_logicalRect.shiftRightTo(logicalRight); }
     void moveVertically(LayoutUnit delta) { m_logicalRect.moveVertically(delta); }
     void moveHorizontally(LayoutUnit delta) { m_logicalRect.moveHorizontally(delta); }
-    void expandVertically(LayoutUnit delta) { m_logicalRect.expand(0, delta); }
-    void expandHorizontally(LayoutUnit delta) { m_logicalRect.expand(delta, 0); }
+    void expandVertically(LayoutUnit delta) { m_logicalRect.expandVertically(delta); }
+    void expandHorizontally(LayoutUnit delta) { m_logicalRect.expandHorizontally(delta); }
 
     void setTextContext(TextContext textContext) { m_textContext.emplace(textContext); }
     Optional<TextContext>& textContext() { return m_textContext; }
index 607b16b..ef76b7e 100644 (file)
@@ -67,7 +67,7 @@ private:
         LayoutUnit widthConstraint() const { return m_usedHorizontalValues.constraints.width; }
 
         LineContent placeInlineItems(const LineInput&) const;
-        void createDisplayRuns(const LineContent&);
+        void setupDisplayBoxes(const LineContent&);
         void alignRuns(TextAlignMode, InlineRuns&, unsigned firstRunIndex, LayoutUnit availableWidth) const;
 
     private:
index eff232e..957e901 100644 (file)
@@ -285,7 +285,7 @@ void InlineFormattingContext::InlineLayout::layout(const InlineItems& inlineItem
         auto lineLayout = LineLayout { formattingContext(), lineInput };
 
         auto lineContent = lineLayout.layout();
-        createDisplayRuns(lineContent);
+        setupDisplayBoxes(lineContent);
 
         if (lineContent.lastCommitted) {
             currentInlineItem = { lineContent.lastCommitted->index + 1, WTF::nullopt };
@@ -358,7 +358,7 @@ LayoutUnit InlineFormattingContext::InlineLayout::computedIntrinsicWidth(const I
     return maximumLineWidth;
 }
 
-void InlineFormattingContext::InlineLayout::createDisplayRuns(const LineContent& lineContent)
+void InlineFormattingContext::InlineLayout::setupDisplayBoxes(const LineContent& lineContent)
 {
     auto& formattingContext = this->formattingContext();
     auto& formattingState = this->formattingState();
@@ -381,40 +381,16 @@ void InlineFormattingContext::InlineLayout::createDisplayRuns(const LineContent&
     // 9.4.2 Inline formatting contexts
     // A line box is always tall enough for all of the boxes it contains.
 
-    // Create final display runs.
-    auto& lineRuns = lineContent.runList;
-    for (unsigned index = 0; index < lineRuns.size(); ++index) {
-        auto& run = lineRuns.at(index);
+    // Add final display runs to state.
+    for (auto& lineRun : lineContent.runList) {
         // Inline level containers (<span>) don't generate inline runs.
-        if (run->isContainerStart() || run->isContainerEnd())
-            continue;
-        auto& logicalRect = run->logicalRect();
-        // Inline level box (replaced or inline-block) or <br>/<wbr>
-        if (run->isLineBreak() || run->isBox()) {
-            formattingState.addInlineRun(run->displayRun());
-            continue;
-        }
-        if (run->isText()) {
-            // Collapsed line runs don't generate display runs.
-            if (run->isVisuallyEmpty())
-                continue;
-            // Try to join multiple text runs when possible.
-            const Line::Run* previousRun = !index ? nullptr : lineRuns[index - 1].get();
-            auto previousRunCanBeExtended = previousRun && previousRun->canBeExtended();
-            auto currentRunCanBeMergedWithPrevious = !previousRun || &run->layoutBox() == &previousRun->layoutBox();
-
-            if (previousRunCanBeExtended && currentRunCanBeMergedWithPrevious) {
-                auto& previousDisplayRun = formattingState.inlineRuns().last();
-                previousDisplayRun.expandHorizontally(logicalRect.width());
-                previousDisplayRun.textContext()->expand(run->displayRun().textContext()->length());
-            } else
-                formattingState.addInlineRun(run->displayRun());
+        if (lineRun->isContainerStart() || lineRun->isContainerEnd())
             continue;
-        }
-        ASSERT_NOT_REACHED();
+        formattingState.addInlineRun(lineRun->displayRun());
     }
 
     auto geometry = formattingContext.geometry();
+    auto& lineRuns = lineContent.runList;
     for (unsigned index = 0; index < lineRuns.size(); ++index) {
         auto& lineRun = lineRuns.at(index);
         auto& logicalRect = lineRun->logicalRect();
@@ -458,7 +434,6 @@ void InlineFormattingContext::InlineLayout::createDisplayRuns(const LineContent&
             continue;
         }
 
-        // Text content. Try to join multiple text runs when possible.
         if (lineRun->isText()) {
             const Line::Run* previousLineRun = !index ? nullptr : lineRuns[index - 1].get();
             // FIXME take content breaking into account when part of the layout box is on the previous line.
index d3aa3ce..12f8021 100644 (file)
@@ -159,6 +159,31 @@ Line::RunList Line::close()
             run->moveHorizontally(this->logicalLeft());
         }
     }
+
+    // Let's join text runs together when possible.
+    // FIXME: Check if we can do it as part of the loop above.
+    unsigned index = 1;
+    while (index < m_runList.size()) {
+        auto& previousRun = m_runList[index - 1];
+        if (!previousRun->canBeExtended()) {
+            ++index;
+            continue;
+        }
+        auto& currentRun = m_runList[index];
+        if (&currentRun->layoutBox() != &previousRun->layoutBox()) {
+            // Do not merge runs from different boxes (<span>foo</span><span>bar</span>).
+            ++index;
+            continue;
+        }
+        // Only text content can be extended atm.
+        ASSERT(previousRun->isText());
+        ASSERT(currentRun->isText());
+        auto& previousDisplayRun = previousRun->displayRun();
+        auto& currentDisplayRun = currentRun->displayRun();
+        previousDisplayRun.expandHorizontally(currentDisplayRun.logicalWidth());
+        previousDisplayRun.textContext()->expand(currentDisplayRun.textContext()->length());
+        m_runList.remove(index);
+    }
     return WTFMove(m_runList);
 }
 
index 225d4ae..1a6bed1 100644 (file)
@@ -69,6 +69,7 @@ public:
         Run(const InlineItem&, const Display::Run&);
 
         const Display::Run& displayRun() const { return m_displayRun; }
+        Display::Run& displayRun() { return m_displayRun; }
         const Box& layoutBox() const { return m_inlineItem.layoutBox(); }
 
         const Display::Rect& logicalRect() const { return m_displayRun.logicalRect(); }