/work/obj-fuzz/dist/include/mozilla/layers/LayerMetricsWrapper.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 GFX_LAYERMETRICSWRAPPER_H |
8 | | #define GFX_LAYERMETRICSWRAPPER_H |
9 | | |
10 | | #include "Layers.h" |
11 | | #include "UnitTransforms.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace layers { |
15 | | |
16 | | /** |
17 | | * A wrapper class around a target Layer with that allows user code to |
18 | | * walk through the FrameMetrics objects on the layer the same way it |
19 | | * would walk through a ContainerLayer hierarchy. Consider the following |
20 | | * layer tree: |
21 | | * |
22 | | * +---+ |
23 | | * | A | |
24 | | * +---+ |
25 | | * / | \ |
26 | | * / | \ |
27 | | * / | \ |
28 | | * +---+ +-----+ +---+ |
29 | | * | B | | C | | D | |
30 | | * +---+ +-----+ +---+ |
31 | | * | FMn | |
32 | | * | . | |
33 | | * | . | |
34 | | * | . | |
35 | | * | FM1 | |
36 | | * | FM0 | |
37 | | * +-----+ |
38 | | * / \ |
39 | | * / \ |
40 | | * +---+ +---+ |
41 | | * | E | | F | |
42 | | * +---+ +---+ |
43 | | * |
44 | | * In this layer tree, there are six layers with A being the root and B,D,E,F |
45 | | * being leaf nodes. Layer C is in the middle and has n+1 FrameMetrics, labelled |
46 | | * FM0...FMn. FM0 is the FrameMetrics you get by calling c->GetFrameMetrics(0) |
47 | | * and FMn is the FrameMetrics you can obtain by calling |
48 | | * c->GetFrameMetrics(c->GetScrollMetadataCount() - 1). This layer tree is |
49 | | * conceptually equivalent to this one below: |
50 | | * |
51 | | * +---+ |
52 | | * | A | |
53 | | * +---+ |
54 | | * / | \ |
55 | | * / | \ |
56 | | * / | \ |
57 | | * +---+ +-----+ +---+ |
58 | | * | B | | Cn | | D | |
59 | | * +---+ +-----+ +---+ |
60 | | * | |
61 | | * . |
62 | | * . |
63 | | * . |
64 | | * | |
65 | | * +-----+ |
66 | | * | C1 | |
67 | | * +-----+ |
68 | | * | |
69 | | * +-----+ |
70 | | * | C0 | |
71 | | * +-----+ |
72 | | * / \ |
73 | | * / \ |
74 | | * +---+ +---+ |
75 | | * | E | | F | |
76 | | * +---+ +---+ |
77 | | * |
78 | | * In this layer tree, the layer C has been expanded into a stack of container |
79 | | * layers C1...Cn, where C1 has FrameMetrics FM1 and Cn has FrameMetrics Fn. |
80 | | * Although in this example C (in the first layer tree) and C0 (in the second |
81 | | * layer tree) are both ContainerLayers (because they have children), they |
82 | | * do not have to be. They may just be PaintedLayers or ColorLayers, for example, |
83 | | * which do not have any children. However, the type of C will always be the |
84 | | * same as the type of C0. |
85 | | * |
86 | | * The LayerMetricsWrapper class allows client code to treat the first layer |
87 | | * tree as though it were the second. That is, instead of client code having |
88 | | * to iterate through the FrameMetrics objects directly, it can use a |
89 | | * LayerMetricsWrapper to encapsulate that aspect of the layer tree and just |
90 | | * walk the tree as if it were a stack of ContainerLayers. |
91 | | * |
92 | | * The functions on this class do different things depending on which |
93 | | * simulated ContainerLayer is being wrapped. For example, if the |
94 | | * LayerMetricsWrapper is pretending to be C0, the GetNextSibling() function |
95 | | * will return null even though the underlying layer C does actually have |
96 | | * a next sibling. The LayerMetricsWrapper pretending to be Cn will return |
97 | | * D as the next sibling. |
98 | | * |
99 | | * Implementation notes: |
100 | | * |
101 | | * The AtTopLayer() and AtBottomLayer() functions in this class refer to |
102 | | * Cn and C0 in the second layer tree above; that is, they are predicates |
103 | | * to test if the LayerMetricsWrapper is simulating the topmost or bottommost |
104 | | * layer, as those will have special behaviour. |
105 | | * |
106 | | * It is possible to wrap a nullptr in a LayerMetricsWrapper, in which case |
107 | | * the IsValid() function will return false. This is required to allow |
108 | | * LayerMetricsWrapper to be a MOZ_STACK_CLASS (desirable because it is used |
109 | | * in loops and recursion). |
110 | | * |
111 | | * This class purposely does not expose the wrapped layer directly to avoid |
112 | | * user code from accidentally calling functions directly on it. Instead |
113 | | * any necessary functions should be wrapped in this class. It does expose |
114 | | * the wrapped layer as a void* for printf purposes. |
115 | | * |
116 | | * The implementation may look like it special-cases mIndex == 0 and/or |
117 | | * GetScrollMetadataCount() == 0. This is an artifact of the fact that both |
118 | | * mIndex and GetScrollMetadataCount() are uint32_t and GetScrollMetadataCount() |
119 | | * can return 0 but mIndex cannot store -1. This seems better than the |
120 | | * alternative of making mIndex a int32_t that can store -1, but then having |
121 | | * to cast to uint32_t all over the place. |
122 | | */ |
123 | | class MOZ_STACK_CLASS LayerMetricsWrapper { |
124 | | public: |
125 | | enum StartAt { |
126 | | TOP, |
127 | | BOTTOM, |
128 | | }; |
129 | | |
130 | | LayerMetricsWrapper() |
131 | | : mLayer(nullptr) |
132 | | , mIndex(0) |
133 | 0 | { |
134 | 0 | } |
135 | | |
136 | | explicit LayerMetricsWrapper(Layer* aRoot, StartAt aStart = StartAt::TOP) |
137 | | : mLayer(aRoot) |
138 | | , mIndex(0) |
139 | 0 | { |
140 | 0 | if (!mLayer) { |
141 | 0 | return; |
142 | 0 | } |
143 | 0 | |
144 | 0 | switch (aStart) { |
145 | 0 | case StartAt::TOP: |
146 | 0 | mIndex = mLayer->GetScrollMetadataCount(); |
147 | 0 | if (mIndex > 0) { |
148 | 0 | mIndex--; |
149 | 0 | } |
150 | 0 | break; |
151 | 0 | case StartAt::BOTTOM: |
152 | 0 | mIndex = 0; |
153 | 0 | break; |
154 | 0 | default: |
155 | 0 | MOZ_ASSERT_UNREACHABLE("Unknown startAt value"); |
156 | 0 | break; |
157 | 0 | } |
158 | 0 | } |
159 | | |
160 | | explicit LayerMetricsWrapper(Layer* aLayer, uint32_t aMetricsIndex) |
161 | | : mLayer(aLayer) |
162 | | , mIndex(aMetricsIndex) |
163 | 0 | { |
164 | 0 | MOZ_ASSERT(mLayer); |
165 | 0 | MOZ_ASSERT(mIndex == 0 || mIndex < mLayer->GetScrollMetadataCount()); |
166 | 0 | } |
167 | | |
168 | | bool IsValid() const |
169 | 0 | { |
170 | 0 | return mLayer != nullptr; |
171 | 0 | } |
172 | | |
173 | | explicit operator bool() const |
174 | 0 | { |
175 | 0 | return IsValid(); |
176 | 0 | } |
177 | | |
178 | | LayerMetricsWrapper GetParent() const |
179 | 0 | { |
180 | 0 | MOZ_ASSERT(IsValid()); |
181 | 0 |
|
182 | 0 | if (!AtTopLayer()) { |
183 | 0 | return LayerMetricsWrapper(mLayer, mIndex + 1); |
184 | 0 | } |
185 | 0 | if (mLayer->GetParent()) { |
186 | 0 | return LayerMetricsWrapper(mLayer->GetParent(), StartAt::BOTTOM); |
187 | 0 | } |
188 | 0 | return LayerMetricsWrapper(nullptr); |
189 | 0 | } |
190 | | |
191 | | LayerMetricsWrapper GetFirstChild() const |
192 | 0 | { |
193 | 0 | MOZ_ASSERT(IsValid()); |
194 | 0 |
|
195 | 0 | if (!AtBottomLayer()) { |
196 | 0 | return LayerMetricsWrapper(mLayer, mIndex - 1); |
197 | 0 | } |
198 | 0 | return LayerMetricsWrapper(mLayer->GetFirstChild()); |
199 | 0 | } |
200 | | |
201 | | LayerMetricsWrapper GetLastChild() const |
202 | 0 | { |
203 | 0 | MOZ_ASSERT(IsValid()); |
204 | 0 |
|
205 | 0 | if (!AtBottomLayer()) { |
206 | 0 | return LayerMetricsWrapper(mLayer, mIndex - 1); |
207 | 0 | } |
208 | 0 | return LayerMetricsWrapper(mLayer->GetLastChild()); |
209 | 0 | } |
210 | | |
211 | | LayerMetricsWrapper GetPrevSibling() const |
212 | 0 | { |
213 | 0 | MOZ_ASSERT(IsValid()); |
214 | 0 |
|
215 | 0 | if (AtTopLayer()) { |
216 | 0 | return LayerMetricsWrapper(mLayer->GetPrevSibling()); |
217 | 0 | } |
218 | 0 | return LayerMetricsWrapper(nullptr); |
219 | 0 | } |
220 | | |
221 | | LayerMetricsWrapper GetNextSibling() const |
222 | 0 | { |
223 | 0 | MOZ_ASSERT(IsValid()); |
224 | 0 |
|
225 | 0 | if (AtTopLayer()) { |
226 | 0 | return LayerMetricsWrapper(mLayer->GetNextSibling()); |
227 | 0 | } |
228 | 0 | return LayerMetricsWrapper(nullptr); |
229 | 0 | } |
230 | | |
231 | | const ScrollMetadata& Metadata() const |
232 | 0 | { |
233 | 0 | MOZ_ASSERT(IsValid()); |
234 | 0 |
|
235 | 0 | if (mIndex >= mLayer->GetScrollMetadataCount()) { |
236 | 0 | return *ScrollMetadata::sNullMetadata; |
237 | 0 | } |
238 | 0 | return mLayer->GetScrollMetadata(mIndex); |
239 | 0 | } |
240 | | |
241 | | const FrameMetrics& Metrics() const |
242 | 0 | { |
243 | 0 | return Metadata().GetMetrics(); |
244 | 0 | } |
245 | | |
246 | | AsyncPanZoomController* GetApzc() const |
247 | 0 | { |
248 | 0 | MOZ_ASSERT(IsValid()); |
249 | 0 |
|
250 | 0 | if (mIndex >= mLayer->GetScrollMetadataCount()) { |
251 | 0 | return nullptr; |
252 | 0 | } |
253 | 0 | return mLayer->GetAsyncPanZoomController(mIndex); |
254 | 0 | } |
255 | | |
256 | | void SetApzc(AsyncPanZoomController* aApzc) const |
257 | 0 | { |
258 | 0 | MOZ_ASSERT(IsValid()); |
259 | 0 |
|
260 | 0 | if (mLayer->GetScrollMetadataCount() == 0) { |
261 | 0 | MOZ_ASSERT(mIndex == 0); |
262 | 0 | MOZ_ASSERT(aApzc == nullptr); |
263 | 0 | return; |
264 | 0 | } |
265 | 0 | MOZ_ASSERT(mIndex < mLayer->GetScrollMetadataCount()); |
266 | 0 | mLayer->SetAsyncPanZoomController(mIndex, aApzc); |
267 | 0 | } |
268 | | |
269 | | const char* Name() const |
270 | 0 | { |
271 | 0 | MOZ_ASSERT(IsValid()); |
272 | 0 |
|
273 | 0 | if (AtBottomLayer()) { |
274 | 0 | return mLayer->Name(); |
275 | 0 | } |
276 | 0 | return "DummyContainerLayer"; |
277 | 0 | } |
278 | | |
279 | | LayerManager* Manager() const |
280 | 0 | { |
281 | 0 | MOZ_ASSERT(IsValid()); |
282 | 0 |
|
283 | 0 | return mLayer->Manager(); |
284 | 0 | } |
285 | | |
286 | | gfx::Matrix4x4 GetTransform() const |
287 | 0 | { |
288 | 0 | MOZ_ASSERT(IsValid()); |
289 | 0 |
|
290 | 0 | if (AtBottomLayer()) { |
291 | 0 | return mLayer->GetTransform(); |
292 | 0 | } |
293 | 0 | return gfx::Matrix4x4(); |
294 | 0 | } |
295 | | |
296 | | CSSTransformMatrix GetTransformTyped() const |
297 | 0 | { |
298 | 0 | return ViewAs<CSSTransformMatrix>(GetTransform()); |
299 | 0 | } |
300 | | |
301 | | bool TransformIsPerspective() const |
302 | 0 | { |
303 | 0 | MOZ_ASSERT(IsValid()); |
304 | 0 |
|
305 | 0 | // mLayer->GetTransformIsPerspective() tells us whether |
306 | 0 | // mLayer->GetTransform() is a perspective transform. Since |
307 | 0 | // mLayer->GetTransform() is only used at the bottom layer, we only |
308 | 0 | // need to check GetTransformIsPerspective() at the bottom layer too. |
309 | 0 | if (AtBottomLayer()) { |
310 | 0 | return mLayer->GetTransformIsPerspective(); |
311 | 0 | } |
312 | 0 | return false; |
313 | 0 | } |
314 | | |
315 | | EventRegions GetEventRegions() const |
316 | 0 | { |
317 | 0 | MOZ_ASSERT(IsValid()); |
318 | 0 |
|
319 | 0 | if (AtBottomLayer()) { |
320 | 0 | return mLayer->GetEventRegions(); |
321 | 0 | } |
322 | 0 | return EventRegions(); |
323 | 0 | } |
324 | | |
325 | | LayerIntRegion GetVisibleRegion() const |
326 | 0 | { |
327 | 0 | MOZ_ASSERT(IsValid()); |
328 | 0 |
|
329 | 0 | if (AtBottomLayer()) { |
330 | 0 | return mLayer->GetVisibleRegion(); |
331 | 0 | } |
332 | 0 | |
333 | 0 | return ViewAs<LayerPixel>( |
334 | 0 | TransformBy(mLayer->GetTransformTyped(), mLayer->GetVisibleRegion()), |
335 | 0 | PixelCastJustification::MovingDownToChildren); |
336 | 0 | } |
337 | | |
338 | | bool HasTransformAnimation() const |
339 | 0 | { |
340 | 0 | MOZ_ASSERT(IsValid()); |
341 | 0 |
|
342 | 0 | if (AtBottomLayer()) { |
343 | 0 | return mLayer->HasTransformAnimation(); |
344 | 0 | } |
345 | 0 | return false; |
346 | 0 | } |
347 | | |
348 | | RefLayer* AsRefLayer() const |
349 | 0 | { |
350 | 0 | MOZ_ASSERT(IsValid()); |
351 | 0 |
|
352 | 0 | if (AtBottomLayer()) { |
353 | 0 | return mLayer->AsRefLayer(); |
354 | 0 | } |
355 | 0 | return nullptr; |
356 | 0 | } |
357 | | |
358 | | Maybe<LayersId> GetReferentId() const |
359 | 0 | { |
360 | 0 | MOZ_ASSERT(IsValid()); |
361 | 0 |
|
362 | 0 | if (AtBottomLayer()) { |
363 | 0 | return mLayer->AsRefLayer() |
364 | 0 | ? Some(mLayer->AsRefLayer()->GetReferentId()) |
365 | 0 | : Nothing(); |
366 | 0 | } |
367 | 0 | return Nothing(); |
368 | 0 | } |
369 | | |
370 | | Maybe<ParentLayerIntRect> GetClipRect() const |
371 | 0 | { |
372 | 0 | MOZ_ASSERT(IsValid()); |
373 | 0 |
|
374 | 0 | Maybe<ParentLayerIntRect> result; |
375 | 0 |
|
376 | 0 | // The layer can have a clip rect and a scrolled clip, which are considered |
377 | 0 | // to apply only to the bottommost LayerMetricsWrapper. |
378 | 0 | // TODO: These actually apply in a different coordinate space than the |
379 | 0 | // scroll clip of the bottommost metrics, so we shouldn't be intersecting |
380 | 0 | // them with the scroll clip; bug 1269537 tracks fixing this. |
381 | 0 | if (AtBottomLayer()) { |
382 | 0 | result = mLayer->GetClipRect(); |
383 | 0 | result = IntersectMaybeRects(result, mLayer->GetScrolledClipRect()); |
384 | 0 | } |
385 | 0 |
|
386 | 0 | // The scroll metadata can have a clip rect as well. |
387 | 0 | result = IntersectMaybeRects(result, Metadata().GetClipRect()); |
388 | 0 |
|
389 | 0 | return result; |
390 | 0 | } |
391 | | |
392 | | float GetPresShellResolution() const |
393 | 0 | { |
394 | 0 | MOZ_ASSERT(IsValid()); |
395 | 0 |
|
396 | 0 | if (AtTopLayer() && mLayer->AsContainerLayer()) { |
397 | 0 | return mLayer->AsContainerLayer()->GetPresShellResolution(); |
398 | 0 | } |
399 | 0 | |
400 | 0 | return 1.0f; |
401 | 0 | } |
402 | | |
403 | | EventRegionsOverride GetEventRegionsOverride() const |
404 | 0 | { |
405 | 0 | MOZ_ASSERT(IsValid()); |
406 | 0 |
|
407 | 0 | if (mLayer->AsRefLayer()) { |
408 | 0 | return mLayer->AsRefLayer()->GetEventRegionsOverride(); |
409 | 0 | } |
410 | 0 | return EventRegionsOverride::NoOverride; |
411 | 0 | } |
412 | | |
413 | | const ScrollbarData& GetScrollbarData() const |
414 | 0 | { |
415 | 0 | MOZ_ASSERT(IsValid()); |
416 | 0 |
|
417 | 0 | return mLayer->GetScrollbarData(); |
418 | 0 | } |
419 | | |
420 | | uint64_t GetScrollbarAnimationId() const |
421 | 0 | { |
422 | 0 | MOZ_ASSERT(IsValid()); |
423 | 0 | // This function is only really needed for template-compatibility with |
424 | 0 | // WebRenderScrollDataWrapper. Although it will be called, the return |
425 | 0 | // value is not used. |
426 | 0 | return 0; |
427 | 0 | } |
428 | | |
429 | | FrameMetrics::ViewID GetFixedPositionScrollContainerId() const |
430 | 0 | { |
431 | 0 | MOZ_ASSERT(IsValid()); |
432 | 0 |
|
433 | 0 | return mLayer->GetFixedPositionScrollContainerId(); |
434 | 0 | } |
435 | | |
436 | | bool IsBackfaceHidden() const |
437 | 0 | { |
438 | 0 | MOZ_ASSERT(IsValid()); |
439 | 0 |
|
440 | 0 | return mLayer->IsBackfaceHidden(); |
441 | 0 | } |
442 | | |
443 | | // Expose an opaque pointer to the layer. Mostly used for printf |
444 | | // purposes. This is not intended to be a general-purpose accessor |
445 | | // for the underlying layer. |
446 | | const void* GetLayer() const |
447 | 0 | { |
448 | 0 | MOZ_ASSERT(IsValid()); |
449 | 0 |
|
450 | 0 | return (void*)mLayer; |
451 | 0 | } |
452 | | |
453 | | bool operator==(const LayerMetricsWrapper& aOther) const |
454 | 0 | { |
455 | 0 | return mLayer == aOther.mLayer |
456 | 0 | && mIndex == aOther.mIndex; |
457 | 0 | } |
458 | | |
459 | | bool operator!=(const LayerMetricsWrapper& aOther) const |
460 | 0 | { |
461 | 0 | return !(*this == aOther); |
462 | 0 | } |
463 | | |
464 | | private: |
465 | | bool AtBottomLayer() const |
466 | 0 | { |
467 | 0 | return mIndex == 0; |
468 | 0 | } |
469 | | |
470 | | bool AtTopLayer() const |
471 | 0 | { |
472 | 0 | return mLayer->GetScrollMetadataCount() == 0 || mIndex == mLayer->GetScrollMetadataCount() - 1; |
473 | 0 | } |
474 | | |
475 | | private: |
476 | | Layer* mLayer; |
477 | | uint32_t mIndex; |
478 | | }; |
479 | | |
480 | | } // namespace layers |
481 | | } // namespace mozilla |
482 | | |
483 | | #endif /* GFX_LAYERMETRICSWRAPPER_H */ |