[LayoutState cleanup] Move m_layoutState from RenderView to LayoutContext
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Nov 2017 04:09:59 +0000 (04:09 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 7 Nov 2017 04:09:59 +0000 (04:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=179282
<rdar://problem/35348653>

Reviewed by Antti Koivisto.

LayoutContext now owns the top level LayoutState object.
It makes RenderView behave like any other renderer by constructing a LayoutStateMaintainer on the stack.
This is mostly moving code from RenderView.h/.cpp to LayoutContext.h/.cpp and fixing the callsites.
(While view().frameView().layoutContext().layoutState() is a bit lengthy, it's
temporary only, since LayoutState is planned to be an argument of the layout() method.

Covered by existing test.

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::notificationPostTimerFired):
* page/LayoutContext.cpp:
(WebCore::LayoutContext::layoutDelta const):
(WebCore::LayoutContext::addLayoutDelta):
(WebCore::LayoutContext::layoutDeltaMatches):
(WebCore::LayoutContext::pushLayoutState):
(WebCore::LayoutContext::pushLayoutStateForPaginationIfNeeded):
(WebCore::LayoutContext::popLayoutState):
(WebCore::LayoutContext::checkLayoutState):
* page/LayoutContext.h:
(WebCore::LayoutContext::layoutState const):
(WebCore::LayoutContext::layoutStateEnabled const):
(WebCore::LayoutContext::disableLayoutState):
(WebCore::LayoutContext::enableLayoutState):
* rendering/LayoutState.cpp:
(WebCore::LayoutState::LayoutState):
(WebCore::LayoutState::computeClipRect):
(WebCore::LayoutStateMaintainer::LayoutStateMaintainer):
(WebCore::LayoutStateMaintainer::push):
(WebCore::LayoutStateMaintainer::pop):
(WebCore::LayoutStateDisabler::LayoutStateDisabler):
(WebCore::LayoutStateDisabler::~LayoutStateDisabler):
(WebCore::SubtreeLayoutStateMaintainer::SubtreeLayoutStateMaintainer):
(WebCore::SubtreeLayoutStateMaintainer::~SubtreeLayoutStateMaintainer):
(WebCore::PaginatedLayoutStateMaintainer::PaginatedLayoutStateMaintainer):
(WebCore::PaginatedLayoutStateMaintainer::~PaginatedLayoutStateMaintainer):
* rendering/LayoutState.h:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::setLogicalLeftForChild):
(WebCore::RenderBlock::setLogicalTopForChild):
(WebCore::RenderBlock::layoutPositionedObject):
(WebCore::RenderBlock::markForPaginationRelayoutIfNeeded):
(WebCore::RenderBlock::adjustLogicalLeftOffsetForLine const):
(WebCore::RenderBlock::adjustLogicalRightOffsetForLine const):
(WebCore::RenderBlock::offsetFromLogicalTopOfFirstPage const):
(WebCore::RenderBlock::childBoxIsUnsplittableForFragmentation const):
* rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::layoutBlock):
(WebCore::RenderBlockFlow::layoutBlockChildren):
(WebCore::RenderBlockFlow::layoutBlockChild):
(WebCore::RenderBlockFlow::collapseMarginsWithChildInfo):
(WebCore::RenderBlockFlow::estimateLogicalTopPosition):
(WebCore::RenderBlockFlow::applyBeforeBreak):
(WebCore::RenderBlockFlow::applyAfterBreak):
(WebCore::RenderBlockFlow::hasNextPage const):
(WebCore::RenderBlockFlow::pageLogicalTopForOffset const):
(WebCore::RenderBlockFlow::pageLogicalHeightForOffset const):
(WebCore::RenderBlockFlow::pageRemainingLogicalHeightForOffset const):
(WebCore::RenderBlockFlow::repaintOverhangingFloats):
(WebCore::RenderBlockFlow::insertFloatingObject):
(WebCore::RenderBlockFlow::positionNewFloats):
(WebCore::RenderBlockFlow::layoutSimpleLines):
* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlockFlow::layoutRunsAndFloats):
(WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange):
(WebCore::RenderBlockFlow::linkToEndLineIfNeeded):
(WebCore::RenderBlockFlow::layoutLineBoxes):
(WebCore::RenderBlockFlow::determineStartPosition):
(WebCore::RenderBlockFlow::checkPaginationAndFloatsAtEndLine):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::outlineBoundsForRepaint const):
(WebCore::RenderBox::mapLocalToContainer const):
(WebCore::RenderBox::clippedOverflowRectForRepaint const):
(WebCore::RenderBox::computeRectForRepaint const):
(WebCore::RenderBox::offsetFromLogicalTopOfFirstPage const):
* rendering/RenderDeprecatedFlexibleBox.cpp:
(WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
(WebCore::layoutChildIfNeededApplyingDelta):
* rendering/RenderElement.cpp:
(WebCore::RenderElement::insertChildInternal):
(WebCore::RenderElement::takeChildInternal):
* rendering/RenderEmbeddedObject.cpp:
* rendering/RenderFragmentedFlow.cpp:
(WebCore::RenderFragmentedFlow::repaintRectangleInFragments const):
* rendering/RenderGrid.cpp:
* rendering/RenderInline.cpp:
(WebCore::RenderInline::clippedOverflowRectForRepaint const):
(WebCore::RenderInline::computeRectForRepaint const):
(WebCore::RenderInline::mapLocalToContainer const):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateLayerPositions):
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::layout):
* rendering/RenderMediaControlElements.cpp:
(WebCore::RenderMediaVolumeSliderContainer::layout):
(WebCore::RenderMediaControlTimelineContainer::layout):
(WebCore::RenderTextTrackContainerElement::layout):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::repaintRectangle const):
* rendering/RenderReplaced.cpp:
(WebCore::RenderReplaced::clippedOverflowRectForRepaint const):
* rendering/RenderTable.cpp:
(WebCore::RenderTable::layout):
(WebCore::RenderTable::markForPaginationRelayoutIfNeeded):
* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::clippedOverflowRectForRepaint const):
(WebCore::RenderTableCell::computeRectForRepaint const):
* rendering/RenderTableRow.cpp:
(WebCore::RenderTableRow::layout):
* rendering/RenderTableSection.cpp:
(WebCore::RenderTableSection::calcRowLogicalHeight):
(WebCore::RenderTableSection::layout):
(WebCore::RenderTableSection::layoutRows):
(WebCore::RenderTableSection::setLogicalPositionForCell const):
* rendering/RenderVTTCue.cpp:
* rendering/RenderView.cpp:
(WebCore::RenderView::layout):
(WebCore::RenderView::layoutContent): Deleted.
(WebCore::RenderView::checkLayoutState): Deleted.
(WebCore::RenderView::initializeLayoutState): Deleted.
(WebCore::RenderView::pushLayoutState): Deleted.
(WebCore::RenderView::pushLayoutStateForPaginationIfNeeded): Deleted.
* rendering/RenderView.h:
* rendering/RootInlineBox.cpp:
(WebCore::RootInlineBox::lineSnapAdjustment const):
* rendering/svg/RenderSVGContainer.cpp:
(WebCore::RenderSVGContainer::layout):
* rendering/svg/RenderSVGForeignObject.cpp:
(WebCore::RenderSVGForeignObject::layout):
* rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::layout):
* style/RenderTreeUpdaterFirstLetter.cpp:
(WebCore::RenderTreeUpdater::FirstLetter::update):
* style/RenderTreeUpdaterListItem.cpp:
(WebCore::RenderTreeUpdater::ListItem::updateMarker):

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

34 files changed:
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.cpp
Source/WebCore/page/LayoutContext.cpp
Source/WebCore/page/LayoutContext.h
Source/WebCore/rendering/LayoutState.cpp
Source/WebCore/rendering/LayoutState.h
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBlockFlow.cpp
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp
Source/WebCore/rendering/RenderElement.cpp
Source/WebCore/rendering/RenderEmbeddedObject.cpp
Source/WebCore/rendering/RenderFragmentedFlow.cpp
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderInline.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderListBox.cpp
Source/WebCore/rendering/RenderMediaControlElements.cpp
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderReplaced.cpp
Source/WebCore/rendering/RenderTable.cpp
Source/WebCore/rendering/RenderTableCell.cpp
Source/WebCore/rendering/RenderTableRow.cpp
Source/WebCore/rendering/RenderTableSection.cpp
Source/WebCore/rendering/RenderVTTCue.cpp
Source/WebCore/rendering/RenderView.cpp
Source/WebCore/rendering/RenderView.h
Source/WebCore/rendering/RootInlineBox.cpp
Source/WebCore/rendering/svg/RenderSVGContainer.cpp
Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
Source/WebCore/rendering/svg/RenderSVGRoot.cpp
Source/WebCore/style/RenderTreeUpdaterFirstLetter.cpp
Source/WebCore/style/RenderTreeUpdaterListItem.cpp

