Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 #ifndef DISPLAYLISTCLIPSTATE_H_
7 #define DISPLAYLISTCLIPSTATE_H_
9 #include "DisplayItemClip.h"
11 #include "mozilla/DebugOnly.h"
13 class nsIFrame;
14 class nsDisplayListBuilder;
16 namespace mozilla {
18 /**
19 * All clip coordinates are in appunits relative to the reference frame
20 * for the display item we're building.
21 */
22 class DisplayListClipState {
23 public:
24 DisplayListClipState()
25 : mClipContentDescendants(nullptr)
26 , mClipContainingBlockDescendants(nullptr)
27 , mCurrentCombinedClip(nullptr)
28 {}
30 /**
31 * Returns intersection of mClipContainingBlockDescendants and
32 * mClipContentDescendants, allocated on aBuilder's arena.
33 */
34 const DisplayItemClip* GetCurrentCombinedClip(nsDisplayListBuilder* aBuilder);
36 const DisplayItemClip* GetClipForContainingBlockDescendants() const
37 {
38 return mClipContainingBlockDescendants;
39 }
40 const DisplayItemClip* GetClipForContentDescendants() const
41 {
42 return mClipContentDescendants;
43 }
45 class AutoSaveRestore;
46 friend class AutoSaveRestore;
48 class AutoClipContainingBlockDescendantsToContentBox;
49 friend class AutoClipContainingBlockDescendantsToContentBox;
51 class AutoClipMultiple;
52 friend class AutoClipMultiple;
54 enum {
55 ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT = 0x01
56 };
58 private:
59 void SetClipForContainingBlockDescendants(const DisplayItemClip* aClip)
60 {
61 mClipContainingBlockDescendants = aClip;
62 mCurrentCombinedClip = nullptr;
63 }
65 void Clear()
66 {
67 mClipContentDescendants = nullptr;
68 mClipContainingBlockDescendants = nullptr;
69 mCurrentCombinedClip = nullptr;
70 }
72 /**
73 * Intersects the given clip rect (with optional aRadii) with the current
74 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
75 * the result, stored in aClipOnStack.
76 */
77 void ClipContainingBlockDescendants(const nsRect& aRect,
78 const nscoord* aRadii,
79 DisplayItemClip& aClipOnStack);
81 void ClipContentDescendants(const nsRect& aRect,
82 const nscoord* aRadii,
83 DisplayItemClip& aClipOnStack);
85 /**
86 * Clips containing-block descendants to the frame's content-box,
87 * taking border-radius into account.
88 * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
89 * we assume display items will not draw outside the content rect, so
90 * clipping is only required if there is a border-radius. This is an
91 * optimization to reduce the amount of clipping required.
92 */
93 void ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
94 nsIFrame* aFrame,
95 DisplayItemClip& aClipOnStack,
96 uint32_t aFlags);
98 /**
99 * All content descendants (i.e. following placeholder frames to their
100 * out-of-flows if necessary) should be clipped by mClipContentDescendants.
101 * Null if no clipping applies.
102 */
103 const DisplayItemClip* mClipContentDescendants;
104 /**
105 * All containing-block descendants (i.e. frame descendants), including
106 * display items for the current frame, should be clipped by
107 * mClipContainingBlockDescendants.
108 * Null if no clipping applies.
109 */
110 const DisplayItemClip* mClipContainingBlockDescendants;
111 /**
112 * The intersection of mClipContentDescendants and
113 * mClipContainingBlockDescendants.
114 * Allocated in the nsDisplayListBuilder arena. Null if none has been
115 * allocated or both mClipContentDescendants and mClipContainingBlockDescendants
116 * are null.
117 */
118 const DisplayItemClip* mCurrentCombinedClip;
119 };
121 /**
122 * A class to automatically save and restore the current clip state. Also
123 * offers methods for modifying the clip state. Only one modification is allowed
124 * to be in scope at a time using one of these objects; multiple modifications
125 * require nested objects. The interface is written this way to prevent
126 * dangling pointers to DisplayItemClips.
127 */
128 class DisplayListClipState::AutoSaveRestore {
129 public:
130 AutoSaveRestore(nsDisplayListBuilder* aBuilder);
131 void Restore()
132 {
133 mState = mSavedState;
134 mRestored = true;
135 }
136 ~AutoSaveRestore()
137 {
138 mState = mSavedState;
139 }
141 void Clear()
142 {
143 NS_ASSERTION(!mRestored, "Already restored!");
144 mState.Clear();
145 mClipUsed = false;
146 }
148 /**
149 * Intersects the given clip rect (with optional aRadii) with the current
150 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
151 * the result, stored in aClipOnStack.
152 */
153 void ClipContainingBlockDescendants(const nsRect& aRect,
154 const nscoord* aRadii = nullptr)
155 {
156 NS_ASSERTION(!mRestored, "Already restored!");
157 NS_ASSERTION(!mClipUsed, "mClip already used");
158 mClipUsed = true;
159 mState.ClipContainingBlockDescendants(aRect, aRadii, mClip);
160 }
162 void ClipContentDescendants(const nsRect& aRect,
163 const nscoord* aRadii = nullptr)
164 {
165 NS_ASSERTION(!mRestored, "Already restored!");
166 NS_ASSERTION(!mClipUsed, "mClip already used");
167 mClipUsed = true;
168 mState.ClipContentDescendants(aRect, aRadii, mClip);
169 }
171 /**
172 * Clips containing-block descendants to the frame's content-box,
173 * taking border-radius into account.
174 * If aFlags contains ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT then
175 * we assume display items will not draw outside the content rect, so
176 * clipping is only required if there is a border-radius. This is an
177 * optimization to reduce the amount of clipping required.
178 */
179 void ClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
180 nsIFrame* aFrame,
181 uint32_t aFlags = 0)
182 {
183 NS_ASSERTION(!mRestored, "Already restored!");
184 NS_ASSERTION(!mClipUsed, "mClip already used");
185 mClipUsed = true;
186 mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags);
187 }
189 protected:
190 DisplayListClipState& mState;
191 DisplayListClipState mSavedState;
192 DisplayItemClip mClip;
193 DebugOnly<bool> mClipUsed;
194 DebugOnly<bool> mRestored;
195 };
197 class DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox : public AutoSaveRestore {
198 public:
199 AutoClipContainingBlockDescendantsToContentBox(nsDisplayListBuilder* aBuilder,
200 nsIFrame* aFrame,
201 uint32_t aFlags = 0)
202 : AutoSaveRestore(aBuilder)
203 {
204 mClipUsed = true;
205 mState.ClipContainingBlockDescendantsToContentBox(aBuilder, aFrame, mClip, aFlags);
206 }
207 };
209 /**
210 * Do not use this outside of nsFrame::BuildDisplayListForChild, use
211 * multiple AutoSaveRestores instead. We provide this class just to ensure
212 * BuildDisplayListForChild is as efficient as possible.
213 */
214 class DisplayListClipState::AutoClipMultiple : public AutoSaveRestore {
215 public:
216 AutoClipMultiple(nsDisplayListBuilder* aBuilder)
217 : AutoSaveRestore(aBuilder)
218 , mExtraClipUsed(false)
219 {}
221 /**
222 * *aClip must survive longer than this object. Be careful!!!
223 */
224 void SetClipForContainingBlockDescendants(const DisplayItemClip* aClip)
225 {
226 mState.SetClipForContainingBlockDescendants(aClip);
227 }
229 /**
230 * Intersects the given clip rect (with optional aRadii) with the current
231 * mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
232 * the result, stored in aClipOnStack.
233 */
234 void ClipContainingBlockDescendantsExtra(const nsRect& aRect,
235 const nscoord* aRadii)
236 {
237 NS_ASSERTION(!mRestored, "Already restored!");
238 NS_ASSERTION(!mExtraClipUsed, "mExtraClip already used");
239 mExtraClipUsed = true;
240 mState.ClipContainingBlockDescendants(aRect, aRadii, mExtraClip);
241 }
243 protected:
244 DisplayItemClip mExtraClip;
245 DebugOnly<bool> mExtraClipUsed;
246 };
248 }
250 #endif /* DISPLAYLISTCLIPSTATE_H_ */