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/. */
7 #ifndef DISPLAYLISTCLIPSTATE_H_
8 #define DISPLAYLISTCLIPSTATE_H_
10 #include "DisplayItemClip.h"
11 #include "DisplayItemClipChain.h"
13 #include "mozilla/DebugOnly.h"
16 class nsIScrollableFrame
;
20 class nsDisplayListBuilder
;
23 * All clip coordinates are in appunits relative to the reference frame
24 * for the display item we're building.
26 class DisplayListClipState
{
28 DisplayListClipState()
29 : mClipChainContentDescendants(nullptr),
30 mClipChainContainingBlockDescendants(nullptr),
31 mCurrentCombinedClipChain(nullptr),
32 mCurrentCombinedClipChainIsValid(false),
33 mClippedToDisplayPort(false) {}
35 void SetClippedToDisplayPort() { mClippedToDisplayPort
= true; }
36 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
39 * Returns intersection of mClipChainContainingBlockDescendants and
40 * mClipChainContentDescendants, allocated on aBuilder's arena.
42 const DisplayItemClipChain
* GetCurrentCombinedClipChain(
43 nsDisplayListBuilder
* aBuilder
);
45 const DisplayItemClipChain
* GetClipChainForContainingBlockDescendants()
47 return mClipChainContainingBlockDescendants
;
49 const DisplayItemClipChain
* GetClipChainForContentDescendants() const {
50 return mClipChainContentDescendants
;
53 const ActiveScrolledRoot
* GetContentClipASR() const {
54 return mClipChainContentDescendants
? mClipChainContentDescendants
->mASR
58 class AutoSaveRestore
;
60 class AutoClipContainingBlockDescendantsToContentBox
;
62 class AutoClipMultiple
;
64 enum { ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT
= 0x01 };
68 mClipChainContentDescendants
= nullptr;
69 mClipChainContainingBlockDescendants
= nullptr;
70 mCurrentCombinedClipChain
= nullptr;
71 mCurrentCombinedClipChainIsValid
= false;
72 mClippedToDisplayPort
= false;
75 void SetClipChainForContainingBlockDescendants(
76 const DisplayItemClipChain
* aClipChain
) {
77 mClipChainContainingBlockDescendants
= aClipChain
;
78 InvalidateCurrentCombinedClipChain(aClipChain
? aClipChain
->mASR
: nullptr);
82 * Intersects the given clip rect (with optional aRadii) with the current
83 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
84 * the result, stored in aClipOnStack.
86 void ClipContainingBlockDescendants(nsDisplayListBuilder
* aBuilder
,
88 const nscoord
* aRadii
,
89 DisplayItemClipChain
& aClipChainOnStack
);
91 void ClipContentDescendants(nsDisplayListBuilder
* aBuilder
,
92 const nsRect
& aRect
, const nscoord
* aRadii
,
93 DisplayItemClipChain
& aClipChainOnStack
);
94 void ClipContentDescendants(nsDisplayListBuilder
* aBuilder
,
95 const nsRect
& aRect
, const nsRect
& aRoundedRect
,
96 const nscoord
* aRadii
,
97 DisplayItemClipChain
& aClipChainOnStack
);
99 void InvalidateCurrentCombinedClipChain(
100 const ActiveScrolledRoot
* aInvalidateUpTo
);
103 * Clips containing-block descendants to the frame's content-box,
104 * taking border-radius into account.
105 * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
106 * we assume display items will not draw outside the content rect, so
107 * clipping is only required if there is a border-radius. This is an
108 * optimization to reduce the amount of clipping required.
110 void ClipContainingBlockDescendantsToContentBox(
111 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
112 DisplayItemClipChain
& aClipChainOnStack
, uint32_t aFlags
);
115 * All content descendants (i.e. following placeholder frames to their
116 * out-of-flows if necessary) should be clipped by
117 * mClipChainContentDescendants. Null if no clipping applies.
119 const DisplayItemClipChain
* mClipChainContentDescendants
;
121 * All containing-block descendants (i.e. frame descendants), including
122 * display items for the current frame, should be clipped by
123 * mClipChainContainingBlockDescendants.
124 * Null if no clipping applies.
126 const DisplayItemClipChain
* mClipChainContainingBlockDescendants
;
128 * The intersection of mClipChainContentDescendants and
129 * mClipChainContainingBlockDescendants.
130 * Allocated in the nsDisplayListBuilder arena. Null if none has been
131 * allocated or both mClipChainContentDescendants and
132 * mClipChainContainingBlockDescendants are null.
134 const DisplayItemClipChain
* mCurrentCombinedClipChain
;
135 bool mCurrentCombinedClipChainIsValid
;
137 * A flag that is used by sticky positioned items to know if the clip applied
138 * to them is just the displayport clip or if there is additional clipping.
140 bool mClippedToDisplayPort
;
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.
150 class DisplayListClipState::AutoSaveRestore
{
152 explicit AutoSaveRestore(nsDisplayListBuilder
* aBuilder
);
154 mState
= mSavedState
;
159 ~AutoSaveRestore() { Restore(); }
162 NS_ASSERTION(!mRestored
, "Already restored!");
169 void SetClipChainForContainingBlockDescendants(
170 const DisplayItemClipChain
* aClipChain
) {
171 mState
.SetClipChainForContainingBlockDescendants(aClipChain
);
175 * Intersects the given clip rect (with optional aRadii) with the current
176 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
177 * the result, stored in aClipOnStack.
179 void ClipContainingBlockDescendants(const nsRect
& aRect
,
180 const nscoord
* aRadii
= nullptr) {
181 NS_ASSERTION(!mRestored
, "Already restored!");
182 NS_ASSERTION(!mClipUsed
, "mClip already used");
186 mState
.ClipContainingBlockDescendants(mBuilder
, aRect
, aRadii
, mClipChain
);
189 void ClipContentDescendants(const nsRect
& aRect
,
190 const nscoord
* aRadii
= nullptr) {
191 NS_ASSERTION(!mRestored
, "Already restored!");
192 NS_ASSERTION(!mClipUsed
, "mClip already used");
196 mState
.ClipContentDescendants(mBuilder
, aRect
, aRadii
, mClipChain
);
199 void ClipContentDescendants(const nsRect
& aRect
, const nsRect
& aRoundedRect
,
200 const nscoord
* aRadii
= nullptr) {
201 NS_ASSERTION(!mRestored
, "Already restored!");
202 NS_ASSERTION(!mClipUsed
, "mClip already used");
206 mState
.ClipContentDescendants(mBuilder
, aRect
, aRoundedRect
, aRadii
,
211 * Clips containing-block descendants to the frame's content-box,
212 * taking border-radius into account.
213 * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
214 * we assume display items will not draw outside the content rect, so
215 * clipping is only required if there is a border-radius. This is an
216 * optimization to reduce the amount of clipping required.
218 void ClipContainingBlockDescendantsToContentBox(
219 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, uint32_t aFlags
= 0) {
220 NS_ASSERTION(!mRestored
, "Already restored!");
221 NS_ASSERTION(!mClipUsed
, "mClip already used");
225 mState
.ClipContainingBlockDescendantsToContentBox(aBuilder
, aFrame
,
229 void SetClippedToDisplayPort() { mState
.SetClippedToDisplayPort(); }
230 bool IsClippedToDisplayPort() const {
231 return mState
.IsClippedToDisplayPort();
235 nsDisplayListBuilder
* mBuilder
;
236 DisplayListClipState
& mState
;
237 DisplayListClipState mSavedState
;
238 DisplayItemClipChain mClipChain
;
245 class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
246 : public AutoSaveRestore
{
248 AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder
* aBuilder
,
251 : AutoSaveRestore(aBuilder
) {
255 mState
.ClipContainingBlockDescendantsToContentBox(aBuilder
, aFrame
,
261 * Do not use this outside of nsIFrame::BuildDisplayListForChild, use
262 * multiple AutoSaveRestores instead. We provide this class just to ensure
263 * BuildDisplayListForChild is as efficient as possible.
265 class DisplayListClipState::AutoClipMultiple
: public AutoSaveRestore
{
267 explicit AutoClipMultiple(nsDisplayListBuilder
* aBuilder
)
268 : AutoSaveRestore(aBuilder
)
271 mExtraClipUsed(false)
277 * Intersects the given clip rect (with optional aRadii) with the current
278 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
279 * the result, stored in aClipOnStack.
281 void ClipContainingBlockDescendantsExtra(const nsRect
& aRect
,
282 const nscoord
* aRadii
) {
283 NS_ASSERTION(!mRestored
, "Already restored!");
284 NS_ASSERTION(!mExtraClipUsed
, "mExtraClip already used");
286 mExtraClipUsed
= true;
288 mState
.ClipContainingBlockDescendants(mBuilder
, aRect
, aRadii
,
293 DisplayItemClipChain mExtraClipChain
;
299 } // namespace mozilla
301 #endif /* DISPLAYLISTCLIPSTATE_H_ */