|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
|
2 * vim: set ts=2 sw=2 et tw=78: |
|
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 |
|
8 /* |
|
9 * structures that represent things to be painted (ordered in z-order), |
|
10 * used during painting and hit testing |
|
11 */ |
|
12 |
|
13 #ifndef NSDISPLAYLIST_H_ |
|
14 #define NSDISPLAYLIST_H_ |
|
15 |
|
16 #include "mozilla/Attributes.h" |
|
17 #include "nsCOMPtr.h" |
|
18 #include "nsIFrame.h" |
|
19 #include "nsPoint.h" |
|
20 #include "nsRect.h" |
|
21 #include "nsCaret.h" |
|
22 #include "plarena.h" |
|
23 #include "nsRegion.h" |
|
24 #include "FrameLayerBuilder.h" |
|
25 #include "nsLayoutUtils.h" |
|
26 #include "nsDisplayListInvalidation.h" |
|
27 #include "DisplayListClipState.h" |
|
28 |
|
29 #include <stdint.h> |
|
30 |
|
31 #include <stdlib.h> |
|
32 #include <algorithm> |
|
33 |
|
34 class nsIContent; |
|
35 class nsRenderingContext; |
|
36 class nsDisplayTableItem; |
|
37 class nsISelection; |
|
38 class nsDisplayLayerEventRegions; |
|
39 |
|
40 namespace mozilla { |
|
41 namespace layers { |
|
42 class Layer; |
|
43 class ImageLayer; |
|
44 class ImageContainer; |
|
45 } //namepsace |
|
46 } //namepsace |
|
47 |
|
48 /* |
|
49 * An nsIFrame can have many different visual parts. For example an image frame |
|
50 * can have a background, border, and outline, the image itself, and a |
|
51 * translucent selection overlay. In general these parts can be drawn at |
|
52 * discontiguous z-levels; see CSS2.1 appendix E: |
|
53 * http://www.w3.org/TR/CSS21/zindex.html |
|
54 * |
|
55 * We construct a display list for a frame tree that contains one item |
|
56 * for each visual part. The display list is itself a tree since some items |
|
57 * are containers for other items; however, its structure does not match |
|
58 * the structure of its source frame tree. The display list items are sorted |
|
59 * by z-order. A display list can be used to paint the frames, to determine |
|
60 * which frame is the target of a mouse event, and to determine what areas |
|
61 * need to be repainted when scrolling. The display lists built for each task |
|
62 * may be different for efficiency; in particular some frames need special |
|
63 * display list items only for event handling, and do not create these items |
|
64 * when the display list will be used for painting (the common case). For |
|
65 * example, when painting we avoid creating nsDisplayBackground items for |
|
66 * frames that don't display a visible background, but for event handling |
|
67 * we need those backgrounds because they are not transparent to events. |
|
68 * |
|
69 * We could avoid constructing an explicit display list by traversing the |
|
70 * frame tree multiple times in clever ways. However, reifying the display list |
|
71 * reduces code complexity and reduces the number of times each frame must be |
|
72 * traversed to one, which seems to be good for performance. It also means |
|
73 * we can share code for painting, event handling and scroll analysis. |
|
74 * |
|
75 * Display lists are short-lived; content and frame trees cannot change |
|
76 * between a display list being created and destroyed. Display lists should |
|
77 * not be created during reflow because the frame tree may be in an |
|
78 * inconsistent state (e.g., a frame's stored overflow-area may not include |
|
79 * the bounds of all its children). However, it should be fine to create |
|
80 * a display list while a reflow is pending, before it starts. |
|
81 * |
|
82 * A display list covers the "extended" frame tree; the display list for a frame |
|
83 * tree containing FRAME/IFRAME elements can include frames from the subdocuments. |
|
84 * |
|
85 * Display item's coordinates are relative to their nearest reference frame ancestor. |
|
86 * Both the display root and any frame with a transform act as a reference frame |
|
87 * for their frame subtrees. |
|
88 */ |
|
89 |
|
90 // All types are defined in nsDisplayItemTypes.h |
|
91 #ifdef MOZ_DUMP_PAINTING |
|
92 #define NS_DISPLAY_DECL_NAME(n, e) \ |
|
93 virtual const char* Name() { return n; } \ |
|
94 virtual Type GetType() { return e; } |
|
95 #else |
|
96 #define NS_DISPLAY_DECL_NAME(n, e) \ |
|
97 virtual Type GetType() { return e; } |
|
98 #endif |
|
99 |
|
100 /** |
|
101 * This manages a display list and is passed as a parameter to |
|
102 * nsIFrame::BuildDisplayList. |
|
103 * It contains the parameters that don't change from frame to frame and manages |
|
104 * the display list memory using a PLArena. It also establishes the reference |
|
105 * coordinate system for all display list items. Some of the parameters are |
|
106 * available from the prescontext/presshell, but we copy them into the builder |
|
107 * for faster/more convenient access. |
|
108 */ |
|
109 class nsDisplayListBuilder { |
|
110 public: |
|
111 typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor; |
|
112 typedef mozilla::FrameLayerBuilder FrameLayerBuilder; |
|
113 typedef mozilla::DisplayItemClip DisplayItemClip; |
|
114 typedef mozilla::DisplayListClipState DisplayListClipState; |
|
115 typedef nsIWidget::ThemeGeometry ThemeGeometry; |
|
116 typedef mozilla::layers::Layer Layer; |
|
117 typedef mozilla::layers::FrameMetrics::ViewID ViewID; |
|
118 |
|
119 /** |
|
120 * @param aReferenceFrame the frame at the root of the subtree; its origin |
|
121 * is the origin of the reference coordinate system for this display list |
|
122 * @param aIsForEvents true if we're creating this list in order to |
|
123 * determine which frame is under the mouse position |
|
124 * @param aBuildCaret whether or not we should include the caret in any |
|
125 * display lists that we make. |
|
126 */ |
|
127 enum Mode { |
|
128 PAINTING, |
|
129 EVENT_DELIVERY, |
|
130 PLUGIN_GEOMETRY, |
|
131 IMAGE_VISIBILITY, |
|
132 OTHER |
|
133 }; |
|
134 nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, bool aBuildCaret); |
|
135 ~nsDisplayListBuilder(); |
|
136 |
|
137 void SetWillComputePluginGeometry(bool aWillComputePluginGeometry) |
|
138 { |
|
139 mWillComputePluginGeometry = aWillComputePluginGeometry; |
|
140 } |
|
141 void SetForPluginGeometry() |
|
142 { |
|
143 NS_ASSERTION(mMode == PAINTING, "Can only switch from PAINTING to PLUGIN_GEOMETRY"); |
|
144 NS_ASSERTION(mWillComputePluginGeometry, "Should have signalled this in advance"); |
|
145 mMode = PLUGIN_GEOMETRY; |
|
146 } |
|
147 |
|
148 /** |
|
149 * @return true if the display is being built in order to determine which |
|
150 * frame is under the mouse position. |
|
151 */ |
|
152 bool IsForEventDelivery() { return mMode == EVENT_DELIVERY; } |
|
153 /** |
|
154 * Be careful with this. The display list will be built in PAINTING mode |
|
155 * first and then switched to PLUGIN_GEOMETRY before a second call to |
|
156 * ComputeVisibility. |
|
157 * @return true if the display list is being built to compute geometry |
|
158 * for plugins. |
|
159 */ |
|
160 bool IsForPluginGeometry() { return mMode == PLUGIN_GEOMETRY; } |
|
161 /** |
|
162 * @return true if the display list is being built for painting. |
|
163 */ |
|
164 bool IsForPainting() { return mMode == PAINTING; } |
|
165 /** |
|
166 * @return true if the display list is being built for determining image |
|
167 * visibility. |
|
168 */ |
|
169 bool IsForImageVisibility() { return mMode == IMAGE_VISIBILITY; } |
|
170 bool WillComputePluginGeometry() { return mWillComputePluginGeometry; } |
|
171 /** |
|
172 * @return true if "painting is suppressed" during page load and we |
|
173 * should paint only the background of the document. |
|
174 */ |
|
175 bool IsBackgroundOnly() { |
|
176 NS_ASSERTION(mPresShellStates.Length() > 0, |
|
177 "don't call this if we're not in a presshell"); |
|
178 return CurrentPresShellState()->mIsBackgroundOnly; |
|
179 } |
|
180 /** |
|
181 * @return true if the currently active BuildDisplayList call is being |
|
182 * applied to a frame at the root of a pseudo stacking context. A pseudo |
|
183 * stacking context is either a real stacking context or basically what |
|
184 * CSS2.1 appendix E refers to with "treat the element as if it created |
|
185 * a new stacking context |
|
186 */ |
|
187 bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; } |
|
188 |
|
189 /** |
|
190 * @return the selection that painting should be restricted to (or nullptr |
|
191 * in the normal unrestricted case) |
|
192 */ |
|
193 nsISelection* GetBoundingSelection() { return mBoundingSelection; } |
|
194 |
|
195 /** |
|
196 * @return the root of given frame's (sub)tree, whose origin |
|
197 * establishes the coordinate system for the child display items. |
|
198 */ |
|
199 const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame) |
|
200 { |
|
201 if (aFrame == mCachedOffsetFrame) { |
|
202 return mCachedReferenceFrame; |
|
203 } |
|
204 for (const nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) |
|
205 { |
|
206 if (f == mReferenceFrame || f->IsTransformed()) { |
|
207 mCachedOffsetFrame = aFrame; |
|
208 mCachedReferenceFrame = f; |
|
209 mCachedOffset = aFrame->GetOffsetToCrossDoc(f); |
|
210 return f; |
|
211 } |
|
212 } |
|
213 mCachedOffsetFrame = aFrame; |
|
214 mCachedReferenceFrame = mReferenceFrame; |
|
215 mCachedOffset = aFrame->GetOffsetToCrossDoc(mReferenceFrame); |
|
216 return mReferenceFrame; |
|
217 } |
|
218 |
|
219 /** |
|
220 * @return the root of the display list's frame (sub)tree, whose origin |
|
221 * establishes the coordinate system for the display list |
|
222 */ |
|
223 nsIFrame* RootReferenceFrame() |
|
224 { |
|
225 return mReferenceFrame; |
|
226 } |
|
227 |
|
228 /** |
|
229 * @return a point pt such that adding pt to a coordinate relative to aFrame |
|
230 * makes it relative to ReferenceFrame(), i.e., returns |
|
231 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in |
|
232 * the appunits of aFrame. It may be optimized to be faster than |
|
233 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()) (but currently isn't). |
|
234 */ |
|
235 const nsPoint& ToReferenceFrame(const nsIFrame* aFrame) { |
|
236 if (aFrame != mCachedOffsetFrame) { |
|
237 FindReferenceFrameFor(aFrame); |
|
238 } |
|
239 return mCachedOffset; |
|
240 } |
|
241 /** |
|
242 * When building the display list, the scrollframe aFrame will be "ignored" |
|
243 * for the purposes of clipping, and its scrollbars will be hidden. We use |
|
244 * this to allow RenderOffscreen to render a whole document without beign |
|
245 * clipped by the viewport or drawing the viewport scrollbars. |
|
246 */ |
|
247 void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; } |
|
248 /** |
|
249 * Get the scrollframe to ignore, if any. |
|
250 */ |
|
251 nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; } |
|
252 /** |
|
253 * Get the ViewID of the nearest scrolling ancestor frame. |
|
254 */ |
|
255 ViewID GetCurrentScrollParentId() const { return mCurrentScrollParentId; } |
|
256 /** |
|
257 * Calling this setter makes us include all out-of-flow descendant |
|
258 * frames in the display list, wherever they may be positioned (even |
|
259 * outside the dirty rects). |
|
260 */ |
|
261 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; } |
|
262 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; } |
|
263 /** |
|
264 * Calling this setter makes us exclude all leaf frames that aren't |
|
265 * selected. |
|
266 */ |
|
267 void SetSelectedFramesOnly() { mSelectedFramesOnly = true; } |
|
268 bool GetSelectedFramesOnly() { return mSelectedFramesOnly; } |
|
269 /** |
|
270 * Calling this setter makes us compute accurate visible regions at the cost |
|
271 * of performance if regions get very complex. |
|
272 */ |
|
273 void SetAccurateVisibleRegions() { mAccurateVisibleRegions = true; } |
|
274 bool GetAccurateVisibleRegions() { return mAccurateVisibleRegions; } |
|
275 /** |
|
276 * Allows callers to selectively override the regular paint suppression checks, |
|
277 * so that methods like GetFrameForPoint work when painting is suppressed. |
|
278 */ |
|
279 void IgnorePaintSuppression() { mIgnoreSuppression = true; } |
|
280 /** |
|
281 * @return Returns if this builder will ignore paint suppression. |
|
282 */ |
|
283 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; } |
|
284 /** |
|
285 * @return Returns if this builder had to ignore painting suppression on some |
|
286 * document when building the display list. |
|
287 */ |
|
288 bool GetHadToIgnorePaintSuppression() { return mHadToIgnoreSuppression; } |
|
289 /** |
|
290 * Call this if we're doing normal painting to the window. |
|
291 */ |
|
292 void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; } |
|
293 bool IsPaintingToWindow() const { return mIsPaintingToWindow; } |
|
294 /** |
|
295 * Call this to prevent descending into subdocuments. |
|
296 */ |
|
297 void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; } |
|
298 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; } |
|
299 |
|
300 /** |
|
301 * Returns true if merging and flattening of display lists should be |
|
302 * performed while computing visibility. |
|
303 */ |
|
304 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; } |
|
305 void SetAllowMergingAndFlattening(bool aAllow) { mAllowMergingAndFlattening = aAllow; } |
|
306 |
|
307 nsDisplayLayerEventRegions* GetLayerEventRegions() { return mLayerEventRegions; } |
|
308 void SetLayerEventRegions(nsDisplayLayerEventRegions* aItem) |
|
309 { |
|
310 mLayerEventRegions = aItem; |
|
311 } |
|
312 bool IsBuildingLayerEventRegions() |
|
313 { |
|
314 // Disable for now. |
|
315 return false; |
|
316 // return mMode == PAINTING; |
|
317 } |
|
318 |
|
319 bool GetAncestorHasTouchEventHandler() { return mAncestorHasTouchEventHandler; } |
|
320 void SetAncestorHasTouchEventHandler(bool aValue) |
|
321 { |
|
322 mAncestorHasTouchEventHandler = aValue; |
|
323 } |
|
324 |
|
325 bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; } |
|
326 void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; } |
|
327 |
|
328 bool SetIsCompositingCheap(bool aCompositingCheap) { |
|
329 bool temp = mIsCompositingCheap; |
|
330 mIsCompositingCheap = aCompositingCheap; |
|
331 return temp; |
|
332 } |
|
333 bool IsCompositingCheap() const { return mIsCompositingCheap; } |
|
334 /** |
|
335 * Display the caret if needed. |
|
336 */ |
|
337 void DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect, |
|
338 nsDisplayList* aList) { |
|
339 nsIFrame* frame = GetCaretFrame(); |
|
340 if (aFrame == frame) { |
|
341 frame->DisplayCaret(this, aDirtyRect, aList); |
|
342 } |
|
343 } |
|
344 /** |
|
345 * Get the frame that the caret is supposed to draw in. |
|
346 * If the caret is currently invisible, this will be null. |
|
347 */ |
|
348 nsIFrame* GetCaretFrame() { |
|
349 return CurrentPresShellState()->mCaretFrame; |
|
350 } |
|
351 /** |
|
352 * Get the caret associated with the current presshell. |
|
353 */ |
|
354 nsCaret* GetCaret(); |
|
355 /** |
|
356 * Notify the display list builder that we're entering a presshell. |
|
357 * aReferenceFrame should be a frame in the new presshell and aDirtyRect |
|
358 * should be the current dirty rect in aReferenceFrame's coordinate space. |
|
359 */ |
|
360 void EnterPresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect); |
|
361 /** |
|
362 * For print-preview documents, we sometimes need to build display items for |
|
363 * the same frames multiple times in the same presentation, with different |
|
364 * clipping. Between each such batch of items, call |
|
365 * ResetMarkedFramesForDisplayList to make sure that the results of |
|
366 * MarkFramesForDisplayList do not carry over between batches. |
|
367 */ |
|
368 void ResetMarkedFramesForDisplayList(); |
|
369 /** |
|
370 * Notify the display list builder that we're leaving a presshell. |
|
371 */ |
|
372 void LeavePresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect); |
|
373 |
|
374 /** |
|
375 * Returns true if we're currently building a display list that's |
|
376 * directly or indirectly under an nsDisplayTransform. |
|
377 */ |
|
378 bool IsInTransform() const { return mInTransform; } |
|
379 /** |
|
380 * Indicate whether or not we're directly or indirectly under and |
|
381 * nsDisplayTransform or SVG foreignObject. |
|
382 */ |
|
383 void SetInTransform(bool aInTransform) { mInTransform = aInTransform; } |
|
384 |
|
385 /** |
|
386 * Returns true if we're currently building display items that are in |
|
387 * true fixed position subtree. |
|
388 */ |
|
389 bool IsInFixedPos() const { return mInFixedPos; } |
|
390 |
|
391 /** |
|
392 * @return true if images have been set to decode synchronously. |
|
393 */ |
|
394 bool ShouldSyncDecodeImages() { return mSyncDecodeImages; } |
|
395 |
|
396 /** |
|
397 * Indicates whether we should synchronously decode images. If true, we decode |
|
398 * and draw whatever image data has been loaded. If false, we just draw |
|
399 * whatever has already been decoded. |
|
400 */ |
|
401 void SetSyncDecodeImages(bool aSyncDecodeImages) { |
|
402 mSyncDecodeImages = aSyncDecodeImages; |
|
403 } |
|
404 |
|
405 /** |
|
406 * Helper method to generate background painting flags based on the |
|
407 * information available in the display list builder. Currently only |
|
408 * accounts for mSyncDecodeImages. |
|
409 */ |
|
410 uint32_t GetBackgroundPaintFlags(); |
|
411 |
|
412 /** |
|
413 * Subtracts aRegion from *aVisibleRegion. We avoid letting |
|
414 * aVisibleRegion become overcomplex by simplifying it if necessary --- |
|
415 * unless mAccurateVisibleRegions is set, in which case we let it |
|
416 * get arbitrarily complex. |
|
417 */ |
|
418 void SubtractFromVisibleRegion(nsRegion* aVisibleRegion, |
|
419 const nsRegion& aRegion); |
|
420 |
|
421 /** |
|
422 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect |
|
423 * (which is relative to aDirtyFrame). If the frames have placeholders |
|
424 * that might not be displayed, we mark the placeholders and their ancestors |
|
425 * to ensure that display list construction descends into them |
|
426 * anyway. nsDisplayListBuilder will take care of unmarking them when it is |
|
427 * destroyed. |
|
428 */ |
|
429 void MarkFramesForDisplayList(nsIFrame* aDirtyFrame, |
|
430 const nsFrameList& aFrames, |
|
431 const nsRect& aDirtyRect); |
|
432 /** |
|
433 * Mark all child frames that Preserve3D() as needing display. |
|
434 * Because these frames include transforms set on their parent, dirty rects |
|
435 * for intermediate frames may be empty, yet child frames could still be visible. |
|
436 */ |
|
437 void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect); |
|
438 |
|
439 /** |
|
440 * Get the area of the final transparent region. |
|
441 */ |
|
442 const nsRegion* GetFinalTransparentRegion() { return mFinalTransparentRegion; } |
|
443 /** |
|
444 * Record the area of the final transparent region after all visibility |
|
445 * calculations were performed. |
|
446 */ |
|
447 void SetFinalTransparentRegion(const nsRegion& aFinalTransparentRegion) |
|
448 { |
|
449 mFinalTransparentRegion = &aFinalTransparentRegion; |
|
450 } |
|
451 |
|
452 const nsTArray<ThemeGeometry>& GetThemeGeometries() { return mThemeGeometries; } |
|
453 |
|
454 /** |
|
455 * Returns true if we need to descend into this frame when building |
|
456 * the display list, even though it doesn't intersect the dirty |
|
457 * rect, because it may have out-of-flows that do so. |
|
458 */ |
|
459 bool ShouldDescendIntoFrame(nsIFrame* aFrame) const { |
|
460 return |
|
461 (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) || |
|
462 GetIncludeAllOutOfFlows(); |
|
463 } |
|
464 |
|
465 /** |
|
466 * Notifies the builder that a particular themed widget exists |
|
467 * at the given rectangle within the currently built display list. |
|
468 * For certain appearance values (currently only |
|
469 * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR, NS_THEME_TOOLBAR and |
|
470 * NS_THEME_WINDOW_TITLEBAR) this gets called during every display list |
|
471 * construction, for every themed widget of the right type within the |
|
472 * display list, except for themed widgets which are transformed or have |
|
473 * effects applied to them (e.g. CSS opacity or filters). |
|
474 * |
|
475 * @param aWidgetType the -moz-appearance value for the themed widget |
|
476 * @param aRect the device-pixel rect relative to the widget's displayRoot |
|
477 * for the themed widget |
|
478 */ |
|
479 void RegisterThemeGeometry(uint8_t aWidgetType, |
|
480 const nsIntRect& aRect) { |
|
481 if (mIsPaintingToWindow && mPresShellStates.Length() == 1) { |
|
482 ThemeGeometry geometry(aWidgetType, aRect); |
|
483 mThemeGeometries.AppendElement(geometry); |
|
484 } |
|
485 } |
|
486 |
|
487 /** |
|
488 * Allocate memory in our arena. It will only be freed when this display list |
|
489 * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem |
|
490 * destructors are called as soon as the item is no longer used. |
|
491 */ |
|
492 void* Allocate(size_t aSize); |
|
493 |
|
494 /** |
|
495 * Allocate a new DisplayListClip in the arena. Will be cleaned up |
|
496 * automatically when the arena goes away. |
|
497 */ |
|
498 const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal); |
|
499 |
|
500 /** |
|
501 * Transfer off main thread animations to the layer. May be called |
|
502 * with aBuilder and aItem both null, but only if the caller has |
|
503 * already checked that off main thread animations should be sent to |
|
504 * the layer. When they are both null, the animations are added to |
|
505 * the layer as pending animations. |
|
506 */ |
|
507 static void AddAnimationsAndTransitionsToLayer(Layer* aLayer, |
|
508 nsDisplayListBuilder* aBuilder, |
|
509 nsDisplayItem* aItem, |
|
510 nsIFrame* aFrame, |
|
511 nsCSSProperty aProperty); |
|
512 /** |
|
513 * A helper class to temporarily set the value of |
|
514 * mIsAtRootOfPseudoStackingContext, and temporarily |
|
515 * update mCachedOffsetFrame/mCachedOffset from a frame to its child. |
|
516 * Also saves and restores mClipState. |
|
517 */ |
|
518 class AutoBuildingDisplayList; |
|
519 friend class AutoBuildingDisplayList; |
|
520 class AutoBuildingDisplayList { |
|
521 public: |
|
522 AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, bool aIsRoot) |
|
523 : mBuilder(aBuilder), |
|
524 mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame), |
|
525 mPrevCachedReferenceFrame(aBuilder->mCachedReferenceFrame), |
|
526 mPrevLayerEventRegions(aBuilder->mLayerEventRegions), |
|
527 mPrevCachedOffset(aBuilder->mCachedOffset), |
|
528 mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext), |
|
529 mPrevAncestorHasTouchEventHandler(aBuilder->mAncestorHasTouchEventHandler) |
|
530 { |
|
531 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot; |
|
532 } |
|
533 AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, |
|
534 nsIFrame* aForChild, bool aIsRoot) |
|
535 : mBuilder(aBuilder), |
|
536 mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame), |
|
537 mPrevCachedReferenceFrame(aBuilder->mCachedReferenceFrame), |
|
538 mPrevLayerEventRegions(aBuilder->mLayerEventRegions), |
|
539 mPrevCachedOffset(aBuilder->mCachedOffset), |
|
540 mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext), |
|
541 mPrevAncestorHasTouchEventHandler(aBuilder->mAncestorHasTouchEventHandler) |
|
542 { |
|
543 if (aForChild->IsTransformed()) { |
|
544 aBuilder->mCachedOffset = nsPoint(); |
|
545 aBuilder->mCachedReferenceFrame = aForChild; |
|
546 } else if (mPrevCachedOffsetFrame == aForChild->GetParent()) { |
|
547 aBuilder->mCachedOffset += aForChild->GetPosition(); |
|
548 } else { |
|
549 aBuilder->mCachedOffset = aBuilder->ToReferenceFrame(aForChild); |
|
550 } |
|
551 aBuilder->mCachedOffsetFrame = aForChild; |
|
552 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot; |
|
553 } |
|
554 ~AutoBuildingDisplayList() { |
|
555 mBuilder->mCachedOffsetFrame = mPrevCachedOffsetFrame; |
|
556 mBuilder->mCachedReferenceFrame = mPrevCachedReferenceFrame; |
|
557 mBuilder->mLayerEventRegions = mPrevLayerEventRegions; |
|
558 mBuilder->mCachedOffset = mPrevCachedOffset; |
|
559 mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext; |
|
560 mBuilder->mAncestorHasTouchEventHandler = mPrevAncestorHasTouchEventHandler; |
|
561 } |
|
562 private: |
|
563 nsDisplayListBuilder* mBuilder; |
|
564 const nsIFrame* mPrevCachedOffsetFrame; |
|
565 const nsIFrame* mPrevCachedReferenceFrame; |
|
566 nsDisplayLayerEventRegions* mPrevLayerEventRegions; |
|
567 nsPoint mPrevCachedOffset; |
|
568 bool mPrevIsAtRootOfPseudoStackingContext; |
|
569 bool mPrevAncestorHasTouchEventHandler; |
|
570 }; |
|
571 |
|
572 /** |
|
573 * A helper class to temporarily set the value of mInTransform. |
|
574 */ |
|
575 class AutoInTransformSetter; |
|
576 friend class AutoInTransformSetter; |
|
577 class AutoInTransformSetter { |
|
578 public: |
|
579 AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform) |
|
580 : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) { |
|
581 aBuilder->mInTransform = aInTransform; |
|
582 } |
|
583 ~AutoInTransformSetter() { |
|
584 mBuilder->mInTransform = mOldValue; |
|
585 } |
|
586 private: |
|
587 nsDisplayListBuilder* mBuilder; |
|
588 bool mOldValue; |
|
589 }; |
|
590 |
|
591 /** |
|
592 * A helper class to temporarily set the value of mInFixedPos. |
|
593 */ |
|
594 class AutoInFixedPosSetter; |
|
595 friend class AutoInFixedPosSetter; |
|
596 class AutoInFixedPosSetter { |
|
597 public: |
|
598 AutoInFixedPosSetter(nsDisplayListBuilder* aBuilder, bool aInFixedPos) |
|
599 : mBuilder(aBuilder), mOldValue(aBuilder->mInFixedPos) { |
|
600 aBuilder->mInFixedPos = aInFixedPos; |
|
601 } |
|
602 ~AutoInFixedPosSetter() { |
|
603 mBuilder->mInFixedPos = mOldValue; |
|
604 } |
|
605 private: |
|
606 nsDisplayListBuilder* mBuilder; |
|
607 bool mOldValue; |
|
608 }; |
|
609 |
|
610 /** |
|
611 * A helper class to temporarily set the value of mCurrentScrollParentId. |
|
612 */ |
|
613 class AutoCurrentScrollParentIdSetter; |
|
614 friend class AutoCurrentScrollParentIdSetter; |
|
615 class AutoCurrentScrollParentIdSetter { |
|
616 public: |
|
617 AutoCurrentScrollParentIdSetter(nsDisplayListBuilder* aBuilder, ViewID aScrollId) |
|
618 : mBuilder(aBuilder), mOldValue(aBuilder->mCurrentScrollParentId) { |
|
619 aBuilder->mCurrentScrollParentId = aScrollId; |
|
620 } |
|
621 ~AutoCurrentScrollParentIdSetter() { |
|
622 mBuilder->mCurrentScrollParentId = mOldValue; |
|
623 } |
|
624 private: |
|
625 nsDisplayListBuilder* mBuilder; |
|
626 ViewID mOldValue; |
|
627 }; |
|
628 |
|
629 // Helpers for tables |
|
630 nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; } |
|
631 void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; } |
|
632 |
|
633 struct OutOfFlowDisplayData { |
|
634 OutOfFlowDisplayData(const DisplayItemClip& aContainingBlockClip, |
|
635 const nsRect &aDirtyRect) |
|
636 : mContainingBlockClip(aContainingBlockClip) |
|
637 , mDirtyRect(aDirtyRect) |
|
638 {} |
|
639 OutOfFlowDisplayData(const nsRect &aDirtyRect) |
|
640 : mDirtyRect(aDirtyRect) |
|
641 {} |
|
642 DisplayItemClip mContainingBlockClip; |
|
643 nsRect mDirtyRect; |
|
644 }; |
|
645 static void DestroyOutOfFlowDisplayData(void* aPropertyValue) |
|
646 { |
|
647 delete static_cast<OutOfFlowDisplayData*>(aPropertyValue); |
|
648 } |
|
649 |
|
650 NS_DECLARE_FRAME_PROPERTY(OutOfFlowDisplayDataProperty, DestroyOutOfFlowDisplayData) |
|
651 NS_DECLARE_FRAME_PROPERTY(Preserve3DDirtyRectProperty, nsIFrame::DestroyRect) |
|
652 |
|
653 nsPresContext* CurrentPresContext() { |
|
654 return CurrentPresShellState()->mPresShell->GetPresContext(); |
|
655 } |
|
656 |
|
657 /** |
|
658 * Accumulates the bounds of box frames that have moz-appearance |
|
659 * -moz-win-exclude-glass style. Used in setting glass margins on |
|
660 * Windows. |
|
661 */ |
|
662 void AddExcludedGlassRegion(nsRect &bounds) { |
|
663 mExcludedGlassRegion.Or(mExcludedGlassRegion, bounds); |
|
664 } |
|
665 const nsRegion& GetExcludedGlassRegion() { |
|
666 return mExcludedGlassRegion; |
|
667 } |
|
668 void SetGlassDisplayItem(nsDisplayItem* aItem) { |
|
669 if (mGlassDisplayItem) { |
|
670 // Web pages or extensions could trigger this by using |
|
671 // -moz-appearance:win-borderless-glass etc on their own elements. |
|
672 // Keep the first one, since that will be the background of the root |
|
673 // window |
|
674 NS_WARNING("Multiple glass backgrounds found?"); |
|
675 } else { |
|
676 mGlassDisplayItem = aItem; |
|
677 } |
|
678 } |
|
679 bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) { |
|
680 return aItem == mGlassDisplayItem; |
|
681 } |
|
682 |
|
683 void SetContainsPluginItem() { mContainsPluginItem = true; } |
|
684 bool ContainsPluginItem() { return mContainsPluginItem; } |
|
685 |
|
686 /** |
|
687 * mContainsBlendMode is true if we processed a display item that |
|
688 * has a blend mode attached. We do this so we can insert a |
|
689 * nsDisplayBlendContainer in the parent stacking context. |
|
690 */ |
|
691 void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; } |
|
692 bool ContainsBlendMode() const { return mContainsBlendMode; } |
|
693 |
|
694 DisplayListClipState& ClipState() { return mClipState; } |
|
695 |
|
696 private: |
|
697 void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, |
|
698 const nsRect& aDirtyRect); |
|
699 |
|
700 struct PresShellState { |
|
701 nsIPresShell* mPresShell; |
|
702 nsIFrame* mCaretFrame; |
|
703 uint32_t mFirstFrameMarkedForDisplay; |
|
704 bool mIsBackgroundOnly; |
|
705 }; |
|
706 PresShellState* CurrentPresShellState() { |
|
707 NS_ASSERTION(mPresShellStates.Length() > 0, |
|
708 "Someone forgot to enter a presshell"); |
|
709 return &mPresShellStates[mPresShellStates.Length() - 1]; |
|
710 } |
|
711 |
|
712 nsIFrame* mReferenceFrame; |
|
713 nsIFrame* mIgnoreScrollFrame; |
|
714 nsDisplayLayerEventRegions* mLayerEventRegions; |
|
715 PLArenaPool mPool; |
|
716 nsCOMPtr<nsISelection> mBoundingSelection; |
|
717 nsAutoTArray<PresShellState,8> mPresShellStates; |
|
718 nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay; |
|
719 nsAutoTArray<ThemeGeometry,2> mThemeGeometries; |
|
720 nsDisplayTableItem* mCurrentTableItem; |
|
721 DisplayListClipState mClipState; |
|
722 const nsRegion* mFinalTransparentRegion; |
|
723 // When mCachedOffsetFrame is non-null, mCachedOffset is the offset from |
|
724 // mCachedOffsetFrame to mReferenceFrame. |
|
725 const nsIFrame* mCachedOffsetFrame; |
|
726 const nsIFrame* mCachedReferenceFrame; |
|
727 nsPoint mCachedOffset; |
|
728 nsRegion mExcludedGlassRegion; |
|
729 // The display item for the Windows window glass background, if any |
|
730 nsDisplayItem* mGlassDisplayItem; |
|
731 nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy; |
|
732 Mode mMode; |
|
733 ViewID mCurrentScrollParentId; |
|
734 bool mBuildCaret; |
|
735 bool mIgnoreSuppression; |
|
736 bool mHadToIgnoreSuppression; |
|
737 bool mIsAtRootOfPseudoStackingContext; |
|
738 bool mIncludeAllOutOfFlows; |
|
739 bool mDescendIntoSubdocuments; |
|
740 bool mSelectedFramesOnly; |
|
741 bool mAccurateVisibleRegions; |
|
742 bool mAllowMergingAndFlattening; |
|
743 bool mWillComputePluginGeometry; |
|
744 // True when we're building a display list that's directly or indirectly |
|
745 // under an nsDisplayTransform |
|
746 bool mInTransform; |
|
747 bool mInFixedPos; |
|
748 bool mSyncDecodeImages; |
|
749 bool mIsPaintingToWindow; |
|
750 bool mIsCompositingCheap; |
|
751 bool mContainsPluginItem; |
|
752 bool mContainsBlendMode; |
|
753 bool mAncestorHasTouchEventHandler; |
|
754 // True when the first async-scrollable scroll frame for which we build a |
|
755 // display list has a display port. An async-scrollable scroll frame is one |
|
756 // which WantsAsyncScroll(). |
|
757 bool mHaveScrollableDisplayPort; |
|
758 }; |
|
759 |
|
760 class nsDisplayItem; |
|
761 class nsDisplayList; |
|
762 /** |
|
763 * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList. |
|
764 * nsDisplayItemLink holds the link. The lists are linked from lowest to |
|
765 * highest in z-order. |
|
766 */ |
|
767 class nsDisplayItemLink { |
|
768 // This is never instantiated directly, so no need to count constructors and |
|
769 // destructors. |
|
770 protected: |
|
771 nsDisplayItemLink() : mAbove(nullptr) {} |
|
772 nsDisplayItem* mAbove; |
|
773 |
|
774 friend class nsDisplayList; |
|
775 }; |
|
776 |
|
777 /** |
|
778 * This is the unit of rendering and event testing. Each instance of this |
|
779 * class represents an entity that can be drawn on the screen, e.g., a |
|
780 * frame's CSS background, or a frame's text string. |
|
781 * |
|
782 * nsDisplayListItems can be containers --- i.e., they can perform hit testing |
|
783 * and painting by recursively traversing a list of child items. |
|
784 * |
|
785 * These are arena-allocated during display list construction. A typical |
|
786 * subclass would just have a frame pointer, so its object would be just three |
|
787 * pointers (vtable, next-item, frame). |
|
788 * |
|
789 * Display items belong to a list at all times (except temporarily as they |
|
790 * move from one list to another). |
|
791 */ |
|
792 class nsDisplayItem : public nsDisplayItemLink { |
|
793 public: |
|
794 typedef mozilla::ContainerLayerParameters ContainerLayerParameters; |
|
795 typedef mozilla::DisplayItemClip DisplayItemClip; |
|
796 typedef mozilla::layers::FrameMetrics::ViewID ViewID; |
|
797 typedef mozilla::layers::Layer Layer; |
|
798 typedef mozilla::layers::LayerManager LayerManager; |
|
799 typedef mozilla::LayerState LayerState; |
|
800 |
|
801 // This is never instantiated directly (it has pure virtual methods), so no |
|
802 // need to count constructors and destructors. |
|
803 nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
804 : mFrame(aFrame) |
|
805 , mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder)) |
|
806 , mInFixedPos(aBuilder->IsInFixedPos()) |
|
807 #ifdef MOZ_DUMP_PAINTING |
|
808 , mPainted(false) |
|
809 #endif |
|
810 { |
|
811 mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame); |
|
812 mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame); |
|
813 } |
|
814 nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
815 const nsIFrame* aReferenceFrame, |
|
816 const nsPoint& aToReferenceFrame) |
|
817 : mFrame(aFrame) |
|
818 , mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder)) |
|
819 , mReferenceFrame(aReferenceFrame) |
|
820 , mToReferenceFrame(aToReferenceFrame) |
|
821 , mInFixedPos(aBuilder->IsInFixedPos()) |
|
822 #ifdef MOZ_DUMP_PAINTING |
|
823 , mPainted(false) |
|
824 #endif |
|
825 { |
|
826 } |
|
827 /** |
|
828 * This constructor is only used in rare cases when we need to construct |
|
829 * temporary items. |
|
830 */ |
|
831 nsDisplayItem(nsIFrame* aFrame) |
|
832 : mFrame(aFrame) |
|
833 , mClip(nullptr) |
|
834 , mReferenceFrame(nullptr) |
|
835 , mInFixedPos(false) |
|
836 #ifdef MOZ_DUMP_PAINTING |
|
837 , mPainted(false) |
|
838 #endif |
|
839 { |
|
840 } |
|
841 virtual ~nsDisplayItem() {} |
|
842 |
|
843 void* operator new(size_t aSize, |
|
844 nsDisplayListBuilder* aBuilder) CPP_THROW_NEW { |
|
845 return aBuilder->Allocate(aSize); |
|
846 } |
|
847 |
|
848 // Contains all the type integers for each display list item type |
|
849 #include "nsDisplayItemTypes.h" |
|
850 |
|
851 struct HitTestState { |
|
852 typedef nsTArray<ViewID> ShadowArray; |
|
853 |
|
854 HitTestState(ShadowArray* aShadows = nullptr) |
|
855 : mShadows(aShadows) { |
|
856 } |
|
857 |
|
858 ~HitTestState() { |
|
859 NS_ASSERTION(mItemBuffer.Length() == 0, |
|
860 "mItemBuffer should have been cleared"); |
|
861 } |
|
862 |
|
863 nsAutoTArray<nsDisplayItem*, 100> mItemBuffer; |
|
864 |
|
865 // It is sometimes useful to hit test for frames that are not in this |
|
866 // process. Display items may append IDs into this array if it is |
|
867 // non-null. |
|
868 ShadowArray* mShadows; |
|
869 }; |
|
870 |
|
871 /** |
|
872 * Some consecutive items should be rendered together as a unit, e.g., |
|
873 * outlines for the same element. For this, we need a way for items to |
|
874 * identify their type. We use the type for other purposes too. |
|
875 */ |
|
876 virtual Type GetType() = 0; |
|
877 /** |
|
878 * Pairing this with the GetUnderlyingFrame() pointer gives a key that |
|
879 * uniquely identifies this display item in the display item tree. |
|
880 * XXX check ScrollLayerWrapper/nsOptionEventGrabberWrapper/nsXULEventRedirectorWrapper |
|
881 */ |
|
882 virtual uint32_t GetPerFrameKey() { return uint32_t(GetType()); } |
|
883 /** |
|
884 * This is called after we've constructed a display list for event handling. |
|
885 * When this is called, we've already ensured that aRect intersects the |
|
886 * item's bounds and that clipping has been taking into account. |
|
887 * |
|
888 * @param aRect the point or rect being tested, relative to the reference |
|
889 * frame. If the width and height are both 1 app unit, it indicates we're |
|
890 * hit testing a point, not a rect. |
|
891 * @param aState must point to a HitTestState. If you don't have one, |
|
892 * just create one with the default constructor and pass it in. |
|
893 * @param aOutFrames each item appends the frame(s) in this display item that |
|
894 * the rect is considered over (if any) to aOutFrames. |
|
895 */ |
|
896 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
897 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {} |
|
898 /** |
|
899 * @return the frame that this display item is based on. This is used to sort |
|
900 * items by z-index and content order and for some other uses. Never |
|
901 * returns null. |
|
902 */ |
|
903 inline nsIFrame* Frame() const { return mFrame; } |
|
904 /** |
|
905 * Compute the used z-index of our frame; returns zero for elements to which |
|
906 * z-index does not apply, and for z-index:auto. |
|
907 * @note This can be overridden, @see nsDisplayWrapList::SetOverrideZIndex. |
|
908 */ |
|
909 virtual int32_t ZIndex() const; |
|
910 /** |
|
911 * The default bounds is the frame border rect. |
|
912 * @param aSnap *aSnap is set to true if the returned rect will be |
|
913 * snapped to nearest device pixel edges during actual drawing. |
|
914 * It might be set to false and snap anyway, so code computing the set of |
|
915 * pixels affected by this display item needs to round outwards to pixel |
|
916 * boundaries when *aSnap is set to false. |
|
917 * This does not take the item's clipping into account. |
|
918 * @return a rectangle relative to aBuilder->ReferenceFrame() that |
|
919 * contains the area drawn by this display item |
|
920 */ |
|
921 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) |
|
922 { |
|
923 *aSnap = false; |
|
924 return nsRect(ToReferenceFrame(), Frame()->GetSize()); |
|
925 } |
|
926 /** |
|
927 * Returns the result of GetBounds intersected with the item's clip. |
|
928 * The intersection is approximate since rounded corners are not taking into |
|
929 * account. |
|
930 */ |
|
931 nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder); |
|
932 nsRect GetBorderRect() { |
|
933 return nsRect(ToReferenceFrame(), Frame()->GetSize()); |
|
934 } |
|
935 nsRect GetPaddingRect() { |
|
936 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame(); |
|
937 } |
|
938 nsRect GetContentRect() { |
|
939 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame(); |
|
940 } |
|
941 |
|
942 /** |
|
943 * Checks if the frame(s) owning this display item have been marked as invalid, |
|
944 * and needing repainting. |
|
945 */ |
|
946 virtual bool IsInvalid(nsRect& aRect) { |
|
947 bool result = mFrame ? mFrame->IsInvalid(aRect) : false; |
|
948 aRect += ToReferenceFrame(); |
|
949 return result; |
|
950 } |
|
951 |
|
952 /** |
|
953 * Creates and initializes an nsDisplayItemGeometry object that retains the current |
|
954 * areas covered by this display item. These need to retain enough information |
|
955 * such that they can be compared against a future nsDisplayItem of the same type, |
|
956 * and determine if repainting needs to happen. |
|
957 * |
|
958 * Subclasses wishing to store more information need to override both this |
|
959 * and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry |
|
960 * subclass. |
|
961 * |
|
962 * The default implementation tracks both the display item bounds, and the frame's |
|
963 * border rect. |
|
964 */ |
|
965 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) |
|
966 { |
|
967 return new nsDisplayItemGenericGeometry(this, aBuilder); |
|
968 } |
|
969 |
|
970 /** |
|
971 * Compares an nsDisplayItemGeometry object from a previous paint against the |
|
972 * current item. Computes if the geometry of the item has changed, and the |
|
973 * invalidation area required for correct repainting. |
|
974 * |
|
975 * The existing geometry will have been created from a display item with a |
|
976 * matching GetPerFrameKey()/mFrame pair to the current item. |
|
977 * |
|
978 * The default implementation compares the display item bounds, and the frame's |
|
979 * border rect, and invalidates the entire bounds if either rect changes. |
|
980 * |
|
981 * @param aGeometry The geometry of the matching display item from the |
|
982 * previous paint. |
|
983 * @param aInvalidRegion Output param, the region to invalidate, or |
|
984 * unchanged if none. |
|
985 */ |
|
986 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
987 const nsDisplayItemGeometry* aGeometry, |
|
988 nsRegion* aInvalidRegion) |
|
989 { |
|
990 const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry); |
|
991 bool snap; |
|
992 if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) || |
|
993 !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) { |
|
994 aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds); |
|
995 } |
|
996 } |
|
997 |
|
998 /** |
|
999 * An alternative default implementation of ComputeInvalidationRegion, |
|
1000 * that instead invalidates only the changed area between the two items. |
|
1001 */ |
|
1002 void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder, |
|
1003 const nsDisplayItemBoundsGeometry* aGeometry, |
|
1004 nsRegion* aInvalidRegion) |
|
1005 { |
|
1006 bool snap; |
|
1007 nsRect bounds = GetBounds(aBuilder, &snap); |
|
1008 |
|
1009 if (!aGeometry->mBounds.IsEqualInterior(bounds)) { |
|
1010 nscoord radii[8]; |
|
1011 if (aGeometry->mHasRoundedCorners || |
|
1012 Frame()->GetBorderRadii(radii)) { |
|
1013 aInvalidRegion->Or(aGeometry->mBounds, bounds); |
|
1014 } else { |
|
1015 aInvalidRegion->Xor(aGeometry->mBounds, bounds); |
|
1016 } |
|
1017 } |
|
1018 } |
|
1019 |
|
1020 /** |
|
1021 * For display items types that just draw a background we use this function |
|
1022 * to do any invalidation that might be needed if we are asked to sync decode |
|
1023 * images. |
|
1024 */ |
|
1025 void AddInvalidRegionForSyncDecodeBackgroundImages( |
|
1026 nsDisplayListBuilder* aBuilder, |
|
1027 const nsDisplayItemGeometry* aGeometry, |
|
1028 nsRegion* aInvalidRegion); |
|
1029 |
|
1030 /** |
|
1031 * Called when the area rendered by this display item has changed (been |
|
1032 * invalidated or changed geometry) since the last paint. This includes |
|
1033 * when the display item was not rendered at all in the last paint. |
|
1034 * It does NOT get called when a display item was being rendered and no |
|
1035 * longer is, because generally that means there is no display item to |
|
1036 * call this method on. |
|
1037 */ |
|
1038 virtual void NotifyRenderingChanged() {} |
|
1039 |
|
1040 /** |
|
1041 * @param aSnap set to true if the edges of the rectangles of the opaque |
|
1042 * region would be snapped to device pixels when drawing |
|
1043 * @return a region of the item that is opaque --- that is, every pixel |
|
1044 * that is visible (according to ComputeVisibility) is painted with an opaque |
|
1045 * color. This is useful for determining when one piece |
|
1046 * of content completely obscures another so that we can do occlusion |
|
1047 * culling. |
|
1048 * This does not take clipping into account. |
|
1049 */ |
|
1050 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
1051 bool* aSnap) |
|
1052 { |
|
1053 *aSnap = false; |
|
1054 return nsRegion(); |
|
1055 } |
|
1056 /** |
|
1057 * If this returns true, then aColor is set to the uniform color |
|
1058 * @return true if the item is guaranteed to paint every pixel in its |
|
1059 * bounds with the same (possibly translucent) color |
|
1060 */ |
|
1061 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) { return false; } |
|
1062 /** |
|
1063 * @return false if the painting performed by the item is invariant |
|
1064 * when the item's underlying frame is moved relative to aFrame. |
|
1065 * In other words, if you render the item at locations P and P', the rendering |
|
1066 * only differs by the translation. |
|
1067 * It return true for all wrapped lists. |
|
1068 */ |
|
1069 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder, |
|
1070 nsIFrame* aFrame) |
|
1071 { return false; } |
|
1072 /** |
|
1073 * @return true if the contents of this item are rendered fixed relative |
|
1074 * to the nearest viewport. |
|
1075 */ |
|
1076 virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) |
|
1077 { return false; } |
|
1078 |
|
1079 /** |
|
1080 * Returns true if all layers that can be active should be forced to be |
|
1081 * active. Requires setting the pref layers.force-active=true. |
|
1082 */ |
|
1083 static bool ForceActiveLayers(); |
|
1084 |
|
1085 /** |
|
1086 * Returns the maximum number of layers that should be created |
|
1087 * or -1 for no limit. Requires setting the pref layers.max-acitve. |
|
1088 */ |
|
1089 static int32_t MaxActiveLayers(); |
|
1090 |
|
1091 /** |
|
1092 * @return LAYER_NONE if BuildLayer will return null. In this case |
|
1093 * there is no layer for the item, and Paint should be called instead |
|
1094 * to paint the content using Thebes. |
|
1095 * Return LAYER_INACTIVE if there is a layer --- BuildLayer will |
|
1096 * not return null (unless there's an error) --- but the layer contents |
|
1097 * are not changing frequently. In this case it makes sense to composite |
|
1098 * the layer into a ThebesLayer with other content, so we don't have to |
|
1099 * recomposite it every time we paint. |
|
1100 * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all |
|
1101 * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also, |
|
1102 * all descendant display item frames must have an active scrolled root |
|
1103 * that's either the same as this item's frame's active scrolled root, or |
|
1104 * a descendant of this item's frame. This ensures that the entire |
|
1105 * set of display items can be collapsed onto a single ThebesLayer. |
|
1106 * Return LAYER_ACTIVE if the layer is active, that is, its contents are |
|
1107 * changing frequently. In this case it makes sense to keep the layer |
|
1108 * as a separate buffer in VRAM and composite it into the destination |
|
1109 * every time we paint. |
|
1110 * |
|
1111 * Users of GetLayerState should check ForceActiveLayers() and if it returns |
|
1112 * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE. |
|
1113 */ |
|
1114 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
1115 LayerManager* aManager, |
|
1116 const ContainerLayerParameters& aParameters) |
|
1117 { return mozilla::LAYER_NONE; } |
|
1118 /** |
|
1119 * Return true to indicate the layer should be constructed even if it's |
|
1120 * completely invisible. |
|
1121 */ |
|
1122 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) |
|
1123 { return false; } |
|
1124 /** |
|
1125 * Actually paint this item to some rendering context. |
|
1126 * Content outside mVisibleRect need not be painted. |
|
1127 * aCtx must be set up as for nsDisplayList::Paint. |
|
1128 */ |
|
1129 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {} |
|
1130 |
|
1131 #ifdef MOZ_DUMP_PAINTING |
|
1132 /** |
|
1133 * Mark this display item as being painted via FrameLayerBuilder::DrawThebesLayer. |
|
1134 */ |
|
1135 bool Painted() { return mPainted; } |
|
1136 |
|
1137 /** |
|
1138 * Check if this display item has been painted. |
|
1139 */ |
|
1140 void SetPainted() { mPainted = true; } |
|
1141 #endif |
|
1142 |
|
1143 /** |
|
1144 * Get the layer drawn by this display item. Call this only if |
|
1145 * GetLayerState() returns something other than LAYER_NONE. |
|
1146 * If GetLayerState returned LAYER_NONE then Paint will be called |
|
1147 * instead. |
|
1148 * This is called while aManager is in the construction phase. |
|
1149 * |
|
1150 * The caller (nsDisplayList) is responsible for setting the visible |
|
1151 * region of the layer. |
|
1152 * |
|
1153 * @param aContainerParameters should be passed to |
|
1154 * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is |
|
1155 * constructed. |
|
1156 */ |
|
1157 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
1158 LayerManager* aManager, |
|
1159 const ContainerLayerParameters& aContainerParameters) |
|
1160 { return nullptr; } |
|
1161 |
|
1162 /** |
|
1163 * On entry, aVisibleRegion contains the region (relative to ReferenceFrame()) |
|
1164 * which may be visible. If the display item opaquely covers an area, it |
|
1165 * can remove that area from aVisibleRegion before returning. |
|
1166 * nsDisplayList::ComputeVisibility automatically subtracts the region |
|
1167 * returned by GetOpaqueRegion, and automatically removes items whose bounds |
|
1168 * do not intersect the visible area, so implementations of |
|
1169 * nsDisplayItem::ComputeVisibility do not need to do these things. |
|
1170 * nsDisplayList::ComputeVisibility will already have set mVisibleRect on |
|
1171 * this item to the intersection of *aVisibleRegion and this item's bounds. |
|
1172 * We rely on that, so this should only be called by |
|
1173 * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility. |
|
1174 * aAllowVisibleRegionExpansion is a rect where we are allowed to |
|
1175 * expand the visible region and is only used for making sure the |
|
1176 * background behind a plugin is visible. |
|
1177 * This method needs to be idempotent. |
|
1178 * |
|
1179 * @return true if the item is visible, false if no part of the item |
|
1180 * is visible. |
|
1181 */ |
|
1182 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
1183 nsRegion* aVisibleRegion, |
|
1184 const nsRect& aAllowVisibleRegionExpansion) |
|
1185 { return !mVisibleRect.IsEmpty(); } |
|
1186 |
|
1187 /** |
|
1188 * Try to merge with the other item (which is below us in the display |
|
1189 * list). This gets used by nsDisplayClip to coalesce clipping operations |
|
1190 * (optimization), by nsDisplayOpacity to merge rendering for the same |
|
1191 * content element into a single opacity group (correctness), and will be |
|
1192 * used by nsDisplayOutline to merge multiple outlines for the same element |
|
1193 * (also for correctness). |
|
1194 * @return true if the merge was successful and the other item should be deleted |
|
1195 */ |
|
1196 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) { |
|
1197 return false; |
|
1198 } |
|
1199 |
|
1200 /** |
|
1201 * Appends the underlying frames of all display items that have been |
|
1202 * merged into this one (excluding this item's own underlying frame) |
|
1203 * to aFrames. |
|
1204 */ |
|
1205 virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) {} |
|
1206 |
|
1207 /** |
|
1208 * During the visibility computation and after TryMerge, display lists may |
|
1209 * return true here to flatten themselves away, removing them. This |
|
1210 * flattening is distinctly different from FlattenTo, which occurs before |
|
1211 * items are merged together. |
|
1212 */ |
|
1213 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) { |
|
1214 return false; |
|
1215 } |
|
1216 |
|
1217 /** |
|
1218 * If this has a child list where the children are in the same coordinate |
|
1219 * system as this item (i.e., they have the same reference frame), |
|
1220 * return the list. |
|
1221 */ |
|
1222 virtual nsDisplayList* GetSameCoordinateSystemChildren() { return nullptr; } |
|
1223 virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {} |
|
1224 |
|
1225 /** |
|
1226 * If this has a child list, return it, even if the children are in |
|
1227 * a different coordinate system to this item. |
|
1228 */ |
|
1229 virtual nsDisplayList* GetChildren() { return nullptr; } |
|
1230 |
|
1231 /** |
|
1232 * Returns the visible rect. Should only be called after ComputeVisibility |
|
1233 * has happened. |
|
1234 */ |
|
1235 const nsRect& GetVisibleRect() { return mVisibleRect; } |
|
1236 |
|
1237 /** |
|
1238 * Stores the given opacity value to be applied when drawing. Returns |
|
1239 * false if this isn't supported for this display item. |
|
1240 */ |
|
1241 virtual bool ApplyOpacity(nsDisplayListBuilder* aBuilder, |
|
1242 float aOpacity, |
|
1243 const DisplayItemClip* aClip) { |
|
1244 return false; |
|
1245 } |
|
1246 |
|
1247 #ifdef MOZ_DUMP_PAINTING |
|
1248 /** |
|
1249 * For debugging and stuff |
|
1250 */ |
|
1251 virtual const char* Name() = 0; |
|
1252 |
|
1253 virtual void WriteDebugInfo(nsACString& aTo) {} |
|
1254 #endif |
|
1255 |
|
1256 nsDisplayItem* GetAbove() { return mAbove; } |
|
1257 |
|
1258 /** |
|
1259 * Like ComputeVisibility, but does the work that nsDisplayList |
|
1260 * does per-item: |
|
1261 * -- Intersects GetBounds with aVisibleRegion and puts the result |
|
1262 * in mVisibleRect |
|
1263 * -- Subtracts bounds from aVisibleRegion if the item is opaque |
|
1264 */ |
|
1265 bool RecomputeVisibility(nsDisplayListBuilder* aBuilder, |
|
1266 nsRegion* aVisibleRegion); |
|
1267 |
|
1268 /** |
|
1269 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame()) |
|
1270 */ |
|
1271 const nsPoint& ToReferenceFrame() const { |
|
1272 NS_ASSERTION(mFrame, "No frame?"); |
|
1273 return mToReferenceFrame; |
|
1274 } |
|
1275 /** |
|
1276 * @return the root of the display list's frame (sub)tree, whose origin |
|
1277 * establishes the coordinate system for the display list |
|
1278 */ |
|
1279 const nsIFrame* ReferenceFrame() const { return mReferenceFrame; } |
|
1280 |
|
1281 /** |
|
1282 * Returns the reference frame for display item children of this item. |
|
1283 */ |
|
1284 virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; } |
|
1285 |
|
1286 /** |
|
1287 * Checks if this display item (or any children) contains content that might |
|
1288 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the |
|
1289 * bounds of the area that needs component alpha, or an empty rect if nothing |
|
1290 * in the item does. |
|
1291 */ |
|
1292 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); } |
|
1293 |
|
1294 /** |
|
1295 * Disable usage of component alpha. Currently only relevant for items that have text. |
|
1296 */ |
|
1297 virtual void DisableComponentAlpha() {} |
|
1298 |
|
1299 /** |
|
1300 * Check if we can add async animations to the layer for this display item. |
|
1301 */ |
|
1302 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) { |
|
1303 return false; |
|
1304 } |
|
1305 |
|
1306 virtual bool SupportsOptimizingToImage() { return false; } |
|
1307 |
|
1308 const DisplayItemClip& GetClip() |
|
1309 { |
|
1310 return mClip ? *mClip : DisplayItemClip::NoClip(); |
|
1311 } |
|
1312 void SetClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip) |
|
1313 { |
|
1314 if (!aClip.HasClip()) { |
|
1315 mClip = nullptr; |
|
1316 return; |
|
1317 } |
|
1318 mClip = aBuilder->AllocateDisplayItemClip(aClip); |
|
1319 } |
|
1320 |
|
1321 void IntersectClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip) |
|
1322 { |
|
1323 if (mClip) { |
|
1324 DisplayItemClip temp = *mClip; |
|
1325 temp.IntersectWith(aClip); |
|
1326 SetClip(aBuilder, temp); |
|
1327 } else { |
|
1328 SetClip(aBuilder, aClip); |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 // If we return false here it means that if this item creates a layer then |
|
1333 // ProcessDisplayItems will not set the visible region on the layer. The item |
|
1334 // should set the visible region, usually in BuildContainerLayer. |
|
1335 virtual bool SetVisibleRegionOnLayer() { return true; } |
|
1336 |
|
1337 bool IsInFixedPos() { return mInFixedPos; } |
|
1338 |
|
1339 protected: |
|
1340 friend class nsDisplayList; |
|
1341 |
|
1342 nsDisplayItem() { mAbove = nullptr; } |
|
1343 |
|
1344 nsIFrame* mFrame; |
|
1345 const DisplayItemClip* mClip; |
|
1346 // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null |
|
1347 const nsIFrame* mReferenceFrame; |
|
1348 // Result of ToReferenceFrame(mFrame), if mFrame is non-null |
|
1349 nsPoint mToReferenceFrame; |
|
1350 // This is the rectangle that needs to be painted. |
|
1351 // nsDisplayList::ComputeVisibility sets this to the visible region |
|
1352 // of the item by intersecting the current visible region with the bounds |
|
1353 // of the item. Paint implementations can use this to limit their drawing. |
|
1354 // Guaranteed to be contained in GetBounds(). |
|
1355 nsRect mVisibleRect; |
|
1356 bool mInFixedPos; |
|
1357 #ifdef MOZ_DUMP_PAINTING |
|
1358 // True if this frame has been painted. |
|
1359 bool mPainted; |
|
1360 #endif |
|
1361 }; |
|
1362 |
|
1363 /** |
|
1364 * Manages a singly-linked list of display list items. |
|
1365 * |
|
1366 * mSentinel is the sentinel list value, the first value in the null-terminated |
|
1367 * linked list of items. mTop is the last item in the list (whose 'above' |
|
1368 * pointer is null). This class has no virtual methods. So list objects are just |
|
1369 * two pointers. |
|
1370 * |
|
1371 * Stepping upward through this list is very fast. Stepping downward is very |
|
1372 * slow so we don't support it. The methods that need to step downward |
|
1373 * (HitTest(), ComputeVisibility()) internally build a temporary array of all |
|
1374 * the items while they do the downward traversal, so overall they're still |
|
1375 * linear time. We have optimized for efficient AppendToTop() of both |
|
1376 * items and lists, with minimal codesize. AppendToBottom() is efficient too. |
|
1377 */ |
|
1378 class nsDisplayList { |
|
1379 public: |
|
1380 typedef mozilla::layers::Layer Layer; |
|
1381 typedef mozilla::layers::LayerManager LayerManager; |
|
1382 typedef mozilla::layers::ThebesLayer ThebesLayer; |
|
1383 |
|
1384 /** |
|
1385 * Create an empty list. |
|
1386 */ |
|
1387 nsDisplayList() : |
|
1388 mIsOpaque(false) |
|
1389 { |
|
1390 mTop = &mSentinel; |
|
1391 mSentinel.mAbove = nullptr; |
|
1392 #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING) |
|
1393 mDidComputeVisibility = false; |
|
1394 #endif |
|
1395 } |
|
1396 ~nsDisplayList() { |
|
1397 if (mSentinel.mAbove) { |
|
1398 NS_WARNING("Nonempty list left over?"); |
|
1399 } |
|
1400 DeleteAll(); |
|
1401 } |
|
1402 |
|
1403 /** |
|
1404 * Append an item to the top of the list. The item must not currently |
|
1405 * be in a list and cannot be null. |
|
1406 */ |
|
1407 void AppendToTop(nsDisplayItem* aItem) { |
|
1408 NS_ASSERTION(aItem, "No item to append!"); |
|
1409 NS_ASSERTION(!aItem->mAbove, "Already in a list!"); |
|
1410 mTop->mAbove = aItem; |
|
1411 mTop = aItem; |
|
1412 } |
|
1413 |
|
1414 /** |
|
1415 * Append a new item to the top of the list. If the item is null we return |
|
1416 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToTop(new ...); |
|
1417 */ |
|
1418 void AppendNewToTop(nsDisplayItem* aItem) { |
|
1419 if (aItem) { |
|
1420 AppendToTop(aItem); |
|
1421 } |
|
1422 } |
|
1423 |
|
1424 /** |
|
1425 * Append a new item to the bottom of the list. If the item is null we return |
|
1426 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToBottom(new ...); |
|
1427 */ |
|
1428 void AppendNewToBottom(nsDisplayItem* aItem) { |
|
1429 if (aItem) { |
|
1430 AppendToBottom(aItem); |
|
1431 } |
|
1432 } |
|
1433 |
|
1434 /** |
|
1435 * Append a new item to the bottom of the list. The item must be non-null |
|
1436 * and not already in a list. |
|
1437 */ |
|
1438 void AppendToBottom(nsDisplayItem* aItem) { |
|
1439 NS_ASSERTION(aItem, "No item to append!"); |
|
1440 NS_ASSERTION(!aItem->mAbove, "Already in a list!"); |
|
1441 aItem->mAbove = mSentinel.mAbove; |
|
1442 mSentinel.mAbove = aItem; |
|
1443 if (mTop == &mSentinel) { |
|
1444 mTop = aItem; |
|
1445 } |
|
1446 } |
|
1447 |
|
1448 /** |
|
1449 * Removes all items from aList and appends them to the top of this list |
|
1450 */ |
|
1451 void AppendToTop(nsDisplayList* aList) { |
|
1452 if (aList->mSentinel.mAbove) { |
|
1453 mTop->mAbove = aList->mSentinel.mAbove; |
|
1454 mTop = aList->mTop; |
|
1455 aList->mTop = &aList->mSentinel; |
|
1456 aList->mSentinel.mAbove = nullptr; |
|
1457 } |
|
1458 } |
|
1459 |
|
1460 /** |
|
1461 * Removes all items from aList and prepends them to the bottom of this list |
|
1462 */ |
|
1463 void AppendToBottom(nsDisplayList* aList) { |
|
1464 if (aList->mSentinel.mAbove) { |
|
1465 aList->mTop->mAbove = mSentinel.mAbove; |
|
1466 mSentinel.mAbove = aList->mSentinel.mAbove; |
|
1467 if (mTop == &mSentinel) { |
|
1468 mTop = aList->mTop; |
|
1469 } |
|
1470 |
|
1471 aList->mTop = &aList->mSentinel; |
|
1472 aList->mSentinel.mAbove = nullptr; |
|
1473 } |
|
1474 } |
|
1475 |
|
1476 /** |
|
1477 * Remove an item from the bottom of the list and return it. |
|
1478 */ |
|
1479 nsDisplayItem* RemoveBottom(); |
|
1480 |
|
1481 /** |
|
1482 * Remove all items from the list and call their destructors. |
|
1483 */ |
|
1484 void DeleteAll(); |
|
1485 |
|
1486 /** |
|
1487 * @return the item at the top of the list, or null if the list is empty |
|
1488 */ |
|
1489 nsDisplayItem* GetTop() const { |
|
1490 return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr; |
|
1491 } |
|
1492 /** |
|
1493 * @return the item at the bottom of the list, or null if the list is empty |
|
1494 */ |
|
1495 nsDisplayItem* GetBottom() const { return mSentinel.mAbove; } |
|
1496 bool IsEmpty() const { return mTop == &mSentinel; } |
|
1497 |
|
1498 /** |
|
1499 * This is *linear time*! |
|
1500 * @return the number of items in the list |
|
1501 */ |
|
1502 uint32_t Count() const; |
|
1503 /** |
|
1504 * Stable sort the list by the z-order of GetUnderlyingFrame() on |
|
1505 * each item. 'auto' is counted as zero. Content order is used as the |
|
1506 * secondary order. |
|
1507 * @param aCommonAncestor a common ancestor of all the content elements |
|
1508 * associated with the display items, for speeding up tree order |
|
1509 * checks, or nullptr if not known; it's only a hint, if it is not an |
|
1510 * ancestor of some elements, then we lose performance but not correctness |
|
1511 */ |
|
1512 void SortByZOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor); |
|
1513 /** |
|
1514 * Stable sort the list by the tree order of the content of |
|
1515 * GetUnderlyingFrame() on each item. z-index is ignored. |
|
1516 * @param aCommonAncestor a common ancestor of all the content elements |
|
1517 * associated with the display items, for speeding up tree order |
|
1518 * checks, or nullptr if not known; it's only a hint, if it is not an |
|
1519 * ancestor of some elements, then we lose performance but not correctness |
|
1520 */ |
|
1521 void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor); |
|
1522 |
|
1523 /** |
|
1524 * Generic stable sort. Take care, because some of the items might be nsDisplayLists |
|
1525 * themselves. |
|
1526 * aCmp(item1, item2) should return true if item1 <= item2. We sort the items |
|
1527 * into increasing order. |
|
1528 */ |
|
1529 typedef bool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2, |
|
1530 void* aClosure); |
|
1531 void Sort(nsDisplayListBuilder* aBuilder, SortLEQ aCmp, void* aClosure); |
|
1532 |
|
1533 /** |
|
1534 * Compute visiblity for the items in the list. |
|
1535 * We put this logic here so it can be shared by top-level |
|
1536 * painting and also display items that maintain child lists. |
|
1537 * This is also a good place to put ComputeVisibility-related logic |
|
1538 * that must be applied to every display item. In particular, this |
|
1539 * sets mVisibleRect on each display item. |
|
1540 * This sets mIsOpaque if the entire visible area of this list has |
|
1541 * been removed from aVisibleRegion when we return. |
|
1542 * This does not remove any items from the list, so we can recompute |
|
1543 * visiblity with different regions later (see |
|
1544 * FrameLayerBuilder::DrawThebesLayer). |
|
1545 * This method needs to be idempotent. |
|
1546 * |
|
1547 * @param aVisibleRegion the area that is visible, relative to the |
|
1548 * reference frame; on return, this contains the area visible under the list. |
|
1549 * I.e., opaque contents of this list are subtracted from aVisibleRegion. |
|
1550 * @param aListVisibleBounds must be equal to the bounds of the intersection |
|
1551 * of aVisibleRegion and GetBounds() for this list. |
|
1552 * @param aDisplayPortFrame If the item for which this list corresponds is |
|
1553 * within a displayport, the scroll frame for which that display port |
|
1554 * applies. For root scroll frames, you can pass the the root frame instead. |
|
1555 * @return true if any item in the list is visible. |
|
1556 */ |
|
1557 bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder, |
|
1558 nsRegion* aVisibleRegion, |
|
1559 const nsRect& aListVisibleBounds, |
|
1560 const nsRect& aAllowVisibleRegionExpansion, |
|
1561 nsIFrame* aDisplayPortFrame = nullptr); |
|
1562 |
|
1563 /** |
|
1564 * As ComputeVisibilityForSublist, but computes visibility for a root |
|
1565 * list (a list that does not belong to an nsDisplayItem). |
|
1566 * This method needs to be idempotent. |
|
1567 * |
|
1568 * @param aVisibleRegion the area that is visible |
|
1569 * @param aDisplayPortFrame The root scroll frame, if a displayport is set |
|
1570 */ |
|
1571 bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder, |
|
1572 nsRegion* aVisibleRegion, |
|
1573 nsIFrame* aDisplayPortFrame = nullptr); |
|
1574 |
|
1575 /** |
|
1576 * Returns true if the visible region output from ComputeVisiblity was |
|
1577 * empty, i.e. everything visible in this list is opaque. |
|
1578 */ |
|
1579 bool IsOpaque() const { |
|
1580 NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility"); |
|
1581 return mIsOpaque; |
|
1582 } |
|
1583 |
|
1584 /** |
|
1585 * Returns true if during ComputeVisibility any display item |
|
1586 * set the surface to be transparent. |
|
1587 */ |
|
1588 bool NeedsTransparentSurface() const { |
|
1589 NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility"); |
|
1590 return mForceTransparentSurface; |
|
1591 } |
|
1592 /** |
|
1593 * Paint the list to the rendering context. We assume that (0,0) in aCtx |
|
1594 * corresponds to the origin of the reference frame. For best results, |
|
1595 * aCtx's current transform should make (0,0) pixel-aligned. The |
|
1596 * rectangle in aDirtyRect is painted, which *must* be contained in the |
|
1597 * dirty rect used to construct the display list. |
|
1598 * |
|
1599 * If aFlags contains PAINT_USE_WIDGET_LAYERS and |
|
1600 * ShouldUseWidgetLayerManager() is set, then we will paint using |
|
1601 * the reference frame's widget's layer manager (and ctx may be null), |
|
1602 * otherwise we will use a temporary BasicLayerManager and ctx must |
|
1603 * not be null. |
|
1604 * |
|
1605 * If PAINT_FLUSH_LAYERS is set, we'll force a completely new layer |
|
1606 * tree to be created for this paint *and* the next paint. |
|
1607 * |
|
1608 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's |
|
1609 * layer manager has already had BeginTransaction() called on it and |
|
1610 * we should not call it again. |
|
1611 * |
|
1612 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode |
|
1613 * to avoid short cut optimizations. |
|
1614 * |
|
1615 * ComputeVisibility must be called before Paint. |
|
1616 * |
|
1617 * This must only be called on the root display list of the display list |
|
1618 * tree. |
|
1619 */ |
|
1620 enum { |
|
1621 PAINT_DEFAULT = 0, |
|
1622 PAINT_USE_WIDGET_LAYERS = 0x01, |
|
1623 PAINT_FLUSH_LAYERS = 0x02, |
|
1624 PAINT_EXISTING_TRANSACTION = 0x04, |
|
1625 PAINT_NO_COMPOSITE = 0x08, |
|
1626 PAINT_COMPRESSED = 0x10 |
|
1627 }; |
|
1628 void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, |
|
1629 uint32_t aFlags) const; |
|
1630 /** |
|
1631 * Like PaintRoot, but used for internal display sublists. |
|
1632 * aForFrame is the frame that the list is associated with. |
|
1633 */ |
|
1634 void PaintForFrame(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, |
|
1635 nsIFrame* aForFrame, uint32_t aFlags) const; |
|
1636 /** |
|
1637 * Get the bounds. Takes the union of the bounds of all children. |
|
1638 */ |
|
1639 nsRect GetBounds(nsDisplayListBuilder* aBuilder) const; |
|
1640 /** |
|
1641 * Find the topmost display item that returns a non-null frame, and return |
|
1642 * the frame. |
|
1643 */ |
|
1644 void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
1645 nsDisplayItem::HitTestState* aState, |
|
1646 nsTArray<nsIFrame*> *aOutFrames) const; |
|
1647 |
|
1648 #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING) |
|
1649 bool DidComputeVisibility() const { return mDidComputeVisibility; } |
|
1650 #endif |
|
1651 |
|
1652 nsRect GetVisibleRect() const { return mVisibleRect; } |
|
1653 |
|
1654 private: |
|
1655 // This class is only used on stack, so we don't have to worry about leaking |
|
1656 // it. Don't let us be heap-allocated! |
|
1657 void* operator new(size_t sz) CPP_THROW_NEW; |
|
1658 |
|
1659 // Utility function used to massage the list during ComputeVisibility. |
|
1660 void FlattenTo(nsTArray<nsDisplayItem*>* aElements); |
|
1661 |
|
1662 nsDisplayItemLink mSentinel; |
|
1663 nsDisplayItemLink* mTop; |
|
1664 |
|
1665 // This is set by ComputeVisibility |
|
1666 nsRect mVisibleRect; |
|
1667 // This is set to true by ComputeVisibility if the final visible region |
|
1668 // is empty (i.e. everything that was visible is covered by some |
|
1669 // opaque content in this list). |
|
1670 bool mIsOpaque; |
|
1671 // This is set to true by ComputeVisibility if any display item in this |
|
1672 // list needs to force the surface containing this list to be transparent. |
|
1673 bool mForceTransparentSurface; |
|
1674 #if defined(DEBUG) || defined(MOZ_DUMP_PAINTING) |
|
1675 bool mDidComputeVisibility; |
|
1676 #endif |
|
1677 }; |
|
1678 |
|
1679 /** |
|
1680 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method |
|
1681 * will put any generated items onto the appropriate list given here. It's |
|
1682 * basically just a collection with one list for each separate stacking layer. |
|
1683 * The lists themselves are external to this object and thus can be shared |
|
1684 * with others. Some of the list pointers may even refer to the same list. |
|
1685 */ |
|
1686 class nsDisplayListSet { |
|
1687 public: |
|
1688 /** |
|
1689 * @return a list where one should place the border and/or background for |
|
1690 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E) |
|
1691 */ |
|
1692 nsDisplayList* BorderBackground() const { return mBorderBackground; } |
|
1693 /** |
|
1694 * @return a list where one should place the borders and/or backgrounds for |
|
1695 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E) |
|
1696 */ |
|
1697 nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; } |
|
1698 /** |
|
1699 * @return a list where one should place descendant floats (step 5 of |
|
1700 * CSS 2.1 appendix E) |
|
1701 */ |
|
1702 nsDisplayList* Floats() const { return mFloats; } |
|
1703 /** |
|
1704 * @return a list where one should place the (pseudo) stacking contexts |
|
1705 * for descendants of this frame (everything from steps 3, 7 and 8 |
|
1706 * of CSS 2.1 appendix E) |
|
1707 */ |
|
1708 nsDisplayList* PositionedDescendants() const { return mPositioned; } |
|
1709 /** |
|
1710 * @return a list where one should place the outlines |
|
1711 * for this frame and its descendants (step 9 of CSS 2.1 appendix E) |
|
1712 */ |
|
1713 nsDisplayList* Outlines() const { return mOutlines; } |
|
1714 /** |
|
1715 * @return a list where one should place all other content |
|
1716 */ |
|
1717 nsDisplayList* Content() const { return mContent; } |
|
1718 |
|
1719 nsDisplayListSet(nsDisplayList* aBorderBackground, |
|
1720 nsDisplayList* aBlockBorderBackgrounds, |
|
1721 nsDisplayList* aFloats, |
|
1722 nsDisplayList* aContent, |
|
1723 nsDisplayList* aPositionedDescendants, |
|
1724 nsDisplayList* aOutlines) : |
|
1725 mBorderBackground(aBorderBackground), |
|
1726 mBlockBorderBackgrounds(aBlockBorderBackgrounds), |
|
1727 mFloats(aFloats), |
|
1728 mContent(aContent), |
|
1729 mPositioned(aPositionedDescendants), |
|
1730 mOutlines(aOutlines) { |
|
1731 } |
|
1732 |
|
1733 /** |
|
1734 * A copy constructor that lets the caller override the BorderBackground |
|
1735 * list. |
|
1736 */ |
|
1737 nsDisplayListSet(const nsDisplayListSet& aLists, |
|
1738 nsDisplayList* aBorderBackground) : |
|
1739 mBorderBackground(aBorderBackground), |
|
1740 mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()), |
|
1741 mFloats(aLists.Floats()), |
|
1742 mContent(aLists.Content()), |
|
1743 mPositioned(aLists.PositionedDescendants()), |
|
1744 mOutlines(aLists.Outlines()) { |
|
1745 } |
|
1746 |
|
1747 /** |
|
1748 * Move all display items in our lists to top of the corresponding lists in the |
|
1749 * destination. |
|
1750 */ |
|
1751 void MoveTo(const nsDisplayListSet& aDestination) const; |
|
1752 |
|
1753 private: |
|
1754 // This class is only used on stack, so we don't have to worry about leaking |
|
1755 // it. Don't let us be heap-allocated! |
|
1756 void* operator new(size_t sz) CPP_THROW_NEW; |
|
1757 |
|
1758 protected: |
|
1759 nsDisplayList* mBorderBackground; |
|
1760 nsDisplayList* mBlockBorderBackgrounds; |
|
1761 nsDisplayList* mFloats; |
|
1762 nsDisplayList* mContent; |
|
1763 nsDisplayList* mPositioned; |
|
1764 nsDisplayList* mOutlines; |
|
1765 }; |
|
1766 |
|
1767 /** |
|
1768 * A specialization of nsDisplayListSet where the lists are actually internal |
|
1769 * to the object, and all distinct. |
|
1770 */ |
|
1771 struct nsDisplayListCollection : public nsDisplayListSet { |
|
1772 nsDisplayListCollection() : |
|
1773 nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4], |
|
1774 &mLists[5]) {} |
|
1775 nsDisplayListCollection(nsDisplayList* aBorderBackground) : |
|
1776 nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4], |
|
1777 &mLists[5]) {} |
|
1778 |
|
1779 /** |
|
1780 * Sort all lists by content order. |
|
1781 */ |
|
1782 void SortAllByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor) { |
|
1783 for (int32_t i = 0; i < 6; ++i) { |
|
1784 mLists[i].SortByContentOrder(aBuilder, aCommonAncestor); |
|
1785 } |
|
1786 } |
|
1787 |
|
1788 private: |
|
1789 // This class is only used on stack, so we don't have to worry about leaking |
|
1790 // it. Don't let us be heap-allocated! |
|
1791 void* operator new(size_t sz) CPP_THROW_NEW; |
|
1792 |
|
1793 nsDisplayList mLists[6]; |
|
1794 }; |
|
1795 |
|
1796 |
|
1797 class nsDisplayImageContainer : public nsDisplayItem { |
|
1798 public: |
|
1799 typedef mozilla::layers::ImageContainer ImageContainer; |
|
1800 typedef mozilla::layers::ImageLayer ImageLayer; |
|
1801 |
|
1802 nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
1803 : nsDisplayItem(aBuilder, aFrame) |
|
1804 {} |
|
1805 |
|
1806 virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager, |
|
1807 nsDisplayListBuilder* aBuilder) = 0; |
|
1808 virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) = 0; |
|
1809 |
|
1810 virtual bool SupportsOptimizingToImage() MOZ_OVERRIDE { return true; } |
|
1811 }; |
|
1812 |
|
1813 /** |
|
1814 * Use this class to implement not-very-frequently-used display items |
|
1815 * that are not opaque, do not receive events, and are bounded by a frame's |
|
1816 * border-rect. |
|
1817 * |
|
1818 * This should not be used for display items which are created frequently, |
|
1819 * because each item is one or two pointers bigger than an item from a |
|
1820 * custom display item class could be, and fractionally slower. However it does |
|
1821 * save code size. We use this for infrequently-used item types. |
|
1822 */ |
|
1823 class nsDisplayGeneric : public nsDisplayItem { |
|
1824 public: |
|
1825 typedef void (* PaintCallback)(nsIFrame* aFrame, nsRenderingContext* aCtx, |
|
1826 const nsRect& aDirtyRect, nsPoint aFramePt); |
|
1827 |
|
1828 nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
1829 PaintCallback aPaint, const char* aName, Type aType) |
|
1830 : nsDisplayItem(aBuilder, aFrame), mPaint(aPaint) |
|
1831 #ifdef MOZ_DUMP_PAINTING |
|
1832 , mName(aName) |
|
1833 #endif |
|
1834 , mType(aType) |
|
1835 { |
|
1836 MOZ_COUNT_CTOR(nsDisplayGeneric); |
|
1837 } |
|
1838 #ifdef NS_BUILD_REFCNT_LOGGING |
|
1839 virtual ~nsDisplayGeneric() { |
|
1840 MOZ_COUNT_DTOR(nsDisplayGeneric); |
|
1841 } |
|
1842 #endif |
|
1843 |
|
1844 virtual void Paint(nsDisplayListBuilder* aBuilder, |
|
1845 nsRenderingContext* aCtx) MOZ_OVERRIDE { |
|
1846 mPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame()); |
|
1847 } |
|
1848 NS_DISPLAY_DECL_NAME(mName, mType) |
|
1849 |
|
1850 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { |
|
1851 if (mType == nsDisplayItem::TYPE_HEADER_FOOTER) { |
|
1852 bool snap; |
|
1853 return GetBounds(aBuilder, &snap); |
|
1854 } |
|
1855 return nsRect(); |
|
1856 } |
|
1857 |
|
1858 protected: |
|
1859 PaintCallback mPaint; |
|
1860 #ifdef MOZ_DUMP_PAINTING |
|
1861 const char* mName; |
|
1862 #endif |
|
1863 Type mType; |
|
1864 }; |
|
1865 |
|
1866 /** |
|
1867 * Generic display item that can contain overflow. Use this in lieu of |
|
1868 * nsDisplayGeneric if you have a frame that should use the visual overflow |
|
1869 * rect of its frame when drawing items, instead of the frame's bounds. |
|
1870 */ |
|
1871 class nsDisplayGenericOverflow : public nsDisplayGeneric { |
|
1872 public: |
|
1873 nsDisplayGenericOverflow(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
1874 PaintCallback aPaint, const char* aName, Type aType) |
|
1875 : nsDisplayGeneric(aBuilder, aFrame, aPaint, aName, aType) |
|
1876 { |
|
1877 MOZ_COUNT_CTOR(nsDisplayGenericOverflow); |
|
1878 } |
|
1879 #ifdef NS_BUILD_REFCNT_LOGGING |
|
1880 virtual ~nsDisplayGenericOverflow() { |
|
1881 MOZ_COUNT_DTOR(nsDisplayGenericOverflow); |
|
1882 } |
|
1883 #endif |
|
1884 |
|
1885 /** |
|
1886 * Returns the frame's visual overflow rect instead of the frame's bounds. |
|
1887 */ |
|
1888 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, |
|
1889 bool* aSnap) MOZ_OVERRIDE |
|
1890 { |
|
1891 *aSnap = false; |
|
1892 return Frame()->GetVisualOverflowRect() + ToReferenceFrame(); |
|
1893 } |
|
1894 }; |
|
1895 |
|
1896 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF) |
|
1897 /** |
|
1898 * This class implements painting of reflow counts. Ideally, we would simply |
|
1899 * make all the frame names be those returned by nsFrame::GetFrameName |
|
1900 * (except that tosses in the content tag name!) and support only one color |
|
1901 * and eliminate this class altogether in favor of nsDisplayGeneric, but for |
|
1902 * the time being we can't pass args to a PaintCallback, so just have a |
|
1903 * separate class to do the right thing. Sadly, this alsmo means we need to |
|
1904 * hack all leaf frame classes to handle this. |
|
1905 * |
|
1906 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set" |
|
1907 * here... I could switch it all to nscolor, but why bother? |
|
1908 */ |
|
1909 class nsDisplayReflowCount : public nsDisplayItem { |
|
1910 public: |
|
1911 nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
1912 const char* aFrameName, |
|
1913 uint32_t aColor = 0) |
|
1914 : nsDisplayItem(aBuilder, aFrame), |
|
1915 mFrameName(aFrameName), |
|
1916 mColor(aColor) |
|
1917 { |
|
1918 MOZ_COUNT_CTOR(nsDisplayReflowCount); |
|
1919 } |
|
1920 #ifdef NS_BUILD_REFCNT_LOGGING |
|
1921 virtual ~nsDisplayReflowCount() { |
|
1922 MOZ_COUNT_DTOR(nsDisplayReflowCount); |
|
1923 } |
|
1924 #endif |
|
1925 |
|
1926 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE { |
|
1927 mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx, |
|
1928 mFrame->PresContext(), |
|
1929 mFrame, ToReferenceFrame(), |
|
1930 mColor); |
|
1931 } |
|
1932 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT) |
|
1933 protected: |
|
1934 const char* mFrameName; |
|
1935 nscolor mColor; |
|
1936 }; |
|
1937 |
|
1938 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \ |
|
1939 PR_BEGIN_MACRO \ |
|
1940 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \ |
|
1941 PresContext()->PresShell()->IsPaintingFrameCounts()) { \ |
|
1942 aLists.Outlines()->AppendNewToTop( \ |
|
1943 new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \ |
|
1944 } \ |
|
1945 PR_END_MACRO |
|
1946 |
|
1947 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \ |
|
1948 PR_BEGIN_MACRO \ |
|
1949 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \ |
|
1950 PresContext()->PresShell()->IsPaintingFrameCounts()) { \ |
|
1951 aLists.Outlines()->AppendNewToTop( \ |
|
1952 new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \ |
|
1953 } \ |
|
1954 PR_END_MACRO |
|
1955 |
|
1956 /* |
|
1957 Macro to be used for classes that don't actually implement BuildDisplayList |
|
1958 */ |
|
1959 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \ |
|
1960 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \ |
|
1961 const nsRect& aDirtyRect, \ |
|
1962 const nsDisplayListSet& aLists) { \ |
|
1963 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \ |
|
1964 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \ |
|
1965 } |
|
1966 |
|
1967 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF |
|
1968 |
|
1969 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) |
|
1970 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) |
|
1971 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) |
|
1972 |
|
1973 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF |
|
1974 |
|
1975 class nsDisplayCaret : public nsDisplayItem { |
|
1976 public: |
|
1977 nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame, |
|
1978 nsCaret *aCaret) |
|
1979 : nsDisplayItem(aBuilder, aCaretFrame), mCaret(aCaret) { |
|
1980 MOZ_COUNT_CTOR(nsDisplayCaret); |
|
1981 } |
|
1982 #ifdef NS_BUILD_REFCNT_LOGGING |
|
1983 virtual ~nsDisplayCaret() { |
|
1984 MOZ_COUNT_DTOR(nsDisplayCaret); |
|
1985 } |
|
1986 #endif |
|
1987 |
|
1988 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { |
|
1989 *aSnap = false; |
|
1990 // The caret returns a rect in the coordinates of mFrame. |
|
1991 return mCaret->GetCaretRect() + ToReferenceFrame(); |
|
1992 } |
|
1993 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
1994 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET) |
|
1995 protected: |
|
1996 nsRefPtr<nsCaret> mCaret; |
|
1997 }; |
|
1998 |
|
1999 /** |
|
2000 * The standard display item to paint the CSS borders of a frame. |
|
2001 */ |
|
2002 class nsDisplayBorder : public nsDisplayItem { |
|
2003 public: |
|
2004 nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : |
|
2005 nsDisplayItem(aBuilder, aFrame) |
|
2006 { |
|
2007 MOZ_COUNT_CTOR(nsDisplayBorder); |
|
2008 } |
|
2009 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2010 virtual ~nsDisplayBorder() { |
|
2011 MOZ_COUNT_DTOR(nsDisplayBorder); |
|
2012 } |
|
2013 #endif |
|
2014 |
|
2015 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2016 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2017 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2018 nsRegion* aVisibleRegion, |
|
2019 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2020 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER) |
|
2021 |
|
2022 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2023 |
|
2024 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2025 const nsDisplayItemGeometry* aGeometry, |
|
2026 nsRegion* aInvalidRegion) MOZ_OVERRIDE; |
|
2027 |
|
2028 protected: |
|
2029 nsRect CalculateBounds(const nsStyleBorder& aStyleBorder); |
|
2030 }; |
|
2031 |
|
2032 /** |
|
2033 * A simple display item that just renders a solid color across the |
|
2034 * specified bounds. For canvas frames (in the CSS sense) we split off the |
|
2035 * drawing of the background color into this class (from nsDisplayBackground |
|
2036 * via nsDisplayCanvasBackground). This is done so that we can always draw a |
|
2037 * background color to avoid ugly flashes of white when we can't draw a full |
|
2038 * frame tree (ie when a page is loading). The bounds can differ from the |
|
2039 * frame's bounds -- this is needed when a frame/iframe is loading and there |
|
2040 * is not yet a frame tree to go in the frame/iframe so we use the subdoc |
|
2041 * frame of the parent document as a standin. |
|
2042 */ |
|
2043 class nsDisplaySolidColor : public nsDisplayItem { |
|
2044 public: |
|
2045 nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2046 const nsRect& aBounds, nscolor aColor) |
|
2047 : nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor) |
|
2048 { |
|
2049 NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!"); |
|
2050 MOZ_COUNT_CTOR(nsDisplaySolidColor); |
|
2051 } |
|
2052 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2053 virtual ~nsDisplaySolidColor() { |
|
2054 MOZ_COUNT_DTOR(nsDisplaySolidColor); |
|
2055 } |
|
2056 #endif |
|
2057 |
|
2058 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2059 |
|
2060 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2061 bool* aSnap) MOZ_OVERRIDE { |
|
2062 *aSnap = false; |
|
2063 nsRegion result; |
|
2064 if (NS_GET_A(mColor) == 255) { |
|
2065 result = GetBounds(aBuilder, aSnap); |
|
2066 } |
|
2067 return result; |
|
2068 } |
|
2069 |
|
2070 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE |
|
2071 { |
|
2072 *aColor = mColor; |
|
2073 return true; |
|
2074 } |
|
2075 |
|
2076 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2077 |
|
2078 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
2079 { |
|
2080 return new nsDisplaySolidColorGeometry(this, aBuilder, mColor); |
|
2081 } |
|
2082 |
|
2083 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2084 const nsDisplayItemGeometry* aGeometry, |
|
2085 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
2086 { |
|
2087 const nsDisplaySolidColorGeometry* geometry = |
|
2088 static_cast<const nsDisplaySolidColorGeometry*>(aGeometry); |
|
2089 if (mColor != geometry->mColor) { |
|
2090 bool dummy; |
|
2091 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy)); |
|
2092 return; |
|
2093 } |
|
2094 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion); |
|
2095 } |
|
2096 |
|
2097 #ifdef MOZ_DUMP_PAINTING |
|
2098 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; |
|
2099 #endif |
|
2100 |
|
2101 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR) |
|
2102 |
|
2103 private: |
|
2104 nsRect mBounds; |
|
2105 nscolor mColor; |
|
2106 }; |
|
2107 |
|
2108 /** |
|
2109 * A display item to paint one background-image for a frame. Each background |
|
2110 * image layer gets its own nsDisplayBackgroundImage. |
|
2111 */ |
|
2112 class nsDisplayBackgroundImage : public nsDisplayImageContainer { |
|
2113 public: |
|
2114 /** |
|
2115 * aLayer signifies which background layer this item represents. |
|
2116 * aIsThemed should be the value of aFrame->IsThemed. |
|
2117 * aBackgroundStyle should be the result of |
|
2118 * nsCSSRendering::FindBackground, or null if FindBackground returned false. |
|
2119 */ |
|
2120 nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2121 uint32_t aLayer, |
|
2122 const nsStyleBackground* aBackgroundStyle); |
|
2123 virtual ~nsDisplayBackgroundImage(); |
|
2124 |
|
2125 // This will create and append new items for all the layers of the |
|
2126 // background. Returns whether we appended a themed background. |
|
2127 static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder, |
|
2128 nsIFrame* aFrame, |
|
2129 nsDisplayList* aList); |
|
2130 |
|
2131 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2132 LayerManager* aManager, |
|
2133 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; |
|
2134 |
|
2135 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2136 LayerManager* aManager, |
|
2137 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2138 |
|
2139 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
2140 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
2141 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2142 nsRegion* aVisibleRegion, |
|
2143 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2144 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2145 bool* aSnap) MOZ_OVERRIDE; |
|
2146 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder, |
|
2147 nsIFrame* aFrame) MOZ_OVERRIDE; |
|
2148 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE; |
|
2149 /** |
|
2150 * GetBounds() returns the background painting area. |
|
2151 */ |
|
2152 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2153 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2154 virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE; |
|
2155 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND) |
|
2156 |
|
2157 /** |
|
2158 * Return the background positioning area. |
|
2159 * (GetBounds() returns the background painting area.) |
|
2160 * Can be called only when mBackgroundStyle is non-null. |
|
2161 */ |
|
2162 nsRect GetPositioningArea(); |
|
2163 |
|
2164 /** |
|
2165 * Returns true if existing rendered pixels of this display item may need |
|
2166 * to be redrawn if the positioning area size changes but its position does |
|
2167 * not. |
|
2168 * If false, only the changed painting area needs to be redrawn when the |
|
2169 * positioning area size changes but its position does not. |
|
2170 */ |
|
2171 bool RenderingMightDependOnPositioningAreaSizeChange(); |
|
2172 |
|
2173 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
2174 { |
|
2175 return new nsDisplayBackgroundGeometry(this, aBuilder); |
|
2176 } |
|
2177 |
|
2178 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2179 const nsDisplayItemGeometry* aGeometry, |
|
2180 nsRegion* aInvalidRegion) MOZ_OVERRIDE; |
|
2181 |
|
2182 virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager, |
|
2183 nsDisplayListBuilder *aBuilder) MOZ_OVERRIDE; |
|
2184 virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE; |
|
2185 |
|
2186 static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, nsPresContext* aPresContext, uint8_t aClip, |
|
2187 const nsRect& aRect, bool* aSnap); |
|
2188 |
|
2189 protected: |
|
2190 typedef class mozilla::layers::ImageContainer ImageContainer; |
|
2191 typedef class mozilla::layers::ImageLayer ImageLayer; |
|
2192 |
|
2193 bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder); |
|
2194 bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, |
|
2195 const nsRect& aClipRect, |
|
2196 gfxRect* aDestRect); |
|
2197 nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder); |
|
2198 |
|
2199 void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, |
|
2200 const nsRect& aBounds, nsRect* aClipRect); |
|
2201 |
|
2202 // Cache the result of nsCSSRendering::FindBackground. Always null if |
|
2203 // mIsThemed is true or if FindBackground returned false. |
|
2204 const nsStyleBackground* mBackgroundStyle; |
|
2205 /* If this background can be a simple image layer, we store the format here. */ |
|
2206 nsRefPtr<ImageContainer> mImageContainer; |
|
2207 gfxRect mDestRect; |
|
2208 /* Bounds of this display item */ |
|
2209 nsRect mBounds; |
|
2210 uint32_t mLayer; |
|
2211 }; |
|
2212 |
|
2213 |
|
2214 /** |
|
2215 * A display item to paint the native theme background for a frame. |
|
2216 */ |
|
2217 class nsDisplayThemedBackground : public nsDisplayItem { |
|
2218 public: |
|
2219 nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame); |
|
2220 virtual ~nsDisplayThemedBackground(); |
|
2221 |
|
2222 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
2223 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
2224 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2225 bool* aSnap) MOZ_OVERRIDE; |
|
2226 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE; |
|
2227 /** |
|
2228 * GetBounds() returns the background painting area. |
|
2229 */ |
|
2230 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2231 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2232 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND) |
|
2233 |
|
2234 /** |
|
2235 * Return the background positioning area. |
|
2236 * (GetBounds() returns the background painting area.) |
|
2237 * Can be called only when mBackgroundStyle is non-null. |
|
2238 */ |
|
2239 nsRect GetPositioningArea(); |
|
2240 |
|
2241 /** |
|
2242 * Return whether our frame's document does not have the state |
|
2243 * NS_DOCUMENT_STATE_WINDOW_INACTIVE. |
|
2244 */ |
|
2245 bool IsWindowActive(); |
|
2246 |
|
2247 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
2248 { |
|
2249 return new nsDisplayThemedBackgroundGeometry(this, aBuilder); |
|
2250 } |
|
2251 |
|
2252 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2253 const nsDisplayItemGeometry* aGeometry, |
|
2254 nsRegion* aInvalidRegion) MOZ_OVERRIDE; |
|
2255 |
|
2256 #ifdef MOZ_DUMP_PAINTING |
|
2257 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; |
|
2258 #endif |
|
2259 protected: |
|
2260 nsRect GetBoundsInternal(); |
|
2261 |
|
2262 void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, |
|
2263 const nsRect& aBounds, nsRect* aClipRect); |
|
2264 |
|
2265 nsRect mBounds; |
|
2266 nsITheme::Transparency mThemeTransparency; |
|
2267 uint8_t mAppearance; |
|
2268 }; |
|
2269 |
|
2270 class nsDisplayBackgroundColor : public nsDisplayItem |
|
2271 { |
|
2272 public: |
|
2273 nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2274 const nsStyleBackground* aBackgroundStyle, |
|
2275 nscolor aColor) |
|
2276 : nsDisplayItem(aBuilder, aFrame) |
|
2277 , mBackgroundStyle(aBackgroundStyle) |
|
2278 , mColor(aColor) |
|
2279 { } |
|
2280 |
|
2281 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2282 |
|
2283 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2284 bool* aSnap) MOZ_OVERRIDE; |
|
2285 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE; |
|
2286 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
2287 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
2288 |
|
2289 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE |
|
2290 { |
|
2291 *aSnap = true; |
|
2292 return nsRect(ToReferenceFrame(), Frame()->GetSize()); |
|
2293 } |
|
2294 |
|
2295 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
2296 { |
|
2297 return new nsDisplayItemBoundsGeometry(this, aBuilder); |
|
2298 } |
|
2299 |
|
2300 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2301 const nsDisplayItemGeometry* aGeometry, |
|
2302 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
2303 { |
|
2304 const nsDisplayItemBoundsGeometry* geometry = static_cast<const nsDisplayItemBoundsGeometry*>(aGeometry); |
|
2305 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion); |
|
2306 } |
|
2307 |
|
2308 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR) |
|
2309 #ifdef MOZ_DUMP_PAINTING |
|
2310 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; |
|
2311 #endif |
|
2312 |
|
2313 protected: |
|
2314 const nsStyleBackground* mBackgroundStyle; |
|
2315 nscolor mColor; |
|
2316 }; |
|
2317 |
|
2318 /** |
|
2319 * The standard display item to paint the outer CSS box-shadows of a frame. |
|
2320 */ |
|
2321 class nsDisplayBoxShadowOuter : public nsDisplayItem { |
|
2322 public: |
|
2323 nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
2324 : nsDisplayItem(aBuilder, aFrame) |
|
2325 , mOpacity(1.0) { |
|
2326 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter); |
|
2327 mBounds = GetBoundsInternal(); |
|
2328 } |
|
2329 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2330 virtual ~nsDisplayBoxShadowOuter() { |
|
2331 MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter); |
|
2332 } |
|
2333 #endif |
|
2334 |
|
2335 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2336 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2337 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2338 nsRegion* aVisibleRegion, |
|
2339 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2340 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER) |
|
2341 |
|
2342 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2343 const nsDisplayItemGeometry* aGeometry, |
|
2344 nsRegion* aInvalidRegion) MOZ_OVERRIDE; |
|
2345 |
|
2346 virtual bool ApplyOpacity(nsDisplayListBuilder* aBuilder, |
|
2347 float aOpacity, |
|
2348 const DisplayItemClip* aClip) MOZ_OVERRIDE |
|
2349 { |
|
2350 mOpacity = aOpacity; |
|
2351 if (aClip) { |
|
2352 IntersectClip(aBuilder, *aClip); |
|
2353 } |
|
2354 return true; |
|
2355 } |
|
2356 |
|
2357 nsRect GetBoundsInternal(); |
|
2358 |
|
2359 private: |
|
2360 nsRegion mVisibleRegion; |
|
2361 nsRect mBounds; |
|
2362 float mOpacity; |
|
2363 }; |
|
2364 |
|
2365 /** |
|
2366 * The standard display item to paint the inner CSS box-shadows of a frame. |
|
2367 */ |
|
2368 class nsDisplayBoxShadowInner : public nsDisplayItem { |
|
2369 public: |
|
2370 nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
2371 : nsDisplayItem(aBuilder, aFrame) { |
|
2372 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner); |
|
2373 } |
|
2374 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2375 virtual ~nsDisplayBoxShadowInner() { |
|
2376 MOZ_COUNT_DTOR(nsDisplayBoxShadowInner); |
|
2377 } |
|
2378 #endif |
|
2379 |
|
2380 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2381 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2382 nsRegion* aVisibleRegion, |
|
2383 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2384 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER) |
|
2385 |
|
2386 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
2387 { |
|
2388 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder); |
|
2389 } |
|
2390 |
|
2391 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2392 const nsDisplayItemGeometry* aGeometry, |
|
2393 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
2394 { |
|
2395 const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry); |
|
2396 if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) { |
|
2397 // nsDisplayBoxShadowInner is based around the padding rect, but it can |
|
2398 // touch pixels outside of this. We should invalidate the entire bounds. |
|
2399 bool snap; |
|
2400 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap)); |
|
2401 } |
|
2402 } |
|
2403 |
|
2404 private: |
|
2405 nsRegion mVisibleRegion; |
|
2406 }; |
|
2407 |
|
2408 /** |
|
2409 * The standard display item to paint the CSS outline of a frame. |
|
2410 */ |
|
2411 class nsDisplayOutline : public nsDisplayItem { |
|
2412 public: |
|
2413 nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : |
|
2414 nsDisplayItem(aBuilder, aFrame) { |
|
2415 MOZ_COUNT_CTOR(nsDisplayOutline); |
|
2416 } |
|
2417 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2418 virtual ~nsDisplayOutline() { |
|
2419 MOZ_COUNT_DTOR(nsDisplayOutline); |
|
2420 } |
|
2421 #endif |
|
2422 |
|
2423 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2424 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2425 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2426 nsRegion* aVisibleRegion, |
|
2427 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2428 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE) |
|
2429 }; |
|
2430 |
|
2431 /** |
|
2432 * A class that lets you receive events within the frame bounds but never paints. |
|
2433 */ |
|
2434 class nsDisplayEventReceiver : public nsDisplayItem { |
|
2435 public: |
|
2436 nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
2437 : nsDisplayItem(aBuilder, aFrame) { |
|
2438 MOZ_COUNT_CTOR(nsDisplayEventReceiver); |
|
2439 } |
|
2440 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2441 virtual ~nsDisplayEventReceiver() { |
|
2442 MOZ_COUNT_DTOR(nsDisplayEventReceiver); |
|
2443 } |
|
2444 #endif |
|
2445 |
|
2446 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
2447 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
2448 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER) |
|
2449 }; |
|
2450 |
|
2451 /** |
|
2452 * A display item that tracks event-sensitive regions which will be set |
|
2453 * on the ContainerLayer that eventually contains this item. |
|
2454 * |
|
2455 * One of these is created for each stacking context and pseudo-stacking-context. |
|
2456 * It accumulates regions for event targets contributed by the border-boxes of |
|
2457 * frames in its (pseudo) stacking context. A nsDisplayLayerEventRegions |
|
2458 * eventually contributes its regions to the ThebesLayer it is placed in by |
|
2459 * FrameLayerBuilder. (We don't create a display item for every frame that |
|
2460 * could be an event target (i.e. almost all frames), because that would be |
|
2461 * high overhead.) |
|
2462 * |
|
2463 * We always make leaf layers other than ThebesLayers transparent to events. |
|
2464 * For example, an event targeting a canvas or video will actually target the |
|
2465 * background of that element, which is logically in the ThebesLayer behind the |
|
2466 * CanvasFrame or ImageFrame. We only need to create a |
|
2467 * nsDisplayLayerEventRegions when an element's background could be in front |
|
2468 * of a lower z-order element with its own layer. |
|
2469 */ |
|
2470 class nsDisplayLayerEventRegions MOZ_FINAL : public nsDisplayItem { |
|
2471 public: |
|
2472 nsDisplayLayerEventRegions(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
2473 : nsDisplayItem(aBuilder, aFrame) |
|
2474 { |
|
2475 MOZ_COUNT_CTOR(nsDisplayEventReceiver); |
|
2476 AddFrame(aBuilder, aFrame); |
|
2477 } |
|
2478 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2479 virtual ~nsDisplayLayerEventRegions() { |
|
2480 MOZ_COUNT_DTOR(nsDisplayEventReceiver); |
|
2481 } |
|
2482 #endif |
|
2483 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE |
|
2484 { |
|
2485 *aSnap = false; |
|
2486 return mHitRegion.GetBounds().Union(mMaybeHitRegion.GetBounds()); |
|
2487 } |
|
2488 |
|
2489 NS_DISPLAY_DECL_NAME("LayerEventRegions", TYPE_LAYER_EVENT_REGIONS) |
|
2490 |
|
2491 // Indicate that aFrame's border-box contributes to the event regions for |
|
2492 // this layer. aFrame must have the same reference frame as mFrame. |
|
2493 void AddFrame(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame); |
|
2494 |
|
2495 const nsRegion& HitRegion() { return mHitRegion; } |
|
2496 const nsRegion& MaybeHitRegion() { return mMaybeHitRegion; } |
|
2497 const nsRegion& DispatchToContentHitRegion() { return mDispatchToContentHitRegion; } |
|
2498 |
|
2499 private: |
|
2500 // Relative to aFrame's reference frame. |
|
2501 // These are the points that are definitely in the hit region. |
|
2502 nsRegion mHitRegion; |
|
2503 // These are points that may or may not be in the hit region. Only main-thread |
|
2504 // event handling can tell for sure (e.g. because complex shapes are present). |
|
2505 nsRegion mMaybeHitRegion; |
|
2506 // These are points that need to be dispatched to the content thread for |
|
2507 // resolution. Always contained in the union of mHitRegion and mMaybeHitRegion. |
|
2508 nsRegion mDispatchToContentHitRegion; |
|
2509 }; |
|
2510 |
|
2511 /** |
|
2512 * A class that lets you wrap a display list as a display item. |
|
2513 * |
|
2514 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped |
|
2515 * list has many items, it's not clear which one has the 'underlying frame'. |
|
2516 * Thus we force the creator to specify what the underlying frame is. The |
|
2517 * underlying frame should be the root of a stacking context, because sorting |
|
2518 * a list containing this item will not get at the children. |
|
2519 * |
|
2520 * In some cases (e.g., clipping) we want to wrap a list but we don't have a |
|
2521 * particular underlying frame that is a stacking context root. In that case |
|
2522 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must |
|
2523 * detect and handle this case. |
|
2524 */ |
|
2525 class nsDisplayWrapList : public nsDisplayItem { |
|
2526 // This is never instantiated directly, so no need to count constructors and |
|
2527 // destructors. |
|
2528 |
|
2529 public: |
|
2530 /** |
|
2531 * Takes all the items from aList and puts them in our list. |
|
2532 */ |
|
2533 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2534 nsDisplayList* aList); |
|
2535 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2536 nsDisplayItem* aItem); |
|
2537 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2538 nsDisplayItem* aItem, const nsIFrame* aReferenceFrame, const nsPoint& aToReferenceFrame); |
|
2539 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
2540 : nsDisplayItem(aBuilder, aFrame), mOverrideZIndex(0) {} |
|
2541 virtual ~nsDisplayWrapList(); |
|
2542 /** |
|
2543 * Call this if the wrapped list is changed. |
|
2544 */ |
|
2545 virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
2546 { |
|
2547 mBounds = mList.GetBounds(aBuilder); |
|
2548 } |
|
2549 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
2550 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
2551 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2552 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2553 bool* aSnap) MOZ_OVERRIDE; |
|
2554 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE; |
|
2555 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder, |
|
2556 nsIFrame* aFrame) MOZ_OVERRIDE; |
|
2557 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
2558 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2559 nsRegion* aVisibleRegion, |
|
2560 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2561 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE { |
|
2562 NS_WARNING("This list should already have been flattened!!!"); |
|
2563 return false; |
|
2564 } |
|
2565 virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) MOZ_OVERRIDE |
|
2566 { |
|
2567 aFrames->AppendElements(mMergedFrames); |
|
2568 } |
|
2569 virtual bool IsInvalid(nsRect& aRect) MOZ_OVERRIDE |
|
2570 { |
|
2571 if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) { |
|
2572 return true; |
|
2573 } |
|
2574 nsRect temp; |
|
2575 for (uint32_t i = 0; i < mMergedFrames.Length(); i++) { |
|
2576 if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) { |
|
2577 aRect.SetEmpty(); |
|
2578 return true; |
|
2579 } |
|
2580 aRect = aRect.Union(temp); |
|
2581 } |
|
2582 aRect += ToReferenceFrame(); |
|
2583 return !aRect.IsEmpty(); |
|
2584 } |
|
2585 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST) |
|
2586 |
|
2587 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2588 |
|
2589 virtual nsDisplayList* GetSameCoordinateSystemChildren() MOZ_OVERRIDE |
|
2590 { |
|
2591 NS_ASSERTION(mList.IsEmpty() || !ReferenceFrame() || |
|
2592 !mList.GetBottom()->ReferenceFrame() || |
|
2593 mList.GetBottom()->ReferenceFrame() == ReferenceFrame(), |
|
2594 "Children must have same reference frame"); |
|
2595 return &mList; |
|
2596 } |
|
2597 virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return &mList; } |
|
2598 |
|
2599 virtual int32_t ZIndex() const MOZ_OVERRIDE |
|
2600 { |
|
2601 return (mOverrideZIndex > 0) ? mOverrideZIndex : nsDisplayItem::ZIndex(); |
|
2602 } |
|
2603 |
|
2604 void SetOverrideZIndex(int32_t aZIndex) |
|
2605 { |
|
2606 mOverrideZIndex = aZIndex; |
|
2607 } |
|
2608 |
|
2609 /** |
|
2610 * This creates a copy of this item, but wrapping aItem instead of |
|
2611 * our existing list. Only gets called if this item returned nullptr |
|
2612 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from |
|
2613 * GetUnderlyingFrame(). |
|
2614 */ |
|
2615 virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder, |
|
2616 nsDisplayItem* aItem) { |
|
2617 NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!"); |
|
2618 return nullptr; |
|
2619 } |
|
2620 |
|
2621 protected: |
|
2622 nsDisplayWrapList() {} |
|
2623 |
|
2624 void MergeFrom(nsDisplayWrapList* aOther) |
|
2625 { |
|
2626 mList.AppendToBottom(&aOther->mList); |
|
2627 mBounds.UnionRect(mBounds, aOther->mBounds); |
|
2628 } |
|
2629 void MergeFromTrackingMergedFrames(nsDisplayWrapList* aOther) |
|
2630 { |
|
2631 MergeFrom(aOther); |
|
2632 mMergedFrames.AppendElement(aOther->mFrame); |
|
2633 mMergedFrames.MoveElementsFrom(aOther->mMergedFrames); |
|
2634 } |
|
2635 |
|
2636 nsDisplayList mList; |
|
2637 // The frames from items that have been merged into this item, excluding |
|
2638 // this item's own frame. |
|
2639 nsTArray<nsIFrame*> mMergedFrames; |
|
2640 nsRect mBounds; |
|
2641 // Overrides the ZIndex of our frame if > 0. |
|
2642 int32_t mOverrideZIndex; |
|
2643 }; |
|
2644 |
|
2645 /** |
|
2646 * We call WrapDisplayList on the in-flow lists: BorderBackground(), |
|
2647 * BlockBorderBackgrounds() and Content(). |
|
2648 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(), |
|
2649 * and Floats(). This is done to support special wrapping processing for frames |
|
2650 * that may not be in-flow descendants of the current frame. |
|
2651 */ |
|
2652 class nsDisplayWrapper { |
|
2653 public: |
|
2654 // This is never instantiated directly (it has pure virtual methods), so no |
|
2655 // need to count constructors and destructors. |
|
2656 |
|
2657 virtual bool WrapBorderBackground() { return true; } |
|
2658 virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder, |
|
2659 nsIFrame* aFrame, nsDisplayList* aList) = 0; |
|
2660 virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder, |
|
2661 nsDisplayItem* aItem) = 0; |
|
2662 |
|
2663 nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2664 const nsDisplayListSet& aIn, const nsDisplayListSet& aOut); |
|
2665 nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2666 const nsDisplayListSet& aLists); |
|
2667 protected: |
|
2668 nsDisplayWrapper() {} |
|
2669 }; |
|
2670 |
|
2671 /** |
|
2672 * The standard display item to paint a stacking context with translucency |
|
2673 * set by the stacking context root frame's 'opacity' style. |
|
2674 */ |
|
2675 class nsDisplayOpacity : public nsDisplayWrapList { |
|
2676 public: |
|
2677 nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2678 nsDisplayList* aList); |
|
2679 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2680 virtual ~nsDisplayOpacity(); |
|
2681 #endif |
|
2682 |
|
2683 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2684 bool* aSnap) MOZ_OVERRIDE; |
|
2685 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2686 LayerManager* aManager, |
|
2687 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2688 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2689 LayerManager* aManager, |
|
2690 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; |
|
2691 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2692 nsRegion* aVisibleRegion, |
|
2693 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2694 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
2695 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2696 const nsDisplayItemGeometry* aGeometry, |
|
2697 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
2698 { |
|
2699 // We don't need to compute an invalidation region since we have LayerTreeInvalidation |
|
2700 } |
|
2701 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2702 bool NeedsActiveLayer(); |
|
2703 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY) |
|
2704 #ifdef MOZ_DUMP_PAINTING |
|
2705 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; |
|
2706 #endif |
|
2707 |
|
2708 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2709 }; |
|
2710 |
|
2711 class nsDisplayMixBlendMode : public nsDisplayWrapList { |
|
2712 public: |
|
2713 nsDisplayMixBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2714 nsDisplayList* aList, uint32_t aFlags = 0); |
|
2715 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2716 virtual ~nsDisplayMixBlendMode(); |
|
2717 #endif |
|
2718 |
|
2719 nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2720 bool* aSnap) MOZ_OVERRIDE; |
|
2721 |
|
2722 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2723 LayerManager* aManager, |
|
2724 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2725 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
2726 const nsDisplayItemGeometry* aGeometry, |
|
2727 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
2728 { |
|
2729 // We don't need to compute an invalidation region since we have LayerTreeInvalidation |
|
2730 } |
|
2731 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2732 LayerManager* aManager, |
|
2733 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
2734 { |
|
2735 return mozilla::LAYER_INACTIVE; |
|
2736 } |
|
2737 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2738 nsRegion* aVisibleRegion, |
|
2739 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2740 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
2741 NS_DISPLAY_DECL_NAME("MixBlendMode", TYPE_MIX_BLEND_MODE) |
|
2742 }; |
|
2743 |
|
2744 class nsDisplayBlendContainer : public nsDisplayWrapList { |
|
2745 public: |
|
2746 nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2747 nsDisplayList* aList, uint32_t aFlags = 0); |
|
2748 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2749 virtual ~nsDisplayBlendContainer(); |
|
2750 #endif |
|
2751 |
|
2752 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2753 LayerManager* aManager, |
|
2754 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2755 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2756 LayerManager* aManager, |
|
2757 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
2758 { |
|
2759 return mozilla::LAYER_INACTIVE; |
|
2760 } |
|
2761 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
2762 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER) |
|
2763 }; |
|
2764 |
|
2765 /** |
|
2766 * A display item that has no purpose but to ensure its contents get |
|
2767 * their own layer. |
|
2768 */ |
|
2769 class nsDisplayOwnLayer : public nsDisplayWrapList { |
|
2770 public: |
|
2771 |
|
2772 /** |
|
2773 * nsDisplayOwnLayer constructor flags |
|
2774 */ |
|
2775 enum { |
|
2776 GENERATE_SUBDOC_INVALIDATIONS = 0x01, |
|
2777 VERTICAL_SCROLLBAR = 0x02, |
|
2778 HORIZONTAL_SCROLLBAR = 0x04, |
|
2779 GENERATE_SCROLLABLE_LAYER = 0x08 |
|
2780 }; |
|
2781 |
|
2782 /** |
|
2783 * @param aFlags GENERATE_SUBDOC_INVALIDATIONS : |
|
2784 * Add UserData to the created ContainerLayer, so that invalidations |
|
2785 * for this layer are send to our nsPresContext. |
|
2786 * GENERATE_SCROLLABLE_LAYER : only valid on nsDisplaySubDocument (and |
|
2787 * subclasses), indicates this layer is to be a scrollable layer, so call |
|
2788 * RecordFrameMetrics, etc. |
|
2789 * @param aScrollTarget when VERTICAL_SCROLLBAR or HORIZONTAL_SCROLLBAR |
|
2790 * is set in the flags, this parameter should be the ViewID of the |
|
2791 * scrollable content this scrollbar is for. |
|
2792 */ |
|
2793 nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2794 nsDisplayList* aList, uint32_t aFlags = 0, |
|
2795 ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID); |
|
2796 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2797 virtual ~nsDisplayOwnLayer(); |
|
2798 #endif |
|
2799 |
|
2800 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2801 LayerManager* aManager, |
|
2802 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2803 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2804 LayerManager* aManager, |
|
2805 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
2806 { |
|
2807 return mozilla::LAYER_ACTIVE_FORCE; |
|
2808 } |
|
2809 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE |
|
2810 { |
|
2811 // Don't allow merging, each sublist must have its own layer |
|
2812 return false; |
|
2813 } |
|
2814 uint32_t GetFlags() { return mFlags; } |
|
2815 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER) |
|
2816 protected: |
|
2817 uint32_t mFlags; |
|
2818 ViewID mScrollTarget; |
|
2819 }; |
|
2820 |
|
2821 /** |
|
2822 * A display item for subdocuments. This is more or less the same as nsDisplayOwnLayer, |
|
2823 * except that it always populates the FrameMetrics instance on the ContainerLayer it |
|
2824 * builds. |
|
2825 */ |
|
2826 class nsDisplaySubDocument : public nsDisplayOwnLayer { |
|
2827 public: |
|
2828 nsDisplaySubDocument(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2829 nsDisplayList* aList, uint32_t aFlags); |
|
2830 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2831 virtual ~nsDisplaySubDocument(); |
|
2832 #endif |
|
2833 |
|
2834 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2835 LayerManager* aManager, |
|
2836 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2837 |
|
2838 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2839 |
|
2840 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2841 nsRegion* aVisibleRegion, |
|
2842 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2843 |
|
2844 virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return !(mFlags & GENERATE_SCROLLABLE_LAYER); } |
|
2845 |
|
2846 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2847 |
|
2848 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2849 |
|
2850 NS_DISPLAY_DECL_NAME("SubDocument", TYPE_SUBDOCUMENT) |
|
2851 protected: |
|
2852 ViewID mScrollParentId; |
|
2853 }; |
|
2854 |
|
2855 /** |
|
2856 * A display item for subdocuments to capture the resolution from the presShell |
|
2857 * and ensure that it gets applied to all the right elements. This item creates |
|
2858 * a container layer. |
|
2859 */ |
|
2860 class nsDisplayResolution : public nsDisplaySubDocument { |
|
2861 public: |
|
2862 nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2863 nsDisplayList* aList, uint32_t aFlags); |
|
2864 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2865 virtual ~nsDisplayResolution(); |
|
2866 #endif |
|
2867 |
|
2868 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2869 LayerManager* aManager, |
|
2870 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2871 NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION) |
|
2872 }; |
|
2873 |
|
2874 /** |
|
2875 * A display item used to represent sticky position elements. The contents |
|
2876 * gets its own layer and creates a stacking context, and the layer will have |
|
2877 * position-related metadata set on it. |
|
2878 */ |
|
2879 class nsDisplayStickyPosition : public nsDisplayOwnLayer { |
|
2880 public: |
|
2881 nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
2882 nsDisplayList* aList); |
|
2883 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2884 virtual ~nsDisplayStickyPosition(); |
|
2885 #endif |
|
2886 |
|
2887 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2888 LayerManager* aManager, |
|
2889 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2890 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION) |
|
2891 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2892 LayerManager* aManager, |
|
2893 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
2894 { |
|
2895 return mozilla::LAYER_ACTIVE; |
|
2896 } |
|
2897 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
2898 }; |
|
2899 |
|
2900 /** |
|
2901 * This potentially creates a layer for the given list of items, whose |
|
2902 * visibility is determined by the displayport for the given frame instead of |
|
2903 * what is passed in to ComputeVisibility. |
|
2904 * |
|
2905 * Here in content, we can use this to render more content than is actually |
|
2906 * visible. Then, the compositing process can manipulate the generated layer |
|
2907 * through transformations so that asynchronous scrolling can be implemented. |
|
2908 * |
|
2909 * Note that setting the displayport will not change any hit testing! The |
|
2910 * content process will know nothing about what the user is actually seeing, |
|
2911 * so it can only do hit testing for what is supposed to be the visible region. |
|
2912 * |
|
2913 * It is possible for scroll boxes to have content that can be both above and |
|
2914 * below content outside of the scroll box. We cannot create layers for these |
|
2915 * cases. This is accomplished by wrapping display items with |
|
2916 * nsDisplayScrollLayers. nsDisplayScrollLayers with the same scroll frame will |
|
2917 * be merged together. If more than one nsDisplayScrollLayer exists after |
|
2918 * merging, all nsDisplayScrollLayers will be flattened out so that no new |
|
2919 * layer is created at all. |
|
2920 */ |
|
2921 class nsDisplayScrollLayer : public nsDisplayWrapList |
|
2922 { |
|
2923 public: |
|
2924 /** |
|
2925 * @param aScrolledFrame This will determine what the displayport is. It should be |
|
2926 * the root content frame of the scrolled area. Note |
|
2927 * that nsDisplayScrollLayer will expect for |
|
2928 * ScrollLayerCount to be defined on aScrolledFrame. |
|
2929 * @param aScrollFrame The viewport frame you see this content through. |
|
2930 */ |
|
2931 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList, |
|
2932 nsIFrame* aForFrame, nsIFrame* aScrolledFrame, |
|
2933 nsIFrame* aScrollFrame); |
|
2934 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, |
|
2935 nsIFrame* aForFrame, nsIFrame* aScrolledFrame, |
|
2936 nsIFrame* aScrollFrame); |
|
2937 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, |
|
2938 nsIFrame* aForFrame, nsIFrame* aScrolledFrame, |
|
2939 nsIFrame* aScrollFrame); |
|
2940 NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER) |
|
2941 |
|
2942 #ifdef NS_BUILD_REFCNT_LOGGING |
|
2943 virtual ~nsDisplayScrollLayer(); |
|
2944 #endif |
|
2945 |
|
2946 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
2947 |
|
2948 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
2949 LayerManager* aManager, |
|
2950 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
2951 |
|
2952 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2953 |
|
2954 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
2955 bool* aSnap) MOZ_OVERRIDE { |
|
2956 *aSnap = false; |
|
2957 return nsRegion(); |
|
2958 } |
|
2959 |
|
2960 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
2961 nsRegion* aVisibleRegion, |
|
2962 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
2963 |
|
2964 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
2965 LayerManager* aManager, |
|
2966 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; |
|
2967 |
|
2968 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, |
|
2969 nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
2970 |
|
2971 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
2972 |
|
2973 // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this |
|
2974 // number does not include nsDisplayScrollInfoLayers. If this number is not 1 |
|
2975 // after merging, all the nsDisplayScrollLayers should flatten away. |
|
2976 intptr_t GetScrollLayerCount(); |
|
2977 |
|
2978 virtual nsIFrame* GetScrollFrame() { return mScrollFrame; } |
|
2979 virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; } |
|
2980 |
|
2981 virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; } |
|
2982 |
|
2983 #ifdef MOZ_DUMP_PAINTING |
|
2984 virtual void WriteDebugInfo(nsACString& aTo) MOZ_OVERRIDE; |
|
2985 #endif |
|
2986 |
|
2987 protected: |
|
2988 nsIFrame* mScrollFrame; |
|
2989 nsIFrame* mScrolledFrame; |
|
2990 ViewID mScrollParentId; |
|
2991 }; |
|
2992 |
|
2993 /** |
|
2994 * Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This |
|
2995 * creates a layer that has no Thebes child layer, but still allows the |
|
2996 * compositor process to know of the scroll frame's existence. |
|
2997 * |
|
2998 * After visibility computation, nsDisplayScrollInfoLayers should only exist if |
|
2999 * nsDisplayScrollLayers were all flattened away. |
|
3000 * |
|
3001 * Important!! Add info layers to the bottom of the list so they are only |
|
3002 * considered after the others have flattened out! |
|
3003 */ |
|
3004 class nsDisplayScrollInfoLayer : public nsDisplayScrollLayer |
|
3005 { |
|
3006 public: |
|
3007 nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder, |
|
3008 nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame); |
|
3009 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER) |
|
3010 |
|
3011 virtual ~nsDisplayScrollInfoLayer(); |
|
3012 |
|
3013 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
3014 |
|
3015 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
3016 LayerManager* aManager, |
|
3017 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; |
|
3018 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
3019 { return true; } |
|
3020 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, |
|
3021 nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
3022 |
|
3023 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
3024 }; |
|
3025 |
|
3026 /** |
|
3027 * nsDisplayZoom is used for subdocuments that have a different full zoom than |
|
3028 * their parent documents. This item creates a container layer. |
|
3029 */ |
|
3030 class nsDisplayZoom : public nsDisplaySubDocument { |
|
3031 public: |
|
3032 /** |
|
3033 * @param aFrame is the root frame of the subdocument. |
|
3034 * @param aList contains the display items for the subdocument. |
|
3035 * @param aAPD is the app units per dev pixel ratio of the subdocument. |
|
3036 * @param aParentAPD is the app units per dev pixel ratio of the parent |
|
3037 * document. |
|
3038 * @param aFlags GENERATE_SUBDOC_INVALIDATIONS : |
|
3039 * Add UserData to the created ContainerLayer, so that invalidations |
|
3040 * for this layer are send to our nsPresContext. |
|
3041 */ |
|
3042 nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
3043 nsDisplayList* aList, |
|
3044 int32_t aAPD, int32_t aParentAPD, |
|
3045 uint32_t aFlags = 0); |
|
3046 #ifdef NS_BUILD_REFCNT_LOGGING |
|
3047 virtual ~nsDisplayZoom(); |
|
3048 #endif |
|
3049 |
|
3050 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
3051 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; |
|
3052 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
3053 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
3054 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
3055 nsRegion* aVisibleRegion, |
|
3056 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
3057 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
3058 LayerManager* aManager, |
|
3059 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
3060 { |
|
3061 return mozilla::LAYER_ACTIVE; |
|
3062 } |
|
3063 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM) |
|
3064 |
|
3065 // Get the app units per dev pixel ratio of the child document. |
|
3066 int32_t GetChildAppUnitsPerDevPixel() { return mAPD; } |
|
3067 // Get the app units per dev pixel ratio of the parent document. |
|
3068 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; } |
|
3069 |
|
3070 private: |
|
3071 int32_t mAPD, mParentAPD; |
|
3072 }; |
|
3073 |
|
3074 /** |
|
3075 * A display item to paint a stacking context with effects |
|
3076 * set by the stacking context root frame's style. |
|
3077 */ |
|
3078 class nsDisplaySVGEffects : public nsDisplayWrapList { |
|
3079 public: |
|
3080 nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, |
|
3081 nsDisplayList* aList); |
|
3082 #ifdef NS_BUILD_REFCNT_LOGGING |
|
3083 virtual ~nsDisplaySVGEffects(); |
|
3084 #endif |
|
3085 |
|
3086 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
3087 bool* aSnap) MOZ_OVERRIDE; |
|
3088 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, |
|
3089 HitTestState* aState, |
|
3090 nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
3091 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, |
|
3092 bool* aSnap) MOZ_OVERRIDE { |
|
3093 *aSnap = false; |
|
3094 return mEffectsBounds + ToReferenceFrame(); |
|
3095 } |
|
3096 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
3097 nsRegion* aVisibleRegion, |
|
3098 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
3099 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, |
|
3100 nsDisplayItem* aItem) MOZ_OVERRIDE; |
|
3101 NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS) |
|
3102 |
|
3103 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
3104 LayerManager* aManager, |
|
3105 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; |
|
3106 |
|
3107 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
3108 LayerManager* aManager, |
|
3109 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
3110 |
|
3111 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
3112 const nsDisplayItemGeometry* aGeometry, |
|
3113 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
3114 { |
|
3115 // We don't need to compute an invalidation region since we have LayerTreeInvalidation |
|
3116 } |
|
3117 |
|
3118 void PaintAsLayer(nsDisplayListBuilder* aBuilder, |
|
3119 nsRenderingContext* aCtx, |
|
3120 LayerManager* aManager); |
|
3121 |
|
3122 #ifdef MOZ_DUMP_PAINTING |
|
3123 void PrintEffects(nsACString& aTo); |
|
3124 #endif |
|
3125 |
|
3126 private: |
|
3127 // relative to mFrame |
|
3128 nsRect mEffectsBounds; |
|
3129 }; |
|
3130 |
|
3131 /* A display item that applies a transformation to all of its descendant |
|
3132 * elements. This wrapper should only be used if there is a transform applied |
|
3133 * to the root element. |
|
3134 * |
|
3135 * The reason that a "bounds" rect is involved in transform calculations is |
|
3136 * because CSS-transforms allow percentage values for the x and y components |
|
3137 * of <translation-value>s, where percentages are percentages of the element's |
|
3138 * border box. |
|
3139 * |
|
3140 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter |
|
3141 * function. |
|
3142 * INVARIANT: The wrapped frame is non-null. |
|
3143 */ |
|
3144 class nsDisplayTransform: public nsDisplayItem |
|
3145 { |
|
3146 public: |
|
3147 /** |
|
3148 * Returns a matrix (in pixels) for the current frame. The matrix should be relative to |
|
3149 * the current frame's coordinate space. |
|
3150 * |
|
3151 * @param aFrame The frame to compute the transform for. |
|
3152 * @param aAppUnitsPerPixel The number of app units per graphics unit. |
|
3153 */ |
|
3154 typedef gfx3DMatrix (* ComputeTransformFunction)(nsIFrame* aFrame, float aAppUnitsPerPixel); |
|
3155 |
|
3156 /* Constructor accepts a display list, empties it, and wraps it up. It also |
|
3157 * ferries the underlying frame to the nsDisplayItem constructor. |
|
3158 */ |
|
3159 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, |
|
3160 nsDisplayList *aList, uint32_t aIndex = 0); |
|
3161 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, |
|
3162 nsDisplayItem *aItem, uint32_t aIndex = 0); |
|
3163 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, |
|
3164 nsDisplayList *aList, ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0); |
|
3165 |
|
3166 #ifdef NS_BUILD_REFCNT_LOGGING |
|
3167 virtual ~nsDisplayTransform() |
|
3168 { |
|
3169 MOZ_COUNT_DTOR(nsDisplayTransform); |
|
3170 } |
|
3171 #endif |
|
3172 |
|
3173 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM) |
|
3174 |
|
3175 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE |
|
3176 { |
|
3177 if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty()) |
|
3178 return nsRect(); |
|
3179 bool snap; |
|
3180 return GetBounds(aBuilder, &snap); |
|
3181 } |
|
3182 |
|
3183 virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return mStoredList.GetChildren(); } |
|
3184 |
|
3185 virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect, |
|
3186 HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE; |
|
3187 virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap) MOZ_OVERRIDE; |
|
3188 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder, |
|
3189 bool* aSnap) MOZ_OVERRIDE; |
|
3190 virtual bool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor) MOZ_OVERRIDE; |
|
3191 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
3192 LayerManager* aManager, |
|
3193 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; |
|
3194 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
3195 LayerManager* aManager, |
|
3196 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE; |
|
3197 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
3198 virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder, |
|
3199 nsRegion *aVisibleRegion, |
|
3200 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
3201 virtual bool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem) MOZ_OVERRIDE; |
|
3202 |
|
3203 virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); } |
|
3204 |
|
3205 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, |
|
3206 const nsDisplayItemGeometry* aGeometry, |
|
3207 nsRegion* aInvalidRegion) MOZ_OVERRIDE |
|
3208 { |
|
3209 // We don't need to compute an invalidation region since we have LayerTreeInvalidation |
|
3210 } |
|
3211 |
|
3212 virtual const nsIFrame* ReferenceFrameForChildren() const MOZ_OVERRIDE { |
|
3213 // If we were created using a transform-getter, then we don't |
|
3214 // belong to a transformed frame, and aren't a reference frame |
|
3215 // for our children. |
|
3216 if (!mTransformGetter) { |
|
3217 return mFrame; |
|
3218 } |
|
3219 return nsDisplayItem::ReferenceFrameForChildren(); |
|
3220 } |
|
3221 |
|
3222 enum { |
|
3223 INDEX_MAX = UINT32_MAX >> nsDisplayItem::TYPE_BITS |
|
3224 }; |
|
3225 |
|
3226 const gfx3DMatrix& GetTransform(); |
|
3227 |
|
3228 float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint); |
|
3229 |
|
3230 /** |
|
3231 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate |
|
3232 * space) and returns the smallest rectangle (in aFrame's coordinate space) |
|
3233 * containing the transformed image of that rectangle. That is, it takes |
|
3234 * the four corners of the rectangle, transforms them according to the |
|
3235 * matrix associated with the specified frame, then returns the smallest |
|
3236 * rectangle containing the four transformed points. |
|
3237 * |
|
3238 * @param untransformedBounds The rectangle (in app units) to transform. |
|
3239 * @param aFrame The frame whose transformation should be applied. This |
|
3240 * function raises an assertion if aFrame is null or doesn't have a |
|
3241 * transform applied to it. |
|
3242 * @param aOrigin The origin of the transform relative to aFrame's local |
|
3243 * coordinate space. |
|
3244 * @param aBoundsOverride (optional) Rather than using the frame's computed |
|
3245 * bounding rect as frame bounds, use this rectangle instead. Pass |
|
3246 * nullptr (or nothing at all) to use the default. |
|
3247 */ |
|
3248 static nsRect TransformRect(const nsRect &aUntransformedBounds, |
|
3249 const nsIFrame* aFrame, |
|
3250 const nsPoint &aOrigin, |
|
3251 const nsRect* aBoundsOverride = nullptr); |
|
3252 |
|
3253 static nsRect TransformRectOut(const nsRect &aUntransformedBounds, |
|
3254 const nsIFrame* aFrame, |
|
3255 const nsPoint &aOrigin, |
|
3256 const nsRect* aBoundsOverride = nullptr); |
|
3257 |
|
3258 /* UntransformRect is like TransformRect, except that it inverts the |
|
3259 * transform. |
|
3260 */ |
|
3261 static bool UntransformRect(const nsRect &aTransformedBounds, |
|
3262 const nsRect &aChildBounds, |
|
3263 const nsIFrame* aFrame, |
|
3264 const nsPoint &aOrigin, |
|
3265 nsRect *aOutRect); |
|
3266 |
|
3267 bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder, |
|
3268 nsRect* aOutRect); |
|
3269 |
|
3270 static gfxPoint3D GetDeltaToTransformOrigin(const nsIFrame* aFrame, |
|
3271 float aAppUnitsPerPixel, |
|
3272 const nsRect* aBoundsOverride); |
|
3273 |
|
3274 static gfxPoint3D GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame, |
|
3275 float aAppUnitsPerPixel); |
|
3276 |
|
3277 /** |
|
3278 * Returns the bounds of a frame as defined for resolving percentage |
|
3279 * <translation-value>s in CSS transforms. If |
|
3280 * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding |
|
3281 * rectangle, translated to the origin. Otherwise, returns the smallest |
|
3282 * rectangle containing a frame and all of its continuations. For example, |
|
3283 * if there is a <span> element with several continuations split over |
|
3284 * several lines, this function will return the rectangle containing all of |
|
3285 * those continuations. This rectangle is relative to the origin of the |
|
3286 * frame's local coordinate space. |
|
3287 * |
|
3288 * @param aFrame The frame to get the bounding rect for. |
|
3289 * @return The frame's bounding rect, as described above. |
|
3290 */ |
|
3291 static nsRect GetFrameBoundsForTransform(const nsIFrame* aFrame); |
|
3292 |
|
3293 struct FrameTransformProperties |
|
3294 { |
|
3295 FrameTransformProperties(const nsIFrame* aFrame, |
|
3296 float aAppUnitsPerPixel, |
|
3297 const nsRect* aBoundsOverride); |
|
3298 FrameTransformProperties(nsCSSValueSharedList* aTransformList, |
|
3299 const gfxPoint3D& aToTransformOrigin, |
|
3300 const gfxPoint3D& aToPerspectiveOrigin, |
|
3301 nscoord aChildPerspective) |
|
3302 : mFrame(nullptr) |
|
3303 , mTransformList(aTransformList) |
|
3304 , mToTransformOrigin(aToTransformOrigin) |
|
3305 , mToPerspectiveOrigin(aToPerspectiveOrigin) |
|
3306 , mChildPerspective(aChildPerspective) |
|
3307 {} |
|
3308 |
|
3309 const nsIFrame* mFrame; |
|
3310 nsRefPtr<nsCSSValueSharedList> mTransformList; |
|
3311 const gfxPoint3D mToTransformOrigin; |
|
3312 const gfxPoint3D mToPerspectiveOrigin; |
|
3313 nscoord mChildPerspective; |
|
3314 }; |
|
3315 |
|
3316 /** |
|
3317 * Given a frame with the -moz-transform property or an SVG transform, |
|
3318 * returns the transformation matrix for that frame. |
|
3319 * |
|
3320 * @param aFrame The frame to get the matrix from. |
|
3321 * @param aOrigin Relative to which point this transform should be applied. |
|
3322 * @param aAppUnitsPerPixel The number of app units per graphics unit. |
|
3323 * @param aBoundsOverride [optional] If this is nullptr (the default), the |
|
3324 * computation will use the value of GetFrameBoundsForTransform(aFrame) |
|
3325 * for the frame's bounding rectangle. Otherwise, it will use the |
|
3326 * value of aBoundsOverride. This is mostly for internal use and in |
|
3327 * most cases you will not need to specify a value. |
|
3328 */ |
|
3329 static gfx3DMatrix GetResultingTransformMatrix(const nsIFrame* aFrame, |
|
3330 const nsPoint& aOrigin, |
|
3331 float aAppUnitsPerPixel, |
|
3332 const nsRect* aBoundsOverride = nullptr, |
|
3333 nsIFrame** aOutAncestor = nullptr); |
|
3334 static gfx3DMatrix GetResultingTransformMatrix(const FrameTransformProperties& aProperties, |
|
3335 const nsPoint& aOrigin, |
|
3336 float aAppUnitsPerPixel, |
|
3337 const nsRect* aBoundsOverride = nullptr, |
|
3338 nsIFrame** aOutAncestor = nullptr); |
|
3339 /** |
|
3340 * Return true when we should try to prerender the entire contents of the |
|
3341 * transformed frame even when it's not completely visible (yet). |
|
3342 */ |
|
3343 static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder, |
|
3344 nsIFrame* aFrame, |
|
3345 bool aLogAnimations = false); |
|
3346 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; |
|
3347 |
|
3348 virtual bool SetVisibleRegionOnLayer() MOZ_OVERRIDE { return false; } |
|
3349 |
|
3350 private: |
|
3351 static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties, |
|
3352 const nsPoint& aOrigin, |
|
3353 float aAppUnitsPerPixel, |
|
3354 const nsRect* aBoundsOverride, |
|
3355 nsIFrame** aOutAncestor); |
|
3356 |
|
3357 nsDisplayWrapList mStoredList; |
|
3358 gfx3DMatrix mTransform; |
|
3359 ComputeTransformFunction mTransformGetter; |
|
3360 uint32_t mIndex; |
|
3361 }; |
|
3362 |
|
3363 /** |
|
3364 * This class adds basic support for limiting the rendering to the part inside |
|
3365 * the specified edges. It's a base class for the display item classes that |
|
3366 * does the actual work. The two members, mLeftEdge and mRightEdge, are |
|
3367 * relative to the edges of the frame's scrollable overflow rectangle and is |
|
3368 * the amount to suppress on each side. |
|
3369 * |
|
3370 * Setting none, both or only one edge is allowed. |
|
3371 * The values must be non-negative. |
|
3372 * The default value for both edges is zero, which means everything is painted. |
|
3373 */ |
|
3374 class nsCharClipDisplayItem : public nsDisplayItem { |
|
3375 public: |
|
3376 nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
3377 : nsDisplayItem(aBuilder, aFrame), mLeftEdge(0), mRightEdge(0) {} |
|
3378 |
|
3379 nsCharClipDisplayItem(nsIFrame* aFrame) |
|
3380 : nsDisplayItem(aFrame) {} |
|
3381 |
|
3382 struct ClipEdges { |
|
3383 ClipEdges(const nsDisplayItem& aItem, |
|
3384 nscoord aLeftEdge, nscoord aRightEdge) { |
|
3385 nsRect r = aItem.Frame()->GetScrollableOverflowRect() + |
|
3386 aItem.ToReferenceFrame(); |
|
3387 mX = aLeftEdge > 0 ? r.x + aLeftEdge : nscoord_MIN; |
|
3388 mXMost = aRightEdge > 0 ? std::max(r.XMost() - aRightEdge, mX) : nscoord_MAX; |
|
3389 } |
|
3390 void Intersect(nscoord* aX, nscoord* aWidth) const { |
|
3391 nscoord xmost1 = *aX + *aWidth; |
|
3392 *aX = std::max(*aX, mX); |
|
3393 *aWidth = std::max(std::min(xmost1, mXMost) - *aX, 0); |
|
3394 } |
|
3395 nscoord mX; |
|
3396 nscoord mXMost; |
|
3397 }; |
|
3398 |
|
3399 ClipEdges Edges() const { return ClipEdges(*this, mLeftEdge, mRightEdge); } |
|
3400 |
|
3401 static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) { |
|
3402 nsDisplayItem::Type t = aItem->GetType(); |
|
3403 return (t == nsDisplayItem::TYPE_TEXT || |
|
3404 t == nsDisplayItem::TYPE_TEXT_DECORATION || |
|
3405 t == nsDisplayItem::TYPE_TEXT_SHADOW) |
|
3406 ? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr; |
|
3407 } |
|
3408 |
|
3409 nscoord mLeftEdge; // length from the left side |
|
3410 nscoord mRightEdge; // length from the right side |
|
3411 }; |
|
3412 |
|
3413 #endif /*NSDISPLAYLIST_H_*/ |