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;