1 /*
2 * Copyright (C) 2003, 2009, 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. ``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 COMPUTER, 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 #ifndef ClipRect_h
27 #define ClipRect_h
28
29 #include "platform/geometry/LayoutRect.h"
30
31 #include "wtf/Vector.h"
32
33 #ifndef NDEBUG
34 #include "core/rendering/RenderBox.h" // For OverlayScrollbarSizeRelevancy.
35 #endif
36
37 namespace WebCore {
38
39 class RenderLayer;
40 class HitTestLocation;
41
42 class ClipRect {
43 public:
ClipRect()44 ClipRect()
45 : m_hasRadius(false)
46 { }
47
ClipRect(const LayoutRect & rect)48 ClipRect(const LayoutRect& rect)
49 : m_rect(rect)
50 , m_hasRadius(false)
51 { }
52
rect()53 const LayoutRect& rect() const { return m_rect; }
setRect(const LayoutRect & rect)54 void setRect(const LayoutRect& rect) { m_rect = rect; }
55
hasRadius()56 bool hasRadius() const { return m_hasRadius; }
setHasRadius(bool hasRadius)57 void setHasRadius(bool hasRadius) { m_hasRadius = hasRadius; }
58
59 bool operator==(const ClipRect& other) const { return rect() == other.rect() && hasRadius() == other.hasRadius(); }
60 bool operator!=(const ClipRect& other) const { return rect() != other.rect() || hasRadius() != other.hasRadius(); }
61 bool operator!=(const LayoutRect& otherRect) const { return rect() != otherRect; }
62
intersect(const LayoutRect & other)63 void intersect(const LayoutRect& other) { m_rect.intersect(other); }
intersect(const ClipRect & other)64 void intersect(const ClipRect& other)
65 {
66 m_rect.intersect(other.rect());
67 if (other.hasRadius())
68 m_hasRadius = true;
69 }
move(LayoutUnit x,LayoutUnit y)70 void move(LayoutUnit x, LayoutUnit y) { m_rect.move(x, y); }
move(const LayoutSize & size)71 void move(const LayoutSize& size) { m_rect.move(size); }
moveBy(const LayoutPoint & point)72 void moveBy(const LayoutPoint& point) { m_rect.moveBy(point); }
73
isEmpty()74 bool isEmpty() const { return m_rect.isEmpty(); }
intersects(const LayoutRect & rect)75 bool intersects(const LayoutRect& rect) const { return m_rect.intersects(rect); }
76 bool intersects(const HitTestLocation&) const;
77
78 private:
79 LayoutRect m_rect;
80 bool m_hasRadius;
81 };
82
intersection(const ClipRect & a,const ClipRect & b)83 inline ClipRect intersection(const ClipRect& a, const ClipRect& b)
84 {
85 ClipRect c = a;
86 c.intersect(b);
87 return c;
88 }
89
90 class ClipRects {
91 WTF_MAKE_FAST_ALLOCATED;
92 public:
create()93 static PassRefPtr<ClipRects> create()
94 {
95 return adoptRef(new ClipRects);
96 }
97
create(const ClipRects & other)98 static PassRefPtr<ClipRects> create(const ClipRects& other)
99 {
100 return adoptRef(new ClipRects(other));
101 }
102
ClipRects()103 ClipRects()
104 : m_refCnt(1)
105 , m_fixed(0)
106 {
107 }
108
reset(const LayoutRect & r)109 void reset(const LayoutRect& r)
110 {
111 m_overflowClipRect = r;
112 m_fixedClipRect = r;
113 m_posClipRect = r;
114 m_fixed = 0;
115 }
116
overflowClipRect()117 const ClipRect& overflowClipRect() const { return m_overflowClipRect; }
setOverflowClipRect(const ClipRect & r)118 void setOverflowClipRect(const ClipRect& r) { m_overflowClipRect = r; }
119
fixedClipRect()120 const ClipRect& fixedClipRect() const { return m_fixedClipRect; }
setFixedClipRect(const ClipRect & r)121 void setFixedClipRect(const ClipRect&r) { m_fixedClipRect = r; }
122
posClipRect()123 const ClipRect& posClipRect() const { return m_posClipRect; }
setPosClipRect(const ClipRect & r)124 void setPosClipRect(const ClipRect& r) { m_posClipRect = r; }
125
fixed()126 bool fixed() const { return static_cast<bool>(m_fixed); }
setFixed(bool fixed)127 void setFixed(bool fixed) { m_fixed = fixed ? 1 : 0; }
128
ref()129 void ref() { m_refCnt++; }
deref()130 void deref()
131 {
132 if (!--m_refCnt)
133 delete this;
134 }
135
136 bool operator==(const ClipRects& other) const
137 {
138 return m_overflowClipRect == other.overflowClipRect()
139 && m_fixedClipRect == other.fixedClipRect()
140 && m_posClipRect == other.posClipRect()
141 && fixed() == other.fixed();
142 }
143
144 ClipRects& operator=(const ClipRects& other)
145 {
146 m_overflowClipRect = other.overflowClipRect();
147 m_fixedClipRect = other.fixedClipRect();
148 m_posClipRect = other.posClipRect();
149 m_fixed = other.fixed();
150 return *this;
151 }
152
153 private:
ClipRects(const LayoutRect & r)154 ClipRects(const LayoutRect& r)
155 : m_overflowClipRect(r)
156 , m_fixedClipRect(r)
157 , m_posClipRect(r)
158 , m_refCnt(1)
159 , m_fixed(0)
160 {
161 }
162
ClipRects(const ClipRects & other)163 ClipRects(const ClipRects& other)
164 : m_overflowClipRect(other.overflowClipRect())
165 , m_fixedClipRect(other.fixedClipRect())
166 , m_posClipRect(other.posClipRect())
167 , m_refCnt(1)
168 , m_fixed(other.fixed())
169 {
170 }
171
172 ClipRect m_overflowClipRect;
173 ClipRect m_fixedClipRect;
174 ClipRect m_posClipRect;
175 unsigned m_refCnt : 31;
176 unsigned m_fixed : 1;
177 };
178
179 enum ClipRectsType {
180 PaintingClipRects, // Relative to painting ancestor. Used for painting.
181 RootRelativeClipRects, // Relative to the ancestor treated as the root (e.g. transformed layer). Used for hit testing.
182 CompositingClipRects, // Relative to the compositing ancestor. Used for updating graphics layer geometry.
183 AbsoluteClipRects, // Relative to the RenderView's layer. Used for compositing overlap testing.
184 NumCachedClipRectsTypes,
185 AllClipRectTypes,
186 TemporaryClipRects
187 };
188
189 enum ShouldRespectOverflowClip {
190 IgnoreOverflowClip,
191 RespectOverflowClip
192 };
193
194 struct ClipRectsCache {
195 WTF_MAKE_FAST_ALLOCATED;
196 public:
ClipRectsCacheClipRectsCache197 ClipRectsCache()
198 {
199 for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
200 m_clipRectsRoot[i] = 0;
201 #ifndef NDEBUG
202 m_scrollbarRelevancy[i] = IgnoreOverlayScrollbarSize;
203 #endif
204 }
205 }
206
getClipRectsClipRectsCache207 PassRefPtr<ClipRects> getClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow) { return m_clipRects[getIndex(clipRectsType, respectOverflow)]; }
setClipRectsClipRectsCache208 void setClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow, PassRefPtr<ClipRects> clipRects, const RenderLayer* root)
209 {
210 m_clipRects[getIndex(clipRectsType, respectOverflow)] = clipRects;
211 m_clipRectsRoot[clipRectsType] = root;
212 }
213
clipRectsRootClipRectsCache214 const RenderLayer* clipRectsRoot(ClipRectsType clipRectsType) const { return m_clipRectsRoot[clipRectsType]; }
215
216 #ifndef NDEBUG
217 OverlayScrollbarSizeRelevancy m_scrollbarRelevancy[NumCachedClipRectsTypes];
218 #endif
219
220 private:
getIndexClipRectsCache221 int getIndex(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow)
222 {
223 int index = static_cast<int>(clipRectsType);
224 if (respectOverflow == RespectOverflowClip)
225 index += static_cast<int>(NumCachedClipRectsTypes);
226 return index;
227 }
228
229 const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
230 RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes * 2];
231 };
232
233 struct LayerFragment {
234 public:
LayerFragmentLayerFragment235 LayerFragment()
236 : shouldPaintContent(false)
237 { }
238
setRectsLayerFragment239 void setRects(const LayoutRect& bounds, const ClipRect& background, const ClipRect& foreground, const ClipRect& outline)
240 {
241 layerBounds = bounds;
242 backgroundRect = background;
243 foregroundRect = foreground;
244 outlineRect = outline;
245 }
246
moveByLayerFragment247 void moveBy(const LayoutPoint& offset)
248 {
249 layerBounds.moveBy(offset);
250 backgroundRect.moveBy(offset);
251 foregroundRect.moveBy(offset);
252 outlineRect.moveBy(offset);
253 paginationClip.moveBy(offset);
254 }
255
intersectLayerFragment256 void intersect(const LayoutRect& rect)
257 {
258 backgroundRect.intersect(rect);
259 foregroundRect.intersect(rect);
260 outlineRect.intersect(rect);
261 }
262
263 bool shouldPaintContent;
264 LayoutRect layerBounds;
265 ClipRect backgroundRect;
266 ClipRect foregroundRect;
267 ClipRect outlineRect;
268
269 // Unique to paginated fragments. The physical translation to apply to shift the layer when painting/hit-testing.
270 LayoutPoint paginationOffset;
271
272 // Also unique to paginated fragments. An additional clip that applies to the layer. It is in layer-local
273 // (physical) coordinates.
274 LayoutRect paginationClip;
275 };
276
277 typedef Vector<LayerFragment, 1> LayerFragments;
278
279 } // namespace WebCore
280
281 #endif // ClipRect_h
282