index 45b92c9..ec766c8 100644 (file)
@@ -1,3 +1,146 @@
+2017-11-06  Zalan Bujtas  <zalan@apple.com>
+
+        [LayoutState cleanup] Move m_layoutState from RenderView to LayoutContext
+        https://bugs.webkit.org/show_bug.cgi?id=179282
+        <rdar://problem/35348653>
+
+        Reviewed by Antti Koivisto.
+
+        LayoutContext now owns the top level LayoutState object.
+        It makes RenderView behave like any other renderer by constructing a LayoutStateMaintainer on the stack.
+        This is mostly moving code from RenderView.h/.cpp to LayoutContext.h/.cpp and fixing the callsites.
+        (While view().frameView().layoutContext().layoutState() is a bit lengthy, it's
+        temporary only, since LayoutState is planned to be an argument of the layout() method.  
+
+        Covered by existing test.
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::notificationPostTimerFired):
+        * page/LayoutContext.cpp:
+        (WebCore::LayoutContext::layoutDelta const):
+        (WebCore::LayoutContext::addLayoutDelta):
+        (WebCore::LayoutContext::layoutDeltaMatches):
+        (WebCore::LayoutContext::pushLayoutState):
+        (WebCore::LayoutContext::pushLayoutStateForPaginationIfNeeded):
+        (WebCore::LayoutContext::popLayoutState):
+        (WebCore::LayoutContext::checkLayoutState):
+        * page/LayoutContext.h:
+        (WebCore::LayoutContext::layoutState const):
+        (WebCore::LayoutContext::layoutStateEnabled const):
+        (WebCore::LayoutContext::disableLayoutState):
+        (WebCore::LayoutContext::enableLayoutState):
+        * rendering/LayoutState.cpp:
+        (WebCore::LayoutState::LayoutState):
+        (WebCore::LayoutState::computeClipRect):
+        (WebCore::LayoutStateMaintainer::LayoutStateMaintainer):
+        (WebCore::LayoutStateMaintainer::push):
+        (WebCore::LayoutStateMaintainer::pop):
+        (WebCore::LayoutStateDisabler::LayoutStateDisabler):
+        (WebCore::LayoutStateDisabler::~LayoutStateDisabler):
+        (WebCore::SubtreeLayoutStateMaintainer::SubtreeLayoutStateMaintainer):
+        (WebCore::SubtreeLayoutStateMaintainer::~SubtreeLayoutStateMaintainer):
+        (WebCore::PaginatedLayoutStateMaintainer::PaginatedLayoutStateMaintainer):
+        (WebCore::PaginatedLayoutStateMaintainer::~PaginatedLayoutStateMaintainer):
+        * rendering/LayoutState.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::setLogicalLeftForChild):
+        (WebCore::RenderBlock::setLogicalTopForChild):
+        (WebCore::RenderBlock::layoutPositionedObject):
+        (WebCore::RenderBlock::markForPaginationRelayoutIfNeeded):
+        (WebCore::RenderBlock::adjustLogicalLeftOffsetForLine const):
+        (WebCore::RenderBlock::adjustLogicalRightOffsetForLine const):
+        (WebCore::RenderBlock::offsetFromLogicalTopOfFirstPage const):
+        (WebCore::RenderBlock::childBoxIsUnsplittableForFragmentation const):
+        * rendering/RenderBlockFlow.cpp:
+        (WebCore::RenderBlockFlow::layoutBlock):
+        (WebCore::RenderBlockFlow::layoutBlockChildren):
+        (WebCore::RenderBlockFlow::layoutBlockChild):
+        (WebCore::RenderBlockFlow::collapseMarginsWithChildInfo):
+        (WebCore::RenderBlockFlow::estimateLogicalTopPosition):
+        (WebCore::RenderBlockFlow::applyBeforeBreak):
+        (WebCore::RenderBlockFlow::applyAfterBreak):
+        (WebCore::RenderBlockFlow::hasNextPage const):
+        (WebCore::RenderBlockFlow::pageLogicalTopForOffset const):
+        (WebCore::RenderBlockFlow::pageLogicalHeightForOffset const):
+        (WebCore::RenderBlockFlow::pageRemainingLogicalHeightForOffset const):
+        (WebCore::RenderBlockFlow::repaintOverhangingFloats):
+        (WebCore::RenderBlockFlow::insertFloatingObject):
+        (WebCore::RenderBlockFlow::positionNewFloats):
+        (WebCore::RenderBlockFlow::layoutSimpleLines):
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlockFlow::layoutRunsAndFloats):
+        (WebCore::RenderBlockFlow::layoutRunsAndFloatsInRange):
+        (WebCore::RenderBlockFlow::linkToEndLineIfNeeded):
+        (WebCore::RenderBlockFlow::layoutLineBoxes):
+        (WebCore::RenderBlockFlow::determineStartPosition):
+        (WebCore::RenderBlockFlow::checkPaginationAndFloatsAtEndLine):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::outlineBoundsForRepaint const):
+        (WebCore::RenderBox::mapLocalToContainer const):
+        (WebCore::RenderBox::clippedOverflowRectForRepaint const):
+        (WebCore::RenderBox::computeRectForRepaint const):
+        (WebCore::RenderBox::offsetFromLogicalTopOfFirstPage const):
+        * rendering/RenderDeprecatedFlexibleBox.cpp:
+        (WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
+        (WebCore::layoutChildIfNeededApplyingDelta):
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::insertChildInternal):
+        (WebCore::RenderElement::takeChildInternal):
+        * rendering/RenderEmbeddedObject.cpp:
+        * rendering/RenderFragmentedFlow.cpp:
+        (WebCore::RenderFragmentedFlow::repaintRectangleInFragments const):
+        * rendering/RenderGrid.cpp:
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::clippedOverflowRectForRepaint const):
+        (WebCore::RenderInline::computeRectForRepaint const):
+        (WebCore::RenderInline::mapLocalToContainer const):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::updateLayerPositions):
+        * rendering/RenderListBox.cpp:
+        (WebCore::RenderListBox::layout):
+        * rendering/RenderMediaControlElements.cpp:
+        (WebCore::RenderMediaVolumeSliderContainer::layout):
+        (WebCore::RenderMediaControlTimelineContainer::layout):
+        (WebCore::RenderTextTrackContainerElement::layout):
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::repaintRectangle const):
+        * rendering/RenderReplaced.cpp:
+        (WebCore::RenderReplaced::clippedOverflowRectForRepaint const):
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::layout):
+        (WebCore::RenderTable::markForPaginationRelayoutIfNeeded):
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::clippedOverflowRectForRepaint const):
+        (WebCore::RenderTableCell::computeRectForRepaint const):
+        * rendering/RenderTableRow.cpp:
+        (WebCore::RenderTableRow::layout):
+        * rendering/RenderTableSection.cpp:
+        (WebCore::RenderTableSection::calcRowLogicalHeight):
+        (WebCore::RenderTableSection::layout):
+        (WebCore::RenderTableSection::layoutRows):
+        (WebCore::RenderTableSection::setLogicalPositionForCell const):
+        * rendering/RenderVTTCue.cpp:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::layout):
+        (WebCore::RenderView::layoutContent): Deleted.
+        (WebCore::RenderView::checkLayoutState): Deleted.
+        (WebCore::RenderView::initializeLayoutState): Deleted.
+        (WebCore::RenderView::pushLayoutState): Deleted.
+        (WebCore::RenderView::pushLayoutStateForPaginationIfNeeded): Deleted.
+        * rendering/RenderView.h:
+        * rendering/RootInlineBox.cpp:
+        (WebCore::RootInlineBox::lineSnapAdjustment const):
+        * rendering/svg/RenderSVGContainer.cpp:
+        (WebCore::RenderSVGContainer::layout):
+        * rendering/svg/RenderSVGForeignObject.cpp:
+        (WebCore::RenderSVGForeignObject::layout):
+        * rendering/svg/RenderSVGRoot.cpp:
+        (WebCore::RenderSVGRoot::layout):
+        * style/RenderTreeUpdaterFirstLetter.cpp:
+        (WebCore::RenderTreeUpdater::FirstLetter::update):
+        * style/RenderTreeUpdaterListItem.cpp:
+        (WebCore::RenderTreeUpdater::ListItem::updateMarker):
+
 2017-11-06  Said Abou-Hallawa  <sabouhallawa@apple.com>
 
         [CG] Adopt CGContextDrawPathDirect()
index bf50697..2b78219 100644 (file)
@@ -910,7 +910,7 @@ void AXObjectCache::notificationPostTimerFired()
         // Notifications should only be sent after the renderer has finished
         if (is<AccessibilityRenderObject>(*obj)) {
             if (auto* renderer = downcast<AccessibilityRenderObject>(*obj).renderer())
-                ASSERT(!renderer->view().layoutState());
+                ASSERT(!renderer->view().frameView().layoutContext().layoutState());
         }
 #endif
 
index a5bd996..b83e86d 100644 (file)
@@ -31,6 +31,7 @@
 #include "Document.h"
 #include "FrameView.h"
 #include "InspectorInstrumentation.h"
+#include "LayoutState.h"
 #include "Logging.h"
 #include "NoEventDispatchAssertion.h"
 #include "RenderElement.h"
@@ -532,6 +533,82 @@ void LayoutContext::startLayoutAtMainFrameViewIfNeeded()
     parentView->layoutContext().layout();
 }
 
