/src/mozilla-central/layout/painting/DisplayListClipState.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef DISPLAYLISTCLIPSTATE_H_ |
8 | | #define DISPLAYLISTCLIPSTATE_H_ |
9 | | |
10 | | #include "DisplayItemClip.h" |
11 | | #include "DisplayItemClipChain.h" |
12 | | |
13 | | #include "mozilla/DebugOnly.h" |
14 | | |
15 | | class nsIFrame; |
16 | | class nsIScrollableFrame; |
17 | | class nsDisplayListBuilder; |
18 | | |
19 | | namespace mozilla { |
20 | | |
21 | | /** |
22 | | * All clip coordinates are in appunits relative to the reference frame |
23 | | * for the display item we're building. |
24 | | */ |
25 | | class DisplayListClipState |
26 | | { |
27 | | public: |
28 | | DisplayListClipState() |
29 | | : mClipChainContentDescendants(nullptr) |
30 | | , mClipChainContainingBlockDescendants(nullptr) |
31 | | , mCurrentCombinedClipChain(nullptr) |
32 | | , mCurrentCombinedClipChainIsValid(false) |
33 | 0 | { |
34 | 0 | } |
35 | | |
36 | | /** |
37 | | * Returns intersection of mClipChainContainingBlockDescendants and |
38 | | * mClipChainContentDescendants, allocated on aBuilder's arena. |
39 | | */ |
40 | | const DisplayItemClipChain* GetCurrentCombinedClipChain( |
41 | | nsDisplayListBuilder* aBuilder); |
42 | | |
43 | | const DisplayItemClipChain* GetClipChainForContainingBlockDescendants() const |
44 | 0 | { |
45 | 0 | return mClipChainContainingBlockDescendants; |
46 | 0 | } |
47 | | const DisplayItemClipChain* GetClipChainForContentDescendants() const |
48 | | { |
49 | | return mClipChainContentDescendants; |
50 | | } |
51 | | |
52 | | const ActiveScrolledRoot* GetContentClipASR() const |
53 | 0 | { |
54 | 0 | return mClipChainContentDescendants ? mClipChainContentDescendants->mASR |
55 | 0 | : nullptr; |
56 | 0 | } |
57 | | |
58 | | class AutoSaveRestore; |
59 | | |
60 | | class AutoClipContainingBlockDescendantsToContentBox; |
61 | | |
62 | | class AutoClipMultiple; |
63 | | |
64 | | enum |
65 | | { |
66 | | ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01 |
67 | | }; |
68 | | |
69 | | private: |
70 | | void Clear() |
71 | 0 | { |
72 | 0 | mClipChainContentDescendants = nullptr; |
73 | 0 | mClipChainContainingBlockDescendants = nullptr; |
74 | 0 | mCurrentCombinedClipChain = nullptr; |
75 | 0 | mCurrentCombinedClipChainIsValid = false; |
76 | 0 | } |
77 | | |
78 | | void SetClipChainForContainingBlockDescendants( |
79 | | const DisplayItemClipChain* aClipChain) |
80 | 0 | { |
81 | 0 | mClipChainContainingBlockDescendants = aClipChain; |
82 | 0 | InvalidateCurrentCombinedClipChain(aClipChain ? aClipChain->mASR : nullptr); |
83 | 0 | } |
84 | | |
85 | | /** |
86 | | * Intersects the given clip rect (with optional aRadii) with the current |
87 | | * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to |
88 | | * the result, stored in aClipOnStack. |
89 | | */ |
90 | | void ClipContainingBlockDescendants(nsDisplayListBuilder* aBuilder, |
91 | | const nsRect& aRect, |
92 | | const nscoord* aRadii, |
93 | | DisplayItemClipChain& aClipChainOnStack); |
94 | | |
95 | | void ClipContentDescendants(nsDisplayListBuilder* aBuilder, |
96 | | const nsRect& aRect, |
97 | | const nscoord* aRadii, |
98 | | DisplayItemClipChain& aClipChainOnStack); |
99 | | void ClipContentDescendants(nsDisplayListBuilder* aBuilder, |
100 | | const nsRect& aRect, |
101 | | const nsRect& aRoundedRect, |
102 | | const nscoord* aRadii, |
103 | | DisplayItemClipChain& aClipChainOnStack); |
104 | | |
105 | | void InvalidateCurrentCombinedClipChain( |
106 | | const ActiveScrolledRoot* aInvalidateUpTo); |
107 | | |
108 | | /** |
109 | | * Clips containing-block descendants to the frame's content-box, |
110 | | * taking border-radius into account. |
111 | | * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then |
112 | | * we assume display items will not draw outside the content rect, so |
113 | | * clipping is only required if there is a border-radius. This is an |
114 | | * optimization to reduce the amount of clipping required. |
115 | | */ |
116 | | void ClipContainingBlockDescendantsToContentBox( |
117 | | nsDisplayListBuilder* aBuilder, |
118 | | nsIFrame* aFrame, |
119 | | DisplayItemClipChain& aClipChainOnStack, |
120 | | uint32_t aFlags); |
121 | | |
122 | | /** |
123 | | * All content descendants (i.e. following placeholder frames to their |
124 | | * out-of-flows if necessary) should be clipped by |
125 | | * mClipChainContentDescendants. Null if no clipping applies. |
126 | | */ |
127 | | const DisplayItemClipChain* mClipChainContentDescendants; |
128 | | /** |
129 | | * All containing-block descendants (i.e. frame descendants), including |
130 | | * display items for the current frame, should be clipped by |
131 | | * mClipChainContainingBlockDescendants. |
132 | | * Null if no clipping applies. |
133 | | */ |
134 | | const DisplayItemClipChain* mClipChainContainingBlockDescendants; |
135 | | /** |
136 | | * The intersection of mClipChainContentDescendants and |
137 | | * mClipChainContainingBlockDescendants. |
138 | | * Allocated in the nsDisplayListBuilder arena. Null if none has been |
139 | | * allocated or both mClipChainContentDescendants and |
140 | | * mClipChainContainingBlockDescendants are null. |
141 | | */ |
142 | | const DisplayItemClipChain* mCurrentCombinedClipChain; |
143 | | bool mCurrentCombinedClipChainIsValid; |
144 | | }; |
145 | | |
146 | | /** |
147 | | * A class to automatically save and restore the current clip state. Also |
148 | | * offers methods for modifying the clip state. Only one modification is allowed |
149 | | * to be in scope at a time using one of these objects; multiple modifications |
150 | | * require nested objects. The interface is written this way to prevent |
151 | | * dangling pointers to DisplayItemClips. |
152 | | */ |
153 | | class DisplayListClipState::AutoSaveRestore |
154 | | { |
155 | | public: |
156 | | explicit AutoSaveRestore(nsDisplayListBuilder* aBuilder); |
157 | | void Restore() |
158 | 0 | { |
159 | 0 | mState = mSavedState; |
160 | | #ifdef DEBUG |
161 | | mRestored = true; |
162 | | #endif |
163 | | } |
164 | 0 | ~AutoSaveRestore() { Restore(); } |
165 | | |
166 | | void Clear() |
167 | 0 | { |
168 | 0 | NS_ASSERTION(!mRestored, "Already restored!"); |
169 | 0 | mState.Clear(); |
170 | | #ifdef DEBUG |
171 | | mClipUsed = false; |
172 | | #endif |
173 | | } |
174 | | |
175 | | void SetClipChainForContainingBlockDescendants( |
176 | | const DisplayItemClipChain* aClipChain) |
177 | 0 | { |
178 | 0 | mState.SetClipChainForContainingBlockDescendants(aClipChain); |
179 | 0 | } |
180 | | |
181 | | /** |
182 | | * Intersects the given clip rect (with optional aRadii) with the current |
183 | | * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to |
184 | | * the result, stored in aClipOnStack. |
185 | | */ |
186 | | void ClipContainingBlockDescendants(const nsRect& aRect, |
187 | | const nscoord* aRadii = nullptr) |
188 | 0 | { |
189 | 0 | NS_ASSERTION(!mRestored, "Already restored!"); |
190 | 0 | NS_ASSERTION(!mClipUsed, "mClip already used"); |
191 | | #ifdef DEBUG |
192 | | mClipUsed = true; |
193 | | #endif |
194 | | mState.ClipContainingBlockDescendants(mBuilder, aRect, aRadii, mClipChain); |
195 | 0 | } |
196 | | |
197 | | void ClipContentDescendants(const nsRect& aRect, |
198 | | const nscoord* aRadii = nullptr) |
199 | 0 | { |
200 | 0 | NS_ASSERTION(!mRestored, "Already restored!"); |
201 | 0 | NS_ASSERTION(!mClipUsed, "mClip already used"); |
202 | | #ifdef DEBUG |
203 | | mClipUsed = true; |
204 | | #endif |
205 | | mState.ClipContentDescendants(mBuilder, aRect, aRadii, mClipChain); |
206 | 0 | } |
207 | | |
208 | | void ClipContentDescendants(const nsRect& aRect, |
209 | | const nsRect& aRoundedRect, |
210 | | const nscoord* aRadii = nullptr) |
211 | 0 | { |
212 | 0 | NS_ASSERTION(!mRestored, "Already restored!"); |
213 | 0 | NS_ASSERTION(!mClipUsed, "mClip already used"); |
214 | | #ifdef DEBUG |
215 | | mClipUsed = true; |
216 | | #endif |
217 | | mState.ClipContentDescendants( |
218 | 0 | mBuilder, aRect, aRoundedRect, aRadii, mClipChain); |
219 | 0 | } |
220 | | |
221 | | /** |
222 | | * Clips containing-block descendants to the frame's content-box, |
223 | | * taking border-radius into account. |
224 | | * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then |
225 | | * we assume display items will not draw outside the content rect, so |
226 | | * clipping is only required if there is a border-radius. This is an |
227 | | * optimization to reduce the amount of clipping required. |
228 | | */ |
229 | | void ClipContainingBlockDescendantsToContentBox( |
230 | | nsDisplayListBuilder* aBuilder, |
231 | | nsIFrame* aFrame, |
232 | | uint32_t aFlags = 0) |
233 | 0 | { |
234 | 0 | NS_ASSERTION(!mRestored, "Already restored!"); |
235 | 0 | NS_ASSERTION(!mClipUsed, "mClip already used"); |
236 | | #ifdef DEBUG |
237 | | mClipUsed = true; |
238 | | #endif |
239 | | mState.ClipContainingBlockDescendantsToContentBox( |
240 | 0 | aBuilder, aFrame, mClipChain, aFlags); |
241 | 0 | } |
242 | | |
243 | | protected: |
244 | | nsDisplayListBuilder* mBuilder; |
245 | | DisplayListClipState& mState; |
246 | | DisplayListClipState mSavedState; |
247 | | DisplayItemClipChain mClipChain; |
248 | | #ifdef DEBUG |
249 | | bool mClipUsed; |
250 | | bool mRestored; |
251 | | #endif |
252 | | }; |
253 | | |
254 | | class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox |
255 | | : public AutoSaveRestore |
256 | | { |
257 | | public: |
258 | | AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder, |
259 | | nsIFrame* aFrame, |
260 | | uint32_t aFlags = 0) |
261 | | : AutoSaveRestore(aBuilder) |
262 | 0 | { |
263 | | #ifdef DEBUG |
264 | | mClipUsed = true; |
265 | | #endif |
266 | | mState.ClipContainingBlockDescendantsToContentBox( |
267 | 0 | aBuilder, aFrame, mClipChain, aFlags); |
268 | 0 | } |
269 | | }; |
270 | | |
271 | | /** |
272 | | * Do not use this outside of nsFrame::BuildDisplayListForChild, use |
273 | | * multiple AutoSaveRestores instead. We provide this class just to ensure |
274 | | * BuildDisplayListForChild is as efficient as possible. |
275 | | */ |
276 | | class DisplayListClipState::AutoClipMultiple : public AutoSaveRestore |
277 | | { |
278 | | public: |
279 | | explicit AutoClipMultiple(nsDisplayListBuilder* aBuilder) |
280 | | : AutoSaveRestore(aBuilder) |
281 | | #ifdef DEBUG |
282 | | , mExtraClipUsed(false) |
283 | | #endif |
284 | 0 | { |
285 | 0 | } |
286 | | |
287 | | /** |
288 | | * Intersects the given clip rect (with optional aRadii) with the current |
289 | | * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to |
290 | | * the result, stored in aClipOnStack. |
291 | | */ |
292 | | void ClipContainingBlockDescendantsExtra(const nsRect& aRect, |
293 | | const nscoord* aRadii) |
294 | 0 | { |
295 | 0 | NS_ASSERTION(!mRestored, "Already restored!"); |
296 | 0 | NS_ASSERTION(!mExtraClipUsed, "mExtraClip already used"); |
297 | | #ifdef DEBUG |
298 | | mExtraClipUsed = true; |
299 | | #endif |
300 | | mState.ClipContainingBlockDescendants( |
301 | 0 | mBuilder, aRect, aRadii, mExtraClipChain); |
302 | 0 | } |
303 | | |
304 | | protected: |
305 | | DisplayItemClipChain mExtraClipChain; |
306 | | #ifdef DEBUG |
307 | | bool mExtraClipUsed; |
308 | | #endif |
309 | | }; |
310 | | |
311 | | } // namespace mozilla |
312 | | |
313 | | #endif /* DISPLAYLISTCLIPSTATE_H_ */ |