| /* |
| * Copyright (C) 2017 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include "LayoutUnit.h" |
| #include "Timer.h" |
| #include <wtf/WeakPtr.h> |
| |
| namespace WebCore { |
| |
| class Document; |
| class Frame; |
| class FrameView; |
| class LayoutScope; |
| class LayoutSize; |
| class RenderBlockFlow; |
| class RenderBox; |
| class RenderObject; |
| class RenderElement; |
| class RenderLayoutState; |
| class RenderView; |
| #if ENABLE(LAYOUT_FORMATTING_CONTEXT) |
| namespace Layout { |
| class LayoutState; |
| class LayoutTree; |
| } |
| #endif |
| |
| class FrameViewLayoutContext { |
| public: |
| FrameViewLayoutContext(FrameView&); |
| ~FrameViewLayoutContext(); |
| |
| void layout(); |
| bool needsLayout() const; |
| |
| // We rely on the side-effects of layout, like compositing updates, to update state in various subsystems |
| // whose dependencies are poorly defined. This call triggers such updates. |
| void setNeedsLayoutAfterViewConfigurationChange(); |
| |
| void scheduleLayout(); |
| void scheduleSubtreeLayout(RenderElement& layoutRoot); |
| void unscheduleLayout(); |
| |
| void startDisallowingLayout() { ++m_layoutDisallowedCount; } |
| void endDisallowingLayout() { ASSERT(m_layoutDisallowedCount > 0); --m_layoutDisallowedCount; } |
| |
| void disableSetNeedsLayout(); |
| void enableSetNeedsLayout(); |
| |
| enum class LayoutPhase : uint8_t { |
| OutsideLayout, |
| InPreLayout, |
| InRenderTreeLayout, |
| InViewSizeAdjust, |
| InPostLayout |
| }; |
| LayoutPhase layoutPhase() const { return m_layoutPhase; } |
| bool isLayoutNested() const { return m_layoutNestedState == LayoutNestedState::Nested; } |
| bool isLayoutPending() const { return m_layoutTimer.isActive(); } |
| bool isInLayout() const { return layoutPhase() != LayoutPhase::OutsideLayout; } |
| bool isInRenderTreeLayout() const { return layoutPhase() == LayoutPhase::InRenderTreeLayout; } |
| bool inPaintableState() const { return layoutPhase() != LayoutPhase::InRenderTreeLayout && layoutPhase() != LayoutPhase::InViewSizeAdjust && (layoutPhase() != LayoutPhase::InPostLayout || inAsynchronousTasks()); } |
| |
| unsigned layoutCount() const { return m_layoutCount; } |
| |
| RenderElement* subtreeLayoutRoot() const; |
| void clearSubtreeLayoutRoot() { m_subtreeLayoutRoot.clear(); } |
| void convertSubtreeLayoutToFullLayout(); |
| |
| void reset(); |
| void resetFirstLayoutFlag() { m_firstLayout = true; } |
| bool didFirstLayout() const { return !m_firstLayout; } |
| |
| void setNeedsFullRepaint() { m_needsFullRepaint = true; } |
| bool needsFullRepaint() const { return m_needsFullRepaint; } |
| |
| void flushAsynchronousTasks(); |
| |
| RenderLayoutState* layoutState() const PURE_FUNCTION; |
| // Returns true if layoutState should be used for its cached offset and clip. |
| bool isPaintOffsetCacheEnabled() const { return !m_paintOffsetCacheDisableCount && 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_ENABLED |
| bool layoutDeltaMatches(const LayoutSize& delta); |
| #endif |
| using LayoutStateStack = Vector<std::unique_ptr<RenderLayoutState>>; |
| |
| #if ENABLE(LAYOUT_FORMATTING_CONTEXT) |
| const Layout::LayoutState* layoutFormattingState() const { return m_layoutState.get(); } |
| #endif |
| |
| private: |
| friend class LayoutScope; |
| friend class LayoutStateMaintainer; |
| friend class LayoutStateDisabler; |
| friend class SubtreeLayoutStateMaintainer; |
| friend class PaginatedLayoutStateMaintainer; |
| |
| void performLayout(); |
| bool canPerformLayout() const; |
| bool layoutDisallowed() const { return m_layoutDisallowedCount; } |
| bool isLayoutSchedulingEnabled() const { return m_layoutSchedulingIsEnabled; } |
| |
| void layoutTimerFired(); |
| void runAsynchronousTasks(); |
| void runOrScheduleAsynchronousTasks(); |
| bool inAsynchronousTasks() const { return m_inAsynchronousTasks; } |
| |
| void setSubtreeLayoutRoot(RenderElement&); |
| |
| #if ENABLE(TEXT_AUTOSIZING) |
| void applyTextSizingIfNeeded(RenderElement& layoutRoot); |
| #endif |
| void updateStyleForLayout(); |
| |
| bool handleLayoutWithFrameFlatteningIfNeeded(); |
| void startLayoutAtMainFrameViewIfNeeded(); |
| |
| // These functions may only be accessed by LayoutStateMaintainer. |
| // Subtree push/pop |
| void pushLayoutState(RenderElement&); |
| bool pushLayoutStateForPaginationIfNeeded(RenderBlockFlow&); |
| bool pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0_lu, 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 disablePaintOffsetCache() { m_paintOffsetCacheDisableCount++; } |
| void enablePaintOffsetCache() { ASSERT(m_paintOffsetCacheDisableCount > 0); m_paintOffsetCacheDisableCount--; } |
| #if ENABLE(LAYOUT_FORMATTING_CONTEXT) |
| void layoutUsingFormattingContext(); |
| #endif |
| |
| Frame& frame() const; |
| FrameView& view() const; |
| RenderView* renderView() const; |
| Document* document() const; |
| |
| FrameView& m_frameView; |
| Timer m_layoutTimer; |
| Timer m_asynchronousTasksTimer; |
| WeakPtr<RenderElement> m_subtreeLayoutRoot; |
| |
| bool m_layoutSchedulingIsEnabled { true }; |
| bool m_firstLayout { true }; |
| bool m_needsFullRepaint { true }; |
| bool m_inAsynchronousTasks { false }; |
| bool m_setNeedsLayoutWasDeferred { false }; |
| LayoutPhase m_layoutPhase { LayoutPhase::OutsideLayout }; |
| enum class LayoutNestedState : uint8_t { NotInLayout, NotNested, Nested }; |
| LayoutNestedState m_layoutNestedState { LayoutNestedState::NotInLayout }; |
| unsigned m_layoutCount { 0 }; |
| unsigned m_disableSetNeedsLayoutCount { 0 }; |
| int m_layoutDisallowedCount { 0 }; |
| unsigned m_paintOffsetCacheDisableCount { 0 }; |
| LayoutStateStack m_layoutStateStack; |
| #if ENABLE(LAYOUT_FORMATTING_CONTEXT) |
| std::unique_ptr<Layout::LayoutTree> m_layoutTree; |
| std::unique_ptr<Layout::LayoutState> m_layoutState; |
| #endif |
| }; |
| |
| } // namespace WebCore |