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 AbsoluteClipRects, // Relative to the RenderView's layer. Used for compositing overlap testing.
183 NumCachedClipRectsTypes,
184 AllClipRectTypes,
185 TemporaryClipRects
186 };
187
188 enum ShouldRespectOverflowClip {
189 IgnoreOverflowClip,
190 RespectOverflowClip
191 };
192
193 struct ClipRectsCache {
194 WTF_MAKE_FAST_ALLOCATED;
195 public:
ClipRectsCacheClipRectsCache196 ClipRectsCache()
197 {
198 #ifndef NDEBUG
199 for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
200 m_clipRectsRoot[i] = 0;
201 m_scrollbarRelevancy[i] = IgnoreOverlayScrollbarSize;
202 }
203 #endif
204 }
205
getClipRectsClipRectsCache206 PassRefPtr<ClipRects> getClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow) { return m_clipRects[getIndex(clipRectsType, respectOverflow)]; }
setClipRectsClipRectsCache207 void setClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow, PassRefPtr<ClipRects> clipRects) { m_clipRects[getIndex(clipRectsType, respectOverflow)] = clipRects; }
208
209 #ifndef NDEBUG
210 const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
211 OverlayScrollbarSizeRelevancy m_scrollbarRelevancy[NumCachedClipRectsTypes];
212 #endif
213
214 private:
getIndexClipRectsCache215 int getIndex(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow)
216 {
217 int index = static_cast<int>(clipRectsType);
218 if (respectOverflow == RespectOverflowClip)
219 index += static_cast<int>(NumCachedClipRectsTypes);
220 return index;
221 }
222
223 RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes * 2];
224 };
225
226 struct LayerFragment {
227 public:
LayerFragmentLayerFragment228 LayerFragment()
229 : shouldPaintContent(false)
230 { }
231
setRectsLayerFragment232 void setRects(const LayoutRect& bounds, const ClipRect& background, const ClipRect& foreground, const ClipRect& outline)
233 {
234 layerBounds = bounds;
235 backgroundRect = background;
236 foregroundRect = foreground;
237 outlineRect = outline;
238 }
239
moveByLayerFragment240 void moveBy(const LayoutPoint& offset)
241 {
242 layerBounds.moveBy(offset);
243 backgroundRect.moveBy(offset);
244 foregroundRect.moveBy(offset);
245 outlineRect.moveBy(offset);
246 paginationClip.moveBy(offset);
247 }
248
intersectLayerFragment249 void intersect(const LayoutRect& rect)
250 {
251 backgroundRect.intersect(rect);
252 foregroundRect.intersect(rect);
253 outlineRect.intersect(rect);
254 }
255
256 bool shouldPaintContent;
257 LayoutRect layerBounds;
258 ClipRect backgroundRect;
259 ClipRect foregroundRect;
260 ClipRect outlineRect;
261
262 // Unique to paginated fragments. The physical translation to apply to shift the layer when painting/hit-testing.
263 LayoutPoint paginationOffset;
264
265 // Also unique to paginated fragments. An additional clip that applies to the layer. It is in layer-local
266 // (physical) coordinates.
267 LayoutRect paginationClip;
268 };
269
270 typedef Vector<LayerFragment, 1> LayerFragments;
271
272 } // namespace WebCore
273
274 #endif // ClipRect_h
275