layout/base/nsDisplayList.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:31e28748f3b6
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_*/

mercurial