+LayoutSize LayoutContext::layoutDelta() const
+{
+    if (!m_layoutState)
+        return { };
+    return m_layoutState->m_layoutDelta;
+}
+    
+void LayoutContext::addLayoutDelta(const LayoutSize& delta)
+{
+    if (!m_layoutState)
+        return;
+    
+    m_layoutState->m_layoutDelta += delta;
+#if !ASSERT_DISABLED
+    m_layoutState->m_layoutDeltaXSaturated |= m_layoutState->m_layoutDelta.width() == LayoutUnit::max() || m_layoutState->m_layoutDelta.width() == LayoutUnit::min();
+    m_layoutState->m_layoutDeltaYSaturated |= m_layoutState->m_layoutDelta.height() == LayoutUnit::max() || m_layoutState->m_layoutDelta.height() == LayoutUnit::min();
+#endif
+}
+    
+#if !ASSERT_DISABLED
+bool LayoutContext::layoutDeltaMatches(const LayoutSize& delta)
+{
+    if (!m_layoutState)
+        return false;
+    return (delta.width() == m_layoutState->m_layoutDelta.width() || m_layoutState->m_layoutDeltaXSaturated) && (delta.height() == m_layoutState->m_layoutDelta.height() || m_layoutState->m_layoutDeltaYSaturated);
+}
+#endif
+    
+void LayoutContext::pushLayoutState(RenderElement& root)
+{
+    ASSERT(!m_layoutStateDisableCount);
+    ASSERT(!m_layoutState);
+
+    m_layoutState = std::make_unique<LayoutState>(root);
+}
+
+bool LayoutContext::pushLayoutStateForPaginationIfNeeded(RenderBlockFlow& layoutRoot)
+{
+    if (m_layoutState)
+        return false;
+    m_layoutState = std::make_unique<LayoutState>(layoutRoot);
+    m_layoutState->m_isPaginated = true;
+    // This is just a flag for known page height (see RenderBlockFlow::checkForPaginationLogicalHeightChange).
+    m_layoutState->m_pageLogicalHeight = 1;
+    return true;
+}
+    
+void LayoutContext::popLayoutState(RenderObject&)
+{
+    return popLayoutState();
+}
+    
+bool LayoutContext::pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight, bool pageHeightChanged)
+{
+    // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
+    if (!m_layoutState || !needsFullRepaint() || m_layoutState->isPaginated() || renderer.enclosingFragmentedFlow()
+        || m_layoutState->lineGrid() || (renderer.style().lineGrid() != RenderStyle::initialLineGrid() && renderer.isRenderBlockFlow())) {
+        m_layoutState = std::make_unique<LayoutState>(WTFMove(m_layoutState), renderer, offset, pageHeight, pageHeightChanged);
+        return true;
+    }
+    return false;
+}
+    
+void LayoutContext::popLayoutState()
+{
+    m_layoutState = WTFMove(m_layoutState->m_ancestor);
+}
+    
+#ifndef NDEBUG
+void LayoutContext::checkLayoutState()
+{
+    ASSERT(layoutDeltaMatches(LayoutSize()));
+    ASSERT(!m_layoutStateDisableCount);
+}
+#endif
+
 Frame& LayoutContext::frame() const
 {
     return view().frame();
index 1458939..27f444d 100644 (file)
@@ -35,6 +35,8 @@ class Document;
 class Frame;
 class FrameView;
 class LayoutScope;
+class LayoutState;
+class RenderBlockFlow;
 class RenderElement;
 class RenderView;
     
@@ -86,8 +88,30 @@ public:
 
     void flushAsynchronousTasks();
 
+    // Subtree push/pop
+    void pushLayoutState(RenderElement&);
+    bool pushLayoutStateForPaginationIfNeeded(RenderBlockFlow&);
+    void popLayoutState(RenderObject&);
+    LayoutState* layoutState() const { return m_layoutState.get(); }
+    // Returns true if layoutState should be used for its cached offset and clip.
+    bool layoutStateEnabled() const { return !m_layoutStateDisableCount && m_layoutState; }
+#ifndef NDEBUG
+    void checkLayoutState();
+#endif
+    // layoutDelta is used transiently during layout to store how far an object has moved from its
+    // last layout location, in order to repaint correctly.
+    // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
+    LayoutSize layoutDelta() const;
+    void addLayoutDelta(const LayoutSize& delta);
+#if !ASSERT_DISABLED
+    bool layoutDeltaMatches(const LayoutSize& delta);
+#endif
+
 private:
     friend class LayoutScope;
+    friend class LayoutStateMaintainer;
+    friend class LayoutStateDisabler;
+    friend class SubtreeLayoutStateMaintainer;
 
     bool canPerformLayout() const;
     bool layoutDisallowed() const { return m_layoutDisallowedCount; }
@@ -108,6 +132,18 @@ private:
     bool handleLayoutWithFrameFlatteningIfNeeded();
     void startLayoutAtMainFrameViewIfNeeded();
 
+    // These functions may only be accessed by LayoutStateMaintainer.
+    bool pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false);
+    void popLayoutState();
+
+    // Suspends the LayoutState optimization. Used under transforms that cannot be represented by
+    // LayoutState (common in SVG) and when manipulating the render tree during layout in ways
+    // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
+    // Note that even when disabled, LayoutState is still used to store layoutDelta.
+    // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler.
+    void disableLayoutState() { m_layoutStateDisableCount++; }
+    void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
+
     Frame& frame() const;
     FrameView& view() const;
     RenderView* renderView() const;
@@ -130,6 +166,8 @@ private:
     unsigned m_disableSetNeedsLayoutCount { 0 };
     int m_layoutDisallowedCount { 0 };
     WeakPtr<RenderElement> m_subtreeLayoutRoot;
+    std::unique_ptr<LayoutState> m_layoutState;
+    unsigned m_layoutStateDisableCount { 0 };
 };
 
 } // namespace WebCore
index 2928b11..ccd37bb 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "LayoutState.h"
 
+#include "LayoutContext.h"
 #include "RenderFragmentedFlow.h"
 #include "RenderInline.h"
 #include "RenderLayer.h"
@@ -60,13 +61,22 @@ LayoutState::LayoutState(RenderElement& renderer)
 }
 
 LayoutState::LayoutState(std::unique_ptr<LayoutState> ancestor, RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged)
-    : m_ancestor(WTFMove(ancestor))
+    : m_clipped(false)
+    , m_isPaginated(false)
+    , m_pageLogicalHeightChanged(false)
+#if !ASSERT_DISABLED
+    , m_layoutDeltaXSaturated(false)
+    , m_layoutDeltaYSaturated(false)
+#endif
+    , m_ancestor(WTFMove(ancestor))
 #ifndef NDEBUG
     , m_renderer(&renderer)
 #endif
 {
-    computeOffsets(renderer, offset);
-    computeClipRect(renderer);
+    if (m_ancestor) {
+        computeOffsets(renderer, offset);
+        computeClipRect(renderer);
+    }
     computePaginationInformation(renderer, pageLogicalHeight, pageLogicalHeightChanged);
 }
 
@@ -113,7 +123,7 @@ void LayoutState::computeClipRect(RenderBox& renderer)
     if (!renderer.hasOverflowClip())
         return;
 
-    LayoutRect clipRect(toLayoutPoint(m_paintOffset) + renderer.view().layoutDelta(), renderer.cachedSizeForOverflowClip());
+    LayoutRect clipRect(toLayoutPoint(m_paintOffset) + renderer.view().frameView().layoutContext().layoutDelta(), renderer.cachedSizeForOverflowClip());
     if (m_clipped)
         m_clipRect.intersect(clipRect);
     else
@@ -209,14 +219,14 @@ void LayoutState::establishLineGrid(RenderBlockFlow& renderer)
 }
 
 LayoutStateMaintainer::LayoutStateMaintainer(RenderBox& root, LayoutSize offset, bool disableState, LayoutUnit pageHeight, bool pageHeightChanged)
-    : m_view(root.view())
+    : m_layoutContext(root.view().frameView().layoutContext())
     , m_disabled(disableState)
 {
     push(root, offset, pageHeight, pageHeightChanged);
 }
 
-LayoutStateMaintainer::LayoutStateMaintainer(RenderView& view)
-    : m_view(view)
+LayoutStateMaintainer::LayoutStateMaintainer(LayoutContext& layoutContext)
+    : m_layoutContext(layoutContext)
 {
 }
 
@@ -230,11 +240,11 @@ void LayoutStateMaintainer::push(RenderBox& root, LayoutSize offset, LayoutUnit
     ASSERT(!m_didCallPush);
     m_didCallPush = true;
     // We push state even if disabled, because we still need to store layoutDelta
-    m_didPushLayoutState = m_view.pushLayoutState(root, offset, pageHeight, pageHeightChanged);
+    m_didPushLayoutState = m_layoutContext.pushLayoutState(root, offset, pageHeight, pageHeightChanged);
     if (!m_didPushLayoutState)
         return;
     if (m_disabled)
-        m_view.disableLayoutState();
+        m_layoutContext.disableLayoutState();
 }
 
 void LayoutStateMaintainer::pop()
@@ -245,20 +255,20 @@ void LayoutStateMaintainer::pop()
         return;
     if (!m_didPushLayoutState)
         return;
-    m_view.popLayoutState();
+    m_layoutContext.popLayoutState();
     if (m_disabled)
-        m_view.enableLayoutState();
+        m_layoutContext.enableLayoutState();
 }
 
-LayoutStateDisabler::LayoutStateDisabler(RenderView& view)
-    : m_view(view)
+LayoutStateDisabler::LayoutStateDisabler(LayoutContext& layoutContext)
+    : m_layoutContext(layoutContext)
 {
-    m_view.disableLayoutState();
+    m_layoutContext.disableLayoutState();
 }
 
 LayoutStateDisabler::~LayoutStateDisabler()
 {
-    m_view.enableLayoutState();
+    m_layoutContext.enableLayoutState();
 }
 
 static bool shouldDisableLayoutStateForSubtree(RenderElement& subtreeLayoutRoot)
