Title: [230914] trunk/Source/WebCore
Revision
230914
Author
[email protected]
Date
2018-04-23 07:47:00 -0700 (Mon, 23 Apr 2018)

Log Message

[Simple line layout] Generate inline boxtree using simple line layout runs.
https://bugs.webkit.org/show_bug.cgi?id=184833

Reviewed by Antti Koivisto.

RenderBlockFlow::ensureLineBoxes triggers line layout on the block content to replace
the simple line layout runs with an inline boxtree. The runs generated by the fast path
should always match the inline tree boxes.
In this patch instead of triggering layout, we just convert the simple line runs to
inline boxes.
Currently, it works with only one, non-paginated text renderer, but we should be
able to extend it to all the simple line layout content.

Covered by existing tests.

* rendering/InlineBox.h:
(WebCore::InlineBox::setHasHyphen):
(WebCore::InlineBox::setCanHaveLeadingExpansion):
(WebCore::InlineBox::setCanHaveTrailingExpansion):
(WebCore::InlineBox::setForceTrailingExpansion):
(WebCore::InlineBox::setForceLeadingExpansion):
(WebCore::InlineBox::hasHyphen const):
(WebCore::InlineBox::canHaveLeadingExpansion const):
(WebCore::InlineBox::canHaveTrailingExpansion const):
(WebCore::InlineBox::forceTrailingExpansion const):
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::ensureLineBoxes):
* rendering/RenderBlockFlow.h:
* rendering/SimpleLineLayoutFlowContents.h:
(WebCore::SimpleLineLayout::FlowContents::segmentForRun const):
* rendering/SimpleLineLayoutFunctions.cpp:
(WebCore::SimpleLineLayout::canUseForLineBoxTree):
(WebCore::SimpleLineLayout::initializeInlineBox):
(WebCore::SimpleLineLayout::generateLineBoxTree):
* rendering/SimpleLineLayoutFunctions.h:
* rendering/SimpleLineLayoutResolver.cpp:
(WebCore::SimpleLineLayout::RunResolver::rangeForLine const):
* rendering/SimpleLineLayoutResolver.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (230913 => 230914)


--- trunk/Source/WebCore/ChangeLog	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/ChangeLog	2018-04-23 14:47:00 UTC (rev 230914)
@@ -1,3 +1,44 @@
+2018-04-23  Zalan Bujtas  <[email protected]>
+
+        [Simple line layout] Generate inline boxtree using simple line layout runs.
+        https://bugs.webkit.org/show_bug.cgi?id=184833
+
+        Reviewed by Antti Koivisto.
+
+        RenderBlockFlow::ensureLineBoxes triggers line layout on the block content to replace
+        the simple line layout runs with an inline boxtree. The runs generated by the fast path
+        should always match the inline tree boxes.
+        In this patch instead of triggering layout, we just convert the simple line runs to
+        inline boxes.
+        Currently, it works with only one, non-paginated text renderer, but we should be
+        able to extend it to all the simple line layout content.   
+
+        Covered by existing tests.
+
+        * rendering/InlineBox.h:
+        (WebCore::InlineBox::setHasHyphen):
+        (WebCore::InlineBox::setCanHaveLeadingExpansion):
+        (WebCore::InlineBox::setCanHaveTrailingExpansion):
+        (WebCore::InlineBox::setForceTrailingExpansion):
+        (WebCore::InlineBox::setForceLeadingExpansion):
+        (WebCore::InlineBox::hasHyphen const):
+        (WebCore::InlineBox::canHaveLeadingExpansion const):
+        (WebCore::InlineBox::canHaveTrailingExpansion const):
+        (WebCore::InlineBox::forceTrailingExpansion const):
+        * rendering/RenderBlockFlow.cpp:
+        (WebCore::RenderBlockFlow::ensureLineBoxes):
+        * rendering/RenderBlockFlow.h:
+        * rendering/SimpleLineLayoutFlowContents.h:
+        (WebCore::SimpleLineLayout::FlowContents::segmentForRun const):
+        * rendering/SimpleLineLayoutFunctions.cpp:
+        (WebCore::SimpleLineLayout::canUseForLineBoxTree):
+        (WebCore::SimpleLineLayout::initializeInlineBox):
+        (WebCore::SimpleLineLayout::generateLineBoxTree):
+        * rendering/SimpleLineLayoutFunctions.h:
+        * rendering/SimpleLineLayoutResolver.cpp:
+        (WebCore::SimpleLineLayout::RunResolver::rangeForLine const):
+        * rendering/SimpleLineLayoutResolver.h:
+
 2018-04-23  Zan Dobersek  <[email protected]>
 
         [CoordGraphics] Remove unused trajectory cruft in CoordinatedLayerTreeHost, CoordinatedGraphicsLayer

