1 | /* |
2 | * Copyright (C) 2017 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #include "LayoutUnit.h" |
29 | #include "Timer.h" |
30 | #include <wtf/WeakPtr.h> |
31 | |
32 | namespace WebCore { |
33 | |
34 | class Document; |
35 | class Frame; |
36 | class FrameView; |
37 | class LayoutScope; |
38 | class LayoutSize; |
39 | class RenderBlockFlow; |
40 | class RenderBox; |
41 | class RenderObject; |
42 | class RenderElement; |
43 | class RenderLayoutState; |
44 | class RenderView; |
45 | |
46 | class FrameViewLayoutContext { |
47 | public: |
48 | FrameViewLayoutContext(FrameView&); |
49 | ~FrameViewLayoutContext(); |
50 | |
51 | void layout(); |
52 | bool needsLayout() const; |
53 | |
54 | // We rely on the side-effects of layout, like compositing updates, to update state in various subsystems |
55 | // whose dependencies are poorly defined. This call triggers such updates. |
56 | void setNeedsLayoutAfterViewConfigurationChange(); |
57 | |
58 | void scheduleLayout(); |
59 | void scheduleSubtreeLayout(RenderElement& layoutRoot); |
60 | void unscheduleLayout(); |
61 | |
62 | void startDisallowingLayout() { ++m_layoutDisallowedCount; } |
63 | void endDisallowingLayout() { ASSERT(m_layoutDisallowedCount > 0); --m_layoutDisallowedCount; } |
64 | |
65 | void disableSetNeedsLayout(); |
66 | void enableSetNeedsLayout(); |
67 | |
68 | enum class LayoutPhase : uint8_t { |
69 | OutsideLayout, |
70 | InPreLayout, |
71 | InRenderTreeLayout, |
72 | InViewSizeAdjust, |
73 | InPostLayout |
74 | }; |
75 | LayoutPhase layoutPhase() const { return m_layoutPhase; } |
76 | bool isLayoutNested() const { return m_layoutNestedState == LayoutNestedState::Nested; } |
77 | bool isLayoutPending() const { return m_layoutTimer.isActive(); } |
78 | bool isInLayout() const { return layoutPhase() != LayoutPhase::OutsideLayout; } |
79 | bool isInRenderTreeLayout() const { return layoutPhase() == LayoutPhase::InRenderTreeLayout; } |
80 | bool inPaintableState() const { return layoutPhase() != LayoutPhase::InRenderTreeLayout && layoutPhase() != LayoutPhase::InViewSizeAdjust && (layoutPhase() != LayoutPhase::InPostLayout || inAsynchronousTasks()); } |
81 | |
82 | unsigned layoutCount() const { return m_layoutCount; } |
83 | |
84 | RenderElement* subtreeLayoutRoot() const; |
85 | void clearSubtreeLayoutRoot() { m_subtreeLayoutRoot.clear(); } |
86 | void convertSubtreeLayoutToFullLayout(); |
87 | |
88 | void reset(); |
89 | void resetFirstLayoutFlag() { m_firstLayout = true; } |
90 | bool didFirstLayout() const { return !m_firstLayout; } |
91 | |
92 | void setNeedsFullRepaint() { m_needsFullRepaint = true; } |
93 | bool needsFullRepaint() const { return m_needsFullRepaint; } |
94 | |
95 | void flushAsynchronousTasks(); |
96 | |
97 | RenderLayoutState* layoutState() const PURE_FUNCTION; |
98 | // Returns true if layoutState should be used for its cached offset and clip. |
99 | bool isPaintOffsetCacheEnabled() const { return !m_paintOffsetCacheDisableCount && layoutState(); } |
100 | #ifndef NDEBUG |
101 | void checkLayoutState(); |
102 | #endif |
103 | // layoutDelta is used transiently during layout to store how far an object has moved from its |
104 | // last layout location, in order to repaint correctly. |
105 | // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter. |
106 | LayoutSize layoutDelta() const; |
107 | void addLayoutDelta(const LayoutSize& delta); |
108 | #if !ASSERT_DISABLED |
109 | bool layoutDeltaMatches(const LayoutSize& delta); |
110 | #endif |
111 | using LayoutStateStack = Vector<std::unique_ptr<RenderLayoutState>>; |
112 | |
113 | private: |
114 | friend class LayoutScope; |
115 | friend class LayoutStateMaintainer; |
116 | friend class LayoutStateDisabler; |
117 | friend class SubtreeLayoutStateMaintainer; |
118 | friend class PaginatedLayoutStateMaintainer; |
119 | |
120 | bool canPerformLayout() const; |
121 | bool layoutDisallowed() const { return m_layoutDisallowedCount; } |
122 | bool isLayoutSchedulingEnabled() const { return m_layoutSchedulingIsEnabled; } |
123 | |
124 | void layoutTimerFired(); |
125 | void runAsynchronousTasks(); |
126 | void runOrScheduleAsynchronousTasks(); |
127 | bool inAsynchronousTasks() const { return m_inAsynchronousTasks; } |
128 | |
129 | void setSubtreeLayoutRoot(RenderElement&); |
130 | |
131 | #if ENABLE(TEXT_AUTOSIZING) |
132 | void applyTextSizingIfNeeded(RenderElement& layoutRoot); |
133 | #endif |
134 | void updateStyleForLayout(); |
135 | |
136 | bool handleLayoutWithFrameFlatteningIfNeeded(); |
137 | void startLayoutAtMainFrameViewIfNeeded(); |
138 | |
139 | // These functions may only be accessed by LayoutStateMaintainer. |
140 | // Subtree push/pop |
141 | void pushLayoutState(RenderElement&); |
142 | bool (RenderBlockFlow&); |
143 | bool pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0_lu, bool pageHeightChanged = false); |
144 | void popLayoutState(); |
145 | |
146 | // Suspends the LayoutState optimization. Used under transforms that cannot be represented by |
147 | // LayoutState (common in SVG) and when manipulating the render tree during layout in ways |
148 | // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around). |
149 | // Note that even when disabled, LayoutState is still used to store layoutDelta. |
150 | // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler. |
151 | void disablePaintOffsetCache() { m_paintOffsetCacheDisableCount++; } |
152 | void enablePaintOffsetCache() { ASSERT(m_paintOffsetCacheDisableCount > 0); m_paintOffsetCacheDisableCount--; } |
153 | |
154 | Frame& frame() const; |
155 | FrameView& view() const; |
156 | RenderView* renderView() const; |
157 | Document* document() const; |
158 | |
159 | FrameView& m_frameView; |
160 | Timer m_layoutTimer; |
161 | Timer m_asynchronousTasksTimer; |
162 | WeakPtr<RenderElement> m_subtreeLayoutRoot; |
163 | |
164 | bool m_layoutSchedulingIsEnabled { true }; |
165 | bool m_delayedLayout { false }; |
166 | bool m_firstLayout { true }; |
167 | bool m_needsFullRepaint { true }; |
168 | bool m_inAsynchronousTasks { false }; |
169 | bool m_setNeedsLayoutWasDeferred { false }; |
170 | LayoutPhase m_layoutPhase { LayoutPhase::OutsideLayout }; |
171 | enum class LayoutNestedState : uint8_t { NotInLayout, NotNested, Nested }; |
172 | LayoutNestedState m_layoutNestedState { LayoutNestedState::NotInLayout }; |
173 | unsigned m_layoutCount { 0 }; |
174 | unsigned m_disableSetNeedsLayoutCount { 0 }; |
175 | int m_layoutDisallowedCount { 0 }; |
176 | unsigned m_paintOffsetCacheDisableCount { 0 }; |
177 | LayoutStateStack m_layoutStateStack; |
178 | }; |
179 | |
180 | } // namespace WebCore |
181 | |