LCOV - code coverage report
Current view: top level - layout/generic - nsContainerFrame.h (source / functions) Hit Total Coverage
Test: output.info Lines: 24 62 38.7 %
Date: 2017-07-14 16:53:18 Functions: 11 25 44.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /* base class #1 for rendering objects that have child lists */
       7             : 
       8             : #ifndef nsContainerFrame_h___
       9             : #define nsContainerFrame_h___
      10             : 
      11             : #include "mozilla/Attributes.h"
      12             : #include "nsSplittableFrame.h"
      13             : #include "nsFrameList.h"
      14             : #include "nsLayoutUtils.h"
      15             : 
      16             : // Option flags for ReflowChild() and FinishReflowChild()
      17             : // member functions
      18             : #define NS_FRAME_NO_MOVE_VIEW         0x0001
      19             : #define NS_FRAME_NO_MOVE_FRAME        (0x0002 | NS_FRAME_NO_MOVE_VIEW)
      20             : #define NS_FRAME_NO_SIZE_VIEW         0x0004
      21             : #define NS_FRAME_NO_VISIBILITY        0x0008
      22             : // Only applies to ReflowChild; if true, don't delete the next-in-flow, even
      23             : // if the reflow is fully complete.
      24             : #define NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD 0x0010
      25             : 
      26             : class nsOverflowContinuationTracker;
      27             : 
      28             : // Some macros for container classes to do sanity checking on
      29             : // width/height/x/y values computed during reflow.
      30             : // NOTE: AppUnitsPerCSSPixel value hardwired here to remove the
      31             : // dependency on nsDeviceContext.h.  It doesn't matter if it's a
      32             : // little off.
      33             : #ifdef DEBUG
      34             : // 10 million pixels, converted to app units. Note that this a bit larger
      35             : // than 1/4 of nscoord_MAX. So, if any content gets to be this large, we're
      36             : // definitely in danger of grazing up against nscoord_MAX; hence, it's CRAZY.
      37             : #define CRAZY_COORD (10000000*60)
      38             : #define CRAZY_SIZE(_x) (((_x) < -CRAZY_COORD) || ((_x) > CRAZY_COORD))
      39             : #endif
      40             : 
      41             : /**
      42             :  * Implementation of a container frame.
      43             :  */
      44             : class nsContainerFrame : public nsSplittableFrame
      45             : {
      46             : public:
      47             :   NS_DECL_ABSTRACT_FRAME(nsContainerFrame)
      48             :   NS_DECL_QUERYFRAME_TARGET(nsContainerFrame)
      49             :   NS_DECL_QUERYFRAME
      50             : 
      51             :   // nsIFrame overrides
      52             :   virtual void Init(nsIContent*       aContent,
      53             :                     nsContainerFrame* aParent,
      54             :                     nsIFrame*         aPrevInFlow) override;
      55        1093 :   virtual nsContainerFrame* GetContentInsertionFrame() override
      56             :   {
      57        1093 :     return this;
      58             :   }
      59             : 
      60             :   virtual const nsFrameList& GetChildList(ChildListID aList) const override;
      61             :   virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
      62             :   virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
      63             :   virtual void ChildIsDirty(nsIFrame* aChild) override;
      64             : 
      65             :   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) override;
      66             :   virtual FrameSearchResult
      67             :   PeekOffsetCharacter(bool aForward, int32_t* aOffset,
      68             :                       PeekOffsetCharacterOptions aOptions =
      69             :                         PeekOffsetCharacterOptions()) override;
      70             : 
      71             :   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
      72             :                                     nsIAtom*        aAttribute,
      73             :                                     int32_t         aModType) override;
      74             : 
      75             : #ifdef DEBUG_FRAME_DUMP
      76             :   void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const override;
      77             : #endif
      78             : 
      79             :   // nsContainerFrame methods
      80             : 
      81             :   /**
      82             :    * Called to set the initial list of frames. This happens after the frame
      83             :    * has been initialized.
      84             :    *
      85             :    * This is only called once for a given child list, and won't be called
      86             :    * at all for child lists with no initial list of frames.
      87             :    *
      88             :    * @param   aListID the child list identifier.
      89             :    * @param   aChildList list of child frames. Each of the frames has its
      90             :    *            NS_FRAME_IS_DIRTY bit set.  Must not be empty.
      91             :    *            This method cannot handle the child list returned by
      92             :    *            GetAbsoluteListID().
      93             :    * @see     #Init()
      94             :    */
      95             :   virtual void SetInitialChildList(ChildListID aListID,
      96             :                                    nsFrameList& aChildList);
      97             : 
      98             :   /**
      99             :    * This method is responsible for appending frames to the frame
     100             :    * list.  The implementation should append the frames to the specified
     101             :    * child list and then generate a reflow command.
     102             :    *
     103             :    * @param   aListID the child list identifier.
     104             :    * @param   aFrameList list of child frames to append. Each of the frames has
     105             :    *            its NS_FRAME_IS_DIRTY bit set.  Must not be empty.
     106             :    */
     107             :   virtual void AppendFrames(ChildListID aListID, nsFrameList& aFrameList);
     108             : 
     109             :   /**
     110             :    * This method is responsible for inserting frames into the frame
     111             :    * list.  The implementation should insert the new frames into the specified
     112             :    * child list and then generate a reflow command.
     113             :    *
     114             :    * @param   aListID the child list identifier.
     115             :    * @param   aPrevFrame the frame to insert frames <b>after</b>
     116             :    * @param   aFrameList list of child frames to insert <b>after</b> aPrevFrame.
     117             :    *            Each of the frames has its NS_FRAME_IS_DIRTY bit set
     118             :    */
     119             :   virtual void InsertFrames(ChildListID  aListID,
     120             :                             nsIFrame*    aPrevFrame,
     121             :                             nsFrameList& aFrameList);
     122             : 
     123             :   /**
     124             :    * This method is responsible for removing a frame in the frame
     125             :    * list.  The implementation should do something with the removed frame
     126             :    * and then generate a reflow command. The implementation is responsible
     127             :    * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
     128             :    *
     129             :    * @param   aListID the child list identifier.
     130             :    * @param   aOldFrame the frame to remove
     131             :    */
     132             :   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
     133             : 
     134             :   /**
     135             :    * Helper method to create next-in-flows if necessary. If aFrame
     136             :    * already has a next-in-flow then this method does
     137             :    * nothing. Otherwise, a new continuation frame is created and
     138             :    * linked into the flow. In addition, the new frame is inserted
     139             :    * into the principal child list after aFrame.
     140             :    * @note calling this method on a block frame is illegal. Use
     141             :    * nsBlockFrame::CreateContinuationFor() instead.
     142             :    * @return the next-in-flow <b>if and only if</b> one is created. If
     143             :    *         a next-in-flow already exists, nullptr will be returned.
     144             :    */
     145             :   nsIFrame* CreateNextInFlow(nsIFrame* aFrame);
     146             : 
     147             :   /**
     148             :    * Delete aNextInFlow and its next-in-flows.
     149             :    * @param aDeletingEmptyFrames if set, then the reflow for aNextInFlow's
     150             :    * content was complete before aNextInFlow, so aNextInFlow and its
     151             :    * next-in-flows no longer map any real content.
     152             :    */
     153             :   virtual void DeleteNextInFlowChild(nsIFrame* aNextInFlow,
     154             :                                      bool      aDeletingEmptyFrames);
     155             : 
     156             :   // Positions the frame's view based on the frame's origin
     157             :   static void PositionFrameView(nsIFrame* aKidFrame);
     158             : 
     159             :   static nsresult ReparentFrameView(nsIFrame* aChildFrame,
     160             :                                     nsIFrame* aOldParentFrame,
     161             :                                     nsIFrame* aNewParentFrame);
     162             : 
     163             :   static nsresult ReparentFrameViewList(const nsFrameList& aChildFrameList,
     164             :                                         nsIFrame*          aOldParentFrame,
     165             :                                         nsIFrame*          aNewParentFrame);
     166             : 
     167             :   // Set the view's size and position after its frame has been reflowed.
     168             :   //
     169             :   // Flags:
     170             :   // NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
     171             :   //    don't want to automatically sync the frame and view
     172             :   // NS_FRAME_NO_SIZE_VIEW - don't size the view
     173             :   static void SyncFrameViewAfterReflow(nsPresContext* aPresContext,
     174             :                                        nsIFrame*       aFrame,
     175             :                                        nsView*        aView,
     176             :                                        const nsRect&   aVisualOverflowArea,
     177             :                                        uint32_t        aFlags = 0);
     178             : 
     179             :   // Syncs properties to the top level view and window, like transparency and
     180             :   // shadow.
     181             :   // The SET_ASYNC indicates that the actual nsIWidget calls to sync the window
     182             :   // properties should be done async.
     183             :   enum {
     184             :     SET_ASYNC = 0x01,
     185             :   };
     186             :   static void SyncWindowProperties(nsPresContext*       aPresContext,
     187             :                                    nsIFrame*            aFrame,
     188             :                                    nsView*              aView,
     189             :                                    gfxContext*          aRC,
     190             :                                    uint32_t             aFlags);
     191             : 
     192             :   /**
     193             :    * Converts the minimum and maximum sizes given in inner window app units to
     194             :    * outer window device pixel sizes and assigns these constraints to the widget.
     195             :    *
     196             :    * @param aPresContext pres context
     197             :    * @param aWidget widget for this frame
     198             :    * @param minimum size of the window in app units
     199             :    * @param maxmimum size of the window in app units
     200             :    */
     201             :   static void SetSizeConstraints(nsPresContext* aPresContext,
     202             :                                  nsIWidget* aWidget,
     203             :                                  const nsSize& aMinSize,
     204             :                                  const nsSize& aMaxSize);
     205             : 
     206             :   // Used by both nsInlineFrame and nsFirstLetterFrame.
     207             :   void DoInlineIntrinsicISize(gfxContext *aRenderingContext,
     208             :                               InlineIntrinsicISizeData *aData,
     209             :                               nsLayoutUtils::IntrinsicISizeType aType);
     210             : 
     211             :   /**
     212             :    * This is the CSS block concept of computing 'auto' widths, which most
     213             :    * classes derived from nsContainerFrame want.
     214             :    */
     215             :   virtual mozilla::LogicalSize
     216             :   ComputeAutoSize(gfxContext*                 aRenderingContext,
     217             :                   mozilla::WritingMode        aWM,
     218             :                   const mozilla::LogicalSize& aCBSize,
     219             :                   nscoord                     aAvailableISize,
     220             :                   const mozilla::LogicalSize& aMargin,
     221             :                   const mozilla::LogicalSize& aBorder,
     222             :                   const mozilla::LogicalSize& aPadding,
     223             :                   ComputeSizeFlags            aFlags) override;
     224             : 
     225             :   /**
     226             :    * Positions aChildFrame and its view (if requested), and then calls Reflow().
     227             :    * If the reflow status after reflowing the child is FULLY_COMPLETE then any
     228             :    * next-in-flows are deleted using DeleteNextInFlowChild().
     229             :    *
     230             :    * @param aContainerSize  size of the border-box of the containing frame
     231             :    *
     232             :    * Flags:
     233             :    * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
     234             :    *    don't want to automatically sync the frame and view
     235             :    * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aPos is ignored in this
     236             :    *    case. Also implies NS_FRAME_NO_MOVE_VIEW
     237             :    */
     238             :   void ReflowChild(nsIFrame*                      aChildFrame,
     239             :                    nsPresContext*                 aPresContext,
     240             :                    ReflowOutput&           aDesiredSize,
     241             :                    const ReflowInput&       aReflowInput,
     242             :                    const mozilla::WritingMode&    aWM,
     243             :                    const mozilla::LogicalPoint&   aPos,
     244             :                    const nsSize&                  aContainerSize,
     245             :                    uint32_t                       aFlags,
     246             :                    nsReflowStatus&                aStatus,
     247             :                    nsOverflowContinuationTracker* aTracker = nullptr);
     248             : 
     249             :   /**
     250             :    * The second half of frame reflow. Does the following:
     251             :    * - sets the frame's bounds
     252             :    * - sizes and positions (if requested) the frame's view. If the frame's final
     253             :    *   position differs from the current position and the frame itself does not
     254             :    *   have a view, then any child frames with views are positioned so they stay
     255             :    *   in sync
     256             :    * - sets the view's visibility, opacity, content transparency, and clip
     257             :    * - invoked the DidReflow() function
     258             :    *
     259             :    * @param aContainerSize  size of the border-box of the containing frame
     260             :    *
     261             :    * Flags:
     262             :    * NS_FRAME_NO_MOVE_FRAME - don't move the frame. aPos is ignored in this
     263             :    *    case. Also implies NS_FRAME_NO_MOVE_VIEW
     264             :    * NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
     265             :    *    don't want to automatically sync the frame and view
     266             :    * NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
     267             :    */
     268             :   static void FinishReflowChild(nsIFrame*                    aKidFrame,
     269             :                                 nsPresContext*               aPresContext,
     270             :                                 const ReflowOutput&   aDesiredSize,
     271             :                                 const ReflowInput*     aReflowInput,
     272             :                                 const mozilla::WritingMode&  aWM,
     273             :                                 const mozilla::LogicalPoint& aPos,
     274             :                                 const nsSize&                aContainerSize,
     275             :                                 uint32_t                     aFlags);
     276             : 
     277             :   //XXX temporary: hold on to a copy of the old physical versions of
     278             :   //    ReflowChild and FinishReflowChild so that we can convert callers
     279             :   //    incrementally.
     280             :   void ReflowChild(nsIFrame*                      aKidFrame,
     281             :                    nsPresContext*                 aPresContext,
     282             :                    ReflowOutput&           aDesiredSize,
     283             :                    const ReflowInput&       aReflowInput,
     284             :                    nscoord                        aX,
     285             :                    nscoord                        aY,
     286             :                    uint32_t                       aFlags,
     287             :                    nsReflowStatus&                aStatus,
     288             :                    nsOverflowContinuationTracker* aTracker = nullptr);
     289             : 
     290             :   static void FinishReflowChild(nsIFrame*                  aKidFrame,
     291             :                                 nsPresContext*             aPresContext,
     292             :                                 const ReflowOutput& aDesiredSize,
     293             :                                 const ReflowInput*   aReflowInput,
     294             :                                 nscoord                    aX,
     295             :                                 nscoord                    aY,
     296             :                                 uint32_t                   aFlags);
     297             : 
     298             :   static void PositionChildViews(nsIFrame* aFrame);
     299             : 
     300             :   // ==========================================================================
     301             :   /* Overflow containers are continuation frames that hold overflow. They
     302             :    * are created when the frame runs out of computed height, but still has
     303             :    * too much content to fit in the availableHeight. The parent creates a
     304             :    * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
     305             :    * and adds it to its next-in-flow's overflow container list, either by
     306             :    * adding it directly or by putting it in its own excess overflow containers
     307             :    * list (to be drained by the next-in-flow when it calls
     308             :    * ReflowOverflowContainerChildren). The parent continues reflow as if
     309             :    * the frame was complete once it ran out of computed height, but returns a
     310             :    * reflow status with either IsIncomplete() or IsOverflowIncomplete() equal
     311             :    * to true to request a next-in-flow. The parent's next-in-flow is then
     312             :    * responsible for calling ReflowOverflowContainerChildren to (drain and)
     313             :    * reflow these overflow continuations. Overflow containers do not affect
     314             :    * other frames' size or position during reflow (but do affect their
     315             :    * parent's overflow area).
     316             :    *
     317             :    * Overflow container continuations are different from normal continuations
     318             :    * in that
     319             :    *   - more than one child of the frame can have its next-in-flow broken
     320             :    *     off and pushed into the frame's next-in-flow
     321             :    *   - new continuations may need to be spliced into the middle of the list
     322             :    *     or deleted continuations slipped out
     323             :    *     e.g. A, B, C are all fixed-size containers on one page, all have
     324             :    *      overflow beyond availableHeight, and content is dynamically added
     325             :    *      and removed from B
     326             :    * As a result, it is not possible to simply prepend the new continuations
     327             :    * to the old list as with the overflowProperty mechanism. To avoid
     328             :    * complicated list splicing, the code assumes only one overflow containers
     329             :    * list exists for a given frame: either its own overflowContainersProperty
     330             :    * or its prev-in-flow's excessOverflowContainersProperty, not both.
     331             :    *
     332             :    * The nsOverflowContinuationTracker helper class should be used for tracking
     333             :    * overflow containers and adding them to the appropriate list.
     334             :    * See nsBlockFrame::Reflow for a sample implementation.
     335             :    */
     336             : 
     337             :   friend class nsOverflowContinuationTracker;
     338             : 
     339             :   typedef void (*ChildFrameMerger)(nsFrameList& aDest, nsFrameList& aSrc,
     340             :                                    nsContainerFrame* aParent);
     341           0 :   static inline void DefaultChildFrameMerge(nsFrameList& aDest,
     342             :                                             nsFrameList& aSrc,
     343             :                                             nsContainerFrame* aParent)
     344             :   {
     345           0 :     aDest.AppendFrames(nullptr, aSrc);
     346           0 :   }
     347             : 
     348             :   /**
     349             :    * Reflow overflow container children. They are invisible to normal reflow
     350             :    * (i.e. don't affect sizing or placement of other children) and inherit
     351             :    * width and horizontal position from their prev-in-flow.
     352             :    *
     353             :    * This method
     354             :    *   1. Pulls excess overflow containers from the prev-in-flow and adds
     355             :    *      them to our overflow container list
     356             :    *   2. Reflows all our overflow container kids
     357             :    *   3. Expands aOverflowRect as necessary to accomodate these children.
     358             :    *   4. Sets aStatus's mOverflowIncomplete flag (along with
     359             :    *      mNextInFlowNeedsReflow as necessary) if any overflow children
     360             :    *      are incomplete and
     361             :    *   5. Prepends a list of their continuations to our excess overflow
     362             :    *      container list, to be drained into our next-in-flow when it is
     363             :    *      reflowed.
     364             :    *
     365             :    * The caller is responsible for tracking any new overflow container
     366             :    * continuations it makes, removing them from its child list, and
     367             :    * making sure they are stored properly in the overflow container lists.
     368             :    * The nsOverflowContinuationTracker helper class should be used for this.
     369             :    *
     370             :    * @param aFlags is passed through to ReflowChild
     371             :    * @param aMergeFunc is passed to DrainExcessOverflowContainersList
     372             :    */
     373             :   void ReflowOverflowContainerChildren(nsPresContext*           aPresContext,
     374             :                                        const ReflowInput& aReflowInput,
     375             :                                        nsOverflowAreas&         aOverflowRects,
     376             :                                        uint32_t                 aFlags,
     377             :                                        nsReflowStatus&          aStatus,
     378             :                                        ChildFrameMerger aMergeFunc =
     379             :                                          DefaultChildFrameMerge);
     380             : 
     381             :   /**
     382             :    * Move any frames on our overflow list to the end of our principal list.
     383             :    * @return true if there were any overflow frames
     384             :    */
     385             :   virtual bool DrainSelfOverflowList() override;
     386             : 
     387             : 
     388             :   /**
     389             :    * Move all frames on our prev-in-flow's and our own ExcessOverflowContainers
     390             :    * lists to our OverflowContainers list.  If there are frames on multiple
     391             :    * lists they are merged using aMergeFunc.
     392             :    * @return a pointer to our OverflowContainers list, if any
     393             :    */
     394             :   nsFrameList* DrainExcessOverflowContainersList(ChildFrameMerger aMergeFunc =
     395             :                                                    DefaultChildFrameMerge);
     396             : 
     397             :   /**
     398             :    * Removes aChild without destroying it and without requesting reflow.
     399             :    * Continuations are not affected.  Checks the principal and overflow lists,
     400             :    * and also the [excess] overflow containers lists if the frame bit
     401             :    * NS_FRAME_IS_OVERFLOW_CONTAINER is set.  It does not check any other lists.
     402             :    * Returns NS_ERROR_UNEXPECTED if aChild wasn't found on any of the lists
     403             :    * mentioned above.
     404             :    */
     405             :   virtual nsresult StealFrame(nsIFrame* aChild);
     406             : 
     407             :   /**
     408             :    * Removes the next-siblings of aChild without destroying them and without
     409             :    * requesting reflow. Checks the principal and overflow lists (not
     410             :    * overflow containers / excess overflow containers). Does not check any
     411             :    * other auxiliary lists.
     412             :    * @param aChild a child frame or nullptr
     413             :    * @return If aChild is non-null, the next-siblings of aChild, if any.
     414             :    *         If aChild is null, all child frames on the principal list, if any.
     415             :    */
     416             :   nsFrameList StealFramesAfter(nsIFrame* aChild);
     417             : 
     418             :   /**
     419             :    * Add overflow containers to the display list
     420             :    */
     421             :   void DisplayOverflowContainers(nsDisplayListBuilder*   aBuilder,
     422             :                                  const nsRect&           aDirtyRect,
     423             :                                  const nsDisplayListSet& aLists);
     424             : 
     425             :   /**
     426             :    * Builds display lists for the children. The background
     427             :    * of each child is placed in the Content() list (suitable for inline
     428             :    * children and other elements that behave like inlines,
     429             :    * but not for in-flow block children of blocks).  DOES NOT
     430             :    * paint the background/borders/outline of this frame. This should
     431             :    * probably be avoided and eventually removed. It's currently here
     432             :    * to emulate what nsContainerFrame::Paint did.
     433             :    */
     434             :   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     435             :                                 const nsRect&           aDirtyRect,
     436             :                                 const nsDisplayListSet& aLists) override;
     437             : 
     438          66 :   static void PlaceFrameView(nsIFrame* aFrame)
     439             :   {
     440          66 :     if (aFrame->HasView())
     441           0 :       nsContainerFrame::PositionFrameView(aFrame);
     442             :     else
     443          66 :       nsContainerFrame::PositionChildViews(aFrame);
     444          66 :   }
     445             : 
     446             :   static bool FrameStartsCounterScope(nsIFrame* aFrame);
     447             : 
     448             :   /**
     449             :    * Renumber the list of the counter scope started by this frame, if any.
     450             :    * If this returns true, the frame it's called on should get the
     451             :    * NS_FRAME_HAS_DIRTY_CHILDREN bit set on it by the caller; either directly
     452             :    * if it's already in reflow, or via calling FrameNeedsReflow() to schedule
     453             :    * a reflow.
     454             :    */
     455             :   bool RenumberList();
     456             : 
     457             :   /**
     458             :    * Renumber this frame if it's a list-item, then call RenumberChildFrames.
     459             :    * @param aOrdinal Ordinal number to start counting at.
     460             :    *        Modifies this number for each associated list
     461             :    *        item. Changes in the numbering due to setting
     462             :    *        the |value| attribute are included if |aForCounting|
     463             :    *        is false. This value is both an input and output
     464             :    *        of this function, with the output value being the
     465             :    *        next ordinal number to be used.
     466             :    * @param aDepth Current depth in frame tree from root list element.
     467             :    * @param aIncrement Amount to increase by after visiting each associated
     468             :    *        list item, unless overridden by |value|.
     469             :    * @param aForCounting Whether we are counting the elements or actually
     470             :    *        restyling them. When true, this simply visits all children,
     471             :    *        ignoring |<li value="..">| changes, effectively counting them
     472             :    *        and storing the result in |aOrdinal|. This is useful for
     473             :    *        |<ol reversed>|, where we need to count the number of
     474             :    *        applicable child list elements before numbering. When false,
     475             :    *        this will restyle all applicable descendants, and the next
     476             :    *        ordinal value will be stored in |aOrdinal|, taking into account
     477             :    *        any changes from |<li value="..">|.
     478             :    */
     479             :   bool RenumberFrameAndDescendants(int32_t* aOrdinal,
     480             :                                    int32_t aDepth,
     481             :                                    int32_t aIncrement,
     482             :                                    bool aForCounting) override;
     483             :   /**
     484             :    * Renumber the child frames using RenumberFrameAndDescendants.
     485             :    * See RenumberFrameAndDescendants for description of parameters.
     486             :    */
     487             :   virtual bool RenumberChildFrames(int32_t* aOrdinal,
     488             :                                    int32_t aDepth,
     489             :                                    int32_t aIncrement,
     490             :                                    bool aForCounting);
     491             : 
     492             :   /**
     493             :    * Returns a CSS Box Alignment constant which the caller can use to align
     494             :    * the absolutely-positioned child (whose ReflowInput is aChildRI) within
     495             :    * a CSS Box Alignment area associated with this container.
     496             :    *
     497             :    * The lower 8 bits of the returned value are guaranteed to form a valid
     498             :    * argument for CSSAlignUtils::AlignJustifySelf(). (The upper 8 bits may
     499             :    * encode an <overflow-position>.)
     500             :    *
     501             :    * NOTE: This default nsContainerFrame implementation is a stub, and isn't
     502             :    * meant to be called.  Subclasses must provide their own implementations, if
     503             :    * they use CSS Box Alignment to determine the static position of their
     504             :    * absolutely-positioned children. (Though: if subclasses share enough code,
     505             :    * maybe this nsContainerFrame impl should include some shared code.)
     506             :    *
     507             :    * @param aChildRI A ReflowInput for the positioned child frame that's being
     508             :    *                 aligned.
     509             :    * @param aLogicalAxis The axis (of this container frame) in which the caller
     510             :    *                     would like to align the child frame.
     511             :    */
     512             :   virtual uint16_t CSSAlignmentForAbsPosChild(
     513             :                      const ReflowInput& aChildRI,
     514             :                      mozilla::LogicalAxis aLogicalAxis) const;
     515             : 
     516             : #define NS_DECLARE_FRAME_PROPERTY_FRAMELIST(prop) \
     517             :   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, nsFrameList)
     518             : 
     519             :   typedef PropertyDescriptor<nsFrameList> FrameListPropertyDescriptor;
     520             : 
     521        2386 :   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowProperty)
     522        2354 :   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)
     523        2539 :   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(ExcessOverflowContainersProperty)
     524        2376 :   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(BackdropProperty)
     525             : 
     526             :   // Only really used on nsBlockFrame instances, but the caller thinks it could
     527             :   // have arbitrary nsContainerFrames.
     528           0 :   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(FirstLetterProperty, nsIFrame)
     529             : 
     530           0 :   void SetHasFirstLetterChild()
     531             :   {
     532           0 :     mHasFirstLetterChild = true;
     533           0 :   }
     534             : 
     535           0 :   void ClearHasFirstLetterChild()
     536             :   {
     537           0 :     mHasFirstLetterChild = false;
     538           0 :   }
     539             : 
     540             : #ifdef DEBUG
     541             :   // Use this to suppress the CRAZY_SIZE assertions.
     542          75 :   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize, bool)
     543          75 :   bool IsCrazySizeAssertSuppressed() const {
     544          75 :     return GetProperty(DebugReflowingWithInfiniteISize());
     545             :   }
     546             : #endif
     547             : 
     548             : protected:
     549         448 :   nsContainerFrame(nsStyleContext* aContext, ClassID aID)
     550         448 :     : nsSplittableFrame(aContext, aID)
     551         448 :   {}
     552             : 
     553             :   ~nsContainerFrame();
     554             : 
     555             :   /**
     556             :    * Helper for DestroyFrom. DestroyAbsoluteFrames is called before
     557             :    * destroying frames on lists that can contain placeholders.
     558             :    * Derived classes must do that too, if they destroy such frame lists.
     559             :    * See nsBlockFrame::DestroyFrom for an example.
     560             :    */
     561             :   void DestroyAbsoluteFrames(nsIFrame* aDestructRoot);
     562             : 
     563             :   /**
     564             :    * Helper for StealFrame.  Returns true if aChild was removed from its list.
     565             :    */
     566             :   bool MaybeStealOverflowContainerFrame(nsIFrame* aChild);
     567             : 
     568             :   /**
     569             :    * Builds a display list for non-block children that behave like
     570             :    * inlines. This puts the background of each child into the
     571             :    * Content() list (suitable for inline children but not for
     572             :    * in-flow block children of blocks).
     573             :    * @param aForcePseudoStack forces each child into a pseudo-stacking-context
     574             :    * so its background and all other display items (except for positioned
     575             :    * display items) go into the Content() list.
     576             :    */
     577             :   void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder*   aBuilder,
     578             :                                            const nsRect&           aDirtyRect,
     579             :                                            const nsDisplayListSet& aLists,
     580             :                                            uint32_t                aFlags = 0);
     581             : 
     582             :   /**
     583             :    * A version of BuildDisplayList that use DISPLAY_CHILD_INLINE.
     584             :    * Intended as a convenience for derived classes.
     585             :    */
     586           0 :   void BuildDisplayListForInline(nsDisplayListBuilder*   aBuilder,
     587             :                                  const nsRect&           aDirtyRect,
     588             :                                  const nsDisplayListSet& aLists) {
     589           0 :     DisplayBorderBackgroundOutline(aBuilder, aLists);
     590             :     BuildDisplayListForNonBlockChildren(aBuilder, aDirtyRect, aLists,
     591           0 :                                         DISPLAY_CHILD_INLINE);
     592           0 :   }
     593             : 
     594             : 
     595             :   // ==========================================================================
     596             :   /* Overflow Frames are frames that did not fit and must be pulled by
     597             :    * our next-in-flow during its reflow. (The same concept for overflow
     598             :    * containers is called "excess frames". We should probably make the
     599             :    * names match.)
     600             :    */
     601             : 
     602             :   /**
     603             :    * Get the frames on the overflow list.  Can return null if there are no
     604             :    * overflow frames.  The caller does NOT take ownership of the list; it's
     605             :    * still owned by this frame.  A non-null return value indicates that the
     606             :    * list is nonempty.
     607             :    */
     608             :   inline nsFrameList* GetOverflowFrames() const;
     609             : 
     610             :   /**
     611             :    * As GetOverflowFrames, but removes the overflow frames property.  The
     612             :    * caller is responsible for deleting nsFrameList and either passing
     613             :    * ownership of the frames to someone else or destroying the frames.
     614             :    * A non-null return value indicates that the list is nonempty.  The
     615             :    * recommended way to use this function it to assign its return value
     616             :    * into an AutoFrameListPtr.
     617             :    */
     618             :   inline nsFrameList* StealOverflowFrames();
     619             : 
     620             :   /**
     621             :    * Set the overflow list.  aOverflowFrames must not be an empty list.
     622             :    */
     623             :   void SetOverflowFrames(const nsFrameList& aOverflowFrames);
     624             : 
     625             :   /**
     626             :    * Destroy the overflow list, which must be empty.
     627             :    */
     628             :   inline void DestroyOverflowList();
     629             : 
     630             :   /**
     631             :    * Moves any frames on both the prev-in-flow's overflow list and the
     632             :    * receiver's overflow to the receiver's child list.
     633             :    *
     634             :    * Resets the overlist pointers to nullptr, and updates the receiver's child
     635             :    * count and content mapping.
     636             :    *
     637             :    * @return true if any frames were moved and false otherwise
     638             :    */
     639             :   bool MoveOverflowToChildList();
     640             : 
     641             :   /**
     642             :    * Push aFromChild and its next siblings to the next-in-flow. Change
     643             :    * the geometric parent of each frame that's pushed. If there is no
     644             :    * next-in-flow the frames are placed on the overflow list (and the
     645             :    * geometric parent is left unchanged).
     646             :    *
     647             :    * Updates the next-in-flow's child count. Does <b>not</b> update the
     648             :    * pusher's child count.
     649             :    *
     650             :    * @param   aFromChild the first child frame to push. It is disconnected from
     651             :    *            aPrevSibling
     652             :    * @param   aPrevSibling aFromChild's previous sibling. Must not be null.
     653             :    *            It's an error to push a parent's first child frame
     654             :    */
     655             :   void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
     656             : 
     657             :   // ==========================================================================
     658             :   /*
     659             :    * Convenience methods for traversing continuations
     660             :    */
     661             : 
     662             :   struct ContinuationTraversingState
     663             :   {
     664             :     nsContainerFrame* mNextInFlow;
     665           0 :     explicit ContinuationTraversingState(nsContainerFrame* aFrame)
     666           0 :       : mNextInFlow(static_cast<nsContainerFrame*>(aFrame->GetNextInFlow()))
     667           0 :     { }
     668             :   };
     669             : 
     670             :   /**
     671             :    * Find the first frame that is a child of this frame's next-in-flows,
     672             :    * considering both their principal child lists and overflow lists.
     673             :    */
     674             :   nsIFrame* GetNextInFlowChild(ContinuationTraversingState& aState,
     675             :                                bool* aIsInOverflow = nullptr);
     676             : 
     677             :   /**
     678             :    * Remove the result of GetNextInFlowChild from its current parent and
     679             :    * append it to this frame's principal child list.
     680             :    */
     681             :   nsIFrame* PullNextInFlowChild(ContinuationTraversingState& aState);
     682             : 
     683             :   // ==========================================================================
     684             :   /*
     685             :    * Convenience methods for nsFrameLists stored in the
     686             :    * PresContext's proptable
     687             :    */
     688             : 
     689             :   /**
     690             :    * Get the PresContext-stored nsFrameList named aPropID for this frame.
     691             :    * May return null.
     692             :    */
     693             :   nsFrameList* GetPropTableFrames(FrameListPropertyDescriptor aProperty) const;
     694             : 
     695             :   /**
     696             :    * Remove and return the PresContext-stored nsFrameList named aPropID for
     697             :    * this frame. May return null.
     698             :    */
     699             :   nsFrameList* RemovePropTableFrames(FrameListPropertyDescriptor aProperty);
     700             : 
     701             :   /**
     702             :    * Set the PresContext-stored nsFrameList named aPropID for this frame
     703             :    * to the given aFrameList, which must not be null.
     704             :    */
     705             :   void SetPropTableFrames(nsFrameList* aFrameList,
     706             :                           FrameListPropertyDescriptor aProperty);
     707             : 
     708             :   /**
     709             :    * Safely destroy the frames on the nsFrameList stored on aProp for this
     710             :    * frame then remove the property and delete the frame list.
     711             :    * Nothing happens if the property doesn't exist.
     712             :    */
     713             :   void SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
     714             :                                   nsIPresShell* aPresShell,
     715             :                                   FrameListPropertyDescriptor aProp);
     716             : 
     717             :   // ==========================================================================
     718             : 
     719             :   // Helper used by Progress and Meter frames. Returns true if the bar should
     720             :   // be rendered vertically, based on writing-mode and -moz-orient properties.
     721             :   bool ResolvedOrientationIsVertical();
     722             : 
     723             :   // ==========================================================================
     724             : 
     725             :   nsFrameList mFrames;
     726             : };
     727             : 
     728             : // ==========================================================================
     729             : /* The out-of-flow-related code below is for a hacky way of splitting
     730             :  * absolutely-positioned frames. Basically what we do is split the frame
     731             :  * in nsAbsoluteContainingBlock and pretend the continuation is an overflow
     732             :  * container. This isn't an ideal solution, but it lets us print the content
     733             :  * at least. See bug 154892.
     734             :  */
     735             : 
     736             : #define IS_TRUE_OVERFLOW_CONTAINER(frame)                      \
     737             :   (  (frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)  \
     738             :   && !( (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&      \
     739             :         frame->IsAbsolutelyPositioned()  )  )
     740             : //XXXfr This check isn't quite correct, because it doesn't handle cases
     741             : //      where the out-of-flow has overflow.. but that's rare.
     742             : //      We'll need to revisit the way abspos continuations are handled later
     743             : //      for various reasons, this detail is one of them. See bug 154892
     744             : 
     745             : /**
     746             :  * Helper class for tracking overflow container continuations during reflow.
     747             :  *
     748             :  * A frame is related to two sets of overflow containers: those that /are/
     749             :  * its own children, and those that are /continuations/ of its children.
     750             :  * This tracker walks through those continuations (the frame's NIF's children)
     751             :  * and their prev-in-flows (a subset of the frame's normal and overflow
     752             :  * container children) in parallel. It allows the reflower to synchronously
     753             :  * walk its overflow continuations while it loops through and reflows its
     754             :  * children. This makes it possible to insert new continuations at the correct
     755             :  * place in the overflow containers list.
     756             :  *
     757             :  * The reflower is expected to loop through its children in the same order it
     758             :  * looped through them the last time (if there was a last time).
     759             :  * For each child, the reflower should either
     760             :  *   - call Skip for the child if was not reflowed in this pass
     761             :  *   - call Insert for the overflow continuation if the child was reflowed
     762             :  *     but has incomplete overflow
     763             :  *   - call Finished for the child if it was reflowed in this pass but
     764             :  *     is either complete or has a normal next-in-flow. This call can
     765             :  *     be skipped if the child did not previously have an overflow
     766             :  *     continuation.
     767             :  */
     768             : class nsOverflowContinuationTracker {
     769             : public:
     770             :   /**
     771             :    * Initializes an nsOverflowContinuationTracker to help track overflow
     772             :    * continuations of aFrame's children. Typically invoked on 'this'.
     773             :    *
     774             :    * aWalkOOFFrames determines whether the walker skips out-of-flow frames
     775             :    * or skips non-out-of-flow frames.
     776             :    *
     777             :    * Don't set aSkipOverflowContainerChildren to false unless you plan
     778             :    * to walk your own overflow container children. (Usually they are handled
     779             :    * by calling ReflowOverflowContainerChildren.) aWalkOOFFrames is ignored
     780             :    * if aSkipOverflowContainerChildren is false.
     781             :    */
     782             :   nsOverflowContinuationTracker(nsContainerFrame* aFrame,
     783             :                                 bool              aWalkOOFFrames,
     784             :                                 bool              aSkipOverflowContainerChildren = true);
     785             :   /**
     786             :    * This function adds an overflow continuation to our running list and
     787             :    * sets its NS_FRAME_IS_OVERFLOW_CONTAINER flag.
     788             :    *
     789             :    * aReflowStatus should preferably be specific to the recently-reflowed
     790             :    * child and not influenced by any of its siblings' statuses. This
     791             :    * function sets the NS_FRAME_IS_DIRTY bit on aOverflowCont if it needs
     792             :    * to be reflowed. (Its need for reflow depends on changes to its
     793             :    * prev-in-flow, not to its parent--for whom it is invisible, reflow-wise.)
     794             :    *
     795             :    * The caller MUST disconnect the frame from its parent's child list
     796             :    * if it was not previously an NS_FRAME_IS_OVERFLOW_CONTAINER (because
     797             :    * StealFrame is much more inefficient than disconnecting in place
     798             :    * during Reflow, which the caller is able to do but we are not).
     799             :    *
     800             :    * The caller MUST NOT disconnect the frame from its parent's
     801             :    * child list if it is already an NS_FRAME_IS_OVERFLOW_CONTAINER.
     802             :    * (In this case we will disconnect and reconnect it ourselves.)
     803             :    */
     804             :   nsresult Insert(nsIFrame*       aOverflowCont,
     805             :                   nsReflowStatus& aReflowStatus);
     806             :   /**
     807             :    * Begin/EndFinish() must be called for each child that is reflowed
     808             :    * but no longer has an overflow continuation. (It may be called for
     809             :    * other children, but in that case has no effect.) It increments our
     810             :    * walker and makes sure we drop any dangling pointers to its
     811             :    * next-in-flow. This function MUST be called before stealing or
     812             :    * deleting aChild's next-in-flow.
     813             :    * The AutoFinish helper object does that for you. Use it like so:
     814             :    * if (kidNextInFlow) {
     815             :    *   nsOverflowContinuationTracker::AutoFinish fini(tracker, kid);
     816             :    *   ... DeleteNextInFlowChild/StealFrame(kidNextInFlow) here ...
     817             :    * }
     818             :    */
     819             :   class MOZ_RAII AutoFinish {
     820             :   public:
     821           0 :     AutoFinish(nsOverflowContinuationTracker* aTracker, nsIFrame* aChild)
     822           0 :       : mTracker(aTracker), mChild(aChild)
     823             :     {
     824           0 :       if (mTracker) mTracker->BeginFinish(mChild);
     825           0 :     }
     826           0 :     ~AutoFinish()
     827           0 :     {
     828           0 :       if (mTracker) mTracker->EndFinish(mChild);
     829           0 :     }
     830             :   private:
     831             :     nsOverflowContinuationTracker* mTracker;
     832             :     nsIFrame* mChild;
     833             :   };
     834             : 
     835             :   /**
     836             :    * This function should be called for each child that isn't reflowed.
     837             :    * It increments our walker and sets the mOverflowIncomplete
     838             :    * reflow flag if it encounters an overflow continuation so that our
     839             :    * next-in-flow doesn't get prematurely deleted. It MUST be called on
     840             :    * each unreflowed child that has an overflow container continuation;
     841             :    * it MAY be called on other children, but it isn't necessary (doesn't
     842             :    * do anything).
     843             :    */
     844          66 :   void Skip(nsIFrame* aChild, nsReflowStatus& aReflowStatus)
     845             :   {
     846          66 :     NS_PRECONDITION(aChild, "null ptr");
     847          66 :     if (aChild == mSentry) {
     848           0 :       StepForward();
     849           0 :       if (aReflowStatus.IsComplete()) {
     850           0 :         aReflowStatus.SetOverflowIncomplete();
     851             :       }
     852             :     }
     853          66 :   }
     854             : 
     855             : private:
     856             : 
     857             :   /**
     858             :    * @see class AutoFinish
     859             :    */
     860             :   void BeginFinish(nsIFrame* aChild);
     861             :   void EndFinish(nsIFrame* aChild);
     862             : 
     863             :   void SetupOverflowContList();
     864             :   void SetUpListWalker();
     865             :   void StepForward();
     866             : 
     867             :   /* We hold a pointer to either the next-in-flow's overflow containers list
     868             :      or, if that doesn't exist, our frame's excess overflow containers list.
     869             :      We need to make sure that we drop that pointer if the list becomes
     870             :      empty and is deleted elsewhere. */
     871             :   nsFrameList* mOverflowContList;
     872             :   /* We hold a pointer to the most recently-reflowed child that has an
     873             :      overflow container next-in-flow. We do this because it's a known
     874             :      good point; this pointer won't be deleted on us. We can use it to
     875             :      recover our place in the list. */
     876             :   nsIFrame* mPrevOverflowCont;
     877             :   /* This is a pointer to the next overflow container's prev-in-flow, which
     878             :      is (or should be) a child of our frame. When we hit this, we will need
     879             :      to increment this walker to the next overflow container. */
     880             :   nsIFrame* mSentry;
     881             :   /* Parent of all frames in mOverflowContList. If our mOverflowContList
     882             :      is an excessOverflowContainersProperty, or null, then this is our frame
     883             :      (the frame that was passed in to our constructor). Otherwise this is
     884             :      that frame's next-in-flow, and our mOverflowContList is mParent's
     885             :      overflowContainersProperty */
     886             :   nsContainerFrame* mParent;
     887             :   /* Tells SetUpListWalker whether or not to walk us past any continuations
     888             :      of overflow containers. aWalkOOFFrames is ignored when this is false. */
     889             :   bool mSkipOverflowContainerChildren;
     890             :   /* Tells us whether to pay attention to OOF frames or non-OOF frames */
     891             :   bool mWalkOOFFrames;
     892             : };
     893             : 
     894             : inline
     895             : nsFrameList*
     896           0 : nsContainerFrame::GetOverflowFrames() const
     897             : {
     898           0 :   nsFrameList* list = GetProperty(OverflowProperty());
     899           0 :   NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
     900           0 :   return list;
     901             : }
     902             : 
     903             : inline
     904             : nsFrameList*
     905          32 : nsContainerFrame::StealOverflowFrames()
     906             : {
     907          32 :   nsFrameList* list = RemoveProperty(OverflowProperty());
     908          32 :   NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
     909          32 :   return list;
     910             : }
     911             : 
     912             : inline void
     913           0 : nsContainerFrame::DestroyOverflowList()
     914             : {
     915           0 :   nsFrameList* list = RemovePropTableFrames(OverflowProperty());
     916           0 :   MOZ_ASSERT(list && list->IsEmpty());
     917           0 :   list->Delete(PresContext()->PresShell());
     918           0 : }
     919             : 
     920             : #endif /* nsContainerFrame_h___ */

Generated by: LCOV version 1.13