Merge mozilla-beta to b2g28. a=merge
[gecko.git] / layout / base / nsDisplayList.h
bloba3926c09c176bf27a5ebca40d98fc7e62d435a84
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 */
8 /*
9 * structures that represent things to be painted (ordered in z-order),
10 * used during painting and hit testing
13 #ifndef NSDISPLAYLIST_H_
14 #define NSDISPLAYLIST_H_
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"
29 #include <stdint.h>
31 #include <stdlib.h>
32 #include <algorithm>
34 class nsIContent;
35 class nsRenderingContext;
36 class nsDisplayTableItem;
37 class nsISelection;
39 namespace mozilla {
40 namespace layers {
41 class ImageLayer;
42 class ImageContainer;
43 } //namepsace
44 } //namepsace
47 * An nsIFrame can have many different visual parts. For example an image frame
48 * can have a background, border, and outline, the image itself, and a
49 * translucent selection overlay. In general these parts can be drawn at
50 * discontiguous z-levels; see CSS2.1 appendix E:
51 * http://www.w3.org/TR/CSS21/zindex.html
53 * We construct a display list for a frame tree that contains one item
54 * for each visual part. The display list is itself a tree since some items
55 * are containers for other items; however, its structure does not match
56 * the structure of its source frame tree. The display list items are sorted
57 * by z-order. A display list can be used to paint the frames, to determine
58 * which frame is the target of a mouse event, and to determine what areas
59 * need to be repainted when scrolling. The display lists built for each task
60 * may be different for efficiency; in particular some frames need special
61 * display list items only for event handling, and do not create these items
62 * when the display list will be used for painting (the common case). For
63 * example, when painting we avoid creating nsDisplayBackground items for
64 * frames that don't display a visible background, but for event handling
65 * we need those backgrounds because they are not transparent to events.
67 * We could avoid constructing an explicit display list by traversing the
68 * frame tree multiple times in clever ways. However, reifying the display list
69 * reduces code complexity and reduces the number of times each frame must be
70 * traversed to one, which seems to be good for performance. It also means
71 * we can share code for painting, event handling and scroll analysis.
73 * Display lists are short-lived; content and frame trees cannot change
74 * between a display list being created and destroyed. Display lists should
75 * not be created during reflow because the frame tree may be in an
76 * inconsistent state (e.g., a frame's stored overflow-area may not include
77 * the bounds of all its children). However, it should be fine to create
78 * a display list while a reflow is pending, before it starts.
80 * A display list covers the "extended" frame tree; the display list for a frame
81 * tree containing FRAME/IFRAME elements can include frames from the subdocuments.
83 * Display item's coordinates are relative to their nearest reference frame ancestor.
84 * Both the display root and any frame with a transform act as a reference frame
85 * for their frame subtrees.
88 // All types are defined in nsDisplayItemTypes.h
89 #ifdef MOZ_DUMP_PAINTING
90 #define NS_DISPLAY_DECL_NAME(n, e) \
91 virtual const char* Name() { return n; } \
92 virtual Type GetType() { return e; }
93 #else
94 #define NS_DISPLAY_DECL_NAME(n, e) \
95 virtual Type GetType() { return e; }
96 #endif
98 /**
99 * This manages a display list and is passed as a parameter to
100 * nsIFrame::BuildDisplayList.
101 * It contains the parameters that don't change from frame to frame and manages
102 * the display list memory using a PLArena. It also establishes the reference
103 * coordinate system for all display list items. Some of the parameters are
104 * available from the prescontext/presshell, but we copy them into the builder
105 * for faster/more convenient access.
107 class nsDisplayListBuilder {
108 public:
109 typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
110 typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
111 typedef mozilla::DisplayItemClip DisplayItemClip;
112 typedef mozilla::DisplayListClipState DisplayListClipState;
113 typedef nsIWidget::ThemeGeometry ThemeGeometry;
116 * @param aReferenceFrame the frame at the root of the subtree; its origin
117 * is the origin of the reference coordinate system for this display list
118 * @param aIsForEvents true if we're creating this list in order to
119 * determine which frame is under the mouse position
120 * @param aBuildCaret whether or not we should include the caret in any
121 * display lists that we make.
123 enum Mode {
124 PAINTING,
125 EVENT_DELIVERY,
126 PLUGIN_GEOMETRY,
127 IMAGE_VISIBILITY,
128 OTHER
130 nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, bool aBuildCaret);
131 ~nsDisplayListBuilder();
133 void SetWillComputePluginGeometry(bool aWillComputePluginGeometry)
135 mWillComputePluginGeometry = aWillComputePluginGeometry;
137 void SetForPluginGeometry()
139 NS_ASSERTION(mMode == PAINTING, "Can only switch from PAINTING to PLUGIN_GEOMETRY");
140 NS_ASSERTION(mWillComputePluginGeometry, "Should have signalled this in advance");
141 mMode = PLUGIN_GEOMETRY;
145 * @return true if the display is being built in order to determine which
146 * frame is under the mouse position.
148 bool IsForEventDelivery() { return mMode == EVENT_DELIVERY; }
150 * Be careful with this. The display list will be built in PAINTING mode
151 * first and then switched to PLUGIN_GEOMETRY before a second call to
152 * ComputeVisibility.
153 * @return true if the display list is being built to compute geometry
154 * for plugins.
156 bool IsForPluginGeometry() { return mMode == PLUGIN_GEOMETRY; }
158 * @return true if the display list is being built for painting.
160 bool IsForPainting() { return mMode == PAINTING; }
162 * @return true if the display list is being built for determining image
163 * visibility.
165 bool IsForImageVisibility() { return mMode == IMAGE_VISIBILITY; }
166 bool WillComputePluginGeometry() { return mWillComputePluginGeometry; }
168 * @return true if "painting is suppressed" during page load and we
169 * should paint only the background of the document.
171 bool IsBackgroundOnly() {
172 NS_ASSERTION(mPresShellStates.Length() > 0,
173 "don't call this if we're not in a presshell");
174 return CurrentPresShellState()->mIsBackgroundOnly;
177 * @return true if the currently active BuildDisplayList call is being
178 * applied to a frame at the root of a pseudo stacking context. A pseudo
179 * stacking context is either a real stacking context or basically what
180 * CSS2.1 appendix E refers to with "treat the element as if it created
181 * a new stacking context
183 bool IsAtRootOfPseudoStackingContext() { return mIsAtRootOfPseudoStackingContext; }
186 * @return the selection that painting should be restricted to (or nullptr
187 * in the normal unrestricted case)
189 nsISelection* GetBoundingSelection() { return mBoundingSelection; }
192 * @return the root of given frame's (sub)tree, whose origin
193 * establishes the coordinate system for the child display items.
195 const nsIFrame* FindReferenceFrameFor(const nsIFrame *aFrame)
197 if (aFrame == mCachedOffsetFrame) {
198 return mCachedReferenceFrame;
200 for (const nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f))
202 if (f == mReferenceFrame || f->IsTransformed()) {
203 mCachedOffsetFrame = aFrame;
204 mCachedReferenceFrame = f;
205 mCachedOffset = aFrame->GetOffsetToCrossDoc(f);
206 return f;
209 mCachedOffsetFrame = aFrame;
210 mCachedReferenceFrame = mReferenceFrame;
211 mCachedOffset = aFrame->GetOffsetToCrossDoc(mReferenceFrame);
212 return mReferenceFrame;
216 * @return the root of the display list's frame (sub)tree, whose origin
217 * establishes the coordinate system for the display list
219 nsIFrame* RootReferenceFrame()
221 return mReferenceFrame;
225 * @return a point pt such that adding pt to a coordinate relative to aFrame
226 * makes it relative to ReferenceFrame(), i.e., returns
227 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()). The returned point is in
228 * the appunits of aFrame. It may be optimized to be faster than
229 * aFrame->GetOffsetToCrossDoc(ReferenceFrame()) (but currently isn't).
231 const nsPoint& ToReferenceFrame(const nsIFrame* aFrame) {
232 if (aFrame != mCachedOffsetFrame) {
233 FindReferenceFrameFor(aFrame);
235 return mCachedOffset;
238 * When building the display list, the scrollframe aFrame will be "ignored"
239 * for the purposes of clipping, and its scrollbars will be hidden. We use
240 * this to allow RenderOffscreen to render a whole document without beign
241 * clipped by the viewport or drawing the viewport scrollbars.
243 void SetIgnoreScrollFrame(nsIFrame* aFrame) { mIgnoreScrollFrame = aFrame; }
245 * Get the scrollframe to ignore, if any.
247 nsIFrame* GetIgnoreScrollFrame() { return mIgnoreScrollFrame; }
249 * Calling this setter makes us include all out-of-flow descendant
250 * frames in the display list, wherever they may be positioned (even
251 * outside the dirty rects).
253 void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
254 bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
256 * Calling this setter makes us exclude all leaf frames that aren't
257 * selected.
259 void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
260 bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
262 * Calling this setter makes us compute accurate visible regions at the cost
263 * of performance if regions get very complex.
265 void SetAccurateVisibleRegions() { mAccurateVisibleRegions = true; }
266 bool GetAccurateVisibleRegions() { return mAccurateVisibleRegions; }
268 * Allows callers to selectively override the regular paint suppression checks,
269 * so that methods like GetFrameForPoint work when painting is suppressed.
271 void IgnorePaintSuppression() { mIgnoreSuppression = true; }
273 * @return Returns if this builder will ignore paint suppression.
275 bool IsIgnoringPaintSuppression() { return mIgnoreSuppression; }
277 * @return Returns if this builder had to ignore painting suppression on some
278 * document when building the display list.
280 bool GetHadToIgnorePaintSuppression() { return mHadToIgnoreSuppression; }
282 * Call this if we're doing normal painting to the window.
284 void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
285 bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
287 * Call this to prevent descending into subdocuments.
289 void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; }
290 bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
293 * Returns true if merging and flattening of display lists should be
294 * performed while computing visibility.
296 bool AllowMergingAndFlattening() { return mAllowMergingAndFlattening; }
297 void SetAllowMergingAndFlattening(bool aAllow) { mAllowMergingAndFlattening = aAllow; }
299 bool SetIsCompositingCheap(bool aCompositingCheap) {
300 bool temp = mIsCompositingCheap;
301 mIsCompositingCheap = aCompositingCheap;
302 return temp;
304 bool IsCompositingCheap() const { return mIsCompositingCheap; }
306 * Display the caret if needed.
308 void DisplayCaret(nsIFrame* aFrame, const nsRect& aDirtyRect,
309 nsDisplayList* aList) {
310 nsIFrame* frame = GetCaretFrame();
311 if (aFrame == frame) {
312 frame->DisplayCaret(this, aDirtyRect, aList);
316 * Get the frame that the caret is supposed to draw in.
317 * If the caret is currently invisible, this will be null.
319 nsIFrame* GetCaretFrame() {
320 return CurrentPresShellState()->mCaretFrame;
323 * Get the caret associated with the current presshell.
325 nsCaret* GetCaret();
327 * Notify the display list builder that we're entering a presshell.
328 * aReferenceFrame should be a frame in the new presshell and aDirtyRect
329 * should be the current dirty rect in aReferenceFrame's coordinate space.
331 void EnterPresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
333 * For print-preview documents, we sometimes need to build display items for
334 * the same frames multiple times in the same presentation, with different
335 * clipping. Between each such batch of items, call
336 * ResetMarkedFramesForDisplayList to make sure that the results of
337 * MarkFramesForDisplayList do not carry over between batches.
339 void ResetMarkedFramesForDisplayList();
341 * Notify the display list builder that we're leaving a presshell.
343 void LeavePresShell(nsIFrame* aReferenceFrame, const nsRect& aDirtyRect);
346 * Returns true if we're currently building a display list that's
347 * directly or indirectly under an nsDisplayTransform.
349 bool IsInTransform() const { return mInTransform; }
351 * Indicate whether or not we're directly or indirectly under and
352 * nsDisplayTransform or SVG foreignObject.
354 void SetInTransform(bool aInTransform) { mInTransform = aInTransform; }
357 * Determines if this item is scrolled by content-document display-port
358 * scrolling. aAnimatedGeometryRoot will be set to the animated geometry root
359 * of the item. This may not necessarily correspond to the animated geometry
360 * root of the item's underlying frame.
361 * If specified, aOverrideAnimatedGeometryRoot will be treated as the active
362 * scrolled root.
364 bool IsFixedItem(nsDisplayItem* aItem,
365 const nsIFrame** aAnimatedGeometryRoot = nullptr,
366 const nsIFrame* aOverrideAnimatedGeometryScrolledRoot = nullptr);
369 * @return true if images have been set to decode synchronously.
371 bool ShouldSyncDecodeImages() { return mSyncDecodeImages; }
374 * Indicates whether we should synchronously decode images. If true, we decode
375 * and draw whatever image data has been loaded. If false, we just draw
376 * whatever has already been decoded.
378 void SetSyncDecodeImages(bool aSyncDecodeImages) {
379 mSyncDecodeImages = aSyncDecodeImages;
383 * Helper method to generate background painting flags based on the
384 * information available in the display list builder. Currently only
385 * accounts for mSyncDecodeImages.
387 uint32_t GetBackgroundPaintFlags();
390 * Subtracts aRegion from *aVisibleRegion. We avoid letting
391 * aVisibleRegion become overcomplex by simplifying it if necessary ---
392 * unless mAccurateVisibleRegions is set, in which case we let it
393 * get arbitrarily complex.
395 void SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
396 const nsRegion& aRegion);
399 * Mark the frames in aFrames to be displayed if they intersect aDirtyRect
400 * (which is relative to aDirtyFrame). If the frames have placeholders
401 * that might not be displayed, we mark the placeholders and their ancestors
402 * to ensure that display list construction descends into them
403 * anyway. nsDisplayListBuilder will take care of unmarking them when it is
404 * destroyed.
406 void MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
407 const nsFrameList& aFrames,
408 const nsRect& aDirtyRect);
410 * Mark all child frames that Preserve3D() as needing display.
411 * Because these frames include transforms set on their parent, dirty rects
412 * for intermediate frames may be empty, yet child frames could still be visible.
414 void MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect);
417 * Get the area of the final transparent region.
419 const nsRegion* GetFinalTransparentRegion() { return mFinalTransparentRegion; }
421 * Record the area of the final transparent region after all visibility
422 * calculations were performed.
424 void SetFinalTransparentRegion(const nsRegion& aFinalTransparentRegion)
426 mFinalTransparentRegion = &aFinalTransparentRegion;
429 const nsTArray<ThemeGeometry>& GetThemeGeometries() { return mThemeGeometries; }
432 * Returns true if we need to descend into this frame when building
433 * the display list, even though it doesn't intersect the dirty
434 * rect, because it may have out-of-flows that do so.
436 bool ShouldDescendIntoFrame(nsIFrame* aFrame) const {
437 return
438 (aFrame->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO) ||
439 GetIncludeAllOutOfFlows();
443 * Notifies the builder that a particular themed widget exists
444 * at the given rectangle within the currently built display list.
445 * For certain appearance values (currently only
446 * NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR, NS_THEME_TOOLBAR and
447 * NS_THEME_WINDOW_TITLEBAR) this gets called during every display list
448 * construction, for every themed widget of the right type within the
449 * display list, except for themed widgets which are transformed or have
450 * effects applied to them (e.g. CSS opacity or filters).
452 * @param aWidgetType the -moz-appearance value for the themed widget
453 * @param aRect the device-pixel rect relative to the widget's displayRoot
454 * for the themed widget
456 void RegisterThemeGeometry(uint8_t aWidgetType,
457 const nsIntRect& aRect) {
458 if (mIsPaintingToWindow && mPresShellStates.Length() == 1) {
459 ThemeGeometry geometry(aWidgetType, aRect);
460 mThemeGeometries.AppendElement(geometry);
465 * Allocate memory in our arena. It will only be freed when this display list
466 * builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
467 * destructors are called as soon as the item is no longer used.
469 void* Allocate(size_t aSize);
472 * Allocate a new DisplayListClip in the arena. Will be cleaned up
473 * automatically when the arena goes away.
475 const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal);
478 * A helper class to temporarily set the value of
479 * mIsAtRootOfPseudoStackingContext, and temporarily
480 * update mCachedOffsetFrame/mCachedOffset from a frame to its child.
481 * Also saves and restores mClipState.
483 class AutoBuildingDisplayList;
484 friend class AutoBuildingDisplayList;
485 class AutoBuildingDisplayList {
486 public:
487 AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder, bool aIsRoot)
488 : mBuilder(aBuilder),
489 mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
490 mPrevCachedReferenceFrame(aBuilder->mCachedReferenceFrame),
491 mPrevCachedOffset(aBuilder->mCachedOffset),
492 mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext) {
493 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
495 AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
496 nsIFrame* aForChild, bool aIsRoot)
497 : mBuilder(aBuilder),
498 mPrevCachedOffsetFrame(aBuilder->mCachedOffsetFrame),
499 mPrevCachedReferenceFrame(aBuilder->mCachedReferenceFrame),
500 mPrevCachedOffset(aBuilder->mCachedOffset),
501 mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext)
503 if (aForChild->IsTransformed()) {
504 aBuilder->mCachedOffset = nsPoint();
505 aBuilder->mCachedReferenceFrame = aForChild;
506 } else if (mPrevCachedOffsetFrame == aForChild->GetParent()) {
507 aBuilder->mCachedOffset += aForChild->GetPosition();
508 } else {
509 aBuilder->mCachedOffset = aBuilder->ToReferenceFrame(aForChild);
511 aBuilder->mCachedOffsetFrame = aForChild;
512 aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
514 ~AutoBuildingDisplayList() {
515 mBuilder->mCachedOffsetFrame = mPrevCachedOffsetFrame;
516 mBuilder->mCachedReferenceFrame = mPrevCachedReferenceFrame;
517 mBuilder->mCachedOffset = mPrevCachedOffset;
518 mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
520 private:
521 nsDisplayListBuilder* mBuilder;
522 const nsIFrame* mPrevCachedOffsetFrame;
523 const nsIFrame* mPrevCachedReferenceFrame;
524 nsPoint mPrevCachedOffset;
525 bool mPrevIsAtRootOfPseudoStackingContext;
529 * A helper class to temporarily set the value of mInTransform.
531 class AutoInTransformSetter;
532 friend class AutoInTransformSetter;
533 class AutoInTransformSetter {
534 public:
535 AutoInTransformSetter(nsDisplayListBuilder* aBuilder, bool aInTransform)
536 : mBuilder(aBuilder), mOldValue(aBuilder->mInTransform) {
537 aBuilder->mInTransform = aInTransform;
539 ~AutoInTransformSetter() {
540 mBuilder->mInTransform = mOldValue;
542 private:
543 nsDisplayListBuilder* mBuilder;
544 bool mOldValue;
547 // Helpers for tables
548 nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; }
549 void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
551 struct OutOfFlowDisplayData {
552 OutOfFlowDisplayData(const DisplayItemClip& aContainingBlockClip,
553 const nsRect &aDirtyRect)
554 : mContainingBlockClip(aContainingBlockClip)
555 , mDirtyRect(aDirtyRect)
557 OutOfFlowDisplayData(const nsRect &aDirtyRect)
558 : mDirtyRect(aDirtyRect)
560 DisplayItemClip mContainingBlockClip;
561 nsRect mDirtyRect;
563 static void DestroyOutOfFlowDisplayData(void* aPropertyValue)
565 delete static_cast<OutOfFlowDisplayData*>(aPropertyValue);
568 NS_DECLARE_FRAME_PROPERTY(OutOfFlowDisplayDataProperty, DestroyOutOfFlowDisplayData)
569 NS_DECLARE_FRAME_PROPERTY(Preserve3DDirtyRectProperty, nsIFrame::DestroyRect)
571 nsPresContext* CurrentPresContext() {
572 return CurrentPresShellState()->mPresShell->GetPresContext();
576 * Accumulates the bounds of box frames that have moz-appearance
577 * -moz-win-exclude-glass style. Used in setting glass margins on
578 * Windows.
580 void AddExcludedGlassRegion(nsRect &bounds) {
581 mExcludedGlassRegion.Or(mExcludedGlassRegion, bounds);
583 const nsRegion& GetExcludedGlassRegion() {
584 return mExcludedGlassRegion;
586 void SetGlassDisplayItem(nsDisplayItem* aItem) {
587 if (mGlassDisplayItem) {
588 // Web pages or extensions could trigger this by using
589 // -moz-appearance:win-borderless-glass etc on their own elements.
590 // Keep the first one, since that will be the background of the root
591 // window
592 NS_WARNING("Multiple glass backgrounds found?");
593 } else {
594 mGlassDisplayItem = aItem;
597 bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) {
598 return aItem == mGlassDisplayItem;
601 void SetContainsPluginItem() { mContainsPluginItem = true; }
602 bool ContainsPluginItem() { return mContainsPluginItem; }
605 * mContainsBlendMode is true if we processed a display item that
606 * has a blend mode attached. We do this so we can insert a
607 * nsDisplayBlendContainer in the parent stacking context.
609 void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
610 bool ContainsBlendMode() const { return mContainsBlendMode; }
612 DisplayListClipState& ClipState() { return mClipState; }
614 private:
615 void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
616 const nsRect& aDirtyRect);
618 struct PresShellState {
619 nsIPresShell* mPresShell;
620 nsIFrame* mCaretFrame;
621 uint32_t mFirstFrameMarkedForDisplay;
622 bool mIsBackgroundOnly;
624 PresShellState* CurrentPresShellState() {
625 NS_ASSERTION(mPresShellStates.Length() > 0,
626 "Someone forgot to enter a presshell");
627 return &mPresShellStates[mPresShellStates.Length() - 1];
630 nsIFrame* mReferenceFrame;
631 nsIFrame* mIgnoreScrollFrame;
632 PLArenaPool mPool;
633 nsCOMPtr<nsISelection> mBoundingSelection;
634 nsAutoTArray<PresShellState,8> mPresShellStates;
635 nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
636 nsAutoTArray<ThemeGeometry,2> mThemeGeometries;
637 nsDisplayTableItem* mCurrentTableItem;
638 DisplayListClipState mClipState;
639 const nsRegion* mFinalTransparentRegion;
640 // When mCachedOffsetFrame is non-null, mCachedOffset is the offset from
641 // mCachedOffsetFrame to mReferenceFrame.
642 const nsIFrame* mCachedOffsetFrame;
643 const nsIFrame* mCachedReferenceFrame;
644 nsPoint mCachedOffset;
645 nsRegion mExcludedGlassRegion;
646 // The display item for the Windows window glass background, if any
647 nsDisplayItem* mGlassDisplayItem;
648 nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
649 Mode mMode;
650 bool mBuildCaret;
651 bool mIgnoreSuppression;
652 bool mHadToIgnoreSuppression;
653 bool mIsAtRootOfPseudoStackingContext;
654 bool mIncludeAllOutOfFlows;
655 bool mDescendIntoSubdocuments;
656 bool mSelectedFramesOnly;
657 bool mAccurateVisibleRegions;
658 bool mAllowMergingAndFlattening;
659 bool mWillComputePluginGeometry;
660 // True when we're building a display list that's directly or indirectly
661 // under an nsDisplayTransform
662 bool mInTransform;
663 bool mSyncDecodeImages;
664 bool mIsPaintingToWindow;
665 bool mIsCompositingCheap;
666 bool mContainsPluginItem;
667 bool mContainsBlendMode;
670 class nsDisplayItem;
671 class nsDisplayList;
673 * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
674 * nsDisplayItemLink holds the link. The lists are linked from lowest to
675 * highest in z-order.
677 class nsDisplayItemLink {
678 // This is never instantiated directly, so no need to count constructors and
679 // destructors.
680 protected:
681 nsDisplayItemLink() : mAbove(nullptr) {}
682 nsDisplayItem* mAbove;
684 friend class nsDisplayList;
688 * This is the unit of rendering and event testing. Each instance of this
689 * class represents an entity that can be drawn on the screen, e.g., a
690 * frame's CSS background, or a frame's text string.
692 * nsDisplayListItems can be containers --- i.e., they can perform hit testing
693 * and painting by recursively traversing a list of child items.
695 * These are arena-allocated during display list construction. A typical
696 * subclass would just have a frame pointer, so its object would be just three
697 * pointers (vtable, next-item, frame).
699 * Display items belong to a list at all times (except temporarily as they
700 * move from one list to another).
702 class nsDisplayItem : public nsDisplayItemLink {
703 public:
704 typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
705 typedef mozilla::DisplayItemClip DisplayItemClip;
706 typedef mozilla::layers::FrameMetrics::ViewID ViewID;
707 typedef mozilla::layers::Layer Layer;
708 typedef mozilla::layers::LayerManager LayerManager;
709 typedef mozilla::LayerState LayerState;
711 // This is never instantiated directly (it has pure virtual methods), so no
712 // need to count constructors and destructors.
713 nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
714 : mFrame(aFrame)
715 , mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder))
716 #ifdef MOZ_DUMP_PAINTING
717 , mPainted(false)
718 #endif
720 mReferenceFrame = aBuilder->FindReferenceFrameFor(aFrame);
721 mToReferenceFrame = aBuilder->ToReferenceFrame(aFrame);
723 nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
724 const nsIFrame* aReferenceFrame,
725 const nsPoint& aToReferenceFrame)
726 : mFrame(aFrame)
727 , mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder))
728 , mReferenceFrame(aReferenceFrame)
729 , mToReferenceFrame(aToReferenceFrame)
730 #ifdef MOZ_DUMP_PAINTING
731 , mPainted(false)
732 #endif
736 * This constructor is only used in rare cases when we need to construct
737 * temporary items.
739 nsDisplayItem(nsIFrame* aFrame)
740 : mFrame(aFrame)
741 , mClip(nullptr)
742 , mReferenceFrame(nullptr)
743 #ifdef MOZ_DUMP_PAINTING
744 , mPainted(false)
745 #endif
748 virtual ~nsDisplayItem() {}
750 void* operator new(size_t aSize,
751 nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
752 return aBuilder->Allocate(aSize);
755 // Contains all the type integers for each display list item type
756 #include "nsDisplayItemTypes.h"
758 struct HitTestState {
759 typedef nsTArray<ViewID> ShadowArray;
761 HitTestState(ShadowArray* aShadows = nullptr)
762 : mShadows(aShadows) {
765 ~HitTestState() {
766 NS_ASSERTION(mItemBuffer.Length() == 0,
767 "mItemBuffer should have been cleared");
770 nsAutoTArray<nsDisplayItem*, 100> mItemBuffer;
772 // It is sometimes useful to hit test for frames that are not in this
773 // process. Display items may append IDs into this array if it is
774 // non-null.
775 ShadowArray* mShadows;
779 * Some consecutive items should be rendered together as a unit, e.g.,
780 * outlines for the same element. For this, we need a way for items to
781 * identify their type. We use the type for other purposes too.
783 virtual Type GetType() = 0;
785 * Pairing this with the GetUnderlyingFrame() pointer gives a key that
786 * uniquely identifies this display item in the display item tree.
787 * XXX check ScrollLayerWrapper/nsOptionEventGrabberWrapper/nsXULEventRedirectorWrapper
789 virtual uint32_t GetPerFrameKey() { return uint32_t(GetType()); }
791 * This is called after we've constructed a display list for event handling.
792 * When this is called, we've already ensured that aRect intersects the
793 * item's bounds and that clipping has been taking into account.
795 * @param aRect the point or rect being tested, relative to the reference
796 * frame. If the width and height are both 1 app unit, it indicates we're
797 * hit testing a point, not a rect.
798 * @param aState must point to a HitTestState. If you don't have one,
799 * just create one with the default constructor and pass it in.
800 * @param aOutFrames each item appends the frame(s) in this display item that
801 * the rect is considered over (if any) to aOutFrames.
803 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
804 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {}
806 * @return the frame that this display item is based on. This is used to sort
807 * items by z-index and content order and for some other uses. Never
808 * returns null.
810 inline nsIFrame* Frame() const { return mFrame; }
812 * The default bounds is the frame border rect.
813 * @param aSnap *aSnap is set to true if the returned rect will be
814 * snapped to nearest device pixel edges during actual drawing.
815 * It might be set to false and snap anyway, so code computing the set of
816 * pixels affected by this display item needs to round outwards to pixel
817 * boundaries when *aSnap is set to false.
818 * This does not take the item's clipping into account.
819 * @return a rectangle relative to aBuilder->ReferenceFrame() that
820 * contains the area drawn by this display item
822 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
824 *aSnap = false;
825 return nsRect(ToReferenceFrame(), Frame()->GetSize());
828 * Returns the result of GetBounds intersected with the item's clip.
829 * The intersection is approximate since rounded corners are not taking into
830 * account.
832 nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder);
833 nsRect GetBorderRect() {
834 return nsRect(ToReferenceFrame(), Frame()->GetSize());
836 nsRect GetPaddingRect() {
837 return Frame()->GetPaddingRectRelativeToSelf() + ToReferenceFrame();
839 nsRect GetContentRect() {
840 return Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
844 * Checks if the frame(s) owning this display item have been marked as invalid,
845 * and needing repainting.
847 virtual bool IsInvalid(nsRect& aRect) {
848 bool result = mFrame ? mFrame->IsInvalid(aRect) : false;
849 aRect += ToReferenceFrame();
850 return result;
854 * Creates and initializes an nsDisplayItemGeometry object that retains the current
855 * areas covered by this display item. These need to retain enough information
856 * such that they can be compared against a future nsDisplayItem of the same type,
857 * and determine if repainting needs to happen.
859 * Subclasses wishing to store more information need to override both this
860 * and ComputeInvalidationRegion, as well as implementing an nsDisplayItemGeometry
861 * subclass.
863 * The default implementation tracks both the display item bounds, and the frame's
864 * border rect.
866 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
868 return new nsDisplayItemGenericGeometry(this, aBuilder);
872 * Compares an nsDisplayItemGeometry object from a previous paint against the
873 * current item. Computes if the geometry of the item has changed, and the
874 * invalidation area required for correct repainting.
876 * The existing geometry will have been created from a display item with a
877 * matching GetPerFrameKey()/mFrame pair to the current item.
879 * The default implementation compares the display item bounds, and the frame's
880 * border rect, and invalidates the entire bounds if either rect changes.
882 * @param aGeometry The geometry of the matching display item from the
883 * previous paint.
884 * @param aInvalidRegion Output param, the region to invalidate, or
885 * unchanged if none.
887 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
888 const nsDisplayItemGeometry* aGeometry,
889 nsRegion* aInvalidRegion)
891 const nsDisplayItemGenericGeometry* geometry = static_cast<const nsDisplayItemGenericGeometry*>(aGeometry);
892 bool snap;
893 if (!geometry->mBounds.IsEqualInterior(GetBounds(aBuilder, &snap)) ||
894 !geometry->mBorderRect.IsEqualInterior(GetBorderRect())) {
895 aInvalidRegion->Or(GetBounds(aBuilder, &snap), geometry->mBounds);
900 * An alternative default implementation of ComputeInvalidationRegion,
901 * that instead invalidates only the changed area between the two items.
903 void ComputeInvalidationRegionDifference(nsDisplayListBuilder* aBuilder,
904 const nsDisplayItemBoundsGeometry* aGeometry,
905 nsRegion* aInvalidRegion)
907 bool snap;
908 nsRect bounds = GetBounds(aBuilder, &snap);
910 if (!aGeometry->mBounds.IsEqualInterior(bounds)) {
911 nscoord radii[8];
912 if (aGeometry->mHasRoundedCorners ||
913 Frame()->GetBorderRadii(radii)) {
914 aInvalidRegion->Or(aGeometry->mBounds, bounds);
915 } else {
916 aInvalidRegion->Xor(aGeometry->mBounds, bounds);
922 * For display items types that just draw a background we use this function
923 * to do any invalidation that might be needed if we are asked to sync decode
924 * images.
926 void AddInvalidRegionForSyncDecodeBackgroundImages(
927 nsDisplayListBuilder* aBuilder,
928 const nsDisplayItemGeometry* aGeometry,
929 nsRegion* aInvalidRegion);
932 * Called when the area rendered by this display item has changed (been
933 * invalidated or changed geometry) since the last paint. This includes
934 * when the display item was not rendered at all in the last paint.
935 * It does NOT get called when a display item was being rendered and no
936 * longer is, because generally that means there is no display item to
937 * call this method on.
939 virtual void NotifyRenderingChanged() {}
942 * @param aSnap set to true if the edges of the rectangles of the opaque
943 * region would be snapped to device pixels when drawing
944 * @return a region of the item that is opaque --- that is, every pixel
945 * that is visible (according to ComputeVisibility) is painted with an opaque
946 * color. This is useful for determining when one piece
947 * of content completely obscures another so that we can do occlusion
948 * culling.
949 * This does not take clipping into account.
951 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
952 bool* aSnap)
954 *aSnap = false;
955 return nsRegion();
958 * If this returns true, then aColor is set to the uniform color
959 * @return true if the item is guaranteed to paint every pixel in its
960 * bounds with the same (possibly translucent) color
962 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) { return false; }
964 * @return false if the painting performed by the item is invariant
965 * when the item's underlying frame is moved relative to aFrame.
966 * In other words, if you render the item at locations P and P', the rendering
967 * only differs by the translation.
968 * It return true for all wrapped lists.
970 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
971 nsIFrame* aFrame)
972 { return false; }
974 * @return true if the contents of this item are rendered fixed relative
975 * to the nearest viewport *and* they cover the viewport's scrollport.
976 * Only return true if the contents actually vary when scrolling in the viewport.
978 virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
979 { return false; }
982 * Returns true if all layers that can be active should be forced to be
983 * active. Requires setting the pref layers.force-active=true.
985 static bool ForceActiveLayers();
988 * Returns the maximum number of layers that should be created
989 * or -1 for no limit. Requires setting the pref layers.max-acitve.
991 static int32_t MaxActiveLayers();
994 * @return LAYER_NONE if BuildLayer will return null. In this case
995 * there is no layer for the item, and Paint should be called instead
996 * to paint the content using Thebes.
997 * Return LAYER_INACTIVE if there is a layer --- BuildLayer will
998 * not return null (unless there's an error) --- but the layer contents
999 * are not changing frequently. In this case it makes sense to composite
1000 * the layer into a ThebesLayer with other content, so we don't have to
1001 * recomposite it every time we paint.
1002 * Note: GetLayerState is only allowed to return LAYER_INACTIVE if all
1003 * descendant display items returned LAYER_INACTIVE or LAYER_NONE. Also,
1004 * all descendant display item frames must have an active scrolled root
1005 * that's either the same as this item's frame's active scrolled root, or
1006 * a descendant of this item's frame. This ensures that the entire
1007 * set of display items can be collapsed onto a single ThebesLayer.
1008 * Return LAYER_ACTIVE if the layer is active, that is, its contents are
1009 * changing frequently. In this case it makes sense to keep the layer
1010 * as a separate buffer in VRAM and composite it into the destination
1011 * every time we paint.
1013 * Users of GetLayerState should check ForceActiveLayers() and if it returns
1014 * true, change a returned value of LAYER_INACTIVE to LAYER_ACTIVE.
1016 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
1017 LayerManager* aManager,
1018 const ContainerLayerParameters& aParameters)
1019 { return mozilla::LAYER_NONE; }
1021 * Return true to indicate the layer should be constructed even if it's
1022 * completely invisible.
1024 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
1025 { return false; }
1027 * Actually paint this item to some rendering context.
1028 * Content outside mVisibleRect need not be painted.
1029 * aCtx must be set up as for nsDisplayList::Paint.
1031 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) {}
1033 #ifdef MOZ_DUMP_PAINTING
1035 * Mark this display item as being painted via FrameLayerBuilder::DrawThebesLayer.
1037 bool Painted() { return mPainted; }
1040 * Check if this display item has been painted.
1042 void SetPainted() { mPainted = true; }
1043 #endif
1046 * Get the layer drawn by this display item. Call this only if
1047 * GetLayerState() returns something other than LAYER_NONE.
1048 * If GetLayerState returned LAYER_NONE then Paint will be called
1049 * instead.
1050 * This is called while aManager is in the construction phase.
1052 * The caller (nsDisplayList) is responsible for setting the visible
1053 * region of the layer.
1055 * @param aContainerParameters should be passed to
1056 * FrameLayerBuilder::BuildContainerLayerFor if a ContainerLayer is
1057 * constructed.
1059 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
1060 LayerManager* aManager,
1061 const ContainerLayerParameters& aContainerParameters)
1062 { return nullptr; }
1065 * On entry, aVisibleRegion contains the region (relative to ReferenceFrame())
1066 * which may be visible. If the display item opaquely covers an area, it
1067 * can remove that area from aVisibleRegion before returning.
1068 * nsDisplayList::ComputeVisibility automatically subtracts the region
1069 * returned by GetOpaqueRegion, and automatically removes items whose bounds
1070 * do not intersect the visible area, so implementations of
1071 * nsDisplayItem::ComputeVisibility do not need to do these things.
1072 * nsDisplayList::ComputeVisibility will already have set mVisibleRect on
1073 * this item to the intersection of *aVisibleRegion and this item's bounds.
1074 * We rely on that, so this should only be called by
1075 * nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
1076 * aAllowVisibleRegionExpansion is a rect where we are allowed to
1077 * expand the visible region and is only used for making sure the
1078 * background behind a plugin is visible.
1079 * This method needs to be idempotent.
1081 * @return true if the item is visible, false if no part of the item
1082 * is visible.
1084 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1085 nsRegion* aVisibleRegion,
1086 const nsRect& aAllowVisibleRegionExpansion)
1087 { return !mVisibleRect.IsEmpty(); }
1090 * Try to merge with the other item (which is below us in the display
1091 * list). This gets used by nsDisplayClip to coalesce clipping operations
1092 * (optimization), by nsDisplayOpacity to merge rendering for the same
1093 * content element into a single opacity group (correctness), and will be
1094 * used by nsDisplayOutline to merge multiple outlines for the same element
1095 * (also for correctness).
1096 * @return true if the merge was successful and the other item should be deleted
1098 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
1099 return false;
1103 * Appends the underlying frames of all display items that have been
1104 * merged into this one (excluding this item's own underlying frame)
1105 * to aFrames.
1107 virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) {}
1110 * During the visibility computation and after TryMerge, display lists may
1111 * return true here to flatten themselves away, removing them. This
1112 * flattening is distinctly different from FlattenTo, which occurs before
1113 * items are merged together.
1115 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) {
1116 return false;
1120 * If this has a child list where the children are in the same coordinate
1121 * system as this item (i.e., they have the same reference frame),
1122 * return the list.
1124 virtual nsDisplayList* GetSameCoordinateSystemChildren() { return nullptr; }
1125 virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) {}
1128 * If this has a child list, return it, even if the children are in
1129 * a different coordinate system to this item.
1131 virtual nsDisplayList* GetChildren() { return nullptr; }
1134 * Returns the visible rect. Should only be called after ComputeVisibility
1135 * has happened.
1137 const nsRect& GetVisibleRect() { return mVisibleRect; }
1140 * Stores the given opacity value to be applied when drawing. Returns
1141 * false if this isn't supported for this display item.
1143 virtual bool ApplyOpacity(float aOpacity) { return false; }
1145 #ifdef MOZ_DUMP_PAINTING
1147 * For debugging and stuff
1149 virtual const char* Name() = 0;
1151 virtual void WriteDebugInfo(FILE *aOutput) {}
1152 #endif
1154 nsDisplayItem* GetAbove() { return mAbove; }
1157 * Like ComputeVisibility, but does the work that nsDisplayList
1158 * does per-item:
1159 * -- Intersects GetBounds with aVisibleRegion and puts the result
1160 * in mVisibleRect
1161 * -- Subtracts bounds from aVisibleRegion if the item is opaque
1163 bool RecomputeVisibility(nsDisplayListBuilder* aBuilder,
1164 nsRegion* aVisibleRegion);
1167 * Returns the result of aBuilder->ToReferenceFrame(GetUnderlyingFrame())
1169 const nsPoint& ToReferenceFrame() const {
1170 NS_ASSERTION(mFrame, "No frame?");
1171 return mToReferenceFrame;
1174 * @return the root of the display list's frame (sub)tree, whose origin
1175 * establishes the coordinate system for the display list
1177 const nsIFrame* ReferenceFrame() const { return mReferenceFrame; }
1180 * Returns the reference frame for display item children of this item.
1182 virtual const nsIFrame* ReferenceFrameForChildren() const { return mReferenceFrame; }
1185 * Checks if this display item (or any children) contains content that might
1186 * be rendered with component alpha (e.g. subpixel antialiasing). Returns the
1187 * bounds of the area that needs component alpha, or an empty rect if nothing
1188 * in the item does.
1190 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); }
1193 * Disable usage of component alpha. Currently only relevant for items that have text.
1195 virtual void DisableComponentAlpha() {}
1198 * Check if we can add async animations to the layer for this display item.
1200 virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
1201 return false;
1204 virtual bool SupportsOptimizingToImage() { return false; }
1206 const DisplayItemClip& GetClip()
1208 return mClip ? *mClip : DisplayItemClip::NoClip();
1210 void SetClip(nsDisplayListBuilder* aBuilder, const DisplayItemClip& aClip)
1212 if (!aClip.HasClip()) {
1213 mClip = nullptr;
1214 return;
1216 mClip = aBuilder->AllocateDisplayItemClip(aClip);
1219 protected:
1220 friend class nsDisplayList;
1222 nsDisplayItem() { mAbove = nullptr; }
1224 nsIFrame* mFrame;
1225 const DisplayItemClip* mClip;
1226 // Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
1227 const nsIFrame* mReferenceFrame;
1228 // Result of ToReferenceFrame(mFrame), if mFrame is non-null
1229 nsPoint mToReferenceFrame;
1230 // This is the rectangle that needs to be painted.
1231 // nsDisplayList::ComputeVisibility sets this to the visible region
1232 // of the item by intersecting the current visible region with the bounds
1233 // of the item. Paint implementations can use this to limit their drawing.
1234 // Guaranteed to be contained in GetBounds().
1235 nsRect mVisibleRect;
1236 #ifdef MOZ_DUMP_PAINTING
1237 // True if this frame has been painted.
1238 bool mPainted;
1239 #endif
1243 * Manages a singly-linked list of display list items.
1245 * mSentinel is the sentinel list value, the first value in the null-terminated
1246 * linked list of items. mTop is the last item in the list (whose 'above'
1247 * pointer is null). This class has no virtual methods. So list objects are just
1248 * two pointers.
1250 * Stepping upward through this list is very fast. Stepping downward is very
1251 * slow so we don't support it. The methods that need to step downward
1252 * (HitTest(), ComputeVisibility()) internally build a temporary array of all
1253 * the items while they do the downward traversal, so overall they're still
1254 * linear time. We have optimized for efficient AppendToTop() of both
1255 * items and lists, with minimal codesize. AppendToBottom() is efficient too.
1257 class nsDisplayList {
1258 public:
1259 typedef mozilla::layers::Layer Layer;
1260 typedef mozilla::layers::LayerManager LayerManager;
1261 typedef mozilla::layers::ThebesLayer ThebesLayer;
1264 * Create an empty list.
1266 nsDisplayList() :
1267 mIsOpaque(false)
1269 mTop = &mSentinel;
1270 mSentinel.mAbove = nullptr;
1271 #ifdef DEBUG
1272 mDidComputeVisibility = false;
1273 #endif
1275 ~nsDisplayList() {
1276 if (mSentinel.mAbove) {
1277 NS_WARNING("Nonempty list left over?");
1279 DeleteAll();
1283 * Append an item to the top of the list. The item must not currently
1284 * be in a list and cannot be null.
1286 void AppendToTop(nsDisplayItem* aItem) {
1287 NS_ASSERTION(aItem, "No item to append!");
1288 NS_ASSERTION(!aItem->mAbove, "Already in a list!");
1289 mTop->mAbove = aItem;
1290 mTop = aItem;
1294 * Append a new item to the top of the list. If the item is null we return
1295 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToTop(new ...);
1297 void AppendNewToTop(nsDisplayItem* aItem) {
1298 if (aItem) {
1299 AppendToTop(aItem);
1304 * Append a new item to the bottom of the list. If the item is null we return
1305 * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToBottom(new ...);
1307 void AppendNewToBottom(nsDisplayItem* aItem) {
1308 if (aItem) {
1309 AppendToBottom(aItem);
1314 * Append a new item to the bottom of the list. The item must be non-null
1315 * and not already in a list.
1317 void AppendToBottom(nsDisplayItem* aItem) {
1318 NS_ASSERTION(aItem, "No item to append!");
1319 NS_ASSERTION(!aItem->mAbove, "Already in a list!");
1320 aItem->mAbove = mSentinel.mAbove;
1321 mSentinel.mAbove = aItem;
1322 if (mTop == &mSentinel) {
1323 mTop = aItem;
1328 * Removes all items from aList and appends them to the top of this list
1330 void AppendToTop(nsDisplayList* aList) {
1331 if (aList->mSentinel.mAbove) {
1332 mTop->mAbove = aList->mSentinel.mAbove;
1333 mTop = aList->mTop;
1334 aList->mTop = &aList->mSentinel;
1335 aList->mSentinel.mAbove = nullptr;
1340 * Removes all items from aList and prepends them to the bottom of this list
1342 void AppendToBottom(nsDisplayList* aList) {
1343 if (aList->mSentinel.mAbove) {
1344 aList->mTop->mAbove = mSentinel.mAbove;
1345 mSentinel.mAbove = aList->mSentinel.mAbove;
1346 if (mTop == &mSentinel) {
1347 mTop = aList->mTop;
1350 aList->mTop = &aList->mSentinel;
1351 aList->mSentinel.mAbove = nullptr;
1356 * Remove an item from the bottom of the list and return it.
1358 nsDisplayItem* RemoveBottom();
1361 * Remove all items from the list and call their destructors.
1363 void DeleteAll();
1366 * @return the item at the top of the list, or null if the list is empty
1368 nsDisplayItem* GetTop() const {
1369 return mTop != &mSentinel ? static_cast<nsDisplayItem*>(mTop) : nullptr;
1372 * @return the item at the bottom of the list, or null if the list is empty
1374 nsDisplayItem* GetBottom() const { return mSentinel.mAbove; }
1375 bool IsEmpty() const { return mTop == &mSentinel; }
1378 * This is *linear time*!
1379 * @return the number of items in the list
1381 uint32_t Count() const;
1383 * Stable sort the list by the z-order of GetUnderlyingFrame() on
1384 * each item. 'auto' is counted as zero. Content order is used as the
1385 * secondary order.
1386 * @param aCommonAncestor a common ancestor of all the content elements
1387 * associated with the display items, for speeding up tree order
1388 * checks, or nullptr if not known; it's only a hint, if it is not an
1389 * ancestor of some elements, then we lose performance but not correctness
1391 void SortByZOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
1393 * Stable sort the list by the tree order of the content of
1394 * GetUnderlyingFrame() on each item. z-index is ignored.
1395 * @param aCommonAncestor a common ancestor of all the content elements
1396 * associated with the display items, for speeding up tree order
1397 * checks, or nullptr if not known; it's only a hint, if it is not an
1398 * ancestor of some elements, then we lose performance but not correctness
1400 void SortByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor);
1403 * Generic stable sort. Take care, because some of the items might be nsDisplayLists
1404 * themselves.
1405 * aCmp(item1, item2) should return true if item1 <= item2. We sort the items
1406 * into increasing order.
1408 typedef bool (* SortLEQ)(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
1409 void* aClosure);
1410 void Sort(nsDisplayListBuilder* aBuilder, SortLEQ aCmp, void* aClosure);
1413 * Compute visiblity for the items in the list.
1414 * We put this logic here so it can be shared by top-level
1415 * painting and also display items that maintain child lists.
1416 * This is also a good place to put ComputeVisibility-related logic
1417 * that must be applied to every display item. In particular, this
1418 * sets mVisibleRect on each display item.
1419 * This sets mIsOpaque if the entire visible area of this list has
1420 * been removed from aVisibleRegion when we return.
1421 * This does not remove any items from the list, so we can recompute
1422 * visiblity with different regions later (see
1423 * FrameLayerBuilder::DrawThebesLayer).
1424 * This method needs to be idempotent.
1426 * @param aVisibleRegion the area that is visible, relative to the
1427 * reference frame; on return, this contains the area visible under the list.
1428 * I.e., opaque contents of this list are subtracted from aVisibleRegion.
1429 * @param aListVisibleBounds must be equal to the bounds of the intersection
1430 * of aVisibleRegion and GetBounds() for this list.
1431 * @return true if any item in the list is visible.
1433 bool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
1434 nsRegion* aVisibleRegion,
1435 const nsRect& aListVisibleBounds,
1436 const nsRect& aAllowVisibleRegionExpansion);
1439 * As ComputeVisibilityForSublist, but computes visibility for a root
1440 * list (a list that does not belong to an nsDisplayItem).
1441 * This method needs to be idempotent.
1443 * @param aVisibleRegion the area that is visible
1445 bool ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
1446 nsRegion* aVisibleRegion);
1449 * Returns true if the visible region output from ComputeVisiblity was
1450 * empty, i.e. everything visible in this list is opaque.
1452 bool IsOpaque() const {
1453 NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
1454 return mIsOpaque;
1458 * Returns true if during ComputeVisibility any display item
1459 * set the surface to be transparent.
1461 bool NeedsTransparentSurface() const {
1462 NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
1463 return mForceTransparentSurface;
1466 * Paint the list to the rendering context. We assume that (0,0) in aCtx
1467 * corresponds to the origin of the reference frame. For best results,
1468 * aCtx's current transform should make (0,0) pixel-aligned. The
1469 * rectangle in aDirtyRect is painted, which *must* be contained in the
1470 * dirty rect used to construct the display list.
1472 * If aFlags contains PAINT_USE_WIDGET_LAYERS and
1473 * ShouldUseWidgetLayerManager() is set, then we will paint using
1474 * the reference frame's widget's layer manager (and ctx may be null),
1475 * otherwise we will use a temporary BasicLayerManager and ctx must
1476 * not be null.
1478 * If PAINT_FLUSH_LAYERS is set, we'll force a completely new layer
1479 * tree to be created for this paint *and* the next paint.
1481 * If PAINT_EXISTING_TRANSACTION is set, the reference frame's widget's
1482 * layer manager has already had BeginTransaction() called on it and
1483 * we should not call it again.
1485 * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
1486 * to avoid short cut optimizations.
1488 * ComputeVisibility must be called before Paint.
1490 * This must only be called on the root display list of the display list
1491 * tree.
1493 enum {
1494 PAINT_DEFAULT = 0,
1495 PAINT_USE_WIDGET_LAYERS = 0x01,
1496 PAINT_FLUSH_LAYERS = 0x02,
1497 PAINT_EXISTING_TRANSACTION = 0x04,
1498 PAINT_NO_COMPOSITE = 0x08,
1499 PAINT_COMPRESSED = 0x10
1501 void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
1502 uint32_t aFlags) const;
1504 * Like PaintRoot, but used for internal display sublists.
1505 * aForFrame is the frame that the list is associated with.
1507 void PaintForFrame(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
1508 nsIFrame* aForFrame, uint32_t aFlags) const;
1510 * Get the bounds. Takes the union of the bounds of all children.
1512 nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
1514 * Find the topmost display item that returns a non-null frame, and return
1515 * the frame.
1517 void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
1518 nsDisplayItem::HitTestState* aState,
1519 nsTArray<nsIFrame*> *aOutFrames) const;
1521 #ifdef DEBUG
1522 bool DidComputeVisibility() const { return mDidComputeVisibility; }
1523 #endif
1525 nsRect GetVisibleRect() const { return mVisibleRect; }
1527 private:
1528 // This class is only used on stack, so we don't have to worry about leaking
1529 // it. Don't let us be heap-allocated!
1530 void* operator new(size_t sz) CPP_THROW_NEW;
1532 // Utility function used to massage the list during ComputeVisibility.
1533 void FlattenTo(nsTArray<nsDisplayItem*>* aElements);
1535 nsDisplayItemLink mSentinel;
1536 nsDisplayItemLink* mTop;
1538 // This is set by ComputeVisibility
1539 nsRect mVisibleRect;
1540 // This is set to true by ComputeVisibility if the final visible region
1541 // is empty (i.e. everything that was visible is covered by some
1542 // opaque content in this list).
1543 bool mIsOpaque;
1544 // This is set to true by ComputeVisibility if any display item in this
1545 // list needs to force the surface containing this list to be transparent.
1546 bool mForceTransparentSurface;
1547 #ifdef DEBUG
1548 bool mDidComputeVisibility;
1549 #endif
1553 * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
1554 * will put any generated items onto the appropriate list given here. It's
1555 * basically just a collection with one list for each separate stacking layer.
1556 * The lists themselves are external to this object and thus can be shared
1557 * with others. Some of the list pointers may even refer to the same list.
1559 class nsDisplayListSet {
1560 public:
1562 * @return a list where one should place the border and/or background for
1563 * this frame (everything from steps 1 and 2 of CSS 2.1 appendix E)
1565 nsDisplayList* BorderBackground() const { return mBorderBackground; }
1567 * @return a list where one should place the borders and/or backgrounds for
1568 * block-level in-flow descendants (step 4 of CSS 2.1 appendix E)
1570 nsDisplayList* BlockBorderBackgrounds() const { return mBlockBorderBackgrounds; }
1572 * @return a list where one should place descendant floats (step 5 of
1573 * CSS 2.1 appendix E)
1575 nsDisplayList* Floats() const { return mFloats; }
1577 * @return a list where one should place the (pseudo) stacking contexts
1578 * for descendants of this frame (everything from steps 3, 7 and 8
1579 * of CSS 2.1 appendix E)
1581 nsDisplayList* PositionedDescendants() const { return mPositioned; }
1583 * @return a list where one should place the outlines
1584 * for this frame and its descendants (step 9 of CSS 2.1 appendix E)
1586 nsDisplayList* Outlines() const { return mOutlines; }
1588 * @return a list where one should place all other content
1590 nsDisplayList* Content() const { return mContent; }
1592 nsDisplayListSet(nsDisplayList* aBorderBackground,
1593 nsDisplayList* aBlockBorderBackgrounds,
1594 nsDisplayList* aFloats,
1595 nsDisplayList* aContent,
1596 nsDisplayList* aPositionedDescendants,
1597 nsDisplayList* aOutlines) :
1598 mBorderBackground(aBorderBackground),
1599 mBlockBorderBackgrounds(aBlockBorderBackgrounds),
1600 mFloats(aFloats),
1601 mContent(aContent),
1602 mPositioned(aPositionedDescendants),
1603 mOutlines(aOutlines) {
1607 * A copy constructor that lets the caller override the BorderBackground
1608 * list.
1610 nsDisplayListSet(const nsDisplayListSet& aLists,
1611 nsDisplayList* aBorderBackground) :
1612 mBorderBackground(aBorderBackground),
1613 mBlockBorderBackgrounds(aLists.BlockBorderBackgrounds()),
1614 mFloats(aLists.Floats()),
1615 mContent(aLists.Content()),
1616 mPositioned(aLists.PositionedDescendants()),
1617 mOutlines(aLists.Outlines()) {
1621 * Move all display items in our lists to top of the corresponding lists in the
1622 * destination.
1624 void MoveTo(const nsDisplayListSet& aDestination) const;
1626 private:
1627 // This class is only used on stack, so we don't have to worry about leaking
1628 // it. Don't let us be heap-allocated!
1629 void* operator new(size_t sz) CPP_THROW_NEW;
1631 protected:
1632 nsDisplayList* mBorderBackground;
1633 nsDisplayList* mBlockBorderBackgrounds;
1634 nsDisplayList* mFloats;
1635 nsDisplayList* mContent;
1636 nsDisplayList* mPositioned;
1637 nsDisplayList* mOutlines;
1641 * A specialization of nsDisplayListSet where the lists are actually internal
1642 * to the object, and all distinct.
1644 struct nsDisplayListCollection : public nsDisplayListSet {
1645 nsDisplayListCollection() :
1646 nsDisplayListSet(&mLists[0], &mLists[1], &mLists[2], &mLists[3], &mLists[4],
1647 &mLists[5]) {}
1648 nsDisplayListCollection(nsDisplayList* aBorderBackground) :
1649 nsDisplayListSet(aBorderBackground, &mLists[1], &mLists[2], &mLists[3], &mLists[4],
1650 &mLists[5]) {}
1653 * Sort all lists by content order.
1655 void SortAllByContentOrder(nsDisplayListBuilder* aBuilder, nsIContent* aCommonAncestor) {
1656 for (int32_t i = 0; i < 6; ++i) {
1657 mLists[i].SortByContentOrder(aBuilder, aCommonAncestor);
1661 private:
1662 // This class is only used on stack, so we don't have to worry about leaking
1663 // it. Don't let us be heap-allocated!
1664 void* operator new(size_t sz) CPP_THROW_NEW;
1666 nsDisplayList mLists[6];
1670 class nsDisplayImageContainer : public nsDisplayItem {
1671 public:
1672 typedef mozilla::layers::ImageContainer ImageContainer;
1673 typedef mozilla::layers::ImageLayer ImageLayer;
1675 nsDisplayImageContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
1676 : nsDisplayItem(aBuilder, aFrame)
1679 virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
1680 nsDisplayListBuilder* aBuilder) = 0;
1681 virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) = 0;
1683 virtual bool SupportsOptimizingToImage() MOZ_OVERRIDE { return true; }
1687 * Use this class to implement not-very-frequently-used display items
1688 * that are not opaque, do not receive events, and are bounded by a frame's
1689 * border-rect.
1691 * This should not be used for display items which are created frequently,
1692 * because each item is one or two pointers bigger than an item from a
1693 * custom display item class could be, and fractionally slower. However it does
1694 * save code size. We use this for infrequently-used item types.
1696 class nsDisplayGeneric : public nsDisplayItem {
1697 public:
1698 typedef void (* PaintCallback)(nsIFrame* aFrame, nsRenderingContext* aCtx,
1699 const nsRect& aDirtyRect, nsPoint aFramePt);
1701 nsDisplayGeneric(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1702 PaintCallback aPaint, const char* aName, Type aType)
1703 : nsDisplayItem(aBuilder, aFrame), mPaint(aPaint)
1704 #ifdef MOZ_DUMP_PAINTING
1705 , mName(aName)
1706 #endif
1707 , mType(aType)
1709 MOZ_COUNT_CTOR(nsDisplayGeneric);
1711 #ifdef NS_BUILD_REFCNT_LOGGING
1712 virtual ~nsDisplayGeneric() {
1713 MOZ_COUNT_DTOR(nsDisplayGeneric);
1715 #endif
1717 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE {
1718 mPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame());
1720 NS_DISPLAY_DECL_NAME(mName, mType)
1722 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) {
1723 if (mType == nsDisplayItem::TYPE_HEADER_FOOTER) {
1724 bool snap;
1725 return GetBounds(aBuilder, &snap);
1727 return nsRect();
1730 protected:
1731 PaintCallback mPaint;
1732 #ifdef MOZ_DUMP_PAINTING
1733 const char* mName;
1734 #endif
1735 Type mType;
1739 * Generic display item that can contain overflow. Use this in lieu of
1740 * nsDisplayGeneric if you have a frame that should use the visual overflow
1741 * rect of its frame when drawing items, instead of the frame's bounds.
1743 class nsDisplayGenericOverflow : public nsDisplayGeneric {
1744 public:
1745 nsDisplayGenericOverflow(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1746 PaintCallback aPaint, const char* aName, Type aType)
1747 : nsDisplayGeneric(aBuilder, aFrame, aPaint, aName, aType)
1749 MOZ_COUNT_CTOR(nsDisplayGenericOverflow);
1751 #ifdef NS_BUILD_REFCNT_LOGGING
1752 virtual ~nsDisplayGenericOverflow() {
1753 MOZ_COUNT_DTOR(nsDisplayGenericOverflow);
1755 #endif
1758 * Returns the frame's visual overflow rect instead of the frame's bounds.
1760 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
1761 bool* aSnap) MOZ_OVERRIDE
1763 *aSnap = false;
1764 return Frame()->GetVisualOverflowRect() + ToReferenceFrame();
1768 #if defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)
1770 * This class implements painting of reflow counts. Ideally, we would simply
1771 * make all the frame names be those returned by nsFrame::GetFrameName
1772 * (except that tosses in the content tag name!) and support only one color
1773 * and eliminate this class altogether in favor of nsDisplayGeneric, but for
1774 * the time being we can't pass args to a PaintCallback, so just have a
1775 * separate class to do the right thing. Sadly, this alsmo means we need to
1776 * hack all leaf frame classes to handle this.
1778 * XXXbz the color thing is a bit of a mess, but 0 basically means "not set"
1779 * here... I could switch it all to nscolor, but why bother?
1781 class nsDisplayReflowCount : public nsDisplayItem {
1782 public:
1783 nsDisplayReflowCount(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1784 const char* aFrameName,
1785 uint32_t aColor = 0)
1786 : nsDisplayItem(aBuilder, aFrame),
1787 mFrameName(aFrameName),
1788 mColor(aColor)
1790 MOZ_COUNT_CTOR(nsDisplayReflowCount);
1792 #ifdef NS_BUILD_REFCNT_LOGGING
1793 virtual ~nsDisplayReflowCount() {
1794 MOZ_COUNT_DTOR(nsDisplayReflowCount);
1796 #endif
1798 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE {
1799 mFrame->PresContext()->PresShell()->PaintCount(mFrameName, aCtx,
1800 mFrame->PresContext(),
1801 mFrame, ToReferenceFrame(),
1802 mColor);
1804 NS_DISPLAY_DECL_NAME("nsDisplayReflowCount", TYPE_REFLOW_COUNT)
1805 protected:
1806 const char* mFrameName;
1807 nscolor mColor;
1810 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name) \
1811 PR_BEGIN_MACRO \
1812 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
1813 PresContext()->PresShell()->IsPaintingFrameCounts()) { \
1814 aLists.Outlines()->AppendNewToTop( \
1815 new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name)); \
1817 PR_END_MACRO
1819 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color) \
1820 PR_BEGIN_MACRO \
1821 if (!aBuilder->IsBackgroundOnly() && !aBuilder->IsForEventDelivery() && \
1822 PresContext()->PresShell()->IsPaintingFrameCounts()) { \
1823 aLists.Outlines()->AppendNewToTop( \
1824 new (aBuilder) nsDisplayReflowCount(aBuilder, this, _name, _color)); \
1826 PR_END_MACRO
1829 Macro to be used for classes that don't actually implement BuildDisplayList
1831 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super) \
1832 void BuildDisplayList(nsDisplayListBuilder* aBuilder, \
1833 const nsRect& aDirtyRect, \
1834 const nsDisplayListSet& aLists) { \
1835 DO_GLOBAL_REFLOW_COUNT_DSP(#_class); \
1836 _super::BuildDisplayList(aBuilder, aDirtyRect, aLists); \
1839 #else // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
1841 #define DO_GLOBAL_REFLOW_COUNT_DSP(_name)
1842 #define DO_GLOBAL_REFLOW_COUNT_DSP_COLOR(_name, _color)
1843 #define DECL_DO_GLOBAL_REFLOW_COUNT_DSP(_class, _super)
1845 #endif // MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF
1847 class nsDisplayCaret : public nsDisplayItem {
1848 public:
1849 nsDisplayCaret(nsDisplayListBuilder* aBuilder, nsIFrame* aCaretFrame,
1850 nsCaret *aCaret)
1851 : nsDisplayItem(aBuilder, aCaretFrame), mCaret(aCaret) {
1852 MOZ_COUNT_CTOR(nsDisplayCaret);
1854 #ifdef NS_BUILD_REFCNT_LOGGING
1855 virtual ~nsDisplayCaret() {
1856 MOZ_COUNT_DTOR(nsDisplayCaret);
1858 #endif
1860 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE {
1861 *aSnap = false;
1862 // The caret returns a rect in the coordinates of mFrame.
1863 return mCaret->GetCaretRect() + ToReferenceFrame();
1865 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
1866 NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
1867 protected:
1868 nsRefPtr<nsCaret> mCaret;
1872 * The standard display item to paint the CSS borders of a frame.
1874 class nsDisplayBorder : public nsDisplayItem {
1875 public:
1876 nsDisplayBorder(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
1877 nsDisplayItem(aBuilder, aFrame)
1879 MOZ_COUNT_CTOR(nsDisplayBorder);
1881 #ifdef NS_BUILD_REFCNT_LOGGING
1882 virtual ~nsDisplayBorder() {
1883 MOZ_COUNT_DTOR(nsDisplayBorder);
1885 #endif
1887 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
1888 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
1889 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
1890 nsRegion* aVisibleRegion,
1891 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
1892 NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
1894 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder);
1896 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
1897 const nsDisplayItemGeometry* aGeometry,
1898 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
1902 * A simple display item that just renders a solid color across the
1903 * specified bounds. For canvas frames (in the CSS sense) we split off the
1904 * drawing of the background color into this class (from nsDisplayBackground
1905 * via nsDisplayCanvasBackground). This is done so that we can always draw a
1906 * background color to avoid ugly flashes of white when we can't draw a full
1907 * frame tree (ie when a page is loading). The bounds can differ from the
1908 * frame's bounds -- this is needed when a frame/iframe is loading and there
1909 * is not yet a frame tree to go in the frame/iframe so we use the subdoc
1910 * frame of the parent document as a standin.
1912 class nsDisplaySolidColor : public nsDisplayItem {
1913 public:
1914 nsDisplaySolidColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1915 const nsRect& aBounds, nscolor aColor)
1916 : nsDisplayItem(aBuilder, aFrame), mBounds(aBounds), mColor(aColor)
1918 NS_ASSERTION(NS_GET_A(aColor) > 0, "Don't create invisible nsDisplaySolidColors!");
1919 MOZ_COUNT_CTOR(nsDisplaySolidColor);
1921 #ifdef NS_BUILD_REFCNT_LOGGING
1922 virtual ~nsDisplaySolidColor() {
1923 MOZ_COUNT_DTOR(nsDisplaySolidColor);
1925 #endif
1927 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
1929 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
1930 bool* aSnap) MOZ_OVERRIDE {
1931 *aSnap = false;
1932 nsRegion result;
1933 if (NS_GET_A(mColor) == 255) {
1934 result = GetBounds(aBuilder, aSnap);
1936 return result;
1939 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE
1941 *aColor = mColor;
1942 return true;
1945 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
1947 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
1949 return new nsDisplaySolidColorGeometry(this, aBuilder, mColor);
1952 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
1953 const nsDisplayItemGeometry* aGeometry,
1954 nsRegion* aInvalidRegion) MOZ_OVERRIDE
1956 const nsDisplaySolidColorGeometry* geometry =
1957 static_cast<const nsDisplaySolidColorGeometry*>(aGeometry);
1958 if (mColor != geometry->mColor) {
1959 bool dummy;
1960 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &dummy));
1961 return;
1963 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
1966 #ifdef MOZ_DUMP_PAINTING
1967 virtual void WriteDebugInfo(FILE *aOutput) MOZ_OVERRIDE
1969 fprintf_stderr(aOutput, "(rgba %d,%d,%d,%d)",
1970 NS_GET_R(mColor), NS_GET_G(mColor),
1971 NS_GET_B(mColor), NS_GET_A(mColor));
1973 #endif
1975 NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
1977 private:
1978 nsRect mBounds;
1979 nscolor mColor;
1983 * A display item to paint one background-image for a frame. Each background
1984 * image layer gets its own nsDisplayBackgroundImage.
1986 class nsDisplayBackgroundImage : public nsDisplayImageContainer {
1987 public:
1989 * aLayer signifies which background layer this item represents.
1990 * aIsThemed should be the value of aFrame->IsThemed.
1991 * aBackgroundStyle should be the result of
1992 * nsCSSRendering::FindBackground, or null if FindBackground returned false.
1994 nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
1995 uint32_t aLayer,
1996 const nsStyleBackground* aBackgroundStyle);
1997 virtual ~nsDisplayBackgroundImage();
1999 // This will create and append new items for all the layers of the
2000 // background. Returns whether we appended a themed background.
2001 static bool AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuilder,
2002 nsIFrame* aFrame,
2003 nsDisplayList* aList);
2005 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2006 LayerManager* aManager,
2007 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
2009 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2010 LayerManager* aManager,
2011 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2013 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2014 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2015 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2016 nsRegion* aVisibleRegion,
2017 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2018 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2019 bool* aSnap) MOZ_OVERRIDE;
2020 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
2021 nsIFrame* aFrame) MOZ_OVERRIDE;
2022 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
2024 * GetBounds() returns the background painting area.
2026 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2027 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2028 virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE;
2029 NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
2032 * Return the background positioning area.
2033 * (GetBounds() returns the background painting area.)
2034 * Can be called only when mBackgroundStyle is non-null.
2036 nsRect GetPositioningArea();
2039 * Returns true if existing rendered pixels of this display item may need
2040 * to be redrawn if the positioning area size changes but its position does
2041 * not.
2042 * If false, only the changed painting area needs to be redrawn when the
2043 * positioning area size changes but its position does not.
2045 bool RenderingMightDependOnPositioningAreaSizeChange();
2047 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
2049 return new nsDisplayBackgroundGeometry(this, aBuilder);
2052 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2053 const nsDisplayItemGeometry* aGeometry,
2054 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
2056 virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
2057 nsDisplayListBuilder *aBuilder) MOZ_OVERRIDE;
2058 virtual void ConfigureLayer(ImageLayer* aLayer, const nsIntPoint& aOffset) MOZ_OVERRIDE;
2060 static nsRegion GetInsideClipRegion(nsDisplayItem* aItem, nsPresContext* aPresContext, uint8_t aClip,
2061 const nsRect& aRect, bool* aSnap);
2063 protected:
2064 typedef class mozilla::layers::ImageContainer ImageContainer;
2065 typedef class mozilla::layers::ImageLayer ImageLayer;
2067 bool TryOptimizeToImageLayer(LayerManager* aManager, nsDisplayListBuilder* aBuilder);
2068 bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
2069 const nsRect& aClipRect,
2070 gfxRect* aDestRect);
2071 nsRect GetBoundsInternal(nsDisplayListBuilder* aBuilder);
2073 void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
2074 const nsRect& aBounds, nsRect* aClipRect);
2076 // Cache the result of nsCSSRendering::FindBackground. Always null if
2077 // mIsThemed is true or if FindBackground returned false.
2078 const nsStyleBackground* mBackgroundStyle;
2079 /* If this background can be a simple image layer, we store the format here. */
2080 nsRefPtr<ImageContainer> mImageContainer;
2081 gfxRect mDestRect;
2082 /* Bounds of this display item */
2083 nsRect mBounds;
2084 uint32_t mLayer;
2089 * A display item to paint the native theme background for a frame.
2091 class nsDisplayThemedBackground : public nsDisplayItem {
2092 public:
2093 nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
2094 virtual ~nsDisplayThemedBackground();
2096 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2097 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2098 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2099 bool* aSnap) MOZ_OVERRIDE;
2100 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
2102 * GetBounds() returns the background painting area.
2104 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2105 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2106 NS_DISPLAY_DECL_NAME("ThemedBackground", TYPE_THEMED_BACKGROUND)
2109 * Return the background positioning area.
2110 * (GetBounds() returns the background painting area.)
2111 * Can be called only when mBackgroundStyle is non-null.
2113 nsRect GetPositioningArea();
2116 * Return whether our frame's document does not have the state
2117 * NS_DOCUMENT_STATE_WINDOW_INACTIVE.
2119 bool IsWindowActive();
2121 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
2123 return new nsDisplayThemedBackgroundGeometry(this, aBuilder);
2126 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2127 const nsDisplayItemGeometry* aGeometry,
2128 nsRegion* aInvalidRegion) MOZ_OVERRIDE;
2130 #ifdef MOZ_DUMP_PAINTING
2131 virtual void WriteDebugInfo(FILE *aOutput) MOZ_OVERRIDE;
2132 #endif
2133 protected:
2134 nsRect GetBoundsInternal();
2136 void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
2137 const nsRect& aBounds, nsRect* aClipRect);
2139 nsRect mBounds;
2140 nsITheme::Transparency mThemeTransparency;
2141 uint8_t mAppearance;
2144 class nsDisplayBackgroundColor : public nsDisplayItem
2146 public:
2147 nsDisplayBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2148 const nsStyleBackground* aBackgroundStyle,
2149 nscolor aColor)
2150 : nsDisplayItem(aBuilder, aFrame)
2151 , mBackgroundStyle(aBackgroundStyle)
2152 , mColor(aColor)
2155 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2157 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2158 bool* aSnap) MOZ_OVERRIDE;
2159 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
2160 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2161 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2163 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
2165 *aSnap = true;
2166 return nsRect(ToReferenceFrame(), Frame()->GetSize());
2169 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
2171 return new nsDisplayItemBoundsGeometry(this, aBuilder);
2174 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2175 const nsDisplayItemGeometry* aGeometry,
2176 nsRegion* aInvalidRegion) MOZ_OVERRIDE
2178 const nsDisplayItemBoundsGeometry* geometry = static_cast<const nsDisplayItemBoundsGeometry*>(aGeometry);
2179 ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion);
2182 NS_DISPLAY_DECL_NAME("BackgroundColor", TYPE_BACKGROUND_COLOR)
2183 #ifdef MOZ_DUMP_PAINTING
2184 virtual void WriteDebugInfo(FILE *aOutput) MOZ_OVERRIDE {
2185 fprintf_stderr(aOutput, "(rgba %d,%d,%d,%d)",
2186 NS_GET_R(mColor), NS_GET_G(mColor),
2187 NS_GET_B(mColor), NS_GET_A(mColor));
2190 #endif
2192 protected:
2193 const nsStyleBackground* mBackgroundStyle;
2194 nscolor mColor;
2198 * The standard display item to paint the outer CSS box-shadows of a frame.
2200 class nsDisplayBoxShadowOuter : public nsDisplayItem {
2201 public:
2202 nsDisplayBoxShadowOuter(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2203 : nsDisplayItem(aBuilder, aFrame)
2204 , mOpacity(1.0) {
2205 MOZ_COUNT_CTOR(nsDisplayBoxShadowOuter);
2206 mBounds = GetBoundsInternal();
2208 #ifdef NS_BUILD_REFCNT_LOGGING
2209 virtual ~nsDisplayBoxShadowOuter() {
2210 MOZ_COUNT_DTOR(nsDisplayBoxShadowOuter);
2212 #endif
2214 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2215 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2216 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2217 nsRegion* aVisibleRegion,
2218 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2219 NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
2221 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2222 const nsDisplayItemGeometry* aGeometry,
2223 nsRegion* aInvalidRegion);
2225 virtual bool ApplyOpacity(float aOpacity)
2227 mOpacity = aOpacity;
2228 return true;
2231 nsRect GetBoundsInternal();
2233 private:
2234 nsRegion mVisibleRegion;
2235 nsRect mBounds;
2236 float mOpacity;
2240 * The standard display item to paint the inner CSS box-shadows of a frame.
2242 class nsDisplayBoxShadowInner : public nsDisplayItem {
2243 public:
2244 nsDisplayBoxShadowInner(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2245 : nsDisplayItem(aBuilder, aFrame) {
2246 MOZ_COUNT_CTOR(nsDisplayBoxShadowInner);
2248 #ifdef NS_BUILD_REFCNT_LOGGING
2249 virtual ~nsDisplayBoxShadowInner() {
2250 MOZ_COUNT_DTOR(nsDisplayBoxShadowInner);
2252 #endif
2254 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2255 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2256 nsRegion* aVisibleRegion,
2257 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2258 NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
2260 virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder)
2262 return new nsDisplayBoxShadowInnerGeometry(this, aBuilder);
2265 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2266 const nsDisplayItemGeometry* aGeometry,
2267 nsRegion* aInvalidRegion) MOZ_OVERRIDE
2269 const nsDisplayBoxShadowInnerGeometry* geometry = static_cast<const nsDisplayBoxShadowInnerGeometry*>(aGeometry);
2270 if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
2271 // nsDisplayBoxShadowInner is based around the padding rect, but it can
2272 // touch pixels outside of this. We should invalidate the entire bounds.
2273 bool snap;
2274 aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
2278 private:
2279 nsRegion mVisibleRegion;
2283 * The standard display item to paint the CSS outline of a frame.
2285 class nsDisplayOutline : public nsDisplayItem {
2286 public:
2287 nsDisplayOutline(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
2288 nsDisplayItem(aBuilder, aFrame) {
2289 MOZ_COUNT_CTOR(nsDisplayOutline);
2291 #ifdef NS_BUILD_REFCNT_LOGGING
2292 virtual ~nsDisplayOutline() {
2293 MOZ_COUNT_DTOR(nsDisplayOutline);
2295 #endif
2297 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2298 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2299 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2300 nsRegion* aVisibleRegion,
2301 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2302 NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
2306 * A class that lets you receive events within the frame bounds but never paints.
2308 class nsDisplayEventReceiver : public nsDisplayItem {
2309 public:
2310 nsDisplayEventReceiver(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2311 : nsDisplayItem(aBuilder, aFrame) {
2312 MOZ_COUNT_CTOR(nsDisplayEventReceiver);
2314 #ifdef NS_BUILD_REFCNT_LOGGING
2315 virtual ~nsDisplayEventReceiver() {
2316 MOZ_COUNT_DTOR(nsDisplayEventReceiver);
2318 #endif
2320 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2321 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2322 NS_DISPLAY_DECL_NAME("EventReceiver", TYPE_EVENT_RECEIVER)
2326 * A class that lets you wrap a display list as a display item.
2328 * GetUnderlyingFrame() is troublesome for wrapped lists because if the wrapped
2329 * list has many items, it's not clear which one has the 'underlying frame'.
2330 * Thus we force the creator to specify what the underlying frame is. The
2331 * underlying frame should be the root of a stacking context, because sorting
2332 * a list containing this item will not get at the children.
2334 * In some cases (e.g., clipping) we want to wrap a list but we don't have a
2335 * particular underlying frame that is a stacking context root. In that case
2336 * we allow the frame to be nullptr. Callers to GetUnderlyingFrame must
2337 * detect and handle this case.
2339 class nsDisplayWrapList : public nsDisplayItem {
2340 // This is never instantiated directly, so no need to count constructors and
2341 // destructors.
2343 public:
2345 * Takes all the items from aList and puts them in our list.
2347 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2348 nsDisplayList* aList);
2349 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2350 nsDisplayItem* aItem);
2351 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2352 nsDisplayItem* aItem, const nsIFrame* aReferenceFrame, const nsPoint& aToReferenceFrame);
2353 nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
2354 : nsDisplayItem(aBuilder, aFrame) {}
2355 virtual ~nsDisplayWrapList();
2357 * Call this if the wrapped list is changed.
2359 virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
2361 mBounds = mList.GetBounds(aBuilder);
2363 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2364 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2365 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2366 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2367 bool* aSnap) MOZ_OVERRIDE;
2368 virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE;
2369 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
2370 nsIFrame* aFrame) MOZ_OVERRIDE;
2371 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2372 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2373 nsRegion* aVisibleRegion,
2374 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2375 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE {
2376 NS_WARNING("This list should already have been flattened!!!");
2377 return false;
2379 virtual void GetMergedFrames(nsTArray<nsIFrame*>* aFrames) MOZ_OVERRIDE
2381 aFrames->AppendElements(mMergedFrames);
2383 virtual bool IsInvalid(nsRect& aRect) MOZ_OVERRIDE
2385 if (mFrame->IsInvalid(aRect) && aRect.IsEmpty()) {
2386 return true;
2388 nsRect temp;
2389 for (uint32_t i = 0; i < mMergedFrames.Length(); i++) {
2390 if (mMergedFrames[i]->IsInvalid(temp) && temp.IsEmpty()) {
2391 aRect.SetEmpty();
2392 return true;
2394 aRect = aRect.Union(temp);
2396 aRect += ToReferenceFrame();
2397 return !aRect.IsEmpty();
2399 NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST)
2401 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);
2403 virtual nsDisplayList* GetSameCoordinateSystemChildren() MOZ_OVERRIDE
2405 NS_ASSERTION(mList.IsEmpty() || !ReferenceFrame() ||
2406 !mList.GetBottom()->ReferenceFrame() ||
2407 mList.GetBottom()->ReferenceFrame() == ReferenceFrame(),
2408 "Children must have same reference frame");
2409 return &mList;
2411 virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return &mList; }
2414 * This creates a copy of this item, but wrapping aItem instead of
2415 * our existing list. Only gets called if this item returned nullptr
2416 * for GetUnderlyingFrame(). aItem is guaranteed to return non-null from
2417 * GetUnderlyingFrame().
2419 virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
2420 nsDisplayItem* aItem) {
2421 NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!");
2422 return nullptr;
2426 * Returns true if all descendant display items can be placed in the same
2427 * ThebesLayer --- GetLayerState returns LAYER_INACTIVE or LAYER_NONE,
2428 * and they all have the given aAnimatedGeometryRoot.
2430 static LayerState RequiredLayerStateForChildren(nsDisplayListBuilder* aBuilder,
2431 LayerManager* aManager,
2432 const ContainerLayerParameters& aParameters,
2433 const nsDisplayList& aList,
2434 nsIFrame* aItemFrame);
2436 protected:
2437 nsDisplayWrapList() {}
2439 void MergeFrom(nsDisplayWrapList* aOther)
2441 mList.AppendToBottom(&aOther->mList);
2442 mBounds.UnionRect(mBounds, aOther->mBounds);
2444 void MergeFromTrackingMergedFrames(nsDisplayWrapList* aOther)
2446 MergeFrom(aOther);
2447 mMergedFrames.AppendElement(aOther->mFrame);
2448 mMergedFrames.MoveElementsFrom(aOther->mMergedFrames);
2451 nsDisplayList mList;
2452 // The frames from items that have been merged into this item, excluding
2453 // this item's own frame.
2454 nsTArray<nsIFrame*> mMergedFrames;
2455 nsRect mBounds;
2459 * We call WrapDisplayList on the in-flow lists: BorderBackground(),
2460 * BlockBorderBackgrounds() and Content().
2461 * We call WrapDisplayItem on each item of Outlines(), PositionedDescendants(),
2462 * and Floats(). This is done to support special wrapping processing for frames
2463 * that may not be in-flow descendants of the current frame.
2465 class nsDisplayWrapper {
2466 public:
2467 // This is never instantiated directly (it has pure virtual methods), so no
2468 // need to count constructors and destructors.
2470 virtual bool WrapBorderBackground() { return true; }
2471 virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
2472 nsIFrame* aFrame, nsDisplayList* aList) = 0;
2473 virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
2474 nsDisplayItem* aItem) = 0;
2476 nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2477 const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
2478 nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2479 const nsDisplayListSet& aLists);
2480 protected:
2481 nsDisplayWrapper() {}
2485 * The standard display item to paint a stacking context with translucency
2486 * set by the stacking context root frame's 'opacity' style.
2488 class nsDisplayOpacity : public nsDisplayWrapList {
2489 public:
2490 nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2491 nsDisplayList* aList);
2492 #ifdef NS_BUILD_REFCNT_LOGGING
2493 virtual ~nsDisplayOpacity();
2494 #endif
2496 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2497 bool* aSnap) MOZ_OVERRIDE;
2498 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2499 LayerManager* aManager,
2500 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2501 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2502 LayerManager* aManager,
2503 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
2504 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2505 nsRegion* aVisibleRegion,
2506 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2507 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
2508 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2509 const nsDisplayItemGeometry* aGeometry,
2510 nsRegion* aInvalidRegion) MOZ_OVERRIDE
2512 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
2514 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
2515 bool NeedsActiveLayer();
2516 NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
2517 #ifdef MOZ_DUMP_PAINTING
2518 virtual void WriteDebugInfo(FILE *aOutput) MOZ_OVERRIDE {
2519 fprintf_stderr(aOutput, "(opacity %f)", mFrame->StyleDisplay()->mOpacity);
2521 #endif
2523 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
2526 class nsDisplayMixBlendMode : public nsDisplayWrapList {
2527 public:
2528 nsDisplayMixBlendMode(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2529 nsDisplayList* aList, uint32_t aFlags = 0);
2530 #ifdef NS_BUILD_REFCNT_LOGGING
2531 virtual ~nsDisplayMixBlendMode();
2532 #endif
2534 nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap);
2536 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2537 LayerManager* aManager,
2538 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2539 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2540 const nsDisplayItemGeometry* aGeometry,
2541 nsRegion* aInvalidRegion) MOZ_OVERRIDE
2543 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
2545 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2546 LayerManager* aManager,
2547 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
2549 return mozilla::LAYER_INACTIVE;
2551 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2552 nsRegion* aVisibleRegion,
2553 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2554 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
2555 NS_DISPLAY_DECL_NAME("MixBlendMode", TYPE_MIX_BLEND_MODE)
2558 class nsDisplayBlendContainer : public nsDisplayWrapList {
2559 public:
2560 nsDisplayBlendContainer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2561 nsDisplayList* aList, uint32_t aFlags = 0);
2562 #ifdef NS_BUILD_REFCNT_LOGGING
2563 virtual ~nsDisplayBlendContainer();
2564 #endif
2566 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2567 LayerManager* aManager,
2568 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2569 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2570 LayerManager* aManager,
2571 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
2573 return mozilla::LAYER_INACTIVE;
2575 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
2576 NS_DISPLAY_DECL_NAME("BlendContainer", TYPE_BLEND_CONTAINER)
2580 * A display item that has no purpose but to ensure its contents get
2581 * their own layer.
2583 class nsDisplayOwnLayer : public nsDisplayWrapList {
2584 public:
2587 * nsDisplayOwnLayer constructor flags
2589 enum {
2590 GENERATE_SUBDOC_INVALIDATIONS = 0x01,
2591 VERTICAL_SCROLLBAR = 0x02,
2592 HORIZONTAL_SCROLLBAR = 0x04
2596 * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
2597 * Add UserData to the created ContainerLayer, so that invalidations
2598 * for this layer are send to our nsPresContext.
2599 * @param aScrollTarget when VERTICAL_SCROLLBAR or HORIZONTAL_SCROLLBAR
2600 * is set in the flags, this parameter should be the ViewID of the
2601 * scrollable content this scrollbar is for.
2603 nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2604 nsDisplayList* aList, uint32_t aFlags = 0,
2605 ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID);
2606 #ifdef NS_BUILD_REFCNT_LOGGING
2607 virtual ~nsDisplayOwnLayer();
2608 #endif
2610 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2611 LayerManager* aManager,
2612 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2613 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2614 LayerManager* aManager,
2615 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
2617 return mozilla::LAYER_ACTIVE_FORCE;
2619 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE
2621 // Don't allow merging, each sublist must have its own layer
2622 return false;
2624 NS_DISPLAY_DECL_NAME("OwnLayer", TYPE_OWN_LAYER)
2625 private:
2626 uint32_t mFlags;
2627 ViewID mScrollTarget;
2631 * A display item for subdocuments to capture the resolution from the presShell
2632 * and ensure that it gets applied to all the right elements. This item creates
2633 * a container layer.
2635 class nsDisplayResolution : public nsDisplayOwnLayer {
2636 public:
2637 nsDisplayResolution(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2638 nsDisplayList* aList, uint32_t aFlags);
2639 #ifdef NS_BUILD_REFCNT_LOGGING
2640 virtual ~nsDisplayResolution();
2641 #endif
2643 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2644 LayerManager* aManager,
2645 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2646 NS_DISPLAY_DECL_NAME("Resolution", TYPE_RESOLUTION)
2650 * A display item used to represent sticky position elements. The contents
2651 * gets its own layer and creates a stacking context, and the layer will have
2652 * position-related metadata set on it.
2654 class nsDisplayStickyPosition : public nsDisplayOwnLayer {
2655 public:
2656 nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2657 nsIFrame* aStickyPosFrame, nsDisplayList* aList);
2658 #ifdef NS_BUILD_REFCNT_LOGGING
2659 virtual ~nsDisplayStickyPosition();
2660 #endif
2662 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2663 LayerManager* aManager,
2664 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2665 NS_DISPLAY_DECL_NAME("StickyPosition", TYPE_STICKY_POSITION)
2666 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2667 LayerManager* aManager,
2668 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
2670 return mozilla::LAYER_ACTIVE;
2672 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
2674 protected:
2675 nsIFrame* mStickyPosFrame;
2679 * This potentially creates a layer for the given list of items, whose
2680 * visibility is determined by the displayport for the given frame instead of
2681 * what is passed in to ComputeVisibility.
2683 * Here in content, we can use this to render more content than is actually
2684 * visible. Then, the compositing process can manipulate the generated layer
2685 * through transformations so that asynchronous scrolling can be implemented.
2687 * Note that setting the displayport will not change any hit testing! The
2688 * content process will know nothing about what the user is actually seeing,
2689 * so it can only do hit testing for what is supposed to be the visible region.
2691 * It is possible for scroll boxes to have content that can be both above and
2692 * below content outside of the scroll box. We cannot create layers for these
2693 * cases. This is accomplished by wrapping display items with
2694 * nsDisplayScrollLayers. nsDisplayScrollLayers with the same scroll frame will
2695 * be merged together. If more than one nsDisplayScrollLayer exists after
2696 * merging, all nsDisplayScrollLayers will be flattened out so that no new
2697 * layer is created at all.
2699 class nsDisplayScrollLayer : public nsDisplayWrapList
2701 public:
2703 * @param aScrolledFrame This will determine what the displayport is. It should be
2704 * the root content frame of the scrolled area. Note
2705 * that nsDisplayScrollLayer will expect for
2706 * ScrollLayerCount to be defined on aScrolledFrame.
2707 * @param aScrollFrame The viewport frame you see this content through.
2709 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
2710 nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
2711 nsIFrame* aScrollFrame);
2712 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
2713 nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
2714 nsIFrame* aScrollFrame);
2715 nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
2716 nsIFrame* aForFrame, nsIFrame* aScrolledFrame,
2717 nsIFrame* aScrollFrame);
2718 NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
2720 #ifdef NS_BUILD_REFCNT_LOGGING
2721 virtual ~nsDisplayScrollLayer();
2722 #endif
2724 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2726 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2727 LayerManager* aManager,
2728 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2730 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
2732 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2733 bool* aSnap) MOZ_OVERRIDE {
2734 *aSnap = false;
2735 return nsRegion();
2738 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2739 nsRegion* aVisibleRegion,
2740 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2742 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2743 LayerManager* aManager,
2744 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
2746 virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
2747 nsDisplayItem* aItem) MOZ_OVERRIDE;
2749 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
2751 // Get the number of nsDisplayScrollLayers for a scroll frame. Note that this
2752 // number does not include nsDisplayScrollInfoLayers. If this number is not 1
2753 // after merging, all the nsDisplayScrollLayers should flatten away.
2754 intptr_t GetScrollLayerCount();
2756 virtual nsIFrame* GetScrollFrame() { return mScrollFrame; }
2757 virtual nsIFrame* GetScrolledFrame() { return mScrolledFrame; }
2759 protected:
2760 nsIFrame* mScrollFrame;
2761 nsIFrame* mScrolledFrame;
2765 * Like nsDisplayScrollLayer, but only has metadata on the scroll frame. This
2766 * creates a layer that has no Thebes child layer, but still allows the
2767 * compositor process to know of the scroll frame's existence.
2769 * After visibility computation, nsDisplayScrollInfoLayers should only exist if
2770 * nsDisplayScrollLayers were all flattened away.
2772 * Important!! Add info layers to the bottom of the list so they are only
2773 * considered after the others have flattened out!
2775 class nsDisplayScrollInfoLayer : public nsDisplayScrollLayer
2777 public:
2778 nsDisplayScrollInfoLayer(nsDisplayListBuilder* aBuilder,
2779 nsIFrame* aScrolledFrame, nsIFrame* aScrollFrame);
2780 NS_DISPLAY_DECL_NAME("ScrollInfoLayer", TYPE_SCROLL_INFO_LAYER)
2782 virtual ~nsDisplayScrollInfoLayer();
2784 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2786 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2787 LayerManager* aManager,
2788 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
2789 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
2790 { return true; }
2791 virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
2792 nsDisplayItem* aItem) MOZ_OVERRIDE;
2794 virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
2798 * nsDisplayZoom is used for subdocuments that have a different full zoom than
2799 * their parent documents. This item creates a container layer.
2801 class nsDisplayZoom : public nsDisplayOwnLayer {
2802 public:
2804 * @param aFrame is the root frame of the subdocument.
2805 * @param aList contains the display items for the subdocument.
2806 * @param aAPD is the app units per dev pixel ratio of the subdocument.
2807 * @param aParentAPD is the app units per dev pixel ratio of the parent
2808 * document.
2809 * @param aFlags GENERATE_SUBDOC_INVALIDATIONS :
2810 * Add UserData to the created ContainerLayer, so that invalidations
2811 * for this layer are send to our nsPresContext.
2813 nsDisplayZoom(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2814 nsDisplayList* aList,
2815 int32_t aAPD, int32_t aParentAPD,
2816 uint32_t aFlags = 0);
2817 #ifdef NS_BUILD_REFCNT_LOGGING
2818 virtual ~nsDisplayZoom();
2819 #endif
2821 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
2822 virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
2823 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2824 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2825 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2826 nsRegion* aVisibleRegion,
2827 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2828 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2829 LayerManager* aManager,
2830 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
2832 return mozilla::LAYER_ACTIVE;
2834 NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
2836 // Get the app units per dev pixel ratio of the child document.
2837 int32_t GetChildAppUnitsPerDevPixel() { return mAPD; }
2838 // Get the app units per dev pixel ratio of the parent document.
2839 int32_t GetParentAppUnitsPerDevPixel() { return mParentAPD; }
2841 private:
2842 int32_t mAPD, mParentAPD;
2846 * A display item to paint a stacking context with effects
2847 * set by the stacking context root frame's style.
2849 class nsDisplaySVGEffects : public nsDisplayWrapList {
2850 public:
2851 nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
2852 nsDisplayList* aList);
2853 #ifdef NS_BUILD_REFCNT_LOGGING
2854 virtual ~nsDisplaySVGEffects();
2855 #endif
2857 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
2858 bool* aSnap) MOZ_OVERRIDE;
2859 virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
2860 HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2861 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE {
2862 *aSnap = false;
2863 return mEffectsBounds + ToReferenceFrame();
2865 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
2866 nsRegion* aVisibleRegion,
2867 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2868 virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE;
2869 NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
2871 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2872 LayerManager* aManager,
2873 const ContainerLayerParameters& aParameters);
2875 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2876 LayerManager* aManager,
2877 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2879 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2880 const nsDisplayItemGeometry* aGeometry,
2881 nsRegion* aInvalidRegion) MOZ_OVERRIDE
2883 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
2886 void PaintAsLayer(nsDisplayListBuilder* aBuilder,
2887 nsRenderingContext* aCtx,
2888 LayerManager* aManager);
2890 #ifdef MOZ_DUMP_PAINTING
2891 void PrintEffects(FILE* aOutput);
2892 #endif
2894 private:
2895 // relative to mFrame
2896 nsRect mEffectsBounds;
2899 /* A display item that applies a transformation to all of its descendant
2900 * elements. This wrapper should only be used if there is a transform applied
2901 * to the root element.
2903 * The reason that a "bounds" rect is involved in transform calculations is
2904 * because CSS-transforms allow percentage values for the x and y components
2905 * of <translation-value>s, where percentages are percentages of the element's
2906 * border box.
2908 * INVARIANT: The wrapped frame is transformed or we supplied a transform getter
2909 * function.
2910 * INVARIANT: The wrapped frame is non-null.
2912 class nsDisplayTransform: public nsDisplayItem
2914 public:
2916 * Returns a matrix (in pixels) for the current frame. The matrix should be relative to
2917 * the current frame's coordinate space.
2919 * @param aFrame The frame to compute the transform for.
2920 * @param aAppUnitsPerPixel The number of app units per graphics unit.
2922 typedef gfx3DMatrix (* ComputeTransformFunction)(nsIFrame* aFrame, float aAppUnitsPerPixel);
2924 /* Constructor accepts a display list, empties it, and wraps it up. It also
2925 * ferries the underlying frame to the nsDisplayItem constructor.
2927 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
2928 nsDisplayList *aList, uint32_t aIndex = 0);
2929 nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
2930 nsDisplayList *aList, ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0);
2932 #ifdef NS_BUILD_REFCNT_LOGGING
2933 virtual ~nsDisplayTransform()
2935 MOZ_COUNT_DTOR(nsDisplayTransform);
2937 #endif
2939 NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM)
2941 virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
2943 if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty())
2944 return nsRect();
2945 bool snap;
2946 return GetBounds(aBuilder, &snap);
2949 virtual nsDisplayList* GetChildren() MOZ_OVERRIDE { return mStoredList.GetChildren(); }
2951 virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
2952 HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE;
2953 virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap) MOZ_OVERRIDE;
2954 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
2955 bool* aSnap) MOZ_OVERRIDE;
2956 virtual bool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor) MOZ_OVERRIDE;
2957 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
2958 LayerManager* aManager,
2959 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE;
2960 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
2961 LayerManager* aManager,
2962 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE;
2963 virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
2964 virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
2965 nsRegion *aVisibleRegion,
2966 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
2967 virtual bool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem) MOZ_OVERRIDE;
2969 virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
2971 virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
2972 const nsDisplayItemGeometry* aGeometry,
2973 nsRegion* aInvalidRegion) MOZ_OVERRIDE
2975 // We don't need to compute an invalidation region since we have LayerTreeInvalidation
2978 virtual const nsIFrame* ReferenceFrameForChildren() const MOZ_OVERRIDE {
2979 // If we were created using a transform-getter, then we don't
2980 // belong to a transformed frame, and aren't a reference frame
2981 // for our children.
2982 if (!mTransformGetter) {
2983 return mFrame;
2985 return nsDisplayItem::ReferenceFrameForChildren();
2988 enum {
2989 INDEX_MAX = UINT32_MAX >> nsDisplayItem::TYPE_BITS
2992 const gfx3DMatrix& GetTransform();
2994 float GetHitDepthAtPoint(const nsPoint& aPoint);
2997 * TransformRect takes in as parameters a rectangle (in aFrame's coordinate
2998 * space) and returns the smallest rectangle (in aFrame's coordinate space)
2999 * containing the transformed image of that rectangle. That is, it takes
3000 * the four corners of the rectangle, transforms them according to the
3001 * matrix associated with the specified frame, then returns the smallest
3002 * rectangle containing the four transformed points.
3004 * @param untransformedBounds The rectangle (in app units) to transform.
3005 * @param aFrame The frame whose transformation should be applied. This
3006 * function raises an assertion if aFrame is null or doesn't have a
3007 * transform applied to it.
3008 * @param aOrigin The origin of the transform relative to aFrame's local
3009 * coordinate space.
3010 * @param aBoundsOverride (optional) Rather than using the frame's computed
3011 * bounding rect as frame bounds, use this rectangle instead. Pass
3012 * nullptr (or nothing at all) to use the default.
3014 static nsRect TransformRect(const nsRect &aUntransformedBounds,
3015 const nsIFrame* aFrame,
3016 const nsPoint &aOrigin,
3017 const nsRect* aBoundsOverride = nullptr);
3019 static nsRect TransformRectOut(const nsRect &aUntransformedBounds,
3020 const nsIFrame* aFrame,
3021 const nsPoint &aOrigin,
3022 const nsRect* aBoundsOverride = nullptr);
3024 /* UntransformRect is like TransformRect, except that it inverts the
3025 * transform.
3027 static bool UntransformRect(const nsRect &aUntransformedBounds,
3028 const nsIFrame* aFrame,
3029 const nsPoint &aOrigin,
3030 nsRect* aOutRect);
3032 static bool UntransformRectMatrix(const nsRect &aUntransformedBounds,
3033 const gfx3DMatrix& aMatrix,
3034 float aAppUnitsPerPixel,
3035 nsRect* aOutRect);
3037 static gfxPoint3D GetDeltaToTransformOrigin(const nsIFrame* aFrame,
3038 float aAppUnitsPerPixel,
3039 const nsRect* aBoundsOverride);
3041 static gfxPoint3D GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame,
3042 float aAppUnitsPerPixel);
3045 * Returns the bounds of a frame as defined for resolving percentage
3046 * <translation-value>s in CSS transforms. If
3047 * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding
3048 * rectangle, translated to the origin. Otherwise, returns the smallest
3049 * rectangle containing a frame and all of its continuations. For example,
3050 * if there is a <span> element with several continuations split over
3051 * several lines, this function will return the rectangle containing all of
3052 * those continuations. This rectangle is relative to the origin of the
3053 * frame's local coordinate space.
3055 * @param aFrame The frame to get the bounding rect for.
3056 * @return The frame's bounding rect, as described above.
3058 static nsRect GetFrameBoundsForTransform(const nsIFrame* aFrame);
3060 struct FrameTransformProperties
3062 FrameTransformProperties(const nsIFrame* aFrame,
3063 float aAppUnitsPerPixel,
3064 const nsRect* aBoundsOverride);
3065 FrameTransformProperties(const nsCSSValueList* aTransformList,
3066 const gfxPoint3D& aToTransformOrigin,
3067 const gfxPoint3D& aToPerspectiveOrigin,
3068 nscoord aChildPerspective)
3069 : mFrame(nullptr)
3070 , mTransformList(aTransformList)
3071 , mToTransformOrigin(aToTransformOrigin)
3072 , mToPerspectiveOrigin(aToPerspectiveOrigin)
3073 , mChildPerspective(aChildPerspective)
3076 const nsIFrame* mFrame;
3077 const nsCSSValueList* mTransformList;
3078 const gfxPoint3D mToTransformOrigin;
3079 const gfxPoint3D mToPerspectiveOrigin;
3080 nscoord mChildPerspective;
3084 * Given a frame with the -moz-transform property or an SVG transform,
3085 * returns the transformation matrix for that frame.
3087 * @param aFrame The frame to get the matrix from.
3088 * @param aOrigin Relative to which point this transform should be applied.
3089 * @param aAppUnitsPerPixel The number of app units per graphics unit.
3090 * @param aBoundsOverride [optional] If this is nullptr (the default), the
3091 * computation will use the value of GetFrameBoundsForTransform(aFrame)
3092 * for the frame's bounding rectangle. Otherwise, it will use the
3093 * value of aBoundsOverride. This is mostly for internal use and in
3094 * most cases you will not need to specify a value.
3096 static gfx3DMatrix GetResultingTransformMatrix(const nsIFrame* aFrame,
3097 const nsPoint& aOrigin,
3098 float aAppUnitsPerPixel,
3099 const nsRect* aBoundsOverride = nullptr,
3100 nsIFrame** aOutAncestor = nullptr);
3101 static gfx3DMatrix GetResultingTransformMatrix(const FrameTransformProperties& aProperties,
3102 const nsPoint& aOrigin,
3103 float aAppUnitsPerPixel,
3104 const nsRect* aBoundsOverride = nullptr,
3105 nsIFrame** aOutAncestor = nullptr);
3107 * Return true when we should try to prerender the entire contents of the
3108 * transformed frame even when it's not completely visible (yet).
3110 static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
3111 nsIFrame* aFrame,
3112 bool aLogAnimations = false);
3113 bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
3115 private:
3116 static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
3117 const nsPoint& aOrigin,
3118 float aAppUnitsPerPixel,
3119 const nsRect* aBoundsOverride,
3120 nsIFrame** aOutAncestor);
3122 nsDisplayWrapList mStoredList;
3123 gfx3DMatrix mTransform;
3124 ComputeTransformFunction mTransformGetter;
3125 uint32_t mIndex;
3129 * This class adds basic support for limiting the rendering to the part inside
3130 * the specified edges. It's a base class for the display item classes that
3131 * does the actual work. The two members, mLeftEdge and mRightEdge, are
3132 * relative to the edges of the frame's scrollable overflow rectangle and is
3133 * the amount to suppress on each side.
3135 * Setting none, both or only one edge is allowed.
3136 * The values must be non-negative.
3137 * The default value for both edges is zero, which means everything is painted.
3139 class nsCharClipDisplayItem : public nsDisplayItem {
3140 public:
3141 nsCharClipDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
3142 : nsDisplayItem(aBuilder, aFrame), mLeftEdge(0), mRightEdge(0) {}
3144 nsCharClipDisplayItem(nsIFrame* aFrame)
3145 : nsDisplayItem(aFrame) {}
3147 struct ClipEdges {
3148 ClipEdges(const nsDisplayItem& aItem,
3149 nscoord aLeftEdge, nscoord aRightEdge) {
3150 nsRect r = aItem.Frame()->GetScrollableOverflowRect() +
3151 aItem.ToReferenceFrame();
3152 mX = aLeftEdge > 0 ? r.x + aLeftEdge : nscoord_MIN;
3153 mXMost = aRightEdge > 0 ? std::max(r.XMost() - aRightEdge, mX) : nscoord_MAX;
3155 void Intersect(nscoord* aX, nscoord* aWidth) const {
3156 nscoord xmost1 = *aX + *aWidth;
3157 *aX = std::max(*aX, mX);
3158 *aWidth = std::max(std::min(xmost1, mXMost) - *aX, 0);
3160 nscoord mX;
3161 nscoord mXMost;
3164 ClipEdges Edges() const { return ClipEdges(*this, mLeftEdge, mRightEdge); }
3166 static nsCharClipDisplayItem* CheckCast(nsDisplayItem* aItem) {
3167 nsDisplayItem::Type t = aItem->GetType();
3168 return (t == nsDisplayItem::TYPE_TEXT ||
3169 t == nsDisplayItem::TYPE_TEXT_DECORATION ||
3170 t == nsDisplayItem::TYPE_TEXT_SHADOW)
3171 ? static_cast<nsCharClipDisplayItem*>(aItem) : nullptr;
3174 nscoord mLeftEdge; // length from the left side
3175 nscoord mRightEdge; // length from the right side
3178 #endif /*NSDISPLAYLIST_H_*/