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 | |
31 | #include <wtf/WeakPtr.h> |
32 | |
33 | namespace WebCore { |
34 | |
35 | class Document; |
36 | class Frame; |
37 | class FrameView; |
38 | class LayoutScope; |
39 | class LayoutSize; |
40 | class RenderBlockFlow; |
41 | class RenderBox; |
42 | class RenderObject; |
43 | class RenderElement; |
44 | class RenderLayoutState; |
45 | class RenderView; |
46 | |
47 | class FrameViewLayoutContext { |
48 | public: |
49 | FrameViewLayoutContext(FrameView&); |
50 | ~FrameViewLayoutContext(); |
51 | |
52 | void layout(); |
53 | bool needsLayout() const; |
54 | |
55 | // We rely on the side-effects of layout, like compositing updates, to update state in various subsystems |
56 | // whose dependencies are poorly defined. This call triggers such updates. |
57 | void setNeedsLayoutAfterViewConfigurationChange(); |
58 | |
59 | void scheduleLayout(); |
60 | void scheduleSubtreeLayout(RenderElement& layoutRoot); |
61 | void unscheduleLayout(); |
62 | |
63 | void startDisallowingLayout() { ++m_layoutDisallowedCount; } |
64 | void endDisallowingLayout() { ASSERT(m_layoutDisallowedCount > 0); --m_layoutDisallowedCount; } |
65 | |
66 | void disableSetNeedsLayout(); |
67 | void enableSetNeedsLayout(); |
68 | |
69 | enum class LayoutPhase : uint8_t { |
70 | OutsideLayout, |
71 | InPreLayout, |
72 | InRenderTreeLayout, |
73 | InViewSizeAdjust, |
74 | InPostLayout |
75 | }; |
76 | LayoutPhase layoutPhase() const { return m_layoutPhase; } |
77 | bool isLayoutNested() const { return m_layoutNestedState == LayoutNestedState::Nested; } |
78 | bool isLayoutPending() const { return m_layoutTimer.isActive(); } |
79 | bool isInLayout() const { return layoutPhase() != LayoutPhase::OutsideLayout; } |
80 | bool isInRenderTreeLayout() const { return layoutPhase() == LayoutPhase::InRenderTreeLayout; } |
81 | bool inPaintableState() const { return layoutPhase() != LayoutPhase::InRenderTreeLayout && layoutPhase() != LayoutPhase::InViewSizeAdjust && (layoutPhase() != LayoutPhase::InPostLayout || inAsynchronousTasks()); } |
82 | |
83 | unsigned layoutCount() const { return m_layoutCount; } |
84 | |
85 | RenderElement* subtreeLayoutRoot() const { return m_subtreeLayoutRoot.get(); } |
86 | void clearSubtreeLayoutRoot() { m_subtreeLayoutRoot.clear(); } |
87 | void convertSubtreeLayoutToFullLayout(); |
88 | |
89 | void reset(); |
90 | void resetFirstLayoutFlag() { m_firstLayout = true; } |
91 | bool didFirstLayout() const { return !m_firstLayout; } |
92 | |
93 | void setNeedsFullRepaint() { m_needsFullRepaint = true; } |
94 | bool needsFullRepaint() const { return m_needsFullRepaint; } |
95 | |
96 | void flushAsynchronousTasks(); |
97 | |
98 | RenderLayoutState* layoutState() const PURE_FUNCTION; |
99 | // Returns true if layoutState should be used for its cached offset and clip. |
100 | bool isPaintOffsetCacheEnabled() const { return !m_paintOffsetCacheDisableCount && layoutState(); } |
101 | #ifndef NDEBUG |
102 | void checkLayoutState(); |
103 | #endif |
104 | // layoutDelta is used transiently during layout to store how far an object has moved from its |
105 | // last layout location, in order to repaint correctly. |
106 | // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter. |
107 | LayoutSize layoutDelta() const; |
108 | void addLayoutDelta(const LayoutSize& delta); |
109 | #if !ASSERT_DISABLED |
110 | bool layoutDeltaMatches(const LayoutSize& delta); |
111 | #endif |
112 | using LayoutStateStack = Vector<std::unique_ptr<RenderLayoutState>>; |
113 | |
114 | private: |
115 | friend class LayoutScope; |
116 | friend class LayoutStateMaintainer; |
117 | friend class LayoutStateDisabler; |
118 | friend class SubtreeLayoutStateMaintainer; |
119 | friend class PaginatedLayoutStateMaintainer; |
120 | |
121 | bool canPerformLayout() const; |
122 | bool layoutDisallowed() const { return m_layoutDisallowedCount; } |
123 | bool isLayoutSchedulingEnabled() const { return m_layoutSchedulingIsEnabled; } |
124 | |
125 | void layoutTimerFired(); |
126 | void runAsynchronousTasks(); |
127 | void runOrScheduleAsynchronousTasks(); |
128 | bool inAsynchronousTasks() const { return m_inAsynchronousTasks; } |
129 | |
130 | void setSubtreeLayoutRoot(RenderElement&); |
131 | |
132 | #if ENABLE(TEXT_AUTOSIZING) |
133 | void applyTextSizingIfNeeded(RenderElement& layoutRoot); |
134 | #endif |
135 | void updateStyleForLayout(); |
136 | |
137 | bool handleLayoutWithFrameFlatteningIfNeeded(); |
138 | void startLayoutAtMainFrameViewIfNeeded(); |
139 | |
140 | // These functions may only be accessed by LayoutStateMaintainer. |
141 | // Subtree push/pop |
142 | void pushLayoutState(RenderElement&); |
143 | bool (RenderBlockFlow&); |
144 | bool pushLayoutState(RenderBox& renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0_lu, bool pageHeightChanged = false); |
145 | void popLayoutState(); |
146 | |
147 | // Suspends the LayoutState optimization. Used under transforms that cannot be represented by |
148 | // LayoutState (common in SVG) and when manipulating the render tree during layout in ways |
149 | // that can trigger repaint of a non-child (e.g. when a list item moves its list marker around). |
150 | // Note that even when disabled, LayoutState is still used to store layoutDelta. |
151 | // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler. |
152 | void disablePaintOffsetCache() { m_paintOffsetCacheDisableCount++; } |
153 | void enablePaintOffsetCache() { ASSERT(m_paintOffsetCacheDisableCount > 0); m_paintOffsetCacheDisableCount--; } |
154 | |
155 | Frame& frame() const; |
156 | FrameView& view() const; |
157 | RenderView* renderView() const; |
158 | Document* document() const; |
159 | |
160 | FrameView& m_frameView; |
161 | Timer m_layoutTimer; |
162 | Timer m_asynchronousTasksTimer; |
163 | WeakPtr<RenderElement> m_subtreeLayoutRoot; |
164 | |
165 | bool m_layoutSchedulingIsEnabled { true }; |
166 | bool m_delayedLayout { false }; |
167 | bool m_firstLayout { true }; |
168 | bool m_needsFullRepaint { true }; |
169 | bool m_inAsynchronousTasks { false }; |
170 | bool m_setNeedsLayoutWasDeferred { false }; |
171 | LayoutPhase m_layoutPhase { LayoutPhase::OutsideLayout }; |
172 | enum class LayoutNestedState : uint8_t { NotInLayout, NotNested, Nested }; |
173 | LayoutNestedState m_layoutNestedState { LayoutNestedState::NotInLayout }; |
174 | unsigned m_layoutCount { 0 }; |
175 | unsigned m_disableSetNeedsLayoutCount { 0 }; |
176 | int m_layoutDisallowedCount { 0 }; |
177 | unsigned m_paintOffsetCacheDisableCount { 0 }; |
178 | LayoutStateStack m_layoutStateStack; |
179 | }; |
180 | |
181 | } // namespace WebCore |
182 | |