@@ -274,10 +284,10 @@ SubtreeLayoutStateMaintainer::SubtreeLayoutStateMaintainer(RenderElement* subtre
     : m_subtreeLayoutRoot(subtreeLayoutRoot)
 {
     if (m_subtreeLayoutRoot) {
-        RenderView& view = m_subtreeLayoutRoot->view();
-        view.pushLayoutState(*m_subtreeLayoutRoot);
+        auto& layoutContext = m_subtreeLayoutRoot->view().frameView().layoutContext();
+        layoutContext.pushLayoutState(*m_subtreeLayoutRoot);
         if (shouldDisableLayoutStateForSubtree(*m_subtreeLayoutRoot)) {
-            view.disableLayoutState();
+            layoutContext.disableLayoutState();
             m_didDisableLayoutState = true;
         }
     }
@@ -286,23 +296,23 @@ SubtreeLayoutStateMaintainer::SubtreeLayoutStateMaintainer(RenderElement* subtre
 SubtreeLayoutStateMaintainer::~SubtreeLayoutStateMaintainer()
 {
     if (m_subtreeLayoutRoot) {
-        RenderView& view = m_subtreeLayoutRoot->view();
-        view.popLayoutState(*m_subtreeLayoutRoot);
+        auto& layoutContext = m_subtreeLayoutRoot->view().frameView().layoutContext();
+        layoutContext.popLayoutState(*m_subtreeLayoutRoot);
         if (m_didDisableLayoutState)
-            view.enableLayoutState();
+            layoutContext.enableLayoutState();
     }
 }
 
 PaginatedLayoutStateMaintainer::PaginatedLayoutStateMaintainer(RenderBlockFlow& flow)
     : m_flow(flow)
-    , m_pushed(flow.view().pushLayoutStateForPaginationIfNeeded(flow))
+    , m_pushed(flow.view().frameView().layoutContext().pushLayoutStateForPaginationIfNeeded(flow))
 {
 }
 
 PaginatedLayoutStateMaintainer::~PaginatedLayoutStateMaintainer()
 {
     if (m_pushed)
-        m_flow.view().popLayoutState(m_flow);
+        m_flow.view().frameView().layoutContext().popLayoutState(m_flow);
 }
 
 } // namespace WebCore
index a7e0f64..b4549e5 100644 (file)
 
 namespace WebCore {
 
+class LayoutContext;
 class RenderBlockFlow;
 class RenderBox;
 class RenderElement;
 class RenderFragmentedFlow;
 class RenderObject;
-class RenderView;
 
 class LayoutState {
     WTF_MAKE_NONCOPYABLE(LayoutState); WTF_MAKE_FAST_ALLOCATED;
@@ -134,7 +134,7 @@ public:
     // Constructor to push now.
     explicit LayoutStateMaintainer(RenderBox&, LayoutSize offset, bool disableState = false, LayoutUnit pageHeight = 0, bool pageHeightChanged = false);
     // Constructor to maybe push later.
-    explicit LayoutStateMaintainer(RenderView&);
+    explicit LayoutStateMaintainer(LayoutContext&);
     ~LayoutStateMaintainer();
 
     void push(RenderBox& root, LayoutSize offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false);
@@ -142,7 +142,7 @@ public:
     bool didPush() const { return m_didCallPush; }
 
 private:
-    RenderView& m_view;
+    LayoutContext& m_layoutContext;
     bool m_disabled { false };
     bool m_didCallPush { false };
     bool m_didCallPop { false };
@@ -162,11 +162,11 @@ private:
 class LayoutStateDisabler {
     WTF_MAKE_NONCOPYABLE(LayoutStateDisabler);
 public:
-    LayoutStateDisabler(RenderView&);
+    LayoutStateDisabler(LayoutContext&);
     ~LayoutStateDisabler();
 
 private:
-    RenderView& m_view;
+    LayoutContext& m_layoutContext;
 };
 
 class PaginatedLayoutStateMaintainer {
index 2e410af..341c21e 100644 (file)
@@ -1210,11 +1210,11 @@ void RenderBlock::setLogicalLeftForChild(RenderBox& child, LayoutUnit logicalLef
 {
     if (isHorizontalWritingMode()) {
         if (applyDelta == ApplyLayoutDelta)
-            view().addLayoutDelta(LayoutSize(child.x() - logicalLeft, 0));
+            view().frameView().layoutContext().addLayoutDelta(LayoutSize(child.x() - logicalLeft, 0));
         child.setX(logicalLeft);
     } else {
         if (applyDelta == ApplyLayoutDelta)
-            view().addLayoutDelta(LayoutSize(0, child.y() - logicalLeft));
+            view().frameView().layoutContext().addLayoutDelta(LayoutSize(0, child.y() - logicalLeft));
         child.setY(logicalLeft);
     }
 }
@@ -1223,11 +1223,11 @@ void RenderBlock::setLogicalTopForChild(RenderBox& child, LayoutUnit logicalTop,
 {
     if (isHorizontalWritingMode()) {
         if (applyDelta == ApplyLayoutDelta)
-            view().addLayoutDelta(LayoutSize(0, child.y() - logicalTop));
+            view().frameView().layoutContext().addLayoutDelta(LayoutSize(0, child.y() - logicalTop));
         child.setY(logicalTop);
     } else {
         if (applyDelta == ApplyLayoutDelta)
-            view().addLayoutDelta(LayoutSize(child.x() - logicalTop, 0));
+            view().frameView().layoutContext().addLayoutDelta(LayoutSize(child.x() - logicalTop, 0));
         child.setX(logicalTop);
     }
 }
@@ -1440,7 +1440,7 @@ void RenderBlock::layoutPositionedObject(RenderBox& r, bool relayoutChildren, bo
     // If we are paginated or in a line grid, compute a vertical position for our object now.
     // If it's wrong we'll lay out again.
     LayoutUnit oldLogicalTop = 0;
-    bool needsBlockDirectionLocationSetBeforeLayout = r.needsLayout() && view().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
+    bool needsBlockDirectionLocationSetBeforeLayout = r.needsLayout() && view().frameView().layoutContext().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
     if (needsBlockDirectionLocationSetBeforeLayout) {
         if (isHorizontalWritingMode() == r.isHorizontalWritingMode())
             r.updateLogicalHeight();
@@ -1499,10 +1499,11 @@ void RenderBlock::markPositionedObjectsForLayout()
 
 void RenderBlock::markForPaginationRelayoutIfNeeded()
 {
-    if (needsLayout() || !view().layoutState()->isPaginated())
+    auto* layoutState = view().frameView().layoutContext().layoutState();
+    if (needsLayout() || !layoutState->isPaginated())
         return;
 
-    if (view().layoutState()->pageLogicalHeightChanged() || (view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
+    if (layoutState->pageLogicalHeightChanged() || (layoutState->pageLogicalHeight() && layoutState->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
         setChildNeedsLayout(MarkOnlyThis);
 }
 
@@ -2314,7 +2315,7 @@ LayoutUnit RenderBlock::adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloa
         return left;
     
     // Push in our left offset so that it is aligned with the character grid.
-    LayoutState* layoutState = view().layoutState();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
     if (!layoutState)
         return left;
 
@@ -2354,7 +2355,7 @@ LayoutUnit RenderBlock::adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFlo
         return right;
     
     // Push in our right offset so that it is aligned with the character grid.
-    LayoutState* layoutState = view().layoutState();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
     if (!layoutState)
         return right;
 
@@ -3328,7 +3329,7 @@ RenderPtr<RenderBlock> RenderBlock::createAnonymousBlockWithStyleAndDisplay(Docu
 
 LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
 {
-    LayoutState* layoutState = view().layoutState();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
     if (layoutState && !layoutState->isPaginated())
         return 0;
 
@@ -3374,7 +3375,7 @@ bool RenderBlock::childBoxIsUnsplittableForFragmentation(const RenderBox& child)
 {
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
     bool checkColumnBreaks = fragmentedFlow && fragmentedFlow->shouldCheckColumnBreaks();
-    bool checkPageBreaks = !checkColumnBreaks && view().layoutState()->m_pageLogicalHeight;
+    bool checkPageBreaks = !checkColumnBreaks && view().frameView().layoutContext().layoutState()->m_pageLogicalHeight;
     return child.isUnsplittableForPagination() || child.style().breakInside() == AvoidBreakInside
         || (checkColumnBreaks && child.style().breakInside() == AvoidColumnBreakInside)
         || (checkPageBreaks && child.style().breakInside() == AvoidPageBreakInside);
index 1b13595..61fb0c7 100644 (file)
@@ -552,8 +552,8 @@ void RenderBlockFlow::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalH
 
     fitBorderToLinesIfNeeded();
 
-    if (view().layoutState()->m_pageLogicalHeight)
-        setPageLogicalOffset(view().layoutState()->pageLogicalOffset(this, logicalTop()));
+    if (view().frameView().layoutContext().layoutState()->m_pageLogicalHeight)
+        setPageLogicalOffset(view().frameView().layoutContext().layoutState()->pageLogicalOffset(this, logicalTop()));
 
     updateLayerTransform();
 
@@ -612,7 +612,7 @@ void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& max
     setLogicalHeight(beforeEdge);
     
     // Lay out our hypothetical grid line as though it occurs at the top of the block.
-    if (view().layoutState()->lineGrid() == this)
+    if (view().frameView().layoutContext().layoutState()->lineGrid() == this)
         layoutLineGridBox();
 
     // The margin struct caches all our current margin collapsing state.
@@ -690,7 +690,7 @@ void RenderBlockFlow::layoutBlockChild(RenderBox& child, MarginInfo& marginInfo,
     LayoutUnit oldLogicalTop = logicalTopForChild(child);
 
 #if !ASSERT_DISABLED
-    LayoutSize oldLayoutDelta = view().layoutDelta();
+    LayoutSize oldLayoutDelta = view().frameView().layoutContext().layoutDelta();
 #endif
     // Position the child as though it didn't collapse with the top.
     setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
@@ -738,7 +738,7 @@ void RenderBlockFlow::layoutBlockChild(RenderBox& child, MarginInfo& marginInfo,
     // Now check for clear.
     LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
     
-    bool paginated = view().layoutState()->isPaginated();
+    bool paginated = view().frameView().layoutContext().layoutState()->isPaginated();
     if (paginated)
         logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClear, estimateWithoutPagination, child, atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear);
 
@@ -788,7 +788,7 @@ void RenderBlockFlow::layoutBlockChild(RenderBox& child, MarginInfo& marginInfo,
 
     LayoutSize childOffset = child.location() - oldRect.location();
     if (childOffset.width() || childOffset.height()) {
-        view().addLayoutDelta(childOffset);
+        view().frameView().layoutContext().addLayoutDelta(childOffset);
 
         // If the child moved, we have to repaint it as well as any floating/positioned
         // descendants. An exception is if we need a layout. In this case, we know we're going to
@@ -811,7 +811,7 @@ void RenderBlockFlow::layoutBlockChild(RenderBox& child, MarginInfo& marginInfo,
             setLogicalHeight(newHeight);
     }
 
-    ASSERT(view().layoutDeltaMatches(oldLayoutDelta));
+    ASSERT(view().frameView().layoutContext().layoutDeltaMatches(oldLayoutDelta));
 }
 
 void RenderBlockFlow::adjustPositionedBlock(RenderBox& child, const MarginInfo& marginInfo)
@@ -1109,7 +1109,7 @@ LayoutUnit RenderBlockFlow::collapseMarginsWithChildInfo(RenderBox* child, Rende
     
     // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
     // collapsed into the page edge.
-    LayoutState* layoutState = view().layoutState();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
     if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop
         && hasNextPage(beforeCollapseLogicalTop)) {
         LayoutUnit oldLogicalTop = logicalTop;
@@ -1284,7 +1284,7 @@ LayoutUnit RenderBlockFlow::estimateLogicalTopPosition(RenderBox& child, const M
 
     // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
     // page.
-    LayoutState* layoutState = view().layoutState();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
     if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight()
         && hasNextPage(logicalHeight()))
         logicalTopEstimate = std::min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
@@ -1495,7 +1495,7 @@ LayoutUnit RenderBlockFlow::applyBeforeBreak(RenderBox& child, LayoutUnit logica
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
     bool isInsideMulticolFlow = fragmentedFlow;
     bool checkColumnBreaks = fragmentedFlow && fragmentedFlow->shouldCheckColumnBreaks();
-    bool checkPageBreaks = !checkColumnBreaks && view().layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
+    bool checkPageBreaks = !checkColumnBreaks && view().frameView().layoutContext().layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
     bool checkFragmentBreaks = false;
     bool checkBeforeAlways = (checkColumnBreaks && child.style().breakBefore() == ColumnBreakBetween)
         || (checkPageBreaks && alwaysPageBreak(child.style().breakBefore()));
@@ -1520,7 +1520,7 @@ LayoutUnit RenderBlockFlow::applyAfterBreak(RenderBox& child, LayoutUnit logical
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
     bool isInsideMulticolFlow = fragmentedFlow;
     bool checkColumnBreaks = fragmentedFlow && fragmentedFlow->shouldCheckColumnBreaks();
-    bool checkPageBreaks = !checkColumnBreaks && view().layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
+    bool checkPageBreaks = !checkColumnBreaks && view().frameView().layoutContext().layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
     bool checkFragmentBreaks = false;
     bool checkAfterAlways = (checkColumnBreaks && child.style().breakAfter() == ColumnBreakBetween)
         || (checkPageBreaks && alwaysPageBreak(child.style().breakAfter()));
@@ -1807,7 +1807,7 @@ bool RenderBlockFlow::relayoutToAvoidWidows(LayoutStateMaintainer& statePusher)
 
 bool RenderBlockFlow::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
 {
-    ASSERT(view().layoutState() && view().layoutState()->isPaginated());
+    ASSERT(view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->isPaginated());
 
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
     if (!fragmentedFlow)
@@ -1906,12 +1906,13 @@ LayoutUnit RenderBlockFlow::pageLogicalTopForOffset(LayoutUnit offset) const
 {
     // Unsplittable objects clear out the pageLogicalHeight in the layout state as a way of signaling that no
     // pagination should occur. Therefore we have to check this first and bail if the value has been set to 0.
-    LayoutUnit pageLogicalHeight = view().layoutState()->m_pageLogicalHeight;
+    auto* layoutState = view().frameView().layoutContext().layoutState();
+    LayoutUnit pageLogicalHeight = layoutState->m_pageLogicalHeight;
     if (!pageLogicalHeight)
         return 0;
 
-    LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? view().layoutState()->m_pageOffset.height() : view().layoutState()->m_pageOffset.width();
-    LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? view().layoutState()->m_layoutOffset.height() : view().layoutState()->m_layoutOffset.width();
+    LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? layoutState->m_pageOffset.height() : layoutState->m_pageOffset.width();
+    LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? layoutState->m_layoutOffset.height() : layoutState->m_layoutOffset.width();
 
     LayoutUnit cumulativeOffset = offset + blockLogicalTop;
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
@@ -1924,7 +1925,7 @@ LayoutUnit RenderBlockFlow::pageLogicalHeightForOffset(LayoutUnit offset) const
 {
     // Unsplittable objects clear out the pageLogicalHeight in the layout state as a way of signaling that no
     // pagination should occur. Therefore we have to check this first and bail if the value has been set to 0.
-    LayoutUnit pageLogicalHeight = view().layoutState()->m_pageLogicalHeight;
+    LayoutUnit pageLogicalHeight = view().frameView().layoutContext().layoutState()->m_pageLogicalHeight;
     if (!pageLogicalHeight)
         return 0;
     
@@ -1941,7 +1942,7 @@ LayoutUnit RenderBlockFlow::pageRemainingLogicalHeightForOffset(LayoutUnit offse
     
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
     if (!fragmentedFlow) {
-        LayoutUnit pageLogicalHeight = view().layoutState()->m_pageLogicalHeight;
+        LayoutUnit pageLogicalHeight = view().frameView().layoutContext().layoutState()->m_pageLogicalHeight;
         LayoutUnit remainingHeight = pageLogicalHeight - intMod(offset, pageLogicalHeight);
         if (pageBoundaryRule == IncludePageBoundary) {
             // If includeBoundaryPoint is true the line exactly on the top edge of a
@@ -2140,7 +2141,7 @@ void RenderBlockFlow::repaintOverhangingFloats(bool paintAllDescendants)
 
     // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
     // in this block. Better yet would be to push extra state for the containers of other floats.
-    LayoutStateDisabler layoutStateDisabler(view());
+    LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
     const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
     auto end = floatingObjectSet.end();
     for (auto it = floatingObjectSet.begin(); it != end; ++it) {
@@ -2254,10 +2255,10 @@ FloatingObject* RenderBlockFlow::insertFloatingObject(RenderBox& floatBox)
     
     // Our location is irrelevant if we're unsplittable or no pagination is in effect. Just lay out the float.
     bool isChildRenderBlock = floatBox.isRenderBlock();
-    if (isChildRenderBlock && !floatBox.needsLayout() && view().layoutState()->pageLogicalHeightChanged())
+    if (isChildRenderBlock && !floatBox.needsLayout() && view().frameView().layoutContext().layoutState()->pageLogicalHeightChanged())
         floatBox.setChildNeedsLayout(MarkOnlyThis);
-            
-    bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
+
+    bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view().frameView().layoutContext().layoutState()->needsBlockDirectionLocationSetBeforeLayout();
     if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) {
         // We are unsplittable if we're a block flow root.
         floatBox.layoutIfNeeded();
@@ -2500,7 +2501,7 @@ bool RenderBlockFlow::positionNewFloats()
         childBox.markForPaginationRelayoutIfNeeded();
         childBox.layoutIfNeeded();
 
-        LayoutState* layoutState = view().layoutState();
+        auto* layoutState = view().frameView().layoutContext().layoutState();
         bool isPaginated = layoutState->isPaginated();
         if (isPaginated) {
             // If we are unsplittable and don't fit, then we need to move down.
@@ -3583,7 +3584,7 @@ void RenderBlockFlow::layoutSimpleLines(bool relayoutChildren, LayoutUnit& repai
         deleteLineBoxesBeforeSimpleLineLayout();
         m_simpleLineLayout = SimpleLineLayout::create(*this);
     }
-    if (view().layoutState() && view().layoutState()->isPaginated()) {
+    if (view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->isPaginated()) {
         m_simpleLineLayout->setIsPaginated();
         SimpleLineLayout::adjustLinePositionsForPagination(*m_simpleLineLayout, *this);
     }
index fa39754..b736d4c 100644 (file)
@@ -1274,7 +1274,7 @@ void RenderBlockFlow::layoutRunsAndFloats(LineLayoutState& layoutState, bool has
     // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
     if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
         setNeedsLayout(MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
-        if (!view().doingFullRepaint() && hasSelfPaintingLayer() && hasRepaintLayoutRects()) {
+        if (!view().frameView().layoutContext().needsFullRepaint() && hasSelfPaintingLayer() && hasRepaintLayoutRects()) {
             // Because we waited until we were already inside layout to discover
             // that the block really needed a full layout, we missed our chance to repaint the layer
             // before layout started.  Luckily the layer has cached the repaint rect for its original
@@ -1332,7 +1332,7 @@ inline const InlineIterator& RenderBlockFlow::restartLayoutRunsAndFloatsInRange(
 void RenderBlockFlow::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
 {
     const RenderStyle& styleToUse = style();
-    bool paginated = view().layoutState() && view().layoutState()->isPaginated();
+    bool paginated = view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->isPaginated();
     LineWhitespaceCollapsingState& lineWhitespaceCollapsingState = resolver.whitespaceCollapsingState();
     InlineIterator end = resolver.position();
     bool checkForEndLineMatch = layoutState.endLine();
@@ -1571,7 +1571,7 @@ void RenderBlockFlow::linkToEndLineIfNeeded(LineLayoutState& layoutState)
     auto* firstCleanLine = layoutState.endLine();
     if (firstCleanLine) {
         if (layoutState.endLineMatched()) {
-            bool paginated = view().layoutState() && view().layoutState()->isPaginated();
+            bool paginated = view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->isPaginated();
             // Attach all the remaining lines, and then adjust their y-positions as needed.
             LayoutUnit delta = logicalHeight() - layoutState.endLineLogicalTop();
             for (auto* line = firstCleanLine; line; line = line->nextRootBox()) {
@@ -1642,7 +1642,7 @@ void RenderBlockFlow::layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaint
     setLogicalHeight(borderAndPaddingBefore());
     
     // Lay out our hypothetical grid line as though it occurs at the top of the block.
-    if (view().layoutState() && view().layoutState()->lineGrid() == this)
+    if (view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->lineGrid() == this)
         layoutLineGridBox();
 
     RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
@@ -1792,7 +1792,7 @@ RootInlineBox* RenderBlockFlow::determineStartPosition(LineLayoutState& layoutSt
     bool dirtiedByFloat = false;
     if (!layoutState.isFullLayout()) {
         // Paginate all of the clean lines.
-        bool paginated = view().layoutState() && view().layoutState()->isPaginated();
+        bool paginated = view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->isPaginated();
         LayoutUnit paginationDelta = 0;
         auto floatsIterator = floats.begin();
         auto end = floats.end();
@@ -1964,7 +1964,7 @@ bool RenderBlockFlow::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutS
 {
     LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop();
 
-    bool paginated = view().layoutState() && view().layoutState()->isPaginated();
+    bool paginated = view().frameView().layoutContext().layoutState() && view().frameView().layoutContext().layoutState()->isPaginated();
     if (paginated && layoutState.fragmentedFlow()) {
         // Check all lines from here to the end, and see if the hypothetical new position for the lines will result
         // in a different available line width.
index 07e3142..d9fcac4 100644 (file)
@@ -47,6 +47,7 @@
 #include "HTMLTextAreaElement.h"
 #include "HitTestResult.h"
 #include "InlineElementBox.h"
+#include "LayoutState.h"
 #include "MainFrame.h"
 #include "Page.h"
 #include "PaintInfo.h"
@@ -696,7 +697,7 @@ LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repa
     
     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
-    box.move(view().layoutDelta());
+    box.move(view().frameView().layoutContext().layoutDelta());
 
     return LayoutRect(snapRectToDevicePixels(box, document().deviceScaleFactor()));
 }
@@ -1921,8 +1922,8 @@ void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContain
     if (repaintContainer == this)
         return;
 
-    if (view().layoutStateEnabled() && !repaintContainer) {
-        LayoutState* layoutState = view().layoutState();
+    if (view().frameView().layoutContext().layoutStateEnabled() && !repaintContainer) {
+        auto* layoutState = view().frameView().layoutContext().layoutState();
         LayoutSize offset = layoutState->m_paintOffset + locationOffset();
         if (style().hasInFlowPosition() && layer())
             offset += layer()->offsetForInFlowPosition();
@@ -2107,7 +2108,7 @@ LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject
     LayoutRect r = visualOverflowRect();
     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
-    r.move(view().layoutDelta());
+    r.move(view().frameView().layoutContext().layoutDelta());
     return computeRectForRepaint(r, repaintContainer);
 }
 
@@ -2137,8 +2138,8 @@ LayoutRect RenderBox::computeRectForRepaint(const LayoutRect& rect, const Render
     LayoutRect adjustedRect = rect;
     const RenderStyle& styleToUse = style();
     // LayoutState is only valid for root-relative, non-fixed position repainting
-    if (view().layoutStateEnabled() && !repaintContainer && styleToUse.position() != FixedPosition) {
-        LayoutState* layoutState = view().layoutState();
+    if (view().frameView().layoutContext().layoutStateEnabled() && !repaintContainer && styleToUse.position() != FixedPosition) {
+        auto* layoutState = view().frameView().layoutContext().layoutState();
 
         if (layer() && layer()->transform())
             adjustedRect = LayoutRect(encloseRectToDevicePixels(layer()->transform()->mapRect(adjustedRect), document().deviceScaleFactor()));
@@ -4954,7 +4955,7 @@ RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChil
 
 LayoutUnit RenderBox::offsetFromLogicalTopOfFirstPage() const
 {
-    LayoutState* layoutState = view().layoutState();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
     if ((layoutState && !layoutState->isPaginated()) || (!layoutState && !enclosingFragmentedFlow()))
         return 0;
 
index e326797..62bea30 100644 (file)
@@ -297,7 +297,7 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
     m_stretchingChildren = false;
 
 #if !ASSERT_DISABLED
-    LayoutSize oldLayoutDelta = view().layoutDelta();
+    LayoutSize oldLayoutDelta = view().frameView().layoutContext().layoutDelta();
 #endif
 
     // Fieldsets need to find their legend and position it inside the border of the object.
@@ -314,7 +314,7 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
         layoutVerticalBox(relayoutChildren);
 
     repaintChildrenDuringLayoutIfMoved(this, oldChildRects);
-    ASSERT(view().layoutDeltaMatches(oldLayoutDelta));
+    ASSERT(view().frameView().layoutContext().layoutDeltaMatches(oldLayoutDelta));
 
     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
     updateLogicalHeight();
@@ -330,8 +330,8 @@ void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
 
     updateLayerTransform();
 
-    if (view().layoutState()->pageLogicalHeight())
-        setPageLogicalOffset(view().layoutState()->pageLogicalOffset(this, logicalTop()));
+    if (view().frameView().layoutContext().layoutState()->pageLogicalHeight())
+        setPageLogicalOffset(view().frameView().layoutContext().layoutState()->pageLogicalOffset(this, logicalTop()));
 
     // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
     // we overflow or not.
@@ -371,9 +371,9 @@ static void layoutChildIfNeededApplyingDelta(RenderBox* child, const LayoutSize&
     if (!child->needsLayout())
         return;
     
-    child->view().addLayoutDelta(layoutDelta);
+    child->view().frameView().layoutContext().addLayoutDelta(layoutDelta);
     child->layoutIfNeeded();
-    child->view().addLayoutDelta(-layoutDelta);
+    child->view().frameView().layoutContext().addLayoutDelta(-layoutDelta);
 }
 
 void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
index 2c6acbf..5069b8f 100644 (file)
@@ -528,7 +528,7 @@ void RenderElement::destroyLeftoverChildren()
 
 void RenderElement::insertChildInternal(RenderPtr<RenderObject> newChildPtr, RenderObject* beforeChild, NotifyChildrenType notifyChildren)
 {
-    RELEASE_ASSERT_WITH_MESSAGE(!view().layoutState(), "Layout must not mutate render tree");
+    RELEASE_ASSERT_WITH_MESSAGE(!view().frameView().layoutContext().layoutState(), "Layout must not mutate render tree");
 
     ASSERT(canHaveChildren() || canHaveGeneratedChildren());
     ASSERT(!newChildPtr->parent());
@@ -585,7 +585,7 @@ void RenderElement::insertChildInternal(RenderPtr<RenderObject> newChildPtr, Ren
 
 RenderPtr<RenderObject> RenderElement::takeChildInternal(RenderObject& oldChild, NotifyChildrenType notifyChildren)
 {
-    RELEASE_ASSERT_WITH_MESSAGE(!view().layoutState(), "Layout must not mutate render tree");
+    RELEASE_ASSERT_WITH_MESSAGE(!view().frameView().layoutContext().layoutState(), "Layout must not mutate render tree");
 
     ASSERT(canHaveChildren() || canHaveGeneratedChildren());
     ASSERT(oldChild.parent() == this);
index 789722c..ee13565 100644 (file)
@@ -42,6 +42,7 @@
 #include "HTMLParamElement.h"
 #include "HTMLPlugInElement.h"
 #include "HitTestResult.h"
+#include "LayoutState.h"
 #include "LocalizedStrings.h"
 #include "MouseEvent.h"
 #include "Page.h"
index a0d4363..bd76dc5 100644 (file)
@@ -33,6 +33,7 @@
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
 #include "InlineElementBox.h"
+#include "LayoutState.h"
 #include "Node.h"
 #include "PODIntervalTree.h"
 #include "RenderBoxFragmentInfo.h"
@@ -224,7 +225,7 @@ void RenderFragmentedFlow::repaintRectangleInFragments(const LayoutRect& repaint
     if (!shouldRepaint(repaintRect) || !hasValidFragmentInfo())
         return;
 
-    LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the fragments are somewhere else.
+    LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext()); // We can't use layout state to repaint, since the fragments are somewhere else.
 
     for (auto& fragment : m_fragmentList)
         fragment->repaintFragmentedFlowContent(repaintRect);
index a031727..517a722 100644 (file)
@@ -31,6 +31,7 @@
 #include "GridPositionsResolver.h"
 #include "GridTrackSizingAlgorithm.h"
 #include "LayoutRepainter.h"
+#include "LayoutState.h"
 #include "RenderChildIterator.h"
 #include "RenderLayer.h"
 #include "RenderView.h"
index 8e8b96a..70302ac 100644 (file)
@@ -30,6 +30,7 @@
 #include "HitTestResult.h"
 #include "InlineElementBox.h"
 #include "InlineTextBox.h"
+#include "LayoutState.h"
 #include "RenderBlock.h"
 #include "RenderChildIterator.h"
 #include "RenderFragmentedFlow.h"
@@ -1161,7 +1162,7 @@ LayoutRect RenderInline::linesVisualOverflowBoundingBoxInFragment(const RenderFr
 LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
 {
     // Only first-letter renderers are allowed in here during layout. They mutate the tree triggering repaints.
-    ASSERT(!view().layoutStateEnabled() || style().styleType() == FIRST_LETTER || hasSelfPaintingLayer());
+    ASSERT(!view().frameView().layoutContext().layoutStateEnabled() || style().styleType() == FIRST_LETTER || hasSelfPaintingLayer());
 
     if (!firstLineBoxIncludingCulling() && !continuation())
         return LayoutRect();
@@ -1218,8 +1219,8 @@ LayoutRect RenderInline::computeRectForRepaint(const LayoutRect& rect, const Ren
 {
     // LayoutState is only valid for root-relative repainting
     LayoutRect adjustedRect = rect;
-    if (view().layoutStateEnabled() && !repaintContainer) {
-        LayoutState* layoutState = view().layoutState();
+    if (view().frameView().layoutContext().layoutStateEnabled() && !repaintContainer) {
+        auto* layoutState = view().frameView().layoutContext().layoutState();
         if (style().hasInFlowPosition() && layer())
             adjustedRect.move(layer()->offsetForInFlowPosition());
         adjustedRect.move(layoutState->m_paintOffset);
@@ -1286,8 +1287,8 @@ void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintCont
     if (repaintContainer == this)
         return;
 
-    if (view().layoutStateEnabled() && !repaintContainer) {
-        LayoutState* layoutState = view().layoutState();
+    if (view().frameView().layoutContext().layoutStateEnabled() && !repaintContainer) {
+        auto* layoutState = view().frameView().layoutContext().layoutState();
         LayoutSize offset = layoutState->m_paintOffset;
         if (style().hasInFlowPosition() && layer())
             offset += layer()->offsetForInFlowPosition();
index fa9aafe..501fca8 100644 (file)
@@ -517,7 +517,7 @@ void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLay
         // FIXME: LayoutState does not work with RenderLayers as there is not a 1-to-1
         // mapping between them and the RenderObjects. It would be neat to enable
         // LayoutState outside the layout() phase and use it here.
-        ASSERT(!renderer().view().layoutStateEnabled());
+        ASSERT(!renderer().view().frameView().layoutContext().layoutStateEnabled());
 
         RenderLayerModelObject* repaintContainer = renderer().containerForRepaint();
         
index aed0566..afccd59 100644 (file)
@@ -46,6 +46,7 @@
 #include "HTMLOptGroupElement.h"
 #include "HTMLSelectElement.h"
 #include "HitTestResult.h"
+#include "LayoutState.h"
 #include "NodeRenderStyle.h"
 #include "Page.h"
 #include "PaintInfo.h"
@@ -183,7 +184,7 @@ void RenderListBox::layout()
     }
 
     if (m_scrollToRevealSelectionAfterLayout) {
-        LayoutStateDisabler layoutStateDisabler(view());
+        LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
         scrollToRevealSelection();
     }
 }
index 3b563c1..26842e7 100644 (file)
@@ -30,6 +30,7 @@
 #if ENABLE(VIDEO)
 #include "RenderMediaControlElements.h"
 
+#include "LayoutState.h"
 #include "MediaControlElements.h"
 #include "RenderTheme.h"
 #include "RenderView.h"
@@ -51,7 +52,7 @@ void RenderMediaVolumeSliderContainer::layout()
     RenderBox& buttonBox = downcast<RenderBox>(*nextSibling());
     int absoluteOffsetTop = buttonBox.localToAbsolute(FloatPoint(0, -size().height())).y();
 
-    LayoutStateDisabler layoutStateDisabler(view());
+    LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
 
     // If the slider would be rendered outside the page, it should be moved below the controls.
     if (UNLIKELY(absoluteOffsetTop < 0))
@@ -73,7 +74,7 @@ void RenderMediaControlTimelineContainer::layout()
 {
     RenderFlexibleBox::layout();
 
-    LayoutStateDisabler layoutStateDisabler(view());
+    LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
     MediaControlTimelineContainerElement* container = static_cast<MediaControlTimelineContainerElement*>(element());
     container->setTimeDisplaysHidden(width().toInt() < minWidthToDisplayTimeDisplays);
 }
@@ -95,7 +96,7 @@ void RenderTextTrackContainerElement::layout()
 
     ASSERT(mediaControlElementType(element()) == MediaTextTrackDisplayContainer);
 
-    LayoutStateDisabler layoutStateDisabler(view());
+    LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
     static_cast<MediaControlTextTrackContainerElement*>(element())->updateSizes();
 }
 
index 022e0df..8fd4480 100644 (file)
@@ -909,7 +909,7 @@ void RenderObject::repaintRectangle(const LayoutRect& r, bool shouldClipToLayer)
     LayoutRect dirtyRect(r);
     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
-    dirtyRect.move(view.layoutDelta());
+    dirtyRect.move(view.frameView().layoutContext().layoutDelta());
 
     RenderLayerModelObject* repaintContainer = containerForRepaint();
     repaintUsingContainer(repaintContainer, computeRectForRepaint(dirtyRect, repaintContainer), shouldClipToLayer);
index 653fc75..a3b2d91 100644 (file)
@@ -672,7 +672,7 @@ LayoutRect RenderReplaced::clippedOverflowRectForRepaint(const RenderLayerModelO
     LayoutRect r = unionRect(localSelectionRect(false), visualOverflowRect());
     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
-    r.move(view().layoutDelta());
+    r.move(view().frameView().layoutContext().layoutDelta());
     return computeRectForRepaint(r, repaintContainer);
 }
 
index 6e7b195..59a44cf 100644 (file)
@@ -35,6 +35,7 @@
 #include "HTMLNames.h"
 #include "HTMLTableElement.h"
 #include "LayoutRepainter.h"
+#include "LayoutState.h"
 #include "RenderBlockFlow.h"
 #include "RenderChildIterator.h"
 #include "RenderDescendantIterator.h"
@@ -580,8 +581,9 @@ void RenderTable::layout()
 
     statePusher.pop();
 
-    if (view().layoutState()->pageLogicalHeight())
-        setPageLogicalOffset(view().layoutState()->pageLogicalOffset(this, logicalTop()));
+    auto* layoutState = view().frameView().layoutContext().layoutState();
+    if (layoutState->pageLogicalHeight())
+        setPageLogicalOffset(layoutState->pageLogicalOffset(this, logicalTop()));
 
     bool didFullRepaint = repainter.repaintAfterLayout();
     // Repaint with our new bounds if they are different from our old bounds.
@@ -592,7 +594,7 @@ void RenderTable::layout()
             repaintRectangle(LayoutRect(movedSectionLogicalTop, visualOverflowRect().y(), visualOverflowRect().maxX() - movedSectionLogicalTop, visualOverflowRect().height()));
     }
 
-    bool paginated = view().layoutState() && view().layoutState()->isPaginated();
+    bool paginated = layoutState && layoutState->isPaginated();
     if (sectionMoved && paginated) {
         // FIXME: Table layout should always stabilize even when section moves (see webkit.org/b/174412).
         if (!m_inRecursiveSectionMovedWithPagination) {
@@ -1600,7 +1602,8 @@ const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCel
 
 void RenderTable::markForPaginationRelayoutIfNeeded()
 {
-    if (!view().layoutState()->isPaginated() || (!view().layoutState()->pageLogicalHeightChanged() && (!view().layoutState()->pageLogicalHeight() || view().layoutState()->pageLogicalOffset(this, logicalTop()) == pageLogicalOffset())))
+    auto* layoutState = view().frameView().layoutContext().layoutState();
+    if (!layoutState->isPaginated() || (!layoutState->pageLogicalHeightChanged() && (!layoutState->pageLogicalHeight() || layoutState->pageLogicalOffset(this, logicalTop()) == pageLogicalOffset())))
         return;
     
     // When a table moves, we have to dirty all of the sections too.
index 3328ee1..f416034 100644 (file)
@@ -386,7 +386,7 @@ LayoutRect RenderTableCell::clippedOverflowRectForRepaint(const RenderLayerModel
 
     // FIXME: layoutDelta needs to be applied in parts before/after transforms and
     // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
-    r.move(view().layoutDelta());
+    r.move(view().frameView().layoutContext().layoutDelta());
     return computeRectForRepaint(r, repaintContainer);
 }
 
@@ -395,7 +395,7 @@ LayoutRect RenderTableCell::computeRectForRepaint(const LayoutRect& rect, const
     if (repaintContainer == this)
         return rect;
     LayoutRect adjustedRect = rect;
-    if ((!view().layoutStateEnabled() || repaintContainer) && parent())
+    if ((!view().frameView().layoutContext().layoutStateEnabled() || repaintContainer) && parent())
         adjustedRect.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in.
     return RenderBlockFlow::computeRectForRepaint(adjustedRect, repaintContainer, context);
 }
index 900abd0..112bc66 100644 (file)
@@ -28,6 +28,7 @@
 #include "Document.h"
 #include "HTMLNames.h"
 #include "HitTestResult.h"
+#include "LayoutState.h"
 #include "PaintInfo.h"
 #include "RenderTableCell.h"
 #include "RenderView.h"
@@ -178,10 +179,11 @@ void RenderTableRow::layout()
     // Table rows do not add translation.
     LayoutStateMaintainer statePusher(*this, LayoutSize(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
 
-    bool paginated = view().layoutState()->isPaginated();
+    auto* layoutState = view().frameView().layoutContext().layoutState();
+    bool paginated = layoutState->isPaginated();
                 
     for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
-        if (!cell->needsLayout() && paginated && (view().layoutState()->pageLogicalHeightChanged() || (view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())))
+        if (!cell->needsLayout() && paginated && (layoutState->pageLogicalHeightChanged() || (layoutState->pageLogicalHeight() && layoutState->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())))
             cell->setChildNeedsLayout(MarkOnlyThis);
 
         if (cell->needsLayout()) {
index f7e936d..c8b2098 100644 (file)
@@ -28,6 +28,7 @@
 #include "Document.h"
 #include "HitTestResult.h"
 #include "HTMLNames.h"
+#include "LayoutState.h"
 #include "PaintInfo.h"
 #include "RenderChildIterator.h"
 #include "RenderTableCell.h"
@@ -274,7 +275,7 @@ LayoutUnit RenderTableSection::calcRowLogicalHeight()
     if (this == table()->topSection())
         spacing = table()->vBorderSpacing();
 
-    LayoutStateMaintainer statePusher(view());
+    LayoutStateMaintainer statePusher(view().frameView().layoutContext());
 
     m_rowPos.resize(m_grid.size() + 1);
     m_rowPos[0] = spacing;
@@ -386,7 +387,7 @@ void RenderTableSection::layout()
     m_grid.shrinkToFit();
 
     LayoutStateMaintainer statePusher(*this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
-    bool paginated = view().layoutState()->isPaginated();
+    bool paginated = view().frameView().layoutContext().layoutState()->isPaginated();
     
     const Vector<LayoutUnit>& columnPos = table()->columnPositions();
     
@@ -413,7 +414,7 @@ void RenderTableSection::layout()
         }
 
         if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
-            if (!rowRenderer->needsLayout() && paginated && view().layoutState()->pageLogicalHeightChanged())
+            if (!rowRenderer->needsLayout() && paginated && view().frameView().layoutContext().layoutState()->pageLogicalHeightChanged())
                 rowRenderer->setChildNeedsLayout(MarkOnlyThis);
 
             rowRenderer->layoutIfNeeded();
@@ -636,13 +637,14 @@ void RenderTableSection::layoutRows()
 
             setLogicalPositionForCell(cell, c);
 
-            if (!cell->needsLayout() && view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
+            auto* layoutState = view().frameView().layoutContext().layoutState();
+            if (!cell->needsLayout() && layoutState->pageLogicalHeight() && layoutState->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
                 cell->setChildNeedsLayout(MarkOnlyThis);
 
             cell->layoutIfNeeded();
 
             // FIXME: Make pagination work with vertical tables.
-            if (view().layoutState()->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
+            if (layoutState->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
                 // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
                 // We'll also do a basic increase of the row height to accommodate the cell if it's bigger, but this isn't quite right
                 // either. It's at least stable though and won't result in an infinite # of relayouts that may never stabilize.
@@ -653,7 +655,7 @@ void RenderTableSection::layoutRows()
 
             LayoutSize childOffset(cell->location() - oldCellRect.location());
             if (childOffset.width() || childOffset.height()) {
-                view().addLayoutDelta(childOffset);
+                view().frameView().layoutContext().addLayoutDelta(childOffset);
 
                 // If the child moved, we have to repaint it as well as any floating/positioned
                 // descendants.  An exception is if we need a layout.  In this case, we know we're going to
@@ -1614,7 +1616,7 @@ void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsign
         cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing);
 
     cell->setLogicalLocation(cellLocation);
-    view().addLayoutDelta(oldCellLocation - cell->location());
+    view().frameView().layoutContext().addLayoutDelta(oldCellLocation - cell->location());
 }
 
 } // namespace WebCore
index 75e1e97..56fd910 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(VIDEO_TRACK)
 #include "RenderVTTCue.h"
 
+#include "LayoutState.h"
 #include "RenderInline.h"
 #include "RenderView.h"
 #include "TextTrackCueGeneric.h"
index 14b0351..5aa5f18 100644 (file)
@@ -34,6 +34,7 @@
 #include "HTMLIFrameElement.h"
 #include "HitTestResult.h"
 #include "ImageQualityController.h"
+#include "LayoutState.h"
 #include "NodeTraversal.h"
 #include "Page.h"
 #include "RenderDescendantIterator.h"
@@ -193,37 +194,6 @@ bool RenderView::isChildAllowed(const RenderObject& child, const RenderStyle&) c
     return child.isBox();
 }
 
-void RenderView::layoutContent(const LayoutState& state)
-{
-    UNUSED_PARAM(state);
-    ASSERT(needsLayout());
-
-    RenderBlockFlow::layout();
-#ifndef NDEBUG
-    checkLayoutState(state);
-#endif
-}
-
-#ifndef NDEBUG
-void RenderView::checkLayoutState(const LayoutState& state)
-{
-    ASSERT(layoutDeltaMatches(LayoutSize()));
-    ASSERT(!m_layoutStateDisableCount);
-    ASSERT(m_layoutState.get() == &state);
-}
-#endif
-
-void RenderView::initializeLayoutState(LayoutState& state)
-{
-    // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
-    state.m_clipped = false;
-
-    state.m_pageLogicalHeight = m_pageLogicalSize ? m_pageLogicalSize->height() : LayoutUnit(0);
-    state.m_pageLogicalHeightChanged = m_pageLogicalHeightChanged;
-    ASSERT(state.m_pageLogicalHeight >= 0);
-    state.m_isPaginated = state.m_pageLogicalHeight > 0;
-}
-
 void RenderView::layout()
 {
     StackStats::LayoutCheckPoint layoutCheckPoint;
@@ -253,21 +223,20 @@ void RenderView::layout()
         }
     }
 
-    ASSERT(!m_layoutState);
+    ASSERT(!frameView().layoutContext().layoutState());
     if (!needsLayout())
         return;
 
-    m_layoutState = std::make_unique<LayoutState>();
-    initializeLayoutState(*m_layoutState);
+    LayoutStateMaintainer statePusher(*this, { }, false, m_pageLogicalSize.value_or(LayoutSize()).height(), m_pageLogicalHeightChanged);
 
     m_pageLogicalHeightChanged = false;
 
-    layoutContent(*m_layoutState);
+    RenderBlockFlow::layout();
 
 #ifndef NDEBUG
-    checkLayoutState(*m_layoutState);
+    frameView().layoutContext().checkLayoutState();
 #endif
-    m_layoutState = nullptr;
+    statePusher.pop();
     clearNeedsLayout();
 }
 
@@ -753,25 +722,6 @@ float RenderView::zoomFactor() const
     return frameView().frame().pageZoomFactor();
 }
 
-void RenderView::pushLayoutState(RenderElement& root)
-{
-    ASSERT(m_layoutStateDisableCount == 0);
-    ASSERT(m_layoutState == 0);
-
-    m_layoutState = std::make_unique<LayoutState>(root);
-}
-
-bool RenderView::pushLayoutStateForPaginationIfNeeded(RenderBlockFlow& layoutRoot)
-{
-    if (m_layoutState)
-        return false;
-    m_layoutState = std::make_unique<LayoutState>(layoutRoot);
-    m_layoutState->m_isPaginated = true;
-    // This is just a flag for known page height (see RenderBlockFlow::checkForPaginationLogicalHeightChange).
-    m_layoutState->m_pageLogicalHeight = 1;
-    return true;
-}
-
 IntSize RenderView::viewportSizeForCSSViewportUnits() const
 {
     return frameView().viewportSizeForCSSViewportUnits();
index 20ac5d3..d555e9b 100644 (file)
@@ -22,7 +22,6 @@
 #pragma once
 
 #include "FrameView.h"
-#include "LayoutState.h"
 #include "Region.h"
 #include "RenderBlockFlow.h"
 #include "RenderWidget.h"
@@ -34,6 +33,7 @@
 namespace WebCore {
 
 class ImageQualityController;
+class LayoutState;
 class RenderLayerCompositor;
 class RenderQuote;
 
@@ -90,44 +90,6 @@ public:
 
     LayoutRect viewRect() const;
 
-    // layoutDelta is used transiently during layout to store how far an object has moved from its
-    // last layout location, in order to repaint correctly.
-    // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
-    LayoutSize layoutDelta() const
-    {
-        return m_layoutState ? m_layoutState->m_layoutDelta : LayoutSize();
-    }
-    void addLayoutDelta(const LayoutSize& delta) 
-    {
-        if (m_layoutState) {
-            m_layoutState->m_layoutDelta += delta;
-#if !ASSERT_DISABLED
-            m_layoutState->m_layoutDeltaXSaturated |= m_layoutState->m_layoutDelta.width() == LayoutUnit::max() || m_layoutState->m_layoutDelta.width() == LayoutUnit::min();
-            m_layoutState->m_layoutDeltaYSaturated |= m_layoutState->m_layoutDelta.height() == LayoutUnit::max() || m_layoutState->m_layoutDelta.height() == LayoutUnit::min();
-#endif
-        }
-    }
-
-#if !ASSERT_DISABLED
-    bool layoutDeltaMatches(const LayoutSize& delta)
-    {
-        if (!m_layoutState)
-            return false;
-        return (delta.width() == m_layoutState->m_layoutDelta.width() || m_layoutState->m_layoutDeltaXSaturated) && (delta.height() == m_layoutState->m_layoutDelta.height() || m_layoutState->m_layoutDeltaYSaturated);
-    }
-#endif
-
-    bool doingFullRepaint() const { return frameView().layoutContext().needsFullRepaint(); }
-
-    // Subtree push/pop
-    void pushLayoutState(RenderElement&);
-    bool pushLayoutStateForPaginationIfNeeded(RenderBlockFlow&);
-    void popLayoutState(RenderObject&) { return popLayoutState(); } // Just doing this to keep popLayoutState() private and to make the subtree calls symmetrical.
-
-    // Returns true if layoutState should be used for its cached offset and clip.
-    bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; }
-    LayoutState* layoutState() const { return m_layoutState.get(); }
-
     void updateHitTestResult(HitTestResult&, const LayoutPoint&) override;
 
     void setPageLogicalSize(LayoutSize);
@@ -242,46 +204,12 @@ protected:
     bool requiresColumns(int desiredColumnCount) const override;
 
 private:
-    void initializeLayoutState(LayoutState&);
-
     void computeColumnCountAndWidth() override;
 
     bool shouldRepaint(const LayoutRect&) const;
     void flushAccumulatedRepaintRegion() const;
 
-    // These functions may only be accessed by LayoutStateMaintainer.
-    bool pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false)
-    {
-        // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
-        if (!doingFullRepaint() || m_layoutState->isPaginated() || renderer.enclosingFragmentedFlow()
-            || m_layoutState->lineGrid() || (renderer.style().lineGrid() != RenderStyle::initialLineGrid() && renderer.isRenderBlockFlow())) {
-            m_layoutState = std::make_unique<LayoutState>(WTFMove(m_layoutState), renderer, offset, pageHeight, pageHeightChanged);
-            return true;
-        }
-        return false;
-    }
-
-    void popLayoutState()
-    {
-        m_layoutState = WTFMove(m_layoutState->m_ancestor);
-    }
-
-    // Suspends the LayoutState optimization. Used under transforms that cannot be represented by
-    // LayoutState (common in SVG) and when manipulating the render tree during layout in ways
-    // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
-    // Note that even when disabled, LayoutState is still used to store layoutDelta.
-    // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler.
-    void disableLayoutState() { m_layoutStateDisableCount++; }
-    void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
-
     void layoutContent(const LayoutState&);
-#ifndef NDEBUG
-    void checkLayoutState(const LayoutState&);
-#endif
-
-    friend class LayoutStateMaintainer;
-    friend class LayoutStateDisabler;
-    friend class SubtreeLayoutStateMaintainer;
 
     bool isScrollableOrRubberbandableBox() const override;
 
@@ -317,8 +245,6 @@ private:
     std::unique_ptr<ImageQualityController> m_imageQualityController;
     std::optional<LayoutSize> m_pageLogicalSize;
     bool m_pageLogicalHeightChanged { false };
-    std::unique_ptr<LayoutState> m_layoutState;
-    unsigned m_layoutStateDisableCount { 0 };
     std::unique_ptr<RenderLayerCompositor> m_compositor;
 
     bool m_hasQuotesNeedingUpdate { false };
index 981fd53..6c06271 100644 (file)
@@ -335,7 +335,7 @@ LayoutUnit RootInlineBox::lineSnapAdjustment(LayoutUnit delta) const
         return 0;
 
     // Get the current line grid and offset.
-    LayoutState* layoutState = blockFlow().view().layoutState();
+    auto* layoutState = blockFlow().view().frameView().layoutContext().layoutState();
     RenderBlockFlow* lineGrid = layoutState->lineGrid();
     LayoutSize lineGridOffset = layoutState->lineGridOffset();
     if (!lineGrid || lineGrid->style().writingMode() != blockFlow().style().writingMode())
index f522899..4338750 100644 (file)
@@ -53,7 +53,7 @@ void RenderSVGContainer::layout()
     ASSERT(needsLayout());
 
     // RenderSVGRoot disables layoutState for the SVG rendering tree.
-    ASSERT(!view().layoutStateEnabled());
+    ASSERT(!view().frameView().layoutContext().layoutStateEnabled());
 
     LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(*this) || selfWillPaint());
 
index 022b589..7203bb2 100644 (file)
@@ -131,7 +131,7 @@ void RenderSVGForeignObject::layout()
 {
     StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
-    ASSERT(!view().layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
+    ASSERT(!view().frameView().layoutContext().layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
 
     LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(*this));
 
index 024b694..3b2b84d 100644 (file)
@@ -28,6 +28,7 @@
 #include "GraphicsContext.h"
 #include "HitTestResult.h"
 #include "LayoutRepainter.h"
+#include "LayoutState.h"
 #include "Page.h"
 #include "RenderIterator.h"
 #include "RenderLayer.h"
@@ -142,7 +143,7 @@ void RenderSVGRoot::layout()
     m_resourcesNeedingToInvalidateClients.clear();
 
     // Arbitrary affine transforms are incompatible with LayoutState.
-    LayoutStateDisabler layoutStateDisabler(view());
+    LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
 
     bool needsLayout = selfNeedsLayout();
     LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout);
index 5aae884..6ae4845 100644 (file)
@@ -220,7 +220,7 @@ static bool supportsFirstLetter(RenderBlock& block)
 
 void RenderTreeUpdater::FirstLetter::update(RenderBlock& block)
 {
-    ASSERT_WITH_SECURITY_IMPLICATION(!block.view().layoutState());
+    ASSERT_WITH_SECURITY_IMPLICATION(!block.view().frameView().layoutContext().layoutState());
 
     if (!supportsFirstLetter(block))
         return;
index e5f8dff..d1fab6f 100644 (file)
@@ -71,7 +71,7 @@ static RenderObject* firstNonMarkerChild(RenderBlock& parent)
 
 void RenderTreeUpdater::ListItem::updateMarker(RenderListItem& listItemRenderer)
 {
-    ASSERT_WITH_SECURITY_IMPLICATION(!listItemRenderer.view().layoutState());
+    ASSERT_WITH_SECURITY_IMPLICATION(!listItemRenderer.view().frameView().layoutContext().layoutState());
 
     auto& style = listItemRenderer.style();