Simple line layout: Set the pagination strut on the flow when the first line does...
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Feb 2017 22:37:41 +0000 (22:37 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Feb 2017 22:37:41 +0000 (22:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=168738
<rdar://problem/30659469>

Reviewed by Antti Koivisto.

The pagination strut for the first line is tracked by the parent RenderBlockFlow and not by
the line itself (see RenderBlockFlow::adjustLinePositionForPagination()). Also renamed *PaginationStrut* to
*LineStrut* to make sure we don't confuse it with the block level strut.

Not enabled yet.

* rendering/SimpleLineLayout.cpp:
(WebCore::SimpleLineLayout::computeLineTopAndBottomWithOverflow):
(WebCore::SimpleLineLayout::computeLineBreakIndex):
(WebCore::SimpleLineLayout::setPageBreakForLine):
(WebCore::SimpleLineLayout::adjustLinePositionsForPagination):
(WebCore::SimpleLineLayout::create):
(WebCore::SimpleLineLayout::Layout::create):
(WebCore::SimpleLineLayout::Layout::Layout):
* rendering/SimpleLineLayout.h:
(WebCore::SimpleLineLayout::Layout::hasLineStruts):
(WebCore::SimpleLineLayout::Layout::struts):
(WebCore::SimpleLineLayout::Layout::hasPaginationStruts): Deleted.
* rendering/SimpleLineLayoutFunctions.cpp:
(WebCore::SimpleLineLayout::paintFlow):
* rendering/SimpleLineLayoutFunctions.h:
(WebCore::SimpleLineLayout::computeFlowHeight):
* rendering/SimpleLineLayoutResolver.h:
(WebCore::SimpleLineLayout::RunResolver::Run::computeBaselinePosition):

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

Source/WebCore/ChangeLog
Source/WebCore/rendering/SimpleLineLayout.cpp
Source/WebCore/rendering/SimpleLineLayout.h
Source/WebCore/rendering/SimpleLineLayoutFunctions.h
Source/WebCore/rendering/SimpleLineLayoutResolver.h

index b9fb9a4..3e52673 100644 (file)
@@ -1,3 +1,36 @@
+2017-02-22  Zalan Bujtas  <zalan@apple.com>
+
+        Simple line layout: Set the pagination strut on the flow when the first line does not fit the page.
+        https://bugs.webkit.org/show_bug.cgi?id=168738
+        <rdar://problem/30659469>
+
+        Reviewed by Antti Koivisto.
+
+        The pagination strut for the first line is tracked by the parent RenderBlockFlow and not by
+        the line itself (see RenderBlockFlow::adjustLinePositionForPagination()). Also renamed *PaginationStrut* to
+        *LineStrut* to make sure we don't confuse it with the block level strut.
+
+        Not enabled yet.
+
+        * rendering/SimpleLineLayout.cpp:
+        (WebCore::SimpleLineLayout::computeLineTopAndBottomWithOverflow):
+        (WebCore::SimpleLineLayout::computeLineBreakIndex):
+        (WebCore::SimpleLineLayout::setPageBreakForLine):
+        (WebCore::SimpleLineLayout::adjustLinePositionsForPagination):
+        (WebCore::SimpleLineLayout::create):
+        (WebCore::SimpleLineLayout::Layout::create):
+        (WebCore::SimpleLineLayout::Layout::Layout):
+        * rendering/SimpleLineLayout.h:
+        (WebCore::SimpleLineLayout::Layout::hasLineStruts):
+        (WebCore::SimpleLineLayout::Layout::struts):
+        (WebCore::SimpleLineLayout::Layout::hasPaginationStruts): Deleted.
+        * rendering/SimpleLineLayoutFunctions.cpp:
+        (WebCore::SimpleLineLayout::paintFlow):
+        * rendering/SimpleLineLayoutFunctions.h:
+        (WebCore::SimpleLineLayout::computeFlowHeight):
+        * rendering/SimpleLineLayoutResolver.h:
+        (WebCore::SimpleLineLayout::RunResolver::Run::computeBaselinePosition):
+
 2017-02-22  Youenn Fablet  <youenn@apple.com>
 
         [WebRTC] Disable libwebrtc stderr logging in release mode
index 4b8d9a7..f390b37 100644 (file)
@@ -914,7 +914,7 @@ struct PaginatedLine {
 };
 using PaginatedLines = Vector<PaginatedLine, 20>;
 
-static PaginatedLine computeLineTopAndBottomWithOverflow(const RenderBlockFlow& flow, unsigned lineIndex, Layout::SimplePaginationStruts& struts)
+static PaginatedLine computeLineTopAndBottomWithOverflow(const RenderBlockFlow& flow, unsigned lineIndex, Layout::SimpleLineStruts& struts)
 {
     // FIXME: Add visualOverflowForDecorations.
     auto& fontMetrics = flow.style().fontCascade().fontMetrics();
@@ -937,7 +937,7 @@ static PaginatedLine computeLineTopAndBottomWithOverflow(const RenderBlockFlow&
     return { topPosition, bottomPosition, bottomPosition - topPosition };
 }
 
-static unsigned computeLineBreakIndex(unsigned breakCandidate, unsigned lineCount, unsigned widows, const Layout::SimplePaginationStruts& struts)
+static unsigned computeLineBreakIndex(unsigned breakCandidate, unsigned lineCount, unsigned widows, const Layout::SimpleLineStruts& struts)
 {
     // First line does not fit the current page.
     if (!breakCandidate)
@@ -956,19 +956,6 @@ static unsigned computeLineBreakIndex(unsigned breakCandidate, unsigned lineCoun
     return std::max<unsigned>(struts.last().lineBreak + 1, lineBreak);
 }
 
-static void setPageBreakForLine(unsigned lineBreak, PaginatedLines& lines, RenderBlockFlow& flow)
-{
-    if (!lineBreak) {
-        // When the line does not fit the current page, just add a page break in front.
-        auto line = lines.first();
-        flow.setPageBreak(line.top, flow.pageRemainingLogicalHeightForOffset(line.top, RenderBlockFlow::ExcludePageBoundary));
-        return;
-    }
-    auto beforeLineBreak = lines.at(lineBreak - 1);
-    auto spaceShortage = flow.pageRemainingLogicalHeightForOffset(beforeLineBreak.top, RenderBlockFlow::ExcludePageBoundary) - beforeLineBreak.height;
-    flow.setPageBreak(beforeLineBreak.bottom, spaceShortage);
-}
-
 static LayoutUnit computeOffsetAfterLineBreak(LayoutUnit lineBreakPosition, bool isFirstLine, bool atTheTopOfColumnOrPage, const RenderBlockFlow& flow)
 {
     // No offset for top of the page lines unless widows pushed the line break.
@@ -978,6 +965,23 @@ static LayoutUnit computeOffsetAfterLineBreak(LayoutUnit lineBreakPosition, bool
     return offset + flow.pageRemainingLogicalHeightForOffset(lineBreakPosition, RenderBlockFlow::ExcludePageBoundary);
 }
 
+static void setPageBreakForLine(unsigned lineBreakIndex, PaginatedLines& lines, RenderBlockFlow& flow, Layout::SimpleLineStruts& struts,
+    bool atTheTopOfColumnOrPage)
+{
+    if (!lineBreakIndex) {
+        // When the first line does not fit the current page, just add a page break in front and set the strut on the block.
+        auto line = lines.first();
+        auto remainingLogicalHeight = flow.pageRemainingLogicalHeightForOffset(line.top, RenderBlockFlow::ExcludePageBoundary);
+        flow.setPageBreak(line.top, line.height - remainingLogicalHeight);
+        flow.setPaginationStrut(remainingLogicalHeight);
+        return;
+    }
+    auto beforeLineBreak = lines.at(lineBreakIndex - 1);
+    auto spaceShortage = flow.pageRemainingLogicalHeightForOffset(beforeLineBreak.top, RenderBlockFlow::ExcludePageBoundary) - beforeLineBreak.height;
+    flow.setPageBreak(beforeLineBreak.bottom, spaceShortage);
+    struts.append({ lineBreakIndex, computeOffsetAfterLineBreak(lines[lineBreakIndex].top, !lineBreakIndex, atTheTopOfColumnOrPage, flow) });
+}
+
 static void updateMinimumPageHeight(RenderBlockFlow& flow, unsigned lineCount)
 {
     auto& style = flow.style();
@@ -987,7 +991,7 @@ static void updateMinimumPageHeight(RenderBlockFlow& flow, unsigned lineCount)
     flow.updateMinimumPageHeight(0, minimumLineCount * lineHeightFromFlow(flow));
 }
 
-static void adjustLinePositionsForPagination(Layout::RunVector& runs, Layout::SimplePaginationStruts& struts,
+static void adjustLinePositionsForPagination(Layout::RunVector& runs, Layout::SimpleLineStruts& struts,
     RenderBlockFlow& flow, unsigned lineCount)
 {
     updateMinimumPageHeight(flow, lineCount);
@@ -1009,8 +1013,7 @@ static void adjustLinePositionsForPagination(Layout::RunVector& runs, Layout::Si
             auto lineBreakIndex = computeLineBreakIndex(lineIndex, lineCount, widows, struts);
             // Are we still at the top of the column/page?
             atTheTopOfColumnOrPage = atTheTopOfColumnOrPage ? lineIndex == lineBreakIndex : false;
-            setPageBreakForLine(lineBreakIndex, lines, flow);
-            struts.append({ lineBreakIndex, computeOffsetAfterLineBreak(lines[lineBreakIndex].top, !lineBreakIndex, atTheTopOfColumnOrPage, flow) });
+            setPageBreakForLine(lineBreakIndex, lines, flow, struts, atTheTopOfColumnOrPage);
             // Recompute line positions that we already visited but window break pushed them to a new page.
             for (auto i = lineBreakIndex; i < lines.size(); ++i)
                 lines.at(i) = computeLineTopAndBottomWithOverflow(flow, i, struts);
@@ -1044,24 +1047,24 @@ std::unique_ptr<Layout> create(RenderBlockFlow& flow)
     unsigned lineCount = 0;
     Layout::RunVector runs;
     createTextRuns(runs, flow, lineCount);
-    Layout::SimplePaginationStruts struts;
+    Layout::SimpleLineStruts struts;
     auto isPaginated = flow.view().layoutState() && flow.view().layoutState()->isPaginated();
     if (isPaginated)
         adjustLinePositionsForPagination(runs, struts, flow, lineCount);
     return Layout::create(runs, struts, lineCount, isPaginated);
 }
 
-std::unique_ptr<Layout> Layout::create(const RunVector& runVector, SimplePaginationStruts& struts, unsigned lineCount, bool isPaginated)
+std::unique_ptr<Layout> Layout::create(const RunVector& runVector, SimpleLineStruts& struts, unsigned lineCount, bool isPaginated)
 {
     void* slot = WTF::fastMalloc(sizeof(Layout) + sizeof(Run) * runVector.size());
     return std::unique_ptr<Layout>(new (NotNull, slot) Layout(runVector, struts, lineCount, isPaginated));
 }
 
-Layout::Layout(const RunVector& runVector, SimplePaginationStruts& struts, unsigned lineCount, bool isPaginated)
+Layout::Layout(const RunVector& runVector, SimpleLineStruts& struts, unsigned lineCount, bool isPaginated)
     : m_lineCount(lineCount)
     , m_runCount(runVector.size())
     , m_isPaginated(isPaginated)
-    , m_paginationStruts(WTFMove(struts))
+    , m_lineStruts(WTFMove(struts))
 {
     memcpy(m_runs, runVector.data(), m_runCount * sizeof(Run));
 }
index 13e5956..5bd4102 100644 (file)
@@ -66,7 +66,7 @@ struct Run {
     ExpansionBehavior expansionBehavior { ForbidLeadingExpansion | ForbidTrailingExpansion };
 };
 
-struct SimplePaginationStrut {
+struct SimpleLineStrut {
     unsigned lineBreak;
     float offset;
 };
@@ -75,8 +75,8 @@ class Layout {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     using RunVector = Vector<Run, 10>;
-    using SimplePaginationStruts = Vector<SimplePaginationStrut, 4>;
-    static std::unique_ptr<Layout> create(const RunVector&, SimplePaginationStruts&, unsigned lineCount, bool isPaginated);
+    using SimpleLineStruts = Vector<SimpleLineStrut, 4>;
+    static std::unique_ptr<Layout> create(const RunVector&, SimpleLineStruts&, unsigned lineCount, bool isPaginated);
 
     unsigned lineCount() const { return m_lineCount; }
 
@@ -84,15 +84,15 @@ public:
     const Run& runAt(unsigned i) const { return m_runs[i]; }
 
     bool isPaginated() const { return m_isPaginated; }
-    bool hasPaginationStruts() const { return !m_paginationStruts.isEmpty(); }
-    const SimplePaginationStruts& struts() const { return m_paginationStruts; }
+    bool hasLineStruts() const { return !m_lineStruts.isEmpty(); }
+    const SimpleLineStruts& struts() const { return m_lineStruts; }
 private:
-    Layout(const RunVector&, SimplePaginationStruts&, unsigned lineCount, bool isPaginated);
+    Layout(const RunVector&, SimpleLineStruts&, unsigned lineCount, bool isPaginated);
 
     unsigned m_lineCount;
     unsigned m_runCount;
     bool m_isPaginated;
-    SimplePaginationStruts m_paginationStruts;
+    SimpleLineStruts m_lineStruts;
     Run m_runs[0];
 };
 
index 7b30839..ce65a29 100644 (file)
@@ -74,7 +74,7 @@ namespace SimpleLineLayout {
 inline LayoutUnit computeFlowHeight(const RenderBlockFlow& flow, const Layout& layout)
 {
     auto flowHeight = lineHeightFromFlow(flow) * layout.lineCount();
-    if (!layout.hasPaginationStruts())
+    if (!layout.hasLineStruts())
         return flowHeight;
     for (auto& strutEntry : layout.struts())
         flowHeight += strutEntry.offset;
index ce242cb..472a1d2 100644 (file)
@@ -221,7 +221,7 @@ inline float RunResolver::Run::computeBaselinePosition() const
 {
     auto& resolver = m_iterator.resolver();
     auto offset = resolver.m_borderAndPaddingBefore + resolver.m_lineHeight * lineIndex();
-    if (!resolver.m_layout.hasPaginationStruts())
+    if (!resolver.m_layout.hasLineStruts())
         return offset + resolver.m_baseline;
     for (auto& strutEntry : resolver.m_layout.struts()) {
         if (strutEntry.lineBreak > lineIndex())