Modified: trunk/Source/WebCore/rendering/InlineBox.h (230913 => 230914)


--- trunk/Source/WebCore/rendering/InlineBox.h	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/InlineBox.h	2018-04-23 14:47:00 UTC (rev 230914)
@@ -280,6 +280,12 @@
     }
     float expansion() const { return m_expansion; }
 
+    void setHasHyphen(bool hasHyphen) { m_bitfields.setHasEllipsisBoxOrHyphen(hasHyphen); }
+    void setCanHaveLeadingExpansion(bool canHaveLeadingExpansion) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(canHaveLeadingExpansion); }
+    void setCanHaveTrailingExpansion(bool canHaveTrailingExpansion) { m_bitfields.setCanHaveTrailingExpansion(canHaveTrailingExpansion); }
+    void setForceTrailingExpansion() { m_bitfields.setForceTrailingExpansion(true); }
+    void setForceLeadingExpansion() { m_bitfields.setForceLeadingExpansion(true); }
+
 private:
     InlineBox* m_next { nullptr }; // The next element on the same line as us.
     InlineBox* m_prev { nullptr }; // The previous element on the same line as us.
@@ -395,14 +401,9 @@
 
     // For InlineTextBox
     bool hasHyphen() const { return m_bitfields.hasEllipsisBoxOrHyphen(); }
-    void setHasHyphen(bool hasHyphen) { m_bitfields.setHasEllipsisBoxOrHyphen(hasHyphen); }    
     bool canHaveLeadingExpansion() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); }
-    void setCanHaveLeadingExpansion(bool canHaveLeadingExpansion) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(canHaveLeadingExpansion); }
     bool canHaveTrailingExpansion() const { return m_bitfields.canHaveTrailingExpansion(); }
-    void setCanHaveTrailingExpansion(bool canHaveTrailingExpansion) { m_bitfields.setCanHaveTrailingExpansion(canHaveTrailingExpansion); }
-    void setForceTrailingExpansion() { m_bitfields.setForceTrailingExpansion(true); }
     bool forceTrailingExpansion() const { return m_bitfields.forceTrailingExpansion(); }
-    void setForceLeadingExpansion() { m_bitfields.setForceLeadingExpansion(true); }
     bool forceLeadingExpansion() const { return m_bitfields.forceLeadingExpansion(); }
     
     // For InlineFlowBox and InlineTextBox

Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.cpp (230913 => 230914)


--- trunk/Source/WebCore/rendering/RenderBlockFlow.cpp	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.cpp	2018-04-23 14:47:00 UTC (rev 230914)
@@ -53,6 +53,7 @@
 #include "Settings.h"
 #include "SimpleLineLayoutFunctions.h"
 #include "SimpleLineLayoutPagination.h"
+#include "SimpleLineLayoutResolver.h"
 #include "TextAutoSizing.h"
 #include "VerticalPositionCache.h"
 #include "VisiblePosition.h"
@@ -3620,6 +3621,12 @@
     setLineLayoutPath(ForceLineBoxesPath);
     if (!m_simpleLineLayout)
         return;
+
+    if (SimpleLineLayout::canUseForLineBoxTree(*this, *m_simpleLineLayout)) {
+        SimpleLineLayout::generateLineBoxTree(*this, *m_simpleLineLayout);
+        m_simpleLineLayout = nullptr;
+        return;
+    }
     bool isPaginated = m_simpleLineLayout->isPaginated();
     m_simpleLineLayout = nullptr;
 

Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.h (230913 => 230914)


--- trunk/Source/WebCore/rendering/RenderBlockFlow.h	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.h	2018-04-23 14:47:00 UTC (rev 230914)
@@ -360,6 +360,7 @@
     const SimpleLineLayout::Layout* simpleLineLayout() const;
     void deleteLineBoxesBeforeSimpleLineLayout();
     void ensureLineBoxes();
