layout/base/nsDisplayList.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial