Coverage Report

Created: 2018-09-25 14:53

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