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
;
17 class nsDisplayListBuilder
;
22 * All clip coordinates are in appunits relative to the reference frame
23 * for the display item we're building.
25 class DisplayListClipState
{
27 DisplayListClipState()
28 : mClipChainContentDescendants(nullptr),
29 mClipChainContainingBlockDescendants(nullptr),
30 mCurrentCombinedClipChain(nullptr),
31 mCurrentCombinedClipChainIsValid(false),
32 mClippedToDisplayPort(false) {}
34 void SetClippedToDisplayPort() { mClippedToDisplayPort
= true; }
35 bool IsClippedToDisplayPort() const { return mClippedToDisplayPort
; }
38 * Returns intersection of mClipChainContainingBlockDescendants and
39 * mClipChainContentDescendants, allocated on aBuilder's arena.
41 const DisplayItemClipChain
* GetCurrentCombinedClipChain(
42 nsDisplayListBuilder
* aBuilder
);
44 const DisplayItemClipChain
* GetClipChainForContainingBlockDescendants()
46 return mClipChainContainingBlockDescendants
;
48 const DisplayItemClipChain
* GetClipChainForContentDescendants() const {
49 return mClipChainContentDescendants
;
52 const ActiveScrolledRoot
* GetContentClipASR() const {
53 return mClipChainContentDescendants
? mClipChainContentDescendants
->mASR
57 class AutoSaveRestore
;
59 class AutoClipContainingBlockDescendantsToContentBox
;
61 class AutoClipMultiple
;
63 enum { ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT
= 0x01 };
67 mClipChainContentDescendants
= nullptr;
68 mClipChainContainingBlockDescendants
= nullptr;
69 mCurrentCombinedClipChain
= nullptr;
70 mCurrentCombinedClipChainIsValid
= false;
71 mClippedToDisplayPort
= false;
74 void SetClipChainForContainingBlockDescendants(
75 const DisplayItemClipChain
* aClipChain
) {
76 mClipChainContainingBlockDescendants
= aClipChain
;
77 InvalidateCurrentCombinedClipChain(aClipChain
? aClipChain
->mASR
: nullptr);
81 * Intersects the given clip rect (with optional aRadii) with the current
82 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
83 * the result, stored in aClipOnStack.
85 void ClipContainingBlockDescendants(nsDisplayListBuilder
* aBuilder
,
87 const nscoord
* aRadii
,
88 DisplayItemClipChain
& aClipChainOnStack
);
90 void ClipContentDescendants(nsDisplayListBuilder
* aBuilder
,
91 const nsRect
& aRect
, const nscoord
* aRadii
,
92 DisplayItemClipChain
& aClipChainOnStack
);
93 void ClipContentDescendants(nsDisplayListBuilder
* aBuilder
,
94 const nsRect
& aRect
, const nsRect
& aRoundedRect
,
95 const nscoord
* aRadii
,
96 DisplayItemClipChain
& aClipChainOnStack
);
98 void InvalidateCurrentCombinedClipChain(
99 const ActiveScrolledRoot
* aInvalidateUpTo
);
102 * Clips containing-block descendants to the frame's content-box,
103 * taking border-radius into account.
104 * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
105 * we assume display items will not draw outside the content rect, so
106 * clipping is only required if there is a border-radius. This is an
107 * optimization to reduce the amount of clipping required.
109 void ClipContainingBlockDescendantsToContentBox(
110 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
,
111 DisplayItemClipChain
& aClipChainOnStack
, uint32_t aFlags
);
114 * All content descendants (i.e. following placeholder frames to their
115 * out-of-flows if necessary) should be clipped by
116 * mClipChainContentDescendants. Null if no clipping applies.
118 const DisplayItemClipChain
* mClipChainContentDescendants
;
120 * All containing-block descendants (i.e. frame descendants), including
121 * display items for the current frame, should be clipped by
122 * mClipChainContainingBlockDescendants.
123 * Null if no clipping applies.
125 const DisplayItemClipChain
* mClipChainContainingBlockDescendants
;
127 * The intersection of mClipChainContentDescendants and
128 * mClipChainContainingBlockDescendants.
129 * Allocated in the nsDisplayListBuilder arena. Null if none has been
130 * allocated or both mClipChainContentDescendants and
131 * mClipChainContainingBlockDescendants are null.
133 const DisplayItemClipChain
* mCurrentCombinedClipChain
;
134 bool mCurrentCombinedClipChainIsValid
;
136 * A flag that is used by sticky positioned items to know if the clip applied
137 * to them is just the displayport clip or if there is additional clipping.
139 bool mClippedToDisplayPort
;
143 * A class to automatically save and restore the current clip state. Also
144 * offers methods for modifying the clip state. Only one modification is allowed
145 * to be in scope at a time using one of these objects; multiple modifications
146 * require nested objects. The interface is written this way to prevent
147 * dangling pointers to DisplayItemClips.
149 class DisplayListClipState::AutoSaveRestore
{
151 explicit AutoSaveRestore(nsDisplayListBuilder
* aBuilder
);
153 mState
= mSavedState
;
158 ~AutoSaveRestore() { Restore(); }
161 NS_ASSERTION(!mRestored
, "Already restored!");
168 void SetClipChainForContainingBlockDescendants(
169 const DisplayItemClipChain
* aClipChain
) {
170 mState
.SetClipChainForContainingBlockDescendants(aClipChain
);
174 * Intersects the given clip rect (with optional aRadii) with the current
175 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
176 * the result, stored in aClipOnStack.
178 void ClipContainingBlockDescendants(const nsRect
& aRect
,
179 const nscoord
* aRadii
= nullptr) {
180 NS_ASSERTION(!mRestored
, "Already restored!");
181 NS_ASSERTION(!mClipUsed
, "mClip already used");
185 mState
.ClipContainingBlockDescendants(mBuilder
, aRect
, aRadii
, mClipChain
);
188 void ClipContentDescendants(const nsRect
& aRect
,
189 const nscoord
* aRadii
= nullptr) {
190 NS_ASSERTION(!mRestored
, "Already restored!");
191 NS_ASSERTION(!mClipUsed
, "mClip already used");
195 mState
.ClipContentDescendants(mBuilder
, aRect
, aRadii
, mClipChain
);
198 void ClipContentDescendants(const nsRect
& aRect
, const nsRect
& aRoundedRect
,
199 const nscoord
* aRadii
= nullptr) {
200 NS_ASSERTION(!mRestored
, "Already restored!");
201 NS_ASSERTION(!mClipUsed
, "mClip already used");
205 mState
.ClipContentDescendants(mBuilder
, aRect
, aRoundedRect
, aRadii
,
210 * Clips containing-block descendants to the frame's content-box,
211 * taking border-radius into account.
212 * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
213 * we assume display items will not draw outside the content rect, so
214 * clipping is only required if there is a border-radius. This is an
215 * optimization to reduce the amount of clipping required.
217 void ClipContainingBlockDescendantsToContentBox(
218 nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
, uint32_t aFlags
= 0) {
219 NS_ASSERTION(!mRestored
, "Already restored!");
220 NS_ASSERTION(!mClipUsed
, "mClip already used");
224 mState
.ClipContainingBlockDescendantsToContentBox(aBuilder
, aFrame
,
228 void SetClippedToDisplayPort() { mState
.SetClippedToDisplayPort(); }
229 bool IsClippedToDisplayPort() const {
230 return mState
.IsClippedToDisplayPort();
234 nsDisplayListBuilder
* mBuilder
;
235 DisplayListClipState
& mState
;
236 DisplayListClipState mSavedState
;
237 DisplayItemClipChain mClipChain
;
244 class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
245 : public AutoSaveRestore
{
247 AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder
* aBuilder
,
250 : AutoSaveRestore(aBuilder
) {
254 mState
.ClipContainingBlockDescendantsToContentBox(aBuilder
, aFrame
,
260 * Do not use this outside of nsIFrame::BuildDisplayListForChild, use
261 * multiple AutoSaveRestores instead. We provide this class just to ensure
262 * BuildDisplayListForChild is as efficient as possible.
264 class DisplayListClipState::AutoClipMultiple
: public AutoSaveRestore
{
266 explicit AutoClipMultiple(nsDisplayListBuilder
* aBuilder
)
267 : AutoSaveRestore(aBuilder
)
270 mExtraClipUsed(false)
276 * Intersects the given clip rect (with optional aRadii) with the current
277 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
278 * the result, stored in aClipOnStack.
280 void ClipContainingBlockDescendantsExtra(const nsRect
& aRect
,
281 const nscoord
* aRadii
) {
282 NS_ASSERTION(!mRestored
, "Already restored!");
283 NS_ASSERTION(!mExtraClipUsed
, "mExtraClip already used");
285 mExtraClipUsed
= true;
287 mState
.ClipContainingBlockDescendants(mBuilder
, aRect
, aRadii
,
292 DisplayItemClipChain mExtraClipChain
;
298 } // namespace mozilla
300 #endif /* DISPLAYLISTCLIPSTATE_H_ */