Bug 1687263: part 4) Defer and in some cases avoid removing spellchecking-ranges...
[gecko.git] / layout / painting / DisplayListClipState.h
blobf38a6610e75716af9476a73ba43214dde707dbf3
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"
15 class nsIFrame;
16 class nsIScrollableFrame;
17 class nsDisplayListBuilder;
19 namespace mozilla {
21 /**
22 * All clip coordinates are in appunits relative to the reference frame
23 * for the display item we're building.
25 class DisplayListClipState {
26 public:
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; }
37 /**
38 * Returns intersection of mClipChainContainingBlockDescendants and
39 * mClipChainContentDescendants, allocated on aBuilder's arena.
41 const DisplayItemClipChain* GetCurrentCombinedClipChain(
42 nsDisplayListBuilder* aBuilder);
44 const DisplayItemClipChain* GetClipChainForContainingBlockDescendants()
45 const {
46 return mClipChainContainingBlockDescendants;
48 const DisplayItemClipChain* GetClipChainForContentDescendants() const {
49 return mClipChainContentDescendants;
52 const ActiveScrolledRoot* GetContentClipASR() const {
53 return mClipChainContentDescendants ? mClipChainContentDescendants->mASR
54 : nullptr;
57 class AutoSaveRestore;
59 class AutoClipContainingBlockDescendantsToContentBox;
61 class AutoClipMultiple;
63 enum { ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01 };
65 private:
66 void Clear() {
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);
80 /**
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,
86 const nsRect& aRect,
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 {
150 public:
151 explicit AutoSaveRestore(nsDisplayListBuilder* aBuilder);
152 void Restore() {
153 mState = mSavedState;
154 #ifdef DEBUG
155 mRestored = true;
156 #endif
158 ~AutoSaveRestore() { Restore(); }
160 void Clear() {
161 NS_ASSERTION(!mRestored, "Already restored!");
162 mState.Clear();
163 #ifdef DEBUG
164 mClipUsed = false;
165 #endif
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");
182 #ifdef DEBUG
183 mClipUsed = true;
184 #endif
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");
192 #ifdef DEBUG
193 mClipUsed = true;
194 #endif
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");
202 #ifdef DEBUG
203 mClipUsed = true;
204 #endif
205 mState.ClipContentDescendants(mBuilder, aRect, aRoundedRect, aRadii,
206 mClipChain);
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");
221 #ifdef DEBUG
222 mClipUsed = true;
223 #endif
224 mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame,
225 mClipChain, aFlags);
228 void SetClippedToDisplayPort() { mState.SetClippedToDisplayPort(); }
229 bool IsClippedToDisplayPort() const {
230 return mState.IsClippedToDisplayPort();
233 protected:
234 nsDisplayListBuilder* mBuilder;
235 DisplayListClipState& mState;
236 DisplayListClipState mSavedState;
237 DisplayItemClipChain mClipChain;
238 #ifdef DEBUG
239 bool mClipUsed;
240 bool mRestored;
241 #endif
244 class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
245 : public AutoSaveRestore {
246 public:
247 AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
248 nsIFrame* aFrame,
249 uint32_t aFlags = 0)
250 : AutoSaveRestore(aBuilder) {
251 #ifdef DEBUG
252 mClipUsed = true;
253 #endif
254 mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame,
255 mClipChain, aFlags);
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 {
265 public:
266 explicit AutoClipMultiple(nsDisplayListBuilder* aBuilder)
267 : AutoSaveRestore(aBuilder)
268 #ifdef DEBUG
270 mExtraClipUsed(false)
271 #endif
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");
284 #ifdef DEBUG
285 mExtraClipUsed = true;
286 #endif
287 mState.ClipContainingBlockDescendants(mBuilder, aRect, aRadii,
288 mExtraClipChain);
291 protected:
292 DisplayItemClipChain mExtraClipChain;
293 #ifdef DEBUG
294 bool mExtraClipUsed;
295 #endif
298 } // namespace mozilla
300 #endif /* DISPLAYLISTCLIPSTATE_H_ */