1/*
2 * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "FloatRect.h"
29#include "ScrollTypes.h"
30
31namespace WebCore {
32
33// LayoutConstraints classes encapsulate data and logic required to reposition elements whose layout
34// depends on the scroll position of ancestor elements.
35class LayoutConstraints {
36 WTF_MAKE_FAST_ALLOCATED;
37public:
38 LayoutConstraints() = default;
39
40 bool operator==(const LayoutConstraints& other) const
41 {
42 return alignmentOffset() == other.alignmentOffset()
43 && layerPositionAtLastLayout() == other.layerPositionAtLastLayout()
44 && scrollPositioningBehavior() == other.scrollPositioningBehavior();
45 }
46
47 bool operator!=(const LayoutConstraints& other) const { return !(*this == other); }
48
49 FloatSize alignmentOffset() const { return m_alignmentOffset; }
50 void setAlignmentOffset(FloatSize offset) { m_alignmentOffset = offset; }
51
52 FloatPoint layerPositionAtLastLayout() const { return m_layerPositionAtLastLayout; }
53 void setLayerPositionAtLastLayout(FloatPoint position) { m_layerPositionAtLastLayout = position; }
54
55 ScrollPositioningBehavior scrollPositioningBehavior() const { return m_scrollPositioningBehavior; }
56 void setScrollPositioningBehavior(ScrollPositioningBehavior behavior) { m_scrollPositioningBehavior = behavior; }
57
58private:
59 FloatSize m_alignmentOffset;
60 FloatPoint m_layerPositionAtLastLayout;
61 ScrollPositioningBehavior m_scrollPositioningBehavior { ScrollPositioningBehavior::None };
62};
63
64// ViewportConstraints classes encapsulate data and logic required to reposition elements whose layout
65// depends on the viewport rect (positions fixed and sticky), when scrolling and zooming.
66class ViewportConstraints {
67 WTF_MAKE_FAST_ALLOCATED;
68public:
69 enum ConstraintType {
70 FixedPositionConstraint,
71 StickyPositionConstraint
72 };
73
74 enum AnchorEdgeFlags {
75 AnchorEdgeLeft = 1 << 0,
76 AnchorEdgeRight = 1 << 1,
77 AnchorEdgeTop = 1 << 2,
78 AnchorEdgeBottom = 1 << 3
79 };
80 typedef unsigned AnchorEdges;
81
82 virtual ~ViewportConstraints() = default;
83
84 virtual ConstraintType constraintType() const = 0;
85
86 AnchorEdges anchorEdges() const { return m_anchorEdges; }
87 bool hasAnchorEdge(AnchorEdgeFlags flag) const { return m_anchorEdges & flag; }
88 void addAnchorEdge(AnchorEdgeFlags edgeFlag) { m_anchorEdges |= edgeFlag; }
89 void setAnchorEdges(AnchorEdges edges) { m_anchorEdges = edges; }
90
91 FloatSize alignmentOffset() const { return m_alignmentOffset; }
92 void setAlignmentOffset(FloatSize offset) { m_alignmentOffset = offset; }
93
94protected:
95 ViewportConstraints()
96 : m_anchorEdges(0)
97 { }
98
99 FloatSize m_alignmentOffset;
100 AnchorEdges m_anchorEdges;
101};
102
103class FixedPositionViewportConstraints : public ViewportConstraints {
104public:
105 FixedPositionViewportConstraints()
106 : ViewportConstraints()
107 { }
108
109 WEBCORE_EXPORT FloatPoint layerPositionForViewportRect(const FloatRect& viewportRect) const;
110
111 const FloatRect& viewportRectAtLastLayout() const { return m_viewportRectAtLastLayout; }
112 void setViewportRectAtLastLayout(const FloatRect& rect) { m_viewportRectAtLastLayout = rect; }
113
114 const FloatPoint& layerPositionAtLastLayout() const { return m_layerPositionAtLastLayout; }
115 void setLayerPositionAtLastLayout(FloatPoint position) { m_layerPositionAtLastLayout = position; }
116
117 bool operator==(const FixedPositionViewportConstraints& other) const
118 {
119 return m_alignmentOffset == other.m_alignmentOffset
120 && m_anchorEdges == other.m_anchorEdges
121 && m_viewportRectAtLastLayout == other.m_viewportRectAtLastLayout
122 && m_layerPositionAtLastLayout == other.m_layerPositionAtLastLayout;
123 }
124
125 bool operator!=(const FixedPositionViewportConstraints& other) const { return !(*this == other); }
126
127private:
128 ConstraintType constraintType() const override { return FixedPositionConstraint; };
129
130 FloatRect m_viewportRectAtLastLayout;
131 FloatPoint m_layerPositionAtLastLayout;
132};
133
134class StickyPositionViewportConstraints : public ViewportConstraints {
135public:
136 StickyPositionViewportConstraints()
137 : m_leftOffset(0)
138 , m_rightOffset(0)
139 , m_topOffset(0)
140 , m_bottomOffset(0)
141 { }
142
143 FloatSize computeStickyOffset(const FloatRect& constrainingRect) const;
144
145 const FloatSize stickyOffsetAtLastLayout() const { return m_stickyOffsetAtLastLayout; }
146 void setStickyOffsetAtLastLayout(FloatSize offset) { m_stickyOffsetAtLastLayout = offset; }
147
148 WEBCORE_EXPORT FloatPoint layerPositionForConstrainingRect(const FloatRect& constrainingRect) const;
149
150 const FloatPoint& layerPositionAtLastLayout() const { return m_layerPositionAtLastLayout; }
151 void setLayerPositionAtLastLayout(FloatPoint position) { m_layerPositionAtLastLayout = position; }
152
153 float leftOffset() const { return m_leftOffset; }
154 float rightOffset() const { return m_rightOffset; }
155 float topOffset() const { return m_topOffset; }
156 float bottomOffset() const { return m_bottomOffset; }
157
158 void setLeftOffset(float offset) { m_leftOffset = offset; }
159 void setRightOffset(float offset) { m_rightOffset = offset; }
160 void setTopOffset(float offset) { m_topOffset = offset; }
161 void setBottomOffset(float offset) { m_bottomOffset = offset; }
162
163 // constrainingRectAtLastLayout() is the viewport rect if this sticky object sticks to the viewport, and
164 // it is the overflow area's scrolled clip rect if this sticky object sticks inside an overflow area.
165 FloatRect constrainingRectAtLastLayout() const { return m_constrainingRectAtLastLayout; }
166 void setConstrainingRectAtLastLayout(const FloatRect& rect) { m_constrainingRectAtLastLayout = rect; }
167
168 // containingBlockRect() is in the scrolling ancestor's coordinate space.
169 FloatRect containingBlockRect() const { return m_containingBlockRect; }
170 void setContainingBlockRect(const FloatRect& rect) { m_containingBlockRect = rect; }
171
172 // stickyBoxRect() is in the scrolling ancestor's coordinate space.
173 FloatRect stickyBoxRect() const { return m_stickyBoxRect; }
174 void setStickyBoxRect(const FloatRect& rect) { m_stickyBoxRect = rect; }
175
176 bool operator==(const StickyPositionViewportConstraints& other) const
177 {
178 return m_alignmentOffset == other.m_alignmentOffset
179 && m_anchorEdges == other.m_anchorEdges
180 && m_leftOffset == other.m_leftOffset
181 && m_rightOffset == other.m_rightOffset
182 && m_topOffset == other.m_topOffset
183 && m_bottomOffset == other.m_bottomOffset
184 && m_containingBlockRect == other.m_containingBlockRect
185 && m_stickyBoxRect == other.m_stickyBoxRect
186 && m_stickyOffsetAtLastLayout == other.m_stickyOffsetAtLastLayout
187 && m_layerPositionAtLastLayout == other.m_layerPositionAtLastLayout;
188 }
189
190 bool operator!=(const StickyPositionViewportConstraints& other) const { return !(*this == other); }
191
192private:
193 ConstraintType constraintType() const override { return StickyPositionConstraint; };
194
195 float m_leftOffset;
196 float m_rightOffset;
197 float m_topOffset;
198 float m_bottomOffset;
199 FloatRect m_constrainingRectAtLastLayout;
200 FloatRect m_containingBlockRect;
201 FloatRect m_stickyBoxRect;
202 FloatSize m_stickyOffsetAtLastLayout;
203 FloatPoint m_layerPositionAtLastLayout;
204};
205
206
207WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollPositioningBehavior);
208WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const LayoutConstraints&);
209WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const FixedPositionViewportConstraints&);
210WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, const StickyPositionViewportConstraints&);
211
212} // namespace WebCore
213