+    void generateLineBoxTree();
 
 #if ENABLE(TREE_DEBUGGING)
     void outputLineTreeAndMark(WTF::TextStream&, const InlineBox* markedBox, int depth) const;
@@ -533,6 +534,7 @@
     LayoutUnit startAlignedOffsetForLine(LayoutUnit position, IndentTextOrNot shouldIndentText);
     virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
     virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
+    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
 
 private:        
     void adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
@@ -542,7 +544,6 @@
 
     virtual std::unique_ptr<RootInlineBox> createRootInlineBox(); // Subclassed by RenderSVGText.
     InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
-    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
     void setMarginsForRubyRun(BidiRun*, RenderRubyRun&, RenderObject*, const LineInfo&);
     void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
     void updateRubyForJustifiedText(RenderRubyRun&, BidiRun&, const Vector<unsigned, 16>& expansionOpportunities, unsigned& expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth, size_t& expansionIndex);

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h (230913 => 230914)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFlowContents.h	2018-04-23 14:47:00 UTC (rev 230914)
@@ -65,8 +65,9 @@
 inline const FlowContents::Segment& FlowContents::segmentForRun(unsigned start, unsigned end) const
 {
     ASSERT(start <= end);
+    auto isEmptyRange = start == end;
     auto& lastSegment = m_segments[m_lastSegmentIndex];
-    if (lastSegment.start <= start && end <= lastSegment.end)
+    if ((lastSegment.start <= start && end <= lastSegment.end) && (!isEmptyRange || end != lastSegment.end))
         return m_segments[m_lastSegmentIndex];
     return m_segments[segmentIndexForRunSlow(start, end)];
 }

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp (230913 => 230914)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.cpp	2018-04-23 14:47:00 UTC (rev 230914)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "SimpleLineLayoutFunctions.h"
 
+#include "BidiRun.h"
+#include "BidiRunList.h"
 #include "FontCache.h"
 #include "Frame.h"
 #include "GraphicsContext.h"
@@ -33,6 +35,7 @@
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
 #include "InlineTextBox.h"
+#include "LineInfo.h"
 #include "PaintInfo.h"
 #include "RenderBlockFlow.h"
 #include "RenderIterator.h"
@@ -269,6 +272,97 @@
         TextPainter::removeGlyphDisplayList(layout.runAt(i));
 }
 
