1/*
2 * Copyright (C) 2007, 2013 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 "FrameViewLayoutContext.h"
29#include "LayoutRect.h"
30#include <wtf/Noncopyable.h>
31
32namespace WebCore {
33
34class RenderBlockFlow;
35class RenderBox;
36class RenderElement;
37class RenderFragmentedFlow;
38class RenderMultiColumnFlow;
39class RenderObject;
40
41class RenderLayoutState {
42 WTF_MAKE_NONCOPYABLE(RenderLayoutState); WTF_MAKE_FAST_ALLOCATED;
43
44public:
45 RenderLayoutState()
46 : m_clipped(false)
47 , m_isPaginated(false)
48 , m_pageLogicalHeightChanged(false)
49#if !ASSERT_DISABLED
50 , m_layoutDeltaXSaturated(false)
51 , m_layoutDeltaYSaturated(false)
52#endif
53 {
54 }
55 RenderLayoutState(const FrameViewLayoutContext::LayoutStateStack&, RenderBox&, const LayoutSize& offset, LayoutUnit pageHeight, bool pageHeightChanged);
56 enum class IsPaginated { No, Yes };
57 explicit RenderLayoutState(RenderElement&, IsPaginated = IsPaginated::No);
58
59 bool isPaginated() const { return m_isPaginated; }
60
61 // The page logical offset is the object's offset from the top of the page in the page progression
62 // direction (so an x-offset in vertical text and a y-offset for horizontal text).
63 LayoutUnit pageLogicalOffset(RenderBox*, LayoutUnit childLogicalOffset) const;
64
65 LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
66 bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
67
68 RenderBlockFlow* lineGrid() const { return m_lineGrid.get(); }
69 LayoutSize lineGridOffset() const { return m_lineGridOffset; }
70 LayoutSize lineGridPaginationOrigin() const { return m_lineGridPaginationOrigin; }
71
72 LayoutSize paintOffset() const { return m_paintOffset; }
73 LayoutSize layoutOffset() const { return m_layoutOffset; }
74
75 LayoutSize pageOffset() const { return m_pageOffset; }
76
77 bool needsBlockDirectionLocationSetBeforeLayout() const { return m_lineGrid || (m_isPaginated && m_pageLogicalHeight); }
78
79#ifndef NDEBUG
80 RenderElement* renderer() const { return m_renderer; }
81#endif
82 LayoutRect clipRect() const { return m_clipRect; }
83 bool isClipped() const { return m_clipped; }
84
85 void addLayoutDelta(LayoutSize);
86 LayoutSize layoutDelta() const { return m_layoutDelta; }
87#if !ASSERT_DISABLED
88 bool layoutDeltaMatches(LayoutSize) const;
89#endif
90
91private:
92 void computeOffsets(const RenderLayoutState& ancestor, RenderBox&, LayoutSize offset);
93 void computeClipRect(const RenderLayoutState& ancestor, RenderBox&);
94 // FIXME: webkit.org/b/179440 these functions should be part of the pagination code/FrameViewLayoutContext.
95 void computePaginationInformation(const FrameViewLayoutContext::LayoutStateStack&, RenderBox&, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged);
96 void propagateLineGridInfo(const RenderLayoutState& ancestor, RenderBox&);
97 void establishLineGrid(const FrameViewLayoutContext::LayoutStateStack&, RenderBlockFlow&);
98 void computeLineGridPaginationOrigin(const RenderMultiColumnFlow&);
99
100 // Do not add anything apart from bitfields. See https://bugs.webkit.org/show_bug.cgi?id=100173
101 bool m_clipped : 1;
102 bool m_isPaginated : 1;
103 // If our page height has changed, this will force all blocks to relayout.
104 bool m_pageLogicalHeightChanged : 1;
105#if !ASSERT_DISABLED
106 bool m_layoutDeltaXSaturated : 1;
107 bool m_layoutDeltaYSaturated : 1;
108#endif
109 // The current line grid that we're snapping to and the offset of the start of the grid.
110 WeakPtr<RenderBlockFlow> m_lineGrid;
111
112 // FIXME: Distinguish between the layout clip rect and the paint clip rect which may be larger,
113 // e.g., because of composited scrolling.
114 LayoutRect m_clipRect;
115
116 // x/y offset from layout root. Includes in-flow positioning and scroll offsets.
117 LayoutSize m_paintOffset;
118 // x/y offset from layout root. Does not include in-flow positioning or scroll offsets.
119 LayoutSize m_layoutOffset;
120 // Transient offset from the final position of the object
121 // used to ensure that repaints happen in the correct place.
122 // This is a total delta accumulated from the root.
123 LayoutSize m_layoutDelta;
124
125 // The current page height for the pagination model that encloses us.
126 LayoutUnit m_pageLogicalHeight;
127 // The offset of the start of the first page in the nearest enclosing pagination model.
128 LayoutSize m_pageOffset;
129 LayoutSize m_lineGridOffset;
130 LayoutSize m_lineGridPaginationOrigin;
131#ifndef NDEBUG
132 RenderElement* m_renderer { nullptr };
133#endif
134};
135
136// Stack-based class to assist with LayoutState push/pop
137class LayoutStateMaintainer {
138 WTF_MAKE_NONCOPYABLE(LayoutStateMaintainer);
139public:
140 explicit LayoutStateMaintainer(RenderBox&, LayoutSize offset, bool disableState = false, LayoutUnit pageHeight = 0_lu, bool pageHeightChanged = false);
141 ~LayoutStateMaintainer();
142
143private:
144 FrameViewLayoutContext& m_context;
145 bool m_paintOffsetCacheIsDisabled { false };
146 bool m_didPushLayoutState { false };
147};
148
149class SubtreeLayoutStateMaintainer {
150public:
151 SubtreeLayoutStateMaintainer(RenderElement* subtreeLayoutRoot);
152 ~SubtreeLayoutStateMaintainer();
153
154private:
155 FrameViewLayoutContext* m_context { nullptr };
156 bool m_didDisablePaintOffsetCache { false };
157};
158
159class LayoutStateDisabler {
160 WTF_MAKE_NONCOPYABLE(LayoutStateDisabler);
161public:
162 LayoutStateDisabler(FrameViewLayoutContext&);
163 ~LayoutStateDisabler();
164
165private:
166 FrameViewLayoutContext& m_context;
167};
168
169class PaginatedLayoutStateMaintainer {
170public:
171 PaginatedLayoutStateMaintainer(RenderBlockFlow&);
172 ~PaginatedLayoutStateMaintainer();
173
174private:
175 FrameViewLayoutContext& m_context;
176 bool m_pushed { false };
177};
178
179} // namespace WebCore
180