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