+bool canUseForLineBoxTree(RenderBlockFlow& flow, const Layout& layout)
+{
+    if (layout.isPaginated())
+        return false;
+    
+    if (flow.style().preserveNewline())
+        return false;
+    
+    if (!flow.firstChild())
+        return false;
+    
+    if (flow.firstChild() != flow.lastChild())
+        return false;
+
+    if (!is<RenderText>(*flow.firstChild()))
+        return false;
+
+    return true;
+}
+
+static void initializeInlineBox(InlineBox& inlineBox, const RunResolver::Run& run)
+{
+    inlineBox.setLogicalLeft(run.logicalLeft());
+    inlineBox.setLogicalTop(run.rect().y());
+    inlineBox.setLogicalWidth(run.logicalRight() - run.logicalLeft());
+
+    inlineBox.setHasHyphen(run.hasHyphen());
+    inlineBox.setExpansionWithoutGrowing(run.expansion());
+
+    auto expansionBehavior = run.expansionBehavior();
+    inlineBox.setCanHaveLeadingExpansion(expansionBehavior & AllowLeadingExpansion);
+    inlineBox.setCanHaveTrailingExpansion(expansionBehavior & AllowTrailingExpansion);
+    if (expansionBehavior & ForceTrailingExpansion)
+        inlineBox.setForceTrailingExpansion();
+    if (expansionBehavior & ForceLeadingExpansion)
+        inlineBox.setForceLeadingExpansion();
+}
+
+void generateLineBoxTree(RenderBlockFlow& flow, const Layout& layout)
+{
+    ASSERT(!flow.lineBoxes().firstLineBox());
+    if (!layout.runCount())
+        return;
+
+    Ref<BidiContext> bidiContext = BidiContext::create(0, U_LEFT_TO_RIGHT);
+    auto resolver = runResolver(flow, layout);
+    unsigned lineIndex = 0;
+    while (true) {
+        auto range = resolver.rangeForLine(lineIndex++);
+        if (range.begin() == range.end())
+            break;
+
+        // Generate bidi runs out of simple line layout runs.
+        BidiRunList<BidiRun> bidiRuns;
+        for (auto it = range.begin(); it != range.end(); ++it) {
+            auto run = *it;
+            bidiRuns.appendRun(std::make_unique<BidiRun>(run.start(), run.end(), *flow.firstChild(), bidiContext.ptr(), U_LEFT_TO_RIGHT));
+        }
+
+        LineInfo lineInfo;
+        lineInfo.setFirstLine(!flow.lineBoxes().firstLineBox());
+        // FIXME: This is needed for flow boxes -but we don't have them yet.
+        // lineInfo.setLastLine(lastLine);
+        lineInfo.setEmpty(!bidiRuns.runCount());
+        bidiRuns.setLogicallyLastRun(bidiRuns.lastRun());
+        auto* root = flow.constructLine(bidiRuns, lineInfo);
+        bidiRuns.clear();
+        if (!root)
+            continue;
+
+        auto& rootLineBox = *root;
+        auto it = range.begin();
+        float lineWidth = 0;
+        // Set the geometry for the inlineboxes.
+        for (auto* inlineBox = rootLineBox.firstChild(); inlineBox && it != range.end(); inlineBox = inlineBox->nextOnLine(), ++it) {
+            auto run = *it;
+            initializeInlineBox(*inlineBox, run);
+            lineWidth += inlineBox->logicalWidth();
+        }
+
+        // Finish setting up the rootline.
+        auto firstRun = *range.begin();
+        rootLineBox.setLogicalLeft(firstRun.logicalLeft());
+        rootLineBox.setLogicalWidth(lineWidth);
+        auto lineTop = firstRun.rect().y();
+        auto lineHeight = firstRun.rect().height();
+        rootLineBox.setLogicalTop(lineTop);
+        rootLineBox.setLineTopBottomPositions(lineTop, lineTop + lineHeight, lineTop, lineTop + lineHeight);
+    }
+}
+
 #if ENABLE(TREE_DEBUGGING)
 static void printPrefix(TextStream& stream, int& printedCharacters, int depth)
 {

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.h (230913 => 230914)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.h	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutFunctions.h	2018-04-23 14:47:00 UTC (rev 230914)
@@ -64,6 +64,9 @@
 LayoutUnit lineHeightFromFlow(const RenderBlockFlow&);
 LayoutUnit baselineFromFlow(const RenderBlockFlow&);
 
+bool canUseForLineBoxTree(RenderBlockFlow&, const Layout&);
+void generateLineBoxTree(RenderBlockFlow&, const Layout&);
+
 const RenderObject& rendererForPosition(const FlowContents&, unsigned);
 
 void simpleLineLayoutWillBeDeleted(const Layout&);

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp (230913 => 230914)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.cpp	2018-04-23 14:47:00 UTC (rev 230914)
@@ -202,6 +202,16 @@
     return { rangeBegin, rangeEnd };
 }
 
+WTF::IteratorRange<RunResolver::Iterator> RunResolver::rangeForLine(unsigned lineIndex) const
+{
+    auto rangeBegin = begin().advanceLines(lineIndex);
+    if (rangeBegin == end())
+        return { end(), end() };
+    auto rangeEnd = rangeBegin;
+    rangeEnd.advanceLines(1);
+    return { rangeBegin, rangeEnd };
+}
+
 WTF::IteratorRange<RunResolver::Iterator> RunResolver::rangeForRenderer(const RenderObject& renderer) const
 {
     if (begin() == end())

Modified: trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h (230913 => 230914)


--- trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h	2018-04-23 14:16:00 UTC (rev 230913)
+++ trunk/Source/WebCore/rendering/SimpleLineLayoutResolver.h	2018-04-23 14:47:00 UTC (rev 230914)
@@ -104,6 +104,7 @@
 
     WTF::IteratorRange<Iterator> rangeForRect(const LayoutRect&) const;
     WTF::IteratorRange<Iterator> rangeForRenderer(const RenderObject&) const;
+    WTF::IteratorRange<Iterator> rangeForLine(unsigned lineIndex) const;
     Iterator runForPoint(const LayoutPoint&) const;
     WTF::IteratorRange<Iterator> rangeForRendererWithOffsets(const RenderObject&, unsigned start, unsigned end) const;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to