layout/generic/nsIFrame.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/. */
     7 /* interface for all rendering objects */
     9 #ifndef nsIFrame_h___
    10 #define nsIFrame_h___
    12 #ifndef MOZILLA_INTERNAL_API
    13 #error This header/class should only be used within Mozilla code. It should not be used by extensions.
    14 #endif
    16 #define MAX_REFLOW_DEPTH 200
    18 /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
    19    going to be eliminated, and all callers will use nsFrame instead.  At the moment
    20    we're midway through this process, so you will see inlined functions and member
    21    variables in this file.  -dwh */
    23 #include <stdio.h>
    24 #include "nsQueryFrame.h"
    25 #include "nsStyleContext.h"
    26 #include "nsStyleStruct.h"
    27 #include "nsHTMLReflowMetrics.h"
    28 #include "nsFrameList.h"
    29 #include "mozilla/layout/FrameChildList.h"
    30 #include "FramePropertyTable.h"
    31 #include "mozilla/TypedEnum.h"
    32 #include "nsDirection.h"
    33 #include "WritingModes.h"
    34 #include <algorithm>
    35 #include "nsITheme.h"
    36 #include "gfx3DMatrix.h"
    37 #include "nsLayoutUtils.h"
    38 #include "nsFrameState.h"
    40 #ifdef ACCESSIBILITY
    41 #include "mozilla/a11y/AccTypes.h"
    42 #endif
    44 /**
    45  * New rules of reflow:
    46  * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
    47  *    (no separate pass over the tree)
    48  * 2. it's the parent frame's responsibility to size/position the child's view (not
    49  *    the child frame's responsibility as it is today) during reflow (and before
    50  *    sending the DidReflow() notification)
    51  * 3. positioning of child frames (and their views) is done on the way down the tree,
    52  *    and sizing of child frames (and their views) on the way back up
    53  * 4. if you move a frame (outside of the reflow process, or after reflowing it),
    54  *    then you must make sure that its view (or its child frame's views) are re-positioned
    55  *    as well. It's reasonable to not position the view until after all reflowing the
    56  *    entire line, for example, but the frame should still be positioned and sized (and
    57  *    the view sized) during the reflow (i.e., before sending the DidReflow() notification)
    58  * 5. the view system handles moving of widgets, i.e., it's not our problem
    59  */
    61 struct nsHTMLReflowState;
    62 class nsHTMLReflowCommand;
    64 struct gfxMatrix;
    65 class nsIAtom;
    66 class nsPresContext;
    67 class nsIPresShell;
    68 class nsRenderingContext;
    69 class nsView;
    70 class nsIWidget;
    71 class nsIDOMRange;
    72 class nsISelectionController;
    73 class nsBoxLayoutState;
    74 class nsBoxLayout;
    75 class nsILineIterator;
    76 class nsDisplayListBuilder;
    77 class nsDisplayListSet;
    78 class nsDisplayList;
    79 class gfxSkipChars;
    80 class gfxSkipCharsIterator;
    81 class gfxContext;
    82 class nsLineList_iterator;
    83 class nsAbsoluteContainingBlock;
    84 class nsIContent;
    86 struct nsPeekOffsetStruct;
    87 struct nsPoint;
    88 struct nsRect;
    89 struct nsSize;
    90 struct nsMargin;
    91 struct CharacterDataChangeInfo;
    93 namespace mozilla {
    95 class EventStates;
    97 namespace layers {
    98 class Layer;
    99 }
   101 namespace gfx {
   102 class Matrix;
   103 }
   104 }
   106 /**
   107  * Indication of how the frame can be split. This is used when doing runaround
   108  * of floats, and when pulling up child frames from a next-in-flow.
   109  *
   110  * The choices are splittable, not splittable at all, and splittable in
   111  * a non-rectangular fashion. This last type only applies to block-level
   112  * elements, and indicates whether splitting can be used when doing runaround.
   113  * If you can split across page boundaries, but you expect each continuing
   114  * frame to be the same width then return frSplittable and not
   115  * frSplittableNonRectangular.
   116  *
   117  * @see #GetSplittableType()
   118  */
   119 typedef uint32_t nsSplittableType;
   121 #define NS_FRAME_NOT_SPLITTABLE             0   // Note: not a bit!
   122 #define NS_FRAME_SPLITTABLE                 0x1
   123 #define NS_FRAME_SPLITTABLE_NON_RECTANGULAR 0x3
   125 #define NS_FRAME_IS_SPLITTABLE(type)\
   126   (0 != ((type) & NS_FRAME_SPLITTABLE))
   128 #define NS_FRAME_IS_NOT_SPLITTABLE(type)\
   129   (0 == ((type) & NS_FRAME_SPLITTABLE))
   131 #define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
   133 //----------------------------------------------------------------------
   135 #define NS_SUBTREE_DIRTY(_frame)  \
   136   (((_frame)->GetStateBits() &      \
   137     (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
   139 /**
   140  * Constant used to indicate an unconstrained size.
   141  *
   142  * @see #Reflow()
   143  */
   144 #define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
   146 #define NS_INTRINSICSIZE    NS_UNCONSTRAINEDSIZE
   147 #define NS_AUTOHEIGHT       NS_UNCONSTRAINEDSIZE
   148 #define NS_AUTOMARGIN       NS_UNCONSTRAINEDSIZE
   149 #define NS_AUTOOFFSET       NS_UNCONSTRAINEDSIZE
   150 // NOTE: there are assumptions all over that these have the same value, namely NS_UNCONSTRAINEDSIZE
   151 //       if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
   152 //       at least update AdjustComputedHeight/Width and test ad nauseum
   154 //----------------------------------------------------------------------
   156 enum nsSelectionAmount {
   157   eSelectCharacter = 0, // a single Unicode character;
   158                         // do not use this (prefer Cluster) unless you
   159                         // are really sure it's what you want
   160   eSelectCluster   = 1, // a grapheme cluster: this is usually the right
   161                         // choice for movement or selection by "character"
   162                         // as perceived by the user
   163   eSelectWord      = 2,
   164   eSelectLine      = 3, // previous drawn line in flow.
   165   eSelectBeginLine = 4,
   166   eSelectEndLine   = 5,
   167   eSelectNoAmount  = 6, // just bounce back current offset.
   168   eSelectParagraph = 7,  // select a "paragraph"
   169   eSelectWordNoSpace = 8 // select a "word" without selecting the following
   170                          // space, no matter what the default platform
   171                          // behavior is
   172 };
   174 enum nsSpread {
   175   eSpreadNone   = 0,
   176   eSpreadAcross = 1,
   177   eSpreadDown   = 2
   178 };
   180 // Carried out margin flags
   181 #define NS_CARRIED_TOP_MARGIN_IS_AUTO    0x1
   182 #define NS_CARRIED_BOTTOM_MARGIN_IS_AUTO 0x2
   184 //----------------------------------------------------------------------
   186 /**
   187  * Reflow status returned by the reflow methods. There are three
   188  * completion statuses, represented by two bit flags.
   189  *
   190  * NS_FRAME_COMPLETE means the frame is fully complete.
   191  *
   192  * NS_FRAME_NOT_COMPLETE bit flag means the frame does not map all its
   193  * content, and that the parent frame should create a continuing frame.
   194  * If this bit isn't set it means the frame does map all its content.
   195  * This bit is mutually exclusive with NS_FRAME_OVERFLOW_INCOMPLETE.
   196  *
   197  * NS_FRAME_OVERFLOW_INCOMPLETE bit flag means that the frame has
   198  * overflow that is not complete, but its own box is complete.
   199  * (This happens when content overflows a fixed-height box.)
   200  * The reflower should place and size the frame and continue its reflow,
   201  * but needs to create an overflow container as a continuation for this
   202  * frame. See nsContainerFrame.h for more information.
   203  * This bit is mutually exclusive with NS_FRAME_NOT_COMPLETE.
   204  * 
   205  * Please use the SET macro for handling
   206  * NS_FRAME_NOT_COMPLETE and NS_FRAME_OVERFLOW_INCOMPLETE.
   207  *
   208  * NS_FRAME_REFLOW_NEXTINFLOW bit flag means that the next-in-flow is
   209  * dirty, and also needs to be reflowed. This status only makes sense
   210  * for a frame that is not complete, i.e. you wouldn't set both
   211  * NS_FRAME_COMPLETE and NS_FRAME_REFLOW_NEXTINFLOW.
   212  *
   213  * The low 8 bits of the nsReflowStatus are reserved for future extensions;
   214  * the remaining 24 bits are zero (and available for extensions; however
   215  * API's that accept/return nsReflowStatus must not receive/return any
   216  * extension bits).
   217  *
   218  * @see #Reflow()
   219  */
   220 typedef uint32_t nsReflowStatus;
   222 #define NS_FRAME_COMPLETE             0       // Note: not a bit!
   223 #define NS_FRAME_NOT_COMPLETE         0x1
   224 #define NS_FRAME_REFLOW_NEXTINFLOW    0x2
   225 #define NS_FRAME_OVERFLOW_INCOMPLETE  0x4
   227 #define NS_FRAME_IS_COMPLETE(status) \
   228   (0 == ((status) & NS_FRAME_NOT_COMPLETE))
   230 #define NS_FRAME_IS_NOT_COMPLETE(status) \
   231   (0 != ((status) & NS_FRAME_NOT_COMPLETE))
   233 #define NS_FRAME_OVERFLOW_IS_INCOMPLETE(status) \
   234   (0 != ((status) & NS_FRAME_OVERFLOW_INCOMPLETE))
   236 #define NS_FRAME_IS_FULLY_COMPLETE(status) \
   237   (NS_FRAME_IS_COMPLETE(status) && !NS_FRAME_OVERFLOW_IS_INCOMPLETE(status))
   239 // These macros set or switch incomplete statuses without touching the
   240 // NS_FRAME_REFLOW_NEXTINFLOW bit.
   241 #define NS_FRAME_SET_INCOMPLETE(status) \
   242   status = (status & ~NS_FRAME_OVERFLOW_INCOMPLETE) | NS_FRAME_NOT_COMPLETE
   244 #define NS_FRAME_SET_OVERFLOW_INCOMPLETE(status) \
   245   status = (status & ~NS_FRAME_NOT_COMPLETE) | NS_FRAME_OVERFLOW_INCOMPLETE
   247 // This macro tests to see if an nsReflowStatus is an error value
   248 // or just a regular return value
   249 #define NS_IS_REFLOW_ERROR(_status) (int32_t(_status) < 0)
   251 /**
   252  * Extensions to the reflow status bits defined by nsIFrameReflow
   253  */
   255 // This bit is set, when a break is requested. This bit is orthogonal
   256 // to the nsIFrame::nsReflowStatus completion bits.
   257 #define NS_INLINE_BREAK              0x0100
   259 // When a break is requested, this bit when set indicates that the
   260 // break should occur after the frame just reflowed; when the bit is
   261 // clear the break should occur before the frame just reflowed.
   262 #define NS_INLINE_BREAK_BEFORE       0x0000
   263 #define NS_INLINE_BREAK_AFTER        0x0200
   265 // The type of break requested can be found in these bits.
   266 #define NS_INLINE_BREAK_TYPE_MASK    0xF000
   268 // Set when a break was induced by completion of a first-letter
   269 #define NS_INLINE_BREAK_FIRST_LETTER_COMPLETE 0x10000
   271 //----------------------------------------
   272 // Macros that use those bits
   274 #define NS_INLINE_IS_BREAK(_status) \
   275   (0 != ((_status) & NS_INLINE_BREAK))
   277 #define NS_INLINE_IS_BREAK_AFTER(_status) \
   278   (0 != ((_status) & NS_INLINE_BREAK_AFTER))
   280 #define NS_INLINE_IS_BREAK_BEFORE(_status) \
   281   (NS_INLINE_BREAK == ((_status) & (NS_INLINE_BREAK|NS_INLINE_BREAK_AFTER)))
   283 #define NS_INLINE_GET_BREAK_TYPE(_status) (((_status) >> 12) & 0xF)
   285 #define NS_INLINE_MAKE_BREAK_TYPE(_type)  ((_type) << 12)
   287 // Construct a line-break-before status. Note that there is no
   288 // completion status for a line-break before because we *know* that
   289 // the frame will be reflowed later and hence its current completion
   290 // status doesn't matter.
   291 #define NS_INLINE_LINE_BREAK_BEFORE()                                   \
   292   (NS_INLINE_BREAK | NS_INLINE_BREAK_BEFORE |                           \
   293    NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
   295 // Take a completion status and add to it the desire to have a
   296 // line-break after. For this macro we do need the completion status
   297 // because the user of the status will need to know whether to
   298 // continue the frame or not.
   299 #define NS_INLINE_LINE_BREAK_AFTER(_completionStatus)                   \
   300   ((_completionStatus) | NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |      \
   301    NS_INLINE_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
   303 // A frame is "truncated" if the part of the frame before the first
   304 // possible break point was unable to fit in the available vertical
   305 // space.  Therefore, the entire frame should be moved to the next page.
   306 // A frame that begins at the top of the page must never be "truncated".
   307 // Doing so would likely cause an infinite loop.
   308 #define NS_FRAME_TRUNCATED  0x0010
   309 #define NS_FRAME_IS_TRUNCATED(status) \
   310   (0 != ((status) & NS_FRAME_TRUNCATED))
   311 #define NS_FRAME_SET_TRUNCATION(status, aReflowState, aMetrics) \
   312   aReflowState.SetTruncated(aMetrics, &status);
   314 // Merge the incompleteness, truncation and NS_FRAME_REFLOW_NEXTINFLOW
   315 // status from aSecondary into aPrimary.
   316 void NS_MergeReflowStatusInto(nsReflowStatus* aPrimary,
   317                               nsReflowStatus aSecondary);
   319 //----------------------------------------------------------------------
   321 /**
   322  * DidReflow status values.
   323  */
   324 MOZ_BEGIN_ENUM_CLASS(nsDidReflowStatus, uint32_t)
   325   NOT_FINISHED,
   326   FINISHED
   327 MOZ_END_ENUM_CLASS(nsDidReflowStatus)
   329 /**
   330  * When there is no scrollable overflow rect, the visual overflow rect
   331  * may be stored as four 1-byte deltas each strictly LESS THAN 0xff, for
   332  * the four edges of the rectangle, or the four bytes may be read as a
   333  * single 32-bit "overflow-rect type" value including at least one 0xff
   334  * byte as an indicator that the value does NOT represent four deltas.
   335  * If all four deltas are zero, this means that no overflow rect has
   336  * actually been set (this is the initial state of newly-created frames).
   337  */
   338 #define NS_FRAME_OVERFLOW_DELTA_MAX     0xfe // max delta we can store
   340 #define NS_FRAME_OVERFLOW_NONE    0x00000000 // there are no overflow rects;
   341                                              // code relies on this being
   342                                              // the all-zero value
   344 #define NS_FRAME_OVERFLOW_LARGE   0x000000ff // overflow is stored as a
   345                                              // separate rect property
   347 namespace mozilla {
   348 /*
   349  * For replaced elements only. Gets the intrinsic dimensions of this element.
   350  * The dimensions may only be one of the following two types:
   351  *
   352  *   eStyleUnit_Coord   - a length in app units
   353  *   eStyleUnit_None    - the element has no intrinsic size in this dimension
   354  */
   355 struct IntrinsicSize {
   356   nsStyleCoord width, height;
   358   IntrinsicSize()
   359     : width(eStyleUnit_None), height(eStyleUnit_None)
   360   {}
   361   IntrinsicSize(const IntrinsicSize& rhs)
   362     : width(rhs.width), height(rhs.height)
   363   {}
   364   IntrinsicSize& operator=(const IntrinsicSize& rhs) {
   365     width = rhs.width; height = rhs.height; return *this;
   366   }
   367   bool operator==(const IntrinsicSize& rhs) {
   368     return width == rhs.width && height == rhs.height;
   369   }
   370   bool operator!=(const IntrinsicSize& rhs) {
   371     return !(*this == rhs);
   372   }
   373 };
   374 }
   376 //----------------------------------------------------------------------
   378 /**
   379  * A frame in the layout model. This interface is supported by all frame
   380  * objects.
   381  *
   382  * Frames can have multiple child lists: the default child list
   383  * (referred to as the <i>principal</i> child list, and additional named
   384  * child lists. There is an ordering of frames within a child list, but
   385  * there is no order defined between frames in different child lists of
   386  * the same parent frame.
   387  *
   388  * Frames are NOT reference counted. Use the Destroy() member function
   389  * to destroy a frame. The lifetime of the frame hierarchy is bounded by the
   390  * lifetime of the presentation shell which owns the frames.
   391  *
   392  * nsIFrame is a private Gecko interface. If you are not Gecko then you
   393  * should not use it. If you're not in layout, then you won't be able to
   394  * link to many of the functions defined here. Too bad.
   395  *
   396  * If you're not in layout but you must call functions in here, at least
   397  * restrict yourself to calling virtual methods, which won't hurt you as badly.
   398  */
   399 class nsIFrame : public nsQueryFrame
   400 {
   401 public:
   402   typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
   403   typedef mozilla::FrameProperties FrameProperties;
   404   typedef mozilla::layers::Layer Layer;
   405   typedef mozilla::layout::FrameChildList ChildList;
   406   typedef mozilla::layout::FrameChildListID ChildListID;
   407   typedef mozilla::layout::FrameChildListIDs ChildListIDs;
   408   typedef mozilla::layout::FrameChildListIterator ChildListIterator;
   409   typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
   410   typedef mozilla::gfx::Matrix Matrix;
   412   NS_DECL_QUERYFRAME_TARGET(nsIFrame)
   414   nsPresContext* PresContext() const {
   415     return StyleContext()->RuleNode()->PresContext();
   416   }
   418   /**
   419    * Called to initialize the frame. This is called immediately after creating
   420    * the frame.
   421    *
   422    * If the frame is a continuing frame, then aPrevInFlow indicates the previous
   423    * frame (the frame that was split).
   424    *
   425    * If you want a view associated with your frame, you should create the view
   426    * after Init() has returned.
   427    *
   428    * @param   aContent the content object associated with the frame
   429    * @param   aParent the parent frame
   430    * @param   aPrevInFlow the prev-in-flow frame
   431    */
   432   virtual void Init(nsIContent*      aContent,
   433                     nsIFrame*        aParent,
   434                     nsIFrame*        aPrevInFlow) = 0;
   436   /**
   437    * Destroys this frame and each of its child frames (recursively calls
   438    * Destroy() for each child). If this frame is a first-continuation, this
   439    * also removes the frame from the primary frame map and clears undisplayed
   440    * content for its content node.
   441    * If the frame is a placeholder, it also ensures the out-of-flow frame's
   442    * removal and destruction.
   443    */
   444   void Destroy() { DestroyFrom(this); }
   446   /** Flags for PeekOffsetCharacter, PeekOffsetNoAmount, PeekOffsetWord return values.
   447     */
   448   enum FrameSearchResult {
   449     // Peek found a appropriate offset within frame.
   450     FOUND = 0x00,
   451     // try next frame for offset.
   452     CONTINUE = 0x1,
   453     // offset not found because the frame was empty of text.
   454     CONTINUE_EMPTY = 0x2 | CONTINUE,
   455     // offset not found because the frame didn't contain any text that could be selected.
   456     CONTINUE_UNSELECTABLE = 0x4 | CONTINUE,
   457   };
   459 protected:
   460   /**
   461    * Return true if the frame is part of a Selection.
   462    * Helper method to implement the public IsSelected() API.
   463    */
   464   virtual bool IsFrameSelected() const;
   466   /**
   467    * Implements Destroy(). Do not call this directly except from within a
   468    * DestroyFrom() implementation.
   469    *
   470    * @note This will always be called, so it is not necessary to override
   471    *       Destroy() in subclasses of nsFrame, just DestroyFrom().
   472    *
   473    * @param  aDestructRoot is the root of the subtree being destroyed
   474    */
   475   virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
   476   friend class nsFrameList; // needed to pass aDestructRoot through to children
   477   friend class nsLineBox;   // needed to pass aDestructRoot through to children
   478   friend class nsContainerFrame; // needed to pass aDestructRoot through to children
   479 public:
   481   /**
   482    * Called to set the initial list of frames. This happens after the frame
   483    * has been initialized.
   484    *
   485    * This is only called once for a given child list, and won't be called
   486    * at all for child lists with no initial list of frames.
   487    *
   488    * @param   aListID the child list identifier.
   489    * @param   aChildList list of child frames. Each of the frames has its
   490    *            NS_FRAME_IS_DIRTY bit set.  Must not be empty.
   491    *            This method cannot handle the child list returned by
   492    *            GetAbsoluteListID().
   493    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
   494    *            name,
   495    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame or if the
   496    *            initial list of frames has already been set for that child list,
   497    *          NS_OK otherwise.  In this case, SetInitialChildList empties out
   498    *            aChildList in the process of moving the frames over to its own
   499    *            child list.
   500    * @see     #Init()
   501    */
   502   virtual nsresult  SetInitialChildList(ChildListID     aListID,
   503                                         nsFrameList&    aChildList) = 0;
   505   /**
   506    * This method is responsible for appending frames to the frame
   507    * list.  The implementation should append the frames to the specified
   508    * child list and then generate a reflow command.
   509    *
   510    * @param   aListID the child list identifier.
   511    * @param   aFrameList list of child frames to append. Each of the frames has
   512    *            its NS_FRAME_IS_DIRTY bit set.  Must not be empty.
   513    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
   514    *            name,
   515    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame,
   516    *          NS_OK otherwise.  In this case, AppendFrames empties out
   517    *            aFrameList in the process of moving the frames over to its own
   518    *            child list.
   519    */
   520   virtual nsresult AppendFrames(ChildListID     aListID,
   521                                 nsFrameList&    aFrameList) = 0;
   523   /**
   524    * This method is responsible for inserting frames into the frame
   525    * list.  The implementation should insert the new frames into the specified
   526    * child list and then generate a reflow command.
   527    *
   528    * @param   aListID the child list identifier.
   529    * @param   aPrevFrame the frame to insert frames <b>after</b>
   530    * @param   aFrameList list of child frames to insert <b>after</b> aPrevFrame.
   531    *            Each of the frames has its NS_FRAME_IS_DIRTY bit set
   532    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
   533    *            name,
   534    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame,
   535    *          NS_OK otherwise.  In this case, InsertFrames empties out
   536    *            aFrameList in the process of moving the frames over to its own
   537    *            child list.
   538    */
   539   virtual nsresult InsertFrames(ChildListID     aListID,
   540                                 nsIFrame*       aPrevFrame,
   541                                 nsFrameList&    aFrameList) = 0;
   543   /**
   544    * This method is responsible for removing a frame in the frame
   545    * list.  The implementation should do something with the removed frame
   546    * and then generate a reflow command. The implementation is responsible
   547    * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
   548    *
   549    * @param   aListID the child list identifier.
   550    * @param   aOldFrame the frame to remove
   551    * @return  NS_ERROR_INVALID_ARG if there is no child list with the specified
   552    *            name,
   553    *          NS_ERROR_FAILURE if the child frame is not in the specified
   554    *            child list,
   555    *          NS_ERROR_UNEXPECTED if the frame is an atomic frame,
   556    *          NS_OK otherwise
   557    */
   558   virtual nsresult RemoveFrame(ChildListID     aListID,
   559                                nsIFrame*       aOldFrame) = 0;
   561   /**
   562    * Get the content object associated with this frame. Does not add a reference.
   563    */
   564   nsIContent* GetContent() const { return mContent; }
   566   /**
   567    * Get the frame that should be the parent for the frames of child elements
   568    * May return nullptr during reflow
   569    */
   570   virtual nsIFrame* GetContentInsertionFrame() { return this; }
   572   /**
   573    * Move any frames on our overflow list to the end of our principal list.
   574    * @return true if there were any overflow frames
   575    */
   576   virtual bool DrainSelfOverflowList() { return false; }
   578   /**
   579    * Get the frame that should be scrolled if the content associated
   580    * with this frame is targeted for scrolling. For frames implementing
   581    * nsIScrollableFrame this will return the frame itself. For frames
   582    * like nsTextControlFrame that contain a scrollframe, will return
   583    * that scrollframe.
   584    */
   585   virtual nsIScrollableFrame* GetScrollTargetFrame() { return nullptr; }
   587   /**
   588    * Get the offsets of the frame. most will be 0,0
   589    *
   590    */
   591   virtual nsresult GetOffsets(int32_t &start, int32_t &end) const = 0;
   593   /**
   594    * Reset the offsets when splitting frames during Bidi reordering
   595    *
   596    */
   597   virtual void AdjustOffsetsForBidi(int32_t aStart, int32_t aEnd) {}
   599   /**
   600    * Get the style context associated with this frame.
   601    */
   602   nsStyleContext* StyleContext() const { return mStyleContext; }
   603   void SetStyleContext(nsStyleContext* aContext)
   604   { 
   605     if (aContext != mStyleContext) {
   606       nsStyleContext* oldStyleContext = mStyleContext;
   607       mStyleContext = aContext;
   608       aContext->AddRef();
   609       DidSetStyleContext(oldStyleContext);
   610       oldStyleContext->Release();
   611     }
   612   }
   614   /**
   615    * SetStyleContextWithoutNotification is for changes to the style
   616    * context that should suppress style change processing, in other
   617    * words, those that aren't really changes.  This generally means only
   618    * changes that happen during frame construction.
   619    */
   620   void SetStyleContextWithoutNotification(nsStyleContext* aContext)
   621   {
   622     if (aContext != mStyleContext) {
   623       mStyleContext->Release();
   624       mStyleContext = aContext;
   625       aContext->AddRef();
   626     }
   627   }
   629   // Style post processing hook
   630   // Attention: the old style context is the one we're forgetting,
   631   // and hence possibly completely bogus for GetStyle* purposes.
   632   // Use PeekStyleData instead.
   633   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) = 0;
   635   /**
   636    * Define typesafe getter functions for each style struct by
   637    * preprocessing the list of style structs.  These functions are the
   638    * preferred way to get style data.  The macro creates functions like:
   639    *   const nsStyleBorder* StyleBorder();
   640    *   const nsStyleColor* StyleColor();
   641    *
   642    * Callers outside of libxul should use nsIDOMWindow::GetComputedStyle()
   643    * instead of these accessors.
   644    */
   645   #define STYLE_STRUCT(name_, checkdata_cb_)                                  \
   646     const nsStyle##name_ * Style##name_ () const {                            \
   647       NS_ASSERTION(mStyleContext, "No style context found!");                 \
   648       return mStyleContext->Style##name_ ();                                  \
   649     }
   650   #include "nsStyleStructList.h"
   651   #undef STYLE_STRUCT
   653   /** Also forward GetVisitedDependentColor to the style context */
   654   nscolor GetVisitedDependentColor(nsCSSProperty aProperty)
   655     { return mStyleContext->GetVisitedDependentColor(aProperty); }
   657   /**
   658    * These methods are to access any additional style contexts that
   659    * the frame may be holding. These are contexts that are children
   660    * of the frame's primary context and are NOT used as style contexts
   661    * for any child frames. These contexts also MUST NOT have any child 
   662    * contexts whatsoever. If you need to insert style contexts into the
   663    * style tree, then you should create pseudo element frames to own them
   664    * The indicies must be consecutive and implementations MUST return an 
   665    * NS_ERROR_INVALID_ARG if asked for an index that is out of range.
   666    */
   667   virtual nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const = 0;
   669   virtual void SetAdditionalStyleContext(int32_t aIndex,
   670                                          nsStyleContext* aStyleContext) = 0;
   672   /**
   673    * Accessor functions for geometric parent
   674    */
   675   nsIFrame* GetParent() const { return mParent; }
   676   /**
   677    * Set this frame's parent to aParent.
   678    * If the frame may have moved into or out of a scrollframe's
   679    * frame subtree, StickyScrollContainer::NotifyReparentedFrameAcrossScrollFrameBoundary
   680    * must also be called.
   681    */
   682   virtual void SetParent(nsIFrame* aParent) = 0;
   684   /**
   685    * The frame's writing-mode, used for logical layout computations.
   686    */
   687   mozilla::WritingMode GetWritingMode() const {
   688     return mozilla::WritingMode(StyleVisibility());
   689   }
   691   /**
   692    * Get the writing mode of this frame, but if it is styled with
   693    * unicode-bidi: plaintext, reset the direction to the resolved paragraph
   694    * level of the given subframe (typically the first frame on the line),
   695    * not this frame's writing mode, because the container frame could be split
   696    * by hard line breaks into multiple paragraphs with different base direction.
   697    */
   698   mozilla::WritingMode GetWritingMode(nsIFrame* aSubFrame) const;
   700   /**
   701    * Bounding rect of the frame. The values are in app units, and the origin is
   702    * relative to the upper-left of the geometric parent. The size includes the
   703    * content area, borders, and padding.
   704    *
   705    * Note: moving or sizing the frame does not affect the view's size or
   706    * position.
   707    */
   708   nsRect GetRect() const { return mRect; }
   709   nsPoint GetPosition() const { return mRect.TopLeft(); }
   710   nsSize GetSize() const { return mRect.Size(); }
   711   nsRect GetRectRelativeToSelf() const {
   712     return nsRect(nsPoint(0, 0), mRect.Size());
   713   }
   714   /**
   715    * Dimensions and position in logical coordinates in the frame's writing mode
   716    *  or another writing mode
   717    */
   718   mozilla::LogicalRect GetLogicalRect(nscoord aContainerWidth) const {
   719     return GetLogicalRect(GetWritingMode(), aContainerWidth);
   720   }
   721   mozilla::LogicalPoint GetLogicalPosition(nscoord aContainerWidth) const {
   722     return GetLogicalPosition(GetWritingMode(), aContainerWidth);
   723   }
   724   mozilla::LogicalSize GetLogicalSize() const {
   725     return GetLogicalSize(GetWritingMode());
   726   }
   727   mozilla::LogicalRect GetLogicalRect(mozilla::WritingMode aWritingMode,
   728                                       nscoord aContainerWidth) const {
   729     return mozilla::LogicalRect(aWritingMode, GetRect(), aContainerWidth);
   730   }
   731   mozilla::LogicalPoint GetLogicalPosition(mozilla::WritingMode aWritingMode,
   732                                            nscoord aContainerWidth) const {
   733     return GetLogicalRect(aWritingMode, aContainerWidth).Origin(aWritingMode);
   734   }
   735   mozilla::LogicalSize GetLogicalSize(mozilla::WritingMode aWritingMode) const {
   736     return mozilla::LogicalSize(aWritingMode, GetSize());
   737   }
   738   nscoord IStart(nscoord aContainerWidth) const {
   739     return IStart(GetWritingMode(), aContainerWidth);
   740   }
   741   nscoord IStart(mozilla::WritingMode aWritingMode,
   742                  nscoord aContainerWidth) const {
   743     return GetLogicalPosition(aWritingMode, aContainerWidth).I(aWritingMode);
   744   }
   745   nscoord BStart(nscoord aContainerWidth) const {
   746     return BStart(GetWritingMode(), aContainerWidth);
   747   }
   748   nscoord BStart(mozilla::WritingMode aWritingMode,
   749                  nscoord aContainerWidth) const {
   750     return GetLogicalPosition(aWritingMode, aContainerWidth).B(aWritingMode);
   751   }
   752   nscoord ISize() const { return ISize(GetWritingMode()); }
   753   nscoord ISize(mozilla::WritingMode aWritingMode) const {
   754     return GetLogicalSize(aWritingMode).ISize(aWritingMode);
   755   }
   756   nscoord BSize() const { return BSize(GetWritingMode()); }
   757   nscoord BSize(mozilla::WritingMode aWritingMode) const {
   758     return GetLogicalSize(aWritingMode).BSize(aWritingMode);
   759   }
   761   /**
   762    * When we change the size of the frame's border-box rect, we may need to
   763    * reset the overflow rect if it was previously stored as deltas.
   764    * (If it is currently a "large" overflow and could be re-packed as deltas,
   765    * we don't bother as the cost of the allocation has already been paid.)
   766    */
   767   void SetRect(const nsRect& aRect) {
   768     if (mOverflow.mType != NS_FRAME_OVERFLOW_LARGE &&
   769         mOverflow.mType != NS_FRAME_OVERFLOW_NONE) {
   770       nsOverflowAreas overflow = GetOverflowAreas();
   771       mRect = aRect;
   772       SetOverflowAreas(overflow);
   773     } else {
   774       mRect = aRect;
   775     }
   776   }
   777   /**
   778    * Set this frame's rect from a logical rect in its own writing direction
   779    */
   780   void SetRect(const mozilla::LogicalRect& aRect, nscoord aContainerWidth) {
   781     SetRect(GetWritingMode(), aRect, aContainerWidth);
   782   }
   783   /**
   784    * Set this frame's rect from a logical rect in a different writing direction
   785    * (GetPhysicalRect will assert if the writing mode doesn't match)
   786    */
   787   void SetRect(mozilla::WritingMode aWritingMode,
   788                const mozilla::LogicalRect& aRect,
   789                nscoord aContainerWidth) {
   790     SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth));
   791   }
   792   void SetSize(const nsSize& aSize) {
   793     SetRect(nsRect(mRect.TopLeft(), aSize));
   794   }
   795   void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); }
   797   /**
   798    * Move the frame, accounting for relative positioning. Use this when
   799    * adjusting the frame's position by a known amount, to properly update its
   800    * saved normal position (see GetNormalPosition below).
   801    *
   802    * This must be used only when moving a frame *after*
   803    * nsHTMLReflowState::ApplyRelativePositioning is called.  When moving
   804    * a frame during the reflow process prior to calling
   805    * nsHTMLReflowState::ApplyRelativePositioning, the position should
   806    * simply be adjusted directly (e.g., using SetPosition()).
   807    */
   808   void MovePositionBy(const nsPoint& aTranslation);
   810   /**
   811    * Return frame's position without relative positioning
   812    */
   813   nsPoint GetNormalPosition() const;
   814   mozilla::LogicalPoint
   815   GetLogicalNormalPosition(mozilla::WritingMode aWritingMode,
   816                            nscoord aContainerWidth) const
   817   {
   818     return mozilla::LogicalPoint(aWritingMode,
   819                                  GetNormalPosition(), aContainerWidth);
   820   }
   822   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild)
   823   { return aChild->GetPosition(); }
   825   nsPoint GetPositionIgnoringScrolling() {
   826     return mParent ? mParent->GetPositionOfChildIgnoringScrolling(this)
   827       : GetPosition();
   828   }
   830   static void DestroyRegion(void* aPropertyValue);
   832   static void DestroyMargin(void* aPropertyValue)
   833   {
   834     delete static_cast<nsMargin*>(aPropertyValue);
   835   }
   837   static void DestroyRect(void* aPropertyValue)
   838   {
   839     delete static_cast<nsRect*>(aPropertyValue);
   840   }
   842   static void DestroyPoint(void* aPropertyValue)
   843   {
   844     delete static_cast<nsPoint*>(aPropertyValue);
   845   }
   847   static void DestroyOverflowAreas(void* aPropertyValue)
   848   {
   849     delete static_cast<nsOverflowAreas*>(aPropertyValue);
   850   }
   852   static void DestroySurface(void* aPropertyValue);
   853   static void DestroyDT(void* aPropertyValue);
   855 #ifdef _MSC_VER
   856 // XXX Workaround MSVC issue by making the static FramePropertyDescriptor
   857 // non-const.  See bug 555727.
   858 #define NS_PROPERTY_DESCRIPTOR_CONST
   859 #else
   860 #define NS_PROPERTY_DESCRIPTOR_CONST const
   861 #endif
   863 #define NS_DECLARE_FRAME_PROPERTY(prop, dtor)                                                  \
   864   static const FramePropertyDescriptor* prop() {                                               \
   865     static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { dtor, nullptr }; \
   866     return &descriptor;                                                                        \
   867   }
   868 // Don't use this unless you really know what you're doing!
   869 #define NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(prop, dtor)                               \
   870   static const FramePropertyDescriptor* prop() {                                               \
   871     static NS_PROPERTY_DESCRIPTOR_CONST FramePropertyDescriptor descriptor = { nullptr, dtor }; \
   872     return &descriptor;                                                                        \
   873   }
   875   NS_DECLARE_FRAME_PROPERTY(IBSplitSibling, nullptr)
   876   NS_DECLARE_FRAME_PROPERTY(IBSplitPrevSibling, nullptr)
   878   NS_DECLARE_FRAME_PROPERTY(NormalPositionProperty, DestroyPoint)
   879   NS_DECLARE_FRAME_PROPERTY(ComputedOffsetProperty, DestroyMargin)
   881   NS_DECLARE_FRAME_PROPERTY(OutlineInnerRectProperty, DestroyRect)
   882   NS_DECLARE_FRAME_PROPERTY(PreEffectsBBoxProperty, DestroyRect)
   883   NS_DECLARE_FRAME_PROPERTY(PreTransformOverflowAreasProperty,
   884                             DestroyOverflowAreas)
   886   // The initial overflow area passed to FinishAndStoreOverflow. This is only set
   887   // on frames that Preserve3D() or HasPerspective() or IsTransformed(), and
   888   // when at least one of the overflow areas differs from the frame bound rect.
   889   NS_DECLARE_FRAME_PROPERTY(InitialOverflowProperty, DestroyOverflowAreas)
   891 #ifdef DEBUG
   892   // InitialOverflowPropertyDebug is added to the frame to indicate that either
   893   // the InitialOverflowProperty has been stored or the InitialOverflowProperty
   894   // has been suppressed due to being set to the default value (frame bounds)
   895   NS_DECLARE_FRAME_PROPERTY(DebugInitialOverflowPropertyApplied, nullptr)
   896 #endif
   898   NS_DECLARE_FRAME_PROPERTY(UsedMarginProperty, DestroyMargin)
   899   NS_DECLARE_FRAME_PROPERTY(UsedPaddingProperty, DestroyMargin)
   900   NS_DECLARE_FRAME_PROPERTY(UsedBorderProperty, DestroyMargin)
   902   NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nullptr)
   904   NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nullptr)
   906   NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface)
   907   NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImageDT, DestroyDT)
   909   NS_DECLARE_FRAME_PROPERTY(InvalidationRect, DestroyRect)
   911   NS_DECLARE_FRAME_PROPERTY(RefusedAsyncAnimation, nullptr)
   913   /**
   914    * Return the distance between the border edge of the frame and the
   915    * margin edge of the frame.  Like GetRect(), returns the dimensions
   916    * as of the most recent reflow.
   917    *
   918    * This doesn't include any margin collapsing that may have occurred.
   919    *
   920    * It also treats 'auto' margins as zero, and treats any margins that
   921    * should have been turned into 'auto' because of overconstraint as
   922    * having their original values.
   923    */
   924   virtual nsMargin GetUsedMargin() const;
   925   virtual mozilla::LogicalMargin
   926   GetLogicalUsedMargin(mozilla::WritingMode aWritingMode) const {
   927     return mozilla::LogicalMargin(aWritingMode, GetUsedMargin());
   928   }
   930   /**
   931    * Return the distance between the border edge of the frame (which is
   932    * its rect) and the padding edge of the frame. Like GetRect(), returns
   933    * the dimensions as of the most recent reflow.
   934    *
   935    * Note that this differs from StyleBorder()->GetBorder() in that
   936    * this describes region of the frame's box, and
   937    * StyleBorder()->GetBorder() describes a border.  They differ only
   938    * for tables, particularly border-collapse tables.
   939    */
   940   virtual nsMargin GetUsedBorder() const;
   941   virtual mozilla::LogicalMargin
   942   GetLogicalUsedBorder(mozilla::WritingMode aWritingMode) const {
   943     return mozilla::LogicalMargin(aWritingMode, GetUsedBorder());
   944   }
   946   /**
   947    * Return the distance between the padding edge of the frame and the
   948    * content edge of the frame.  Like GetRect(), returns the dimensions
   949    * as of the most recent reflow.
   950    */
   951   virtual nsMargin GetUsedPadding() const;
   952   virtual mozilla::LogicalMargin
   953   GetLogicalUsedPadding(mozilla::WritingMode aWritingMode) const {
   954     return mozilla::LogicalMargin(aWritingMode, GetUsedPadding());
   955   }
   957   nsMargin GetUsedBorderAndPadding() const {
   958     return GetUsedBorder() + GetUsedPadding();
   959   }
   960   mozilla::LogicalMargin
   961   GetLogicalUsedBorderAndPadding(mozilla::WritingMode aWritingMode) const {
   962     return mozilla::LogicalMargin(aWritingMode, GetUsedBorderAndPadding());
   963   }
   965   /**
   966    * Apply the result of GetSkipSides() on this frame to an nsMargin by
   967    * setting to zero any sides that are skipped.
   968    *
   969    * @param aMargin The margin to apply the result of GetSkipSides() to.
   970    * @param aReflowState An optional reflow state parameter, which is used if
   971    *        ApplySkipSides() is being called in the middle of reflow.
   972    *
   973    * @note (See also bug 743402, comment 11) GetSkipSides() and its sister
   974    *       method, ApplySkipSides() checks to see if this frame has a previous
   975    *       or next continuation to determine if a side should be skipped.
   976    *       Unfortunately, this only works after reflow has been completed. In
   977    *       lieu of this, during reflow, an nsHTMLReflowState parameter can be
   978    *       passed in, indicating that it should be used to determine if sides
   979    *       should be skipped during reflow.
   980    */
   981   void ApplySkipSides(nsMargin& aMargin,
   982                       const nsHTMLReflowState* aReflowState = nullptr) const;
   983   void ApplyLogicalSkipSides(mozilla::LogicalMargin& aMargin,
   984                              const nsHTMLReflowState* aReflowState = nullptr) const;
   986   /**
   987    * Like the frame's rect (see |GetRect|), which is the border rect,
   988    * other rectangles of the frame, in app units, relative to the parent.
   989    */
   990   nsRect GetPaddingRect() const;
   991   nsRect GetPaddingRectRelativeToSelf() const;
   992   nsRect GetContentRect() const;
   993   nsRect GetContentRectRelativeToSelf() const;
   994   nsRect GetMarginRectRelativeToSelf() const;
   996   /**
   997    * The area to paint box-shadows around.  The default is the border rect.
   998    * (nsFieldSetFrame overrides this).
   999    */
  1000   virtual nsRect VisualBorderRectRelativeToSelf() const {
  1001     return nsRect(0, 0, mRect.width, mRect.height);
  1004   /**
  1005    * Get the size, in app units, of the border radii. It returns FALSE iff all
  1006    * returned radii == 0 (so no border radii), TRUE otherwise.
  1007    * For the aRadii indexes, use the NS_CORNER_* constants in nsStyleConsts.h
  1008    * If a side is skipped via aSkipSides, its corners are forced to 0.
  1010    * All corner radii are then adjusted so they do not require more
  1011    * space than aBorderArea, according to the algorithm in css3-background.
  1013    * aFrameSize is used as the basis for percentage widths and heights.
  1014    * aBorderArea is used for the adjustment of radii that might be too
  1015    * large.
  1016    * FIXME: In the long run, we can probably get away with only one of
  1017    * these, especially if we change the way we handle outline-radius (by
  1018    * removing it and inflating the border radius)
  1020    * Return whether any radii are nonzero.
  1021    */
  1022   static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
  1023                                    const nsSize& aFrameSize,
  1024                                    const nsSize& aBorderArea,
  1025                                    int aSkipSides,
  1026                                    nscoord aRadii[8]);
  1028   /*
  1029    * Given a set of border radii for one box (e.g., border box), convert
  1030    * it to the equivalent set of radii for another box (e.g., in to
  1031    * padding box, out to outline box) by reducing radii or increasing
  1032    * nonzero radii as appropriate.
  1034    * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
  1036    * Note that InsetBorderRadii is lossy, since it can turn nonzero
  1037    * radii into zero, and OutsetBorderRadii does not inflate zero radii.
  1038    * Therefore, callers should always inset or outset directly from the
  1039    * original value coming from style.
  1040    */
  1041   static void InsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
  1042   static void OutsetBorderRadii(nscoord aRadii[8], const nsMargin &aOffsets);
  1044   /**
  1045    * Fill in border radii for this frame.  Return whether any are
  1046    * nonzero.
  1048    * Indices into aRadii are the NS_CORNER_* constants in nsStyleConsts.h
  1049    */
  1050   virtual bool GetBorderRadii(nscoord aRadii[8]) const;
  1052   bool GetPaddingBoxBorderRadii(nscoord aRadii[8]) const;
  1053   bool GetContentBoxBorderRadii(nscoord aRadii[8]) const;
  1055   /**
  1056    * Get the position of the frame's baseline, relative to the top of
  1057    * the frame (its top border edge).  Only valid when Reflow is not
  1058    * needed.
  1059    */
  1060   virtual nscoord GetBaseline() const = 0;
  1062   /**
  1063    * Get the position of the baseline on which the caret needs to be placed,
  1064    * relative to the top of the frame.  This is mostly needed for frames
  1065    * which return a baseline from GetBaseline which is not useful for
  1066    * caret positioning.
  1067    */
  1068   virtual nscoord GetCaretBaseline() const {
  1069     return GetBaseline();
  1072   /**
  1073    * Get the specified child list.
  1075    * @param   aListID identifies the requested child list.
  1076    * @return  the child list.  If the requested list is unsupported by this
  1077    *          frame type, an empty list will be returned.
  1078    */
  1079   virtual const nsFrameList& GetChildList(ChildListID aListID) const = 0;
  1080   const nsFrameList& PrincipalChildList() { return GetChildList(kPrincipalList); }
  1081   virtual void GetChildLists(nsTArray<ChildList>* aLists) const = 0;
  1083   /**
  1084    * Gets the child lists for this frame, including
  1085    * ones belong to a child document.
  1086    */
  1087   void GetCrossDocChildLists(nsTArray<ChildList>* aLists);
  1089   // XXXbz this method should go away
  1090   nsIFrame* GetFirstChild(ChildListID aListID) const {
  1091     return GetChildList(aListID).FirstChild();
  1093   // XXXmats this method should also go away then
  1094   nsIFrame* GetLastChild(ChildListID aListID) const {
  1095     return GetChildList(aListID).LastChild();
  1097   nsIFrame* GetFirstPrincipalChild() const {
  1098     return GetFirstChild(kPrincipalList);
  1101   // The individual concrete child lists.
  1102   static const ChildListID kPrincipalList = mozilla::layout::kPrincipalList;
  1103   static const ChildListID kAbsoluteList = mozilla::layout::kAbsoluteList;
  1104   static const ChildListID kBulletList = mozilla::layout::kBulletList;
  1105   static const ChildListID kCaptionList = mozilla::layout::kCaptionList;
  1106   static const ChildListID kColGroupList = mozilla::layout::kColGroupList;
  1107   static const ChildListID kExcessOverflowContainersList = mozilla::layout::kExcessOverflowContainersList;
  1108   static const ChildListID kFixedList = mozilla::layout::kFixedList;
  1109   static const ChildListID kFloatList = mozilla::layout::kFloatList;
  1110   static const ChildListID kOverflowContainersList = mozilla::layout::kOverflowContainersList;
  1111   static const ChildListID kOverflowList = mozilla::layout::kOverflowList;
  1112   static const ChildListID kOverflowOutOfFlowList = mozilla::layout::kOverflowOutOfFlowList;
  1113   static const ChildListID kPopupList = mozilla::layout::kPopupList;
  1114   static const ChildListID kPushedFloatsList = mozilla::layout::kPushedFloatsList;
  1115   static const ChildListID kSelectPopupList = mozilla::layout::kSelectPopupList;
  1116   // A special alias for kPrincipalList that do not request reflow.
  1117   static const ChildListID kNoReflowPrincipalList = mozilla::layout::kNoReflowPrincipalList;
  1119   /**
  1120    * Child frames are linked together in a doubly-linked list
  1121    */
  1122   nsIFrame* GetNextSibling() const { return mNextSibling; }
  1123   void SetNextSibling(nsIFrame* aNextSibling) {
  1124     NS_ASSERTION(this != aNextSibling, "Creating a circular frame list, this is very bad.");
  1125     if (mNextSibling && mNextSibling->GetPrevSibling() == this) {
  1126       mNextSibling->mPrevSibling = nullptr;
  1128     mNextSibling = aNextSibling;
  1129     if (mNextSibling) {
  1130       mNextSibling->mPrevSibling = this;
  1134   nsIFrame* GetPrevSibling() const { return mPrevSibling; }
  1136   /**
  1137    * Builds the display lists for the content represented by this frame
  1138    * and its descendants. The background+borders of this element must
  1139    * be added first, before any other content.
  1141    * This should only be called by methods in nsFrame. Instead of calling this
  1142    * directly, call either BuildDisplayListForStackingContext or
  1143    * BuildDisplayListForChild.
  1145    * See nsDisplayList.h for more information about display lists.
  1147    * @param aDirtyRect content outside this rectangle can be ignored; the
  1148    * rectangle is in frame coordinates
  1149    */
  1150   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
  1151                                 const nsRect&           aDirtyRect,
  1152                                 const nsDisplayListSet& aLists) {}
  1153   /**
  1154    * Displays the caret onto the given display list builder. The caret is
  1155    * painted on top of the rest of the display list items.
  1157    * @param aDirtyRect is the dirty rectangle that we're repainting.
  1158    */
  1159   void DisplayCaret(nsDisplayListBuilder* aBuilder,
  1160                     const nsRect&         aDirtyRect,
  1161                     nsDisplayList*        aList);
  1163   /**
  1164    * Get the preferred caret color at the offset.
  1166    * @param aOffset is offset of the content.
  1167    */
  1168   virtual nscolor GetCaretColorAt(int32_t aOffset);
  1171   bool IsThemed(nsITheme::Transparency* aTransparencyState = nullptr) const {
  1172     return IsThemed(StyleDisplay(), aTransparencyState);
  1174   bool IsThemed(const nsStyleDisplay* aDisp,
  1175                   nsITheme::Transparency* aTransparencyState = nullptr) const {
  1176     nsIFrame* mutable_this = const_cast<nsIFrame*>(this);
  1177     if (!aDisp->mAppearance)
  1178       return false;
  1179     nsPresContext* pc = PresContext();
  1180     nsITheme *theme = pc->GetTheme();
  1181     if(!theme ||
  1182        !theme->ThemeSupportsWidget(pc, mutable_this, aDisp->mAppearance))
  1183       return false;
  1184     if (aTransparencyState) {
  1185       *aTransparencyState =
  1186         theme->GetWidgetTransparency(mutable_this, aDisp->mAppearance);
  1188     return true;
  1191   /**
  1192    * Builds a display list for the content represented by this frame,
  1193    * treating this frame as the root of a stacking context.
  1194    * @param aDirtyRect content outside this rectangle can be ignored; the
  1195    * rectangle is in frame coordinates
  1196    */
  1197   void BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
  1198                                           const nsRect&         aDirtyRect,
  1199                                           nsDisplayList*        aList);
  1201   enum {
  1202     DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT = 0x01,
  1203     DISPLAY_CHILD_FORCE_STACKING_CONTEXT = 0x02,
  1204     DISPLAY_CHILD_INLINE = 0x04
  1205   };
  1206   /**
  1207    * Adjusts aDirtyRect for the child's offset, checks that the dirty rect
  1208    * actually intersects the child (or its descendants), calls BuildDisplayList
  1209    * on the child if necessary, and puts things in the right lists if the child
  1210    * is positioned.
  1212    * @param aFlags combination of DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT,
  1213    *    DISPLAY_CHILD_FORCE_STACKING_CONTEXT and DISPLAY_CHILD_INLINE
  1214    */
  1215   void BuildDisplayListForChild(nsDisplayListBuilder*   aBuilder,
  1216                                 nsIFrame*               aChild,
  1217                                 const nsRect&           aDirtyRect,
  1218                                 const nsDisplayListSet& aLists,
  1219                                 uint32_t                aFlags = 0);
  1221   /**
  1222    * Does this frame need a view?
  1223    */
  1224   virtual bool NeedsView() { return false; }
  1226   /**
  1227    * Returns true if this frame is transformed (e.g. has CSS or SVG transforms)
  1228    * or if its parent is an SVG frame that has children-only transforms (e.g.
  1229    * an SVG viewBox attribute).
  1230    */
  1231   bool IsTransformed() const;
  1233   /**
  1234    * Returns true if the frame is translucent for the purposes of creating a
  1235    * stacking context.
  1236    */
  1237   bool HasOpacity() const
  1239     return HasOpacityInternal(1.0f);
  1241   /**
  1242    * Returns true if the frame is translucent for display purposes.
  1243    */
  1244   bool HasVisualOpacity() const
  1246     // Treat an opacity value of 0.99 and above as opaque.  This is an
  1247     // optimization aimed at Web content which use opacity:0.99 as a hint for
  1248     // creating a stacking context only.
  1249     return HasOpacityInternal(0.99f);
  1252    /**
  1253    * Return true if this frame might be using a transform getter.
  1254    */
  1255   virtual bool HasTransformGetter() const { return false; }
  1257   /**
  1258    * Returns true if this frame is an SVG frame that has SVG transforms applied
  1259    * to it, or if its parent frame is an SVG frame that has children-only
  1260    * transforms (e.g. an SVG viewBox attribute).
  1261    * If aOwnTransforms is non-null and the frame has its own SVG transforms,
  1262    * aOwnTransforms will be set to these transforms. If aFromParentTransforms
  1263    * is non-null and the frame has an SVG parent with children-only transforms,
  1264    * then aFromParentTransforms will be set to these transforms.
  1265    */
  1266   virtual bool IsSVGTransformed(Matrix *aOwnTransforms = nullptr,
  1267                                 Matrix *aFromParentTransforms = nullptr) const;
  1269   /**
  1270    * Returns whether this frame will attempt to preserve the 3d transforms of its
  1271    * children. This requires transform-style: preserve-3d, as well as no clipping
  1272    * or svg effects.
  1273    */
  1274   bool Preserves3DChildren() const;
  1276   /**
  1277    * Returns whether this frame has a parent that Preserves3DChildren() and has
  1278    * its own transform (or hidden backface) to be combined with the parent's
  1279    * transform.
  1280    */
  1281   bool Preserves3D() const;
  1283   bool HasPerspective() const;
  1285   bool ChildrenHavePerspective() const;
  1287   // Calculate the overflow size of all child frames, taking preserve-3d into account
  1288   void ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, const nsRect& aBounds);
  1290   void RecomputePerspectiveChildrenOverflow(const nsStyleContext* aStartStyle, const nsRect* aBounds);
  1292   /**
  1293    * Returns the number of ancestors between this and the root of our frame tree
  1294    */
  1295   uint32_t GetDepthInFrameTree() {
  1296     uint32_t result = 0;
  1297     for (nsIFrame* ancestor = GetParent(); ancestor;
  1298          ancestor = ancestor->GetParent()) {
  1299       result++;
  1301     return result;
  1304   /**
  1305    * Event handling of GUI events.
  1307    * @param   aEvent event structure describing the type of event and rge widget
  1308    *            where the event originated
  1309    *          The |point| member of this is in the coordinate system of the
  1310    *          view returned by GetOffsetFromView.
  1311    * @param   aEventStatus a return value indicating whether the event was handled
  1312    *            and whether default processing should be done
  1314    * XXX From a frame's perspective it's unclear what the effect of the event status
  1315    * is. Does it cause the event to continue propagating through the frame hierarchy
  1316    * or is it just returned to the widgets?
  1318    * @see     WidgetGUIEvent
  1319    * @see     nsEventStatus
  1320    */
  1321   virtual nsresult  HandleEvent(nsPresContext* aPresContext,
  1322                                 mozilla::WidgetGUIEvent* aEvent,
  1323                                 nsEventStatus* aEventStatus) = 0;
  1325   virtual nsresult  GetContentForEvent(mozilla::WidgetEvent* aEvent,
  1326                                        nsIContent** aContent) = 0;
  1328   // This structure keeps track of the content node and offsets associated with
  1329   // a point; there is a primary and a secondary offset associated with any
  1330   // point.  The primary and secondary offsets differ when the point is over a
  1331   // non-text object.  The primary offset is the expected position of the
  1332   // cursor calculated from a point; the secondary offset, when it is different,
  1333   // indicates that the point is in the boundaries of some selectable object.
  1334   // Note that the primary offset can be after the secondary offset; for places
  1335   // that need the beginning and end of the object, the StartOffset and 
  1336   // EndOffset helpers can be used.
  1337   struct MOZ_STACK_CLASS ContentOffsets {
  1338     ContentOffsets();
  1339     ContentOffsets(const ContentOffsets&);
  1340     ~ContentOffsets();
  1341     nsCOMPtr<nsIContent> content;
  1342     bool IsNull() { return !content; }
  1343     int32_t offset;
  1344     int32_t secondaryOffset;
  1345     // Helpers for places that need the ends of the offsets and expect them in
  1346     // numerical order, as opposed to wanting the primary and secondary offsets
  1347     int32_t StartOffset() { return std::min(offset, secondaryOffset); }
  1348     int32_t EndOffset() { return std::max(offset, secondaryOffset); }
  1349     // This boolean indicates whether the associated content is before or after
  1350     // the offset; the most visible use is to allow the caret to know which line
  1351     // to display on.
  1352     bool associateWithNext;
  1353   };
  1354   enum {
  1355     IGNORE_SELECTION_STYLE = 0x01,
  1356     // Treat visibility:hidden frames as non-selectable
  1357     SKIP_HIDDEN = 0x02
  1358   };
  1359   /**
  1360    * This function calculates the content offsets for selection relative to
  1361    * a point.  Note that this should generally only be callled on the event
  1362    * frame associated with an event because this function does not account
  1363    * for frame lists other than the primary one.
  1364    * @param aPoint point relative to this frame
  1365    */
  1366   ContentOffsets GetContentOffsetsFromPoint(nsPoint aPoint,
  1367                                             uint32_t aFlags = 0);
  1369   virtual ContentOffsets GetContentOffsetsFromPointExternal(nsPoint aPoint,
  1370                                                             uint32_t aFlags = 0)
  1371   { return GetContentOffsetsFromPoint(aPoint, aFlags); }
  1373   /**
  1374    * Ensure that aImage gets notifed when the underlying image request loads
  1375    * or animates.
  1376    */
  1377   void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext);
  1379   /**
  1380    * This structure holds information about a cursor. mContainer represents a
  1381    * loaded image that should be preferred. If it is not possible to use it, or
  1382    * if it is null, mCursor should be used.
  1383    */
  1384   struct MOZ_STACK_CLASS Cursor {
  1385     nsCOMPtr<imgIContainer> mContainer;
  1386     int32_t                 mCursor;
  1387     bool                    mHaveHotspot;
  1388     float                   mHotspotX, mHotspotY;
  1389   };
  1390   /**
  1391    * Get the cursor for a given frame.
  1392    */
  1393   virtual nsresult  GetCursor(const nsPoint&  aPoint,
  1394                               Cursor&         aCursor) = 0;
  1396   /**
  1397    * Get a point (in the frame's coordinate space) given an offset into
  1398    * the content. This point should be on the baseline of text with
  1399    * the correct horizontal offset
  1400    */
  1401   virtual nsresult  GetPointFromOffset(int32_t                  inOffset,
  1402                                        nsPoint*                 outPoint) = 0;
  1404   /**
  1405    * Get the child frame of this frame which contains the given
  1406    * content offset. outChildFrame may be this frame, or nullptr on return.
  1407    * outContentOffset returns the content offset relative to the start
  1408    * of the returned node. You can also pass a hint which tells the method
  1409    * to stick to the end of the first found frame or the beginning of the 
  1410    * next in case the offset falls on a boundary.
  1411    */
  1412   virtual nsresult GetChildFrameContainingOffset(int32_t    inContentOffset,
  1413                                                  bool       inHint,//false stick left
  1414                                                  int32_t*   outFrameContentOffset,
  1415                                                  nsIFrame** outChildFrame) = 0;
  1417  /**
  1418    * Get the current frame-state value for this frame. aResult is
  1419    * filled in with the state bits. 
  1420    */
  1421   nsFrameState GetStateBits() const { return mState; }
  1423   /**
  1424    * Update the current frame-state value for this frame. 
  1425    */
  1426   void AddStateBits(nsFrameState aBits) { mState |= aBits; }
  1427   void RemoveStateBits(nsFrameState aBits) { mState &= ~aBits; }
  1429   /**
  1430    * Checks if the current frame-state includes all of the listed bits
  1431    */
  1432   bool HasAllStateBits(nsFrameState aBits) const
  1434     return (mState & aBits) == aBits;
  1437   /**
  1438    * Checks if the current frame-state includes any of the listed bits
  1439    */
  1440   bool HasAnyStateBits(nsFrameState aBits) const
  1442     return mState & aBits;
  1445   /**
  1446    * This call is invoked on the primary frame for a character data content
  1447    * node, when it is changed in the content tree.
  1448    */
  1449   virtual nsresult  CharacterDataChanged(CharacterDataChangeInfo* aInfo) = 0;
  1451   /**
  1452    * This call is invoked when the value of a content objects's attribute
  1453    * is changed. 
  1454    * The first frame that maps that content is asked to deal
  1455    * with the change by doing whatever is appropriate.
  1457    * @param aNameSpaceID the namespace of the attribute
  1458    * @param aAttribute the atom name of the attribute
  1459    * @param aModType Whether or not the attribute was added, changed, or removed.
  1460    *   The constants are defined in nsIDOMMutationEvent.h.
  1461    */
  1462   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
  1463                                      nsIAtom*        aAttribute,
  1464                                      int32_t         aModType) = 0;
  1466   /**
  1467    * When the content states of a content object change, this method is invoked
  1468    * on the primary frame of that content object.
  1470    * @param aStates the changed states
  1471    */
  1472   virtual void ContentStatesChanged(mozilla::EventStates aStates);
  1474   /**
  1475    * Return how your frame can be split.
  1476    */
  1477   virtual nsSplittableType GetSplittableType() const = 0;
  1479   /**
  1480    * Continuation member functions
  1481    */
  1482   virtual nsIFrame* GetPrevContinuation() const = 0;
  1483   virtual void SetPrevContinuation(nsIFrame*) = 0;
  1484   virtual nsIFrame* GetNextContinuation() const = 0;
  1485   virtual void SetNextContinuation(nsIFrame*) = 0;
  1486   virtual nsIFrame* FirstContinuation() const {
  1487     return const_cast<nsIFrame*>(this);
  1489   virtual nsIFrame* LastContinuation() const {
  1490     return const_cast<nsIFrame*>(this);
  1493   /**
  1494    * GetTailContinuation gets the last non-overflow-container continuation
  1495    * in the continuation chain, i.e. where the next sibling element
  1496    * should attach).
  1497    */
  1498   nsIFrame* GetTailContinuation();
  1500   /**
  1501    * Flow member functions
  1502    */
  1503   virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
  1504   nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
  1505   virtual void SetPrevInFlow(nsIFrame*) = 0;
  1507   virtual nsIFrame* GetNextInFlowVirtual() const = 0;
  1508   nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
  1509   virtual void SetNextInFlow(nsIFrame*) = 0;
  1511   /**
  1512    * Return the first frame in our current flow. 
  1513    */
  1514   virtual nsIFrame* FirstInFlow() const {
  1515     return const_cast<nsIFrame*>(this);
  1518   /**
  1519    * Return the last frame in our current flow.
  1520    */
  1521   virtual nsIFrame* LastInFlow() const {
  1522     return const_cast<nsIFrame*>(this);
  1526   /**
  1527    * Mark any stored intrinsic width information as dirty (requiring
  1528    * re-calculation).  Note that this should generally not be called
  1529    * directly; nsPresShell::FrameNeedsReflow will call it instead.
  1530    */
  1531   virtual void MarkIntrinsicWidthsDirty() = 0;
  1533   /**
  1534    * Get the intrinsic minimum width of the frame.  This must be less
  1535    * than or equal to the intrinsic width.
  1537    * This is *not* affected by the CSS 'min-width', 'width', and
  1538    * 'max-width' properties on this frame, but it is affected by the
  1539    * values of those properties on this frame's descendants.  (It may be
  1540    * called during computation of the values of those properties, so it
  1541    * cannot depend on any values in the nsStylePosition for this frame.)
  1543    * The value returned should **NOT** include the space required for
  1544    * padding and border.
  1546    * Note that many frames will cache the result of this function call
  1547    * unless MarkIntrinsicWidthsDirty is called.
  1549    * It is not acceptable for a frame to mark itself dirty when this
  1550    * method is called.
  1552    * This method must not return a negative value.
  1553    */
  1554   virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) = 0;
  1556   /**
  1557    * Get the intrinsic width of the frame.  This must be greater than or
  1558    * equal to the intrinsic minimum width.
  1560    * Otherwise, all the comments for |GetMinWidth| above apply.
  1561    */
  1562   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) = 0;
  1564   /**
  1565    * |InlineIntrinsicWidth| represents the intrinsic width information
  1566    * in inline layout.  Code that determines the intrinsic width of a
  1567    * region of inline layout accumulates the result into this structure.
  1568    * This pattern is needed because we need to maintain state
  1569    * information about whitespace (for both collapsing and trimming).
  1570    */
  1571   struct InlineIntrinsicWidthData {
  1572     InlineIntrinsicWidthData()
  1573       : line(nullptr)
  1574       , lineContainer(nullptr)
  1575       , prevLines(0)
  1576       , currentLine(0)
  1577       , skipWhitespace(true)
  1578       , trailingWhitespace(0)
  1579     {}
  1581     // The line. This may be null if the inlines are not associated with
  1582     // a block or if we just don't know the line.
  1583     const nsLineList_iterator* line;
  1585     // The line container.
  1586     nsIFrame* lineContainer;
  1588     // The maximum intrinsic width for all previous lines.
  1589     nscoord prevLines;
  1591     // The maximum intrinsic width for the current line.  At a line
  1592     // break (mandatory for preferred width; allowed for minimum width),
  1593     // the caller should call |Break()|.
  1594     nscoord currentLine;
  1596     // True if initial collapsable whitespace should be skipped.  This
  1597     // should be true at the beginning of a block, after hard breaks
  1598     // and when the last text ended with whitespace.
  1599     bool skipWhitespace;
  1601     // This contains the width of the trimmable whitespace at the end of
  1602     // |currentLine|; it is zero if there is no such whitespace.
  1603     nscoord trailingWhitespace;
  1605     // Floats encountered in the lines.
  1606     class FloatInfo {
  1607     public:
  1608       FloatInfo(const nsIFrame* aFrame, nscoord aWidth)
  1609         : mFrame(aFrame), mWidth(aWidth)
  1610       { }
  1611       const nsIFrame* Frame() const { return mFrame; }
  1612       nscoord         Width() const { return mWidth; }
  1614     private:
  1615       const nsIFrame* mFrame;
  1616       nscoord         mWidth;
  1617     };
  1619     nsTArray<FloatInfo> floats;
  1620   };
  1622   struct InlineMinWidthData : public InlineIntrinsicWidthData {
  1623     InlineMinWidthData()
  1624       : trailingTextFrame(nullptr)
  1625       , atStartOfLine(true)
  1626     {}
  1628     // We need to distinguish forced and optional breaks for cases where the
  1629     // current line total is negative.  When it is, we need to ignore
  1630     // optional breaks to prevent min-width from ending up bigger than
  1631     // pref-width.
  1632     void ForceBreak(nsRenderingContext *aRenderingContext);
  1634     // If the break here is actually taken, aHyphenWidth must be added to the
  1635     // width of the current line.
  1636     void OptionallyBreak(nsRenderingContext *aRenderingContext,
  1637                          nscoord aHyphenWidth = 0);
  1639     // The last text frame processed so far in the current line, when
  1640     // the last characters in that text frame are relevant for line
  1641     // break opportunities.
  1642     nsIFrame *trailingTextFrame;
  1644     // Whether we're currently at the start of the line.  If we are, we
  1645     // can't break (for example, between the text-indent and the first
  1646     // word).
  1647     bool atStartOfLine;
  1648   };
  1650   struct InlinePrefWidthData : public InlineIntrinsicWidthData {
  1651     void ForceBreak(nsRenderingContext *aRenderingContext);
  1652   };
  1654   /**
  1655    * Add the intrinsic minimum width of a frame in a way suitable for
  1656    * use in inline layout to an |InlineIntrinsicWidthData| object that
  1657    * represents the intrinsic width information of all the previous
  1658    * frames in the inline layout region.
  1660    * All *allowed* breakpoints within the frame determine what counts as
  1661    * a line for the |InlineIntrinsicWidthData|.  This means that
  1662    * |aData->trailingWhitespace| will always be zero (unlike for
  1663    * AddInlinePrefWidth).
  1665    * All the comments for |GetMinWidth| apply, except that this function
  1666    * is responsible for adding padding, border, and margin and for
  1667    * considering the effects of 'width', 'min-width', and 'max-width'.
  1669    * This may be called on any frame.  Frames that do not participate in
  1670    * line breaking can inherit the default implementation on nsFrame,
  1671    * which calls |GetMinWidth|.
  1672    */
  1673   virtual void
  1674   AddInlineMinWidth(nsRenderingContext *aRenderingContext,
  1675                     InlineMinWidthData *aData) = 0;
  1677   /**
  1678    * Add the intrinsic preferred width of a frame in a way suitable for
  1679    * use in inline layout to an |InlineIntrinsicWidthData| object that
  1680    * represents the intrinsic width information of all the previous
  1681    * frames in the inline layout region.
  1683    * All the comments for |AddInlineMinWidth| and |GetPrefWidth| apply,
  1684    * except that this fills in an |InlineIntrinsicWidthData| structure
  1685    * based on using all *mandatory* breakpoints within the frame.
  1686    */
  1687   virtual void
  1688   AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
  1689                      InlinePrefWidthData *aData) = 0;
  1691   /**
  1692    * Return the horizontal components of padding, border, and margin
  1693    * that contribute to the intrinsic width that applies to the parent.
  1694    */
  1695   struct IntrinsicWidthOffsetData {
  1696     nscoord hPadding, hBorder, hMargin;
  1697     float hPctPadding, hPctMargin;
  1699     IntrinsicWidthOffsetData()
  1700       : hPadding(0), hBorder(0), hMargin(0)
  1701       , hPctPadding(0.0f), hPctMargin(0.0f)
  1702     {}
  1703   };
  1704   virtual IntrinsicWidthOffsetData
  1705     IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext) = 0;
  1707   virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
  1709   /*
  1710    * Get the intrinsic ratio of this element, or nsSize(0,0) if it has
  1711    * no intrinsic ratio.  The intrinsic ratio is the ratio of the
  1712    * height/width of a box with an intrinsic size or the intrinsic
  1713    * aspect ratio of a scalable vector image without an intrinsic size.
  1715    * Either one of the sides may be zero, indicating a zero or infinite
  1716    * ratio.
  1717    */
  1718   virtual nsSize GetIntrinsicRatio() = 0;
  1720   /**
  1721    * Bit-flags to pass to ComputeSize in |aFlags| parameter.
  1722    */
  1723   enum {
  1724     /* Set if the frame is in a context where non-replaced blocks should
  1725      * shrink-wrap (e.g., it's floating, absolutely positioned, or
  1726      * inline-block). */
  1727     eShrinkWrap =        1 << 0,
  1728     /* Set if we'd like to compute our 'auto' height, regardless of our actual
  1729      * computed value of 'height'. (e.g. to get an intrinsic height for flex
  1730      * items with "min-height: auto" to use during flexbox layout.) */
  1731     eUseAutoHeight =     1 << 1
  1732   };
  1734   /**
  1735    * Compute the size that a frame will occupy.  Called while
  1736    * constructing the nsHTMLReflowState to be used to Reflow the frame,
  1737    * in order to fill its mComputedWidth and mComputedHeight member
  1738    * variables.
  1740    * The |height| member of the return value may be
  1741    * NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
  1743    * Note that the reason that border and padding need to be passed
  1744    * separately is so that the 'box-sizing' property can be handled.
  1745    * Thus aMargin includes absolute positioning offsets as well.
  1747    * @param aCBSize  The size of the element's containing block.  (Well,
  1748    *                 the |height| component isn't really.)
  1749    * @param aAvailableWidth  The available width for 'auto' widths.
  1750    *                         This is usually the same as aCBSize.width,
  1751    *                         but differs in cases such as block
  1752    *                         formatting context roots next to floats, or
  1753    *                         in some cases of float reflow in quirks
  1754    *                         mode.
  1755    * @param aMargin  The sum of the vertical / horizontal margins
  1756    *                 ***AND*** absolute positioning offsets (top, right,
  1757    *                 bottom, left) of the frame, including actual values
  1758    *                 resulting from percentages and from the
  1759    *                 "hypothetical box" for absolute positioning, but
  1760    *                 not including actual values resulting from 'auto'
  1761    *                 margins or ignored 'auto' values in absolute
  1762    *                 positioning.
  1763    * @param aBorder  The sum of the vertical / horizontal border widths
  1764    *                 of the frame.
  1765    * @param aPadding The sum of the vertical / horizontal margins of
  1766    *                 the frame, including actual values resulting from
  1767    *                 percentages.
  1768    * @param aFlags   Flags to further customize behavior (definitions above).
  1769    */
  1770   virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
  1771                              nsSize aCBSize, nscoord aAvailableWidth,
  1772                              nsSize aMargin, nsSize aBorder, nsSize aPadding,
  1773                              uint32_t aFlags) = 0;
  1775   /**
  1776    * Compute a tight bounding rectangle for the frame. This is a rectangle
  1777    * that encloses the pixels that are actually drawn. We're allowed to be
  1778    * conservative and currently we don't try very hard. The rectangle is
  1779    * in appunits and relative to the origin of this frame.
  1781    * This probably only needs to include frame bounds, glyph bounds, and
  1782    * text decorations, but today it sometimes includes other things that
  1783    * contribute to visual overflow.
  1785    * @param aContext a rendering context that can be used if we need
  1786    * to do measurement
  1787    */
  1788   virtual nsRect ComputeTightBounds(gfxContext* aContext) const;
  1790   /**
  1791    * This function is similar to GetPrefWidth and ComputeTightBounds: it
  1792    * computes the left and right coordinates of a preferred tight bounding
  1793    * rectangle for the frame. This is a rectangle that would enclose the pixels
  1794    * that are drawn if we lay out the element without taking any optional line
  1795    * breaks. The rectangle is in appunits and relative to the origin of this
  1796    * frame. Currently, this function is only implemented for nsBlockFrame and
  1797    * nsTextFrame and is used to determine intrinsic widths of MathML token
  1798    * elements.
  1800    * @param aContext a rendering context that can be used if we need
  1801    * to do measurement
  1802    * @param aX      computed left coordinate of the tight bounding rectangle
  1803    * @param aXMost  computed intrinsic width of the tight bounding rectangle
  1805    */
  1806   virtual nsresult GetPrefWidthTightBounds(nsRenderingContext* aContext,
  1807                                            nscoord* aX,
  1808                                            nscoord* aXMost);
  1810   /**
  1811    * Pre-reflow hook. Before a frame is reflowed this method will be called.
  1812    * This call will always be invoked at least once before a subsequent Reflow
  1813    * and DidReflow call. It may be called more than once, In general you will
  1814    * receive on WillReflow notification before each Reflow request.
  1816    * XXX Is this really the semantics we want? Because we have the NS_FRAME_IN_REFLOW
  1817    * bit we can ensure we don't call it more than once...
  1818    */
  1819   virtual nsresult  WillReflow(nsPresContext* aPresContext) = 0;
  1821   /**
  1822    * The frame is given an available size and asked for its desired
  1823    * size.  This is the frame's opportunity to reflow its children.
  1825    * If the frame has the NS_FRAME_IS_DIRTY bit set then it is
  1826    * responsible for completely reflowing itself and all of its
  1827    * descendants.
  1829    * Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
  1830    * set, then it is responsible for reflowing at least those
  1831    * children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
  1832    * set.
  1834    * If a difference in available size from the previous reflow causes
  1835    * the frame's size to change, it should reflow descendants as needed.
  1837    * @param aReflowMetrics <i>out</i> parameter where you should return the
  1838    *          desired size and ascent/descent info. You should include any
  1839    *          space you want for border/padding in the desired size you return.
  1841    *          It's okay to return a desired size that exceeds the avail
  1842    *          size if that's the smallest you can be, i.e. it's your
  1843    *          minimum size.
  1845    *          For an incremental reflow you are responsible for invalidating
  1846    *          any area within your frame that needs repainting (including
  1847    *          borders). If your new desired size is different than your current
  1848    *          size, then your parent frame is responsible for making sure that
  1849    *          the difference between the two rects is repainted
  1851    * @param aReflowState information about your reflow including the reason
  1852    *          for the reflow and the available space in which to lay out. Each
  1853    *          dimension of the available space can either be constrained or
  1854    *          unconstrained (a value of NS_UNCONSTRAINEDSIZE).
  1856    *          Note that the available space can be negative. In this case you
  1857    *          still must return an accurate desired size. If you're a container
  1858    *          you must <b>always</b> reflow at least one frame regardless of the
  1859    *          available space
  1861    * @param aStatus a return value indicating whether the frame is complete
  1862    *          and whether the next-in-flow is dirty and needs to be reflowed
  1863    */
  1864   virtual nsresult Reflow(nsPresContext*          aPresContext,
  1865                           nsHTMLReflowMetrics&     aReflowMetrics,
  1866                           const nsHTMLReflowState& aReflowState,
  1867                           nsReflowStatus&          aStatus) = 0;
  1869   /**
  1870    * Post-reflow hook. After a frame is reflowed this method will be called
  1871    * informing the frame that this reflow process is complete, and telling the
  1872    * frame the status returned by the Reflow member function.
  1874    * This call may be invoked many times, while NS_FRAME_IN_REFLOW is set, before
  1875    * it is finally called once with a NS_FRAME_REFLOW_COMPLETE value. When called
  1876    * with a NS_FRAME_REFLOW_COMPLETE value the NS_FRAME_IN_REFLOW bit in the
  1877    * frame state will be cleared.
  1879    * XXX This doesn't make sense. If the frame is reflowed but not complete, then
  1880    * the status should be NS_FRAME_NOT_COMPLETE and not NS_FRAME_COMPLETE
  1881    * XXX Don't we want the semantics to dictate that we only call this once for
  1882    * a given reflow?
  1883    */
  1884   virtual nsresult  DidReflow(nsPresContext*           aPresContext,
  1885                               const nsHTMLReflowState*  aReflowState,
  1886                               nsDidReflowStatus         aStatus) = 0;
  1888   // XXX Maybe these three should be a separate interface?
  1890   /**
  1891    * Updates the overflow areas of the frame. This can be called if an
  1892    * overflow area of the frame's children has changed without reflowing.
  1893    * @return true if either of the overflow areas for this frame have changed.
  1894    */
  1895   virtual bool UpdateOverflow() = 0;
  1897   /**
  1898    * Helper method used by block reflow to identify runs of text so
  1899    * that proper word-breaking can be done.
  1901    * @return 
  1902    *    true if we can continue a "text run" through the frame. A
  1903    *    text run is text that should be treated contiguously for line
  1904    *    and word breaking.
  1905    */
  1906   virtual bool CanContinueTextRun() const = 0;
  1908   /**
  1909    * Append the rendered text to the passed-in string.
  1910    * The appended text will often not contain all the whitespace from source,
  1911    * depending on whether the CSS rule "white-space: pre" is active for this frame.
  1912    * if aStartOffset + aLength goes past end, or if aLength is not specified
  1913    * then use the text up to the string's end.
  1914    * Call this on the primary frame for a text node.
  1915    * @param aAppendToString   String to append text to, or null if text should not be returned
  1916    * @param aSkipChars         if aSkipIter is non-null, this must also be non-null.
  1917    * This gets used as backing data for the iterator so it should outlive the iterator.
  1918    * @param aSkipIter         Where to fill in the gfxSkipCharsIterator info, or null if not needed by caller
  1919    * @param aStartOffset       Skipped (rendered text) start offset
  1920    * @param aSkippedMaxLength  Maximum number of characters to return
  1921    * The iterator can be used to map content offsets to offsets in the returned string, or vice versa.
  1922    */
  1923   virtual nsresult GetRenderedText(nsAString* aAppendToString = nullptr,
  1924                                    gfxSkipChars* aSkipChars = nullptr,
  1925                                    gfxSkipCharsIterator* aSkipIter = nullptr,
  1926                                    uint32_t aSkippedStartOffset = 0,
  1927                                    uint32_t aSkippedMaxLength = UINT32_MAX)
  1928   { return NS_ERROR_NOT_IMPLEMENTED; }
  1930   /**
  1931    * Returns true if the frame contains any non-collapsed characters.
  1932    * This method is only available for text frames, and it will return false
  1933    * for all other frame types.
  1934    */
  1935   virtual bool HasAnyNoncollapsedCharacters()
  1936   { return false; }
  1938   /**
  1939    * Accessor functions to get/set the associated view object
  1941    * GetView returns non-null if and only if |HasView| returns true.
  1942    */
  1943   bool HasView() const { return !!(mState & NS_FRAME_HAS_VIEW); }
  1944   nsView* GetView() const;
  1945   virtual nsView* GetViewExternal() const;
  1946   nsresult SetView(nsView* aView);
  1948   /**
  1949    * Find the closest view (on |this| or an ancestor).
  1950    * If aOffset is non-null, it will be set to the offset of |this|
  1951    * from the returned view.
  1952    */
  1953   nsView* GetClosestView(nsPoint* aOffset = nullptr) const;
  1955   /**
  1956    * Find the closest ancestor (excluding |this| !) that has a view
  1957    */
  1958   nsIFrame* GetAncestorWithView() const;
  1959   virtual nsIFrame* GetAncestorWithViewExternal() const;
  1961   /**
  1962    * Get the offset between the coordinate systems of |this| and aOther.
  1963    * Adding the return value to a point in the coordinate system of |this|
  1964    * will transform the point to the coordinate system of aOther.
  1966    * aOther must be non-null.
  1968    * This function is fastest when aOther is an ancestor of |this|.
  1970    * This function _DOES NOT_ work across document boundaries.
  1971    * Use this function only when |this| and aOther are in the same document.
  1973    * NOTE: this actually returns the offset from aOther to |this|, but
  1974    * that offset is added to transform _coordinates_ from |this| to
  1975    * aOther.
  1976    */
  1977   nsPoint GetOffsetTo(const nsIFrame* aOther) const;
  1978   virtual nsPoint GetOffsetToExternal(const nsIFrame* aOther) const;
  1980   /**
  1981    * Get the offset between the coordinate systems of |this| and aOther
  1982    * expressed in appunits per dev pixel of |this|' document. Adding the return
  1983    * value to a point that is relative to the origin of |this| will make the
  1984    * point relative to the origin of aOther but in the appunits per dev pixel
  1985    * ratio of |this|.
  1987    * aOther must be non-null.
  1989    * This function is fastest when aOther is an ancestor of |this|.
  1991    * This function works across document boundaries.
  1993    * Because this function may cross document boundaries that have different
  1994    * app units per dev pixel ratios it needs to be used very carefully.
  1996    * NOTE: this actually returns the offset from aOther to |this|, but
  1997    * that offset is added to transform _coordinates_ from |this| to
  1998    * aOther.
  1999    */
  2000   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther) const;
  2002   /**
  2003    * Get the screen rect of the frame in pixels.
  2004    * @return the pixel rect of the frame in screen coordinates.
  2005    */
  2006   nsIntRect GetScreenRect() const;
  2007   virtual nsIntRect GetScreenRectExternal() const;
  2009   /**
  2010    * Get the screen rect of the frame in app units.
  2011    * @return the app unit rect of the frame in screen coordinates.
  2012    */
  2013   nsRect GetScreenRectInAppUnits() const;
  2014   virtual nsRect GetScreenRectInAppUnitsExternal() const;
  2016   /**
  2017    * Returns the offset from this frame to the closest geometric parent that
  2018    * has a view. Also returns the containing view or null in case of error
  2019    */
  2020   void GetOffsetFromView(nsPoint& aOffset, nsView** aView) const;
  2022   /**
  2023    * Returns the nearest widget containing this frame. If this frame has a
  2024    * view and the view has a widget, then this frame's widget is
  2025    * returned, otherwise this frame's geometric parent is checked
  2026    * recursively upwards.
  2027    * XXX virtual because gfx callers use it! (themes)
  2028    */
  2029   virtual nsIWidget* GetNearestWidget() const;
  2031   /**
  2032    * Same as GetNearestWidget() above but uses an outparam to return the offset
  2033    * of this frame to the returned widget expressed in appunits of |this| (the
  2034    * widget might be in a different document with a different zoom).
  2035    */
  2036   virtual nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
  2038   /**
  2039    * Get the "type" of the frame. May return nullptr.
  2041    * @see nsGkAtoms
  2042    */
  2043   virtual nsIAtom* GetType() const = 0;
  2045   /**
  2046    * Returns a transformation matrix that converts points in this frame's
  2047    * coordinate space to points in some ancestor frame's coordinate space.
  2048    * The frame decides which ancestor it will use as a reference point.
  2049    * If this frame has no ancestor, aOutAncestor will be set to null.
  2051    * @param aStopAtAncestor don't look further than aStopAtAncestor. If null,
  2052    *   all ancestors (including across documents) will be traversed.
  2053    * @param aOutAncestor [out] The ancestor frame the frame has chosen.  If
  2054    *   this frame has no ancestor, *aOutAncestor will be set to null. If
  2055    * this frame is not a root frame, then *aOutAncestor will be in the same
  2056    * document as this frame. If this frame IsTransformed(), then *aOutAncestor
  2057    * will be the parent frame (if not preserve-3d) or the nearest non-transformed
  2058    * ancestor (if preserve-3d).
  2059    * @return A gfxMatrix that converts points in this frame's coordinate space
  2060    *   into points in aOutAncestor's coordinate space.
  2061    */
  2062   gfx3DMatrix GetTransformMatrix(const nsIFrame* aStopAtAncestor,
  2063                                  nsIFrame **aOutAncestor);
  2065   /**
  2066    * Bit-flags to pass to IsFrameOfType()
  2067    */
  2068   enum {
  2069     eMathML =                           1 << 0,
  2070     eSVG =                              1 << 1,
  2071     eSVGForeignObject =                 1 << 2,
  2072     eSVGContainer =                     1 << 3,
  2073     eSVGGeometry =                      1 << 4,
  2074     eSVGPaintServer =                   1 << 5,
  2075     eBidiInlineContainer =              1 << 6,
  2076     // the frame is for a replaced element, such as an image
  2077     eReplaced =                         1 << 7,
  2078     // Frame that contains a block but looks like a replaced element
  2079     // from the outside
  2080     eReplacedContainsBlock =            1 << 8,
  2081     // A frame that participates in inline reflow, i.e., one that
  2082     // requires nsHTMLReflowState::mLineLayout.
  2083     eLineParticipant =                  1 << 9,
  2084     eXULBox =                           1 << 10,
  2085     eCanContainOverflowContainers =     1 << 11,
  2086     eBlockFrame =                       1 << 12,
  2087     eTablePart =                        1 << 13,
  2088     // If this bit is set, the frame doesn't allow ignorable whitespace as
  2089     // children. For example, the whitespace between <table>\n<tr>\n<td>
  2090     // will be excluded during the construction of children. 
  2091     eExcludesIgnorableWhitespace =      1 << 14,
  2092     eSupportsCSSTransforms =            1 << 15,
  2094     // These are to allow nsFrame::Init to assert that IsFrameOfType
  2095     // implementations all call the base class method.  They are only
  2096     // meaningful in DEBUG builds.
  2097     eDEBUGAllFrames =                   1 << 30,
  2098     eDEBUGNoFrames =                    1 << 31
  2099   };
  2101   /**
  2102    * API for doing a quick check if a frame is of a given
  2103    * type. Returns true if the frame matches ALL flags passed in.
  2105    * Implementations should always override with inline virtual
  2106    * functions that call the base class's IsFrameOfType method.
  2107    */
  2108   virtual bool IsFrameOfType(uint32_t aFlags) const
  2110 #ifdef DEBUG
  2111     return !(aFlags & ~(nsIFrame::eDEBUGAllFrames | nsIFrame::eSupportsCSSTransforms));
  2112 #else
  2113     return !(aFlags & ~nsIFrame::eSupportsCSSTransforms);
  2114 #endif
  2117   /**
  2118    * Returns true if the frame is a block wrapper.
  2119    */
  2120   bool IsBlockWrapper() const;
  2122   /**
  2123    * Get this frame's CSS containing block.
  2125    * The algorithm is defined in
  2126    * http://www.w3.org/TR/CSS2/visudet.html#containing-block-details.
  2128    * NOTE: This is guaranteed to return a non-null pointer when invoked on any
  2129    * frame other than the root frame.
  2130    */
  2131   nsIFrame* GetContainingBlock() const;
  2133   /**
  2134    * Is this frame a containing block for floating elements?
  2135    * Note that very few frames are, so default to false.
  2136    */
  2137   virtual bool IsFloatContainingBlock() const { return false; }
  2139   /**
  2140    * Is this a leaf frame?  Frames that want the frame constructor to be able
  2141    * to construct kids for them should return false, all others should return
  2142    * true.  Note that returning true here does not mean that the frame _can't_
  2143    * have kids.  It could still have kids created via
  2144    * nsIAnonymousContentCreator.  Returning true indicates that "normal"
  2145    * (non-anonymous, XBL-bound, CSS generated content, etc) children should not
  2146    * be constructed.
  2147    */
  2148   virtual bool IsLeaf() const;
  2150   /**
  2151    * Marks all display items created by this frame as needing a repaint,
  2152    * and calls SchedulePaint() if requested and one is not already pending.
  2154    * This includes all display items created by this frame, including
  2155    * container types.
  2157    * @param aDisplayItemKey If specified, only issues an invalidate
  2158    * if this frame painted a display item of that type during the 
  2159    * previous paint. SVG rendering observers are always notified.
  2160    */
  2161   virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0);
  2163   /**
  2164    * Same as InvalidateFrame(), but only mark a fixed rect as needing
  2165    * repainting.
  2167    * @param aRect The rect to invalidate, relative to the TopLeft of the
  2168    * frame's border box.
  2169    * @param aDisplayItemKey If specified, only issues an invalidate
  2170    * if this frame painted a display item of that type during the 
  2171    * previous paint. SVG rendering observers are always notified.
  2172    */
  2173   virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0);
  2175   /**
  2176    * Calls InvalidateFrame() on all frames descendant frames (including
  2177    * this one).
  2179    * This function doesn't walk through placeholder frames to invalidate
  2180    * the out-of-flow frames.
  2182    * @param aDisplayItemKey If specified, only issues an invalidate
  2183    * if this frame painted a display item of that type during the 
  2184    * previous paint. SVG rendering observers are always notified.
  2185    */
  2186   void InvalidateFrameSubtree(uint32_t aDisplayItemKey = 0);
  2188   /**
  2189    * Called when a frame is about to be removed and needs to be invalidated.
  2190    * Normally does nothing since DLBI handles removed frames.
  2191    */
  2192   virtual void InvalidateFrameForRemoval() {}
  2194   /**
  2195    * When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
  2196    * entire overflow area of this frame has been rendered in its
  2197    * layer(s).
  2198    */
  2199   static void* LayerIsPrerenderedDataKey() { 
  2200     return &sLayerIsPrerenderedDataKey;
  2202   static uint8_t sLayerIsPrerenderedDataKey;
  2204    /**
  2205    * Try to update this frame's transform without invalidating any
  2206    * content.  Return true iff successful.  If unsuccessful, the
  2207    * caller is responsible for scheduling an invalidating paint.
  2209    * If the result is true, aLayerResult will be filled in with the
  2210    * transform layer for the frame.
  2211    */
  2212   bool TryUpdateTransformOnly(Layer** aLayerResult);
  2214   /**
  2215    * Checks if a frame has had InvalidateFrame() called on it since the
  2216    * last paint.
  2218    * If true, then the invalid rect is returned in aRect, with an
  2219    * empty rect meaning all pixels drawn by this frame should be
  2220    * invalidated.
  2221    * If false, aRect is left unchanged.
  2222    */
  2223   bool IsInvalid(nsRect& aRect);
  2225   /**
  2226    * Check if any frame within the frame subtree (including this frame) 
  2227    * returns true for IsInvalid().
  2228    */
  2229   bool HasInvalidFrameInSubtree()
  2231     return HasAnyStateBits(NS_FRAME_NEEDS_PAINT | NS_FRAME_DESCENDANT_NEEDS_PAINT);
  2234   /**
  2235    * Removes the invalid state from the current frame and all
  2236    * descendant frames.
  2237    */
  2238   void ClearInvalidationStateBits();
  2240   /**
  2241    * Ensures that the refresh driver is running, and schedules a view 
  2242    * manager flush on the next tick.
  2244    * The view manager flush will update the layer tree, repaint any 
  2245    * invalid areas in the layer tree and schedule a layer tree
  2246    * composite operation to display the layer tree.
  2248    * In general it is not necessary for frames to call this when they change.
  2249    * For example, changes that result in a reflow will have this called for
  2250    * them by PresContext::DoReflow when the reflow begins. Style changes that 
  2251    * do not trigger a reflow should have this called for them by
  2252    * DoApplyRenderingChangeToTree.
  2254    * @param aType PAINT_COMPOSITE_ONLY : No changes have been made
  2255    * that require a layer tree update, so only schedule a layer
  2256    * tree composite.
  2257    * PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
  2258    * put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
  2259    */
  2260   enum PaintType {
  2261     PAINT_DEFAULT = 0,
  2262     PAINT_COMPOSITE_ONLY,
  2263     PAINT_DELAYED_COMPRESS
  2264   };
  2265   void SchedulePaint(PaintType aType = PAINT_DEFAULT);
  2267   /**
  2268    * Checks if the layer tree includes a dedicated layer for this 
  2269    * frame/display item key pair, and invalidates at least aDamageRect
  2270    * area within that layer.
  2272    * If no layer is found, calls InvalidateFrame() instead.
  2274    * @param aDamageRect Area of the layer to invalidate.
  2275    * @param aDisplayItemKey Display item type.
  2276    * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
  2277    * if the found layer is being composited by a remote
  2278    * compositor.
  2279    * @return Layer, if found, nullptr otherwise.
  2280    */
  2281   enum {
  2282     UPDATE_IS_ASYNC = 1 << 0
  2283   };
  2284   Layer* InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect = nullptr, uint32_t aFlags = 0);
  2286   /**
  2287    * Returns a rect that encompasses everything that might be painted by
  2288    * this frame.  This includes this frame, all its descendent frames, this
  2289    * frame's outline, and descentant frames' outline, but does not include
  2290    * areas clipped out by the CSS "overflow" and "clip" properties.
  2292    * HasOverflowRects() (below) will return true when this overflow
  2293    * rect has been explicitly set, even if it matches mRect.
  2294    * XXX Note: because of a space optimization using the formula above,
  2295    * during reflow this function does not give accurate data if
  2296    * FinishAndStoreOverflow has been called but mRect hasn't yet been
  2297    * updated yet.  FIXME: This actually isn't true, but it should be.
  2299    * The visual overflow rect should NEVER be used for things that
  2300    * affect layout.  The scrollable overflow rect is permitted to affect
  2301    * layout.
  2303    * @return the rect relative to this frame's origin, but after
  2304    * CSS transforms have been applied (i.e. not really this frame's coordinate
  2305    * system, and may not contain the frame's border-box, e.g. if there
  2306    * is a CSS transform scaling it down)
  2307    */
  2308   nsRect GetVisualOverflowRect() const {
  2309     return GetOverflowRect(eVisualOverflow);
  2312   /**
  2313    * Returns a rect that encompasses the area of this frame that the
  2314    * user should be able to scroll to reach.  This is similar to
  2315    * GetVisualOverflowRect, but does not include outline or shadows, and
  2316    * may in the future include more margins than visual overflow does.
  2317    * It does not include areas clipped out by the CSS "overflow" and
  2318    * "clip" properties.
  2320    * HasOverflowRects() (below) will return true when this overflow
  2321    * rect has been explicitly set, even if it matches mRect.
  2322    * XXX Note: because of a space optimization using the formula above,
  2323    * during reflow this function does not give accurate data if
  2324    * FinishAndStoreOverflow has been called but mRect hasn't yet been
  2325    * updated yet.
  2327    * @return the rect relative to this frame's origin, but after
  2328    * CSS transforms have been applied (i.e. not really this frame's coordinate
  2329    * system, and may not contain the frame's border-box, e.g. if there
  2330    * is a CSS transform scaling it down)
  2331    */
  2332   nsRect GetScrollableOverflowRect() const {
  2333     return GetOverflowRect(eScrollableOverflow);
  2336   nsRect GetOverflowRect(nsOverflowType aType) const;
  2338   nsOverflowAreas GetOverflowAreas() const;
  2340   /**
  2341    * Same as GetOverflowAreas, except in this frame's coordinate
  2342    * system (before transforms are applied).
  2344    * @return the overflow areas relative to this frame, before any CSS transforms have
  2345    * been applied, i.e. in this frame's coordinate system
  2346    */
  2347   nsOverflowAreas GetOverflowAreasRelativeToSelf() const;
  2349   /**
  2350    * Same as GetScrollableOverflowRect, except relative to the parent
  2351    * frame.
  2353    * @return the rect relative to the parent frame, in the parent frame's
  2354    * coordinate system
  2355    */
  2356   nsRect GetScrollableOverflowRectRelativeToParent() const;
  2358   /**
  2359    * Same as GetScrollableOverflowRect, except in this frame's coordinate
  2360    * system (before transforms are applied).
  2362    * @return the rect relative to this frame, before any CSS transforms have
  2363    * been applied, i.e. in this frame's coordinate system
  2364    */
  2365   nsRect GetScrollableOverflowRectRelativeToSelf() const;
  2367   /**
  2368    * Like GetVisualOverflowRect, except in this frame's
  2369    * coordinate system (before transforms are applied).
  2371    * @return the rect relative to this frame, before any CSS transforms have
  2372    * been applied, i.e. in this frame's coordinate system
  2373    */
  2374   nsRect GetVisualOverflowRectRelativeToSelf() const;
  2376   /**
  2377    * Returns this frame's visual overflow rect as it would be before taking
  2378    * account of SVG effects or transforms. The rect returned is relative to
  2379    * this frame.
  2380    */
  2381   nsRect GetPreEffectsVisualOverflowRect() const;
  2383   /**
  2384    * Store the overflow area in the frame's mOverflow.mVisualDeltas
  2385    * fields or as a frame property in the frame manager so that it can
  2386    * be retrieved later without reflowing the frame. Returns true if either of
  2387    * the overflow areas changed.
  2388    */
  2389   bool FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas,
  2390                               nsSize aNewSize, nsSize* aOldSize = nullptr);
  2392   bool FinishAndStoreOverflow(nsHTMLReflowMetrics* aMetrics) {
  2393     return FinishAndStoreOverflow(aMetrics->mOverflowAreas,
  2394                                   nsSize(aMetrics->Width(), aMetrics->Height()));
  2397   /**
  2398    * Returns whether the frame has an overflow rect that is different from
  2399    * its border-box.
  2400    */
  2401   bool HasOverflowAreas() const {
  2402     return mOverflow.mType != NS_FRAME_OVERFLOW_NONE;
  2405   /**
  2406    * Removes any stored overflow rects (visual and scrollable) from the frame.
  2407    * Returns true if the overflow changed.
  2408    */
  2409   bool ClearOverflowRects();
  2411   /**
  2412    * Determine whether borders should not be painted on certain sides of the
  2413    * frame.
  2415    * @note (See also bug 743402, comment 11) GetSkipSides() and its sister
  2416    *       method, ApplySkipSides() checks to see if this frame has a previous
  2417    *       or next continuation to determine if a side should be skipped.
  2418    *       Unfortunately, this only works after reflow has been completed. In
  2419    *       lieu of this, during reflow, an nsHTMLReflowState parameter can be
  2420    *       passed in, indicating that it should be used to determine if sides
  2421    *       should be skipped during reflow.
  2422    */
  2423 #define LOGICAL_SIDE_B_START 1
  2424 #define LOGICAL_SIDE_I_START 2
  2425 #define LOGICAL_SIDE_B_END   4
  2426 #define LOGICAL_SIDE_I_END   8
  2427 #define LOGICAL_SIDES_I_BOTH (LOGICAL_SIDE_I_START | LOGICAL_SIDE_I_END)
  2428 #define LOGICAL_SIDES_B_BOTH (LOGICAL_SIDE_B_START | LOGICAL_SIDE_B_END)
  2429 #define LOGICAL_SIDES_ALL (LOGICAL_SIDE_I_START | LOGICAL_SIDE_I_END | \
  2430                            LOGICAL_SIDE_B_START | LOGICAL_SIDE_B_END)
  2431   int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const;
  2432   virtual int
  2433   GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const {
  2434     return 0;
  2437   /**
  2438    * @returns true if this frame is selected.
  2439    */
  2440   bool IsSelected() const;
  2442   /**
  2443    *  called to discover where this frame, or a parent frame has user-select style
  2444    *  applied, which affects that way that it is selected.
  2446    *  @param aIsSelectable out param. Set to true if the frame can be selected
  2447    *                       (i.e. is not affected by user-select: none)
  2448    *  @param aSelectStyle  out param. Returns the type of selection style found
  2449    *                        (using values defined in nsStyleConsts.h).
  2450    */
  2451   virtual nsresult  IsSelectable(bool* aIsSelectable, uint8_t* aSelectStyle) const = 0;
  2453   /** 
  2454    *  Called to retrieve the SelectionController associated with the frame.
  2455    *  @param aSelCon will contain the selection controller associated with
  2456    *  the frame.
  2457    */
  2458   virtual nsresult  GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) = 0;
  2460   /**
  2461    *  Call to get nsFrameSelection for this frame.
  2462    */
  2463   already_AddRefed<nsFrameSelection> GetFrameSelection();
  2465   /**
  2466    * GetConstFrameSelection returns an object which methods are safe to use for
  2467    * example in nsIFrame code.
  2468    */
  2469   const nsFrameSelection* GetConstFrameSelection() const;
  2471   /**
  2472    *  called to find the previous/next character, word, or line  returns the actual 
  2473    *  nsIFrame and the frame offset.  THIS DOES NOT CHANGE SELECTION STATE
  2474    *  uses frame's begin selection state to start. if no selection on this frame will 
  2475    *  return NS_ERROR_FAILURE
  2476    *  @param aPOS is defined in nsFrameSelection
  2477    */
  2478   virtual nsresult PeekOffset(nsPeekOffsetStruct *aPos);
  2480   /**
  2481    *  called to find the previous/next selectable leaf frame.
  2482    *  @param aDirection [in] the direction to move in (eDirPrevious or eDirNext)
  2483    *  @param aVisual [in] whether bidi caret behavior is visual (true) or logical (false)
  2484    *  @param aJumpLines [in] whether to allow jumping across line boundaries
  2485    *  @param aScrollViewStop [in] whether to stop when reaching a scroll frame boundary
  2486    *  @param aOutFrame [out] the previous/next selectable leaf frame
  2487    *  @param aOutOffset [out] 0 indicates that we arrived at the beginning of the output frame;
  2488    *                          -1 indicates that we arrived at its end.
  2489    *  @param aOutJumpedLine [out] whether this frame and the returned frame are on different lines
  2490    */
  2491   nsresult GetFrameFromDirection(nsDirection aDirection, bool aVisual,
  2492                                  bool aJumpLines, bool aScrollViewStop, 
  2493                                  nsIFrame** aOutFrame, int32_t* aOutOffset, bool* aOutJumpedLine);
  2495   /**
  2496    *  called to see if the children of the frame are visible from indexstart to index end.
  2497    *  this does not change any state. returns true only if the indexes are valid and any of
  2498    *  the children are visible.  for textframes this index is the character index.
  2499    *  if aStart = aEnd result will be false
  2500    *  @param aStart start index of first child from 0-N (number of children)
  2501    *  @param aEnd   end index of last child from 0-N
  2502    *  @param aRecurse should this frame talk to siblings to get to the contents other children?
  2503    *  @param aFinished did this frame have the aEndIndex? or is there more work to do
  2504    *  @param _retval  return value true or false. false = range is not rendered.
  2505    */
  2506   virtual nsresult CheckVisibility(nsPresContext* aContext, int32_t aStartIndex, int32_t aEndIndex, bool aRecurse, bool *aFinished, bool *_retval)=0;
  2508   /**
  2509    * Called to tell a frame that one of its child frames is dirty (i.e.,
  2510    * has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
  2511    * set).  This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
  2512    * the frame, and may do other work.
  2513    */
  2514   virtual void ChildIsDirty(nsIFrame* aChild) = 0;
  2516   /**
  2517    * Called to retrieve this frame's accessible.
  2518    * If this frame implements Accessibility return a valid accessible
  2519    * If not return NS_ERROR_NOT_IMPLEMENTED.
  2520    * Note: Accessible must be refcountable. Do not implement directly on your frame
  2521    * Use a mediatior of some kind.
  2522    */
  2523 #ifdef ACCESSIBILITY
  2524   virtual mozilla::a11y::AccType AccessibleType() = 0;
  2525 #endif
  2527   /**
  2528    * Get the frame whose style context should be the parent of this
  2529    * frame's style context (i.e., provide the parent style context).
  2530    * This frame must either be an ancestor of this frame or a child.  If
  2531    * this returns a child frame, then the child frame must be sure to
  2532    * return a grandparent or higher!  Furthermore, if a child frame is
  2533    * returned it must have the same GetContent() as this frame.
  2535    * @return The frame whose style context should be the parent of this frame's
  2536    *         style context.  Null is permitted, and means that this frame's
  2537    *         style context should be the root of the style context tree.
  2538    */
  2539   virtual nsIFrame* GetParentStyleContextFrame() const = 0;
  2541   /**
  2542    * Determines whether a frame is visible for painting;
  2543    * taking into account whether it is painting a selection or printing.
  2544    */
  2545   bool IsVisibleForPainting(nsDisplayListBuilder* aBuilder);
  2546   /**
  2547    * Determines whether a frame is visible for painting or collapsed;
  2548    * taking into account whether it is painting a selection or printing,
  2549    */
  2550   bool IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder);
  2551   /**
  2552    * As above, but slower because we have to recompute some stuff that
  2553    * aBuilder already has.
  2554    */
  2555   bool IsVisibleForPainting();
  2556   /**
  2557    * Check whether this frame is visible in the current selection. Returns
  2558    * true if there is no current selection.
  2559    */
  2560   bool IsVisibleInSelection(nsDisplayListBuilder* aBuilder);
  2562   /**
  2563    * Overridable function to determine whether this frame should be considered
  2564    * "in" the given non-null aSelection for visibility purposes.
  2565    */  
  2566   virtual bool IsVisibleInSelection(nsISelection* aSelection);
  2568   /**
  2569    * Determines whether this frame is a pseudo stacking context, looking
  2570    * only as style --- i.e., assuming that it's in-flow and not a replaced
  2571    * element and not an SVG element.
  2572    * XXX maybe check IsTransformed()?
  2573    */
  2574   bool IsPseudoStackingContextFromStyle();
  2576   virtual bool HonorPrintBackgroundSettings() { return true; }
  2578   /**
  2579    * Determine whether the frame is logically empty, which is roughly
  2580    * whether the layout would be the same whether or not the frame is
  2581    * present.  Placeholder frames should return true.  Block frames
  2582    * should be considered empty whenever margins collapse through them,
  2583    * even though those margins are relevant.  Text frames containing
  2584    * only whitespace that does not contribute to the height of the line
  2585    * should return true.
  2586    */
  2587   virtual bool IsEmpty() = 0;
  2588   /**
  2589    * Return the same as IsEmpty(). This may only be called after the frame
  2590    * has been reflowed and before any further style or content changes.
  2591    */
  2592   virtual bool CachedIsEmpty();
  2593   /**
  2594    * Determine whether the frame is logically empty, assuming that all
  2595    * its children are empty.
  2596    */
  2597   virtual bool IsSelfEmpty() = 0;
  2599   /**
  2600    * IsGeneratedContentFrame returns whether a frame corresponds to
  2601    * generated content
  2603    * @return whether the frame correspods to generated content
  2604    */
  2605   bool IsGeneratedContentFrame() {
  2606     return (mState & NS_FRAME_GENERATED_CONTENT) != 0;
  2609   /**
  2610    * IsPseudoFrame returns whether a frame is a pseudo frame (eg an
  2611    * anonymous table-row frame created for a CSS table-cell without an
  2612    * enclosing table-row.
  2614    * @param aParentContent the content node corresponding to the parent frame
  2615    * @return whether the frame is a pseudo frame
  2616    */   
  2617   bool IsPseudoFrame(nsIContent* aParentContent) {
  2618     return mContent == aParentContent;
  2621   FrameProperties Properties() const {
  2622     return FrameProperties(PresContext()->PropertyTable(), this);
  2625   NS_DECLARE_FRAME_PROPERTY(BaseLevelProperty, nullptr)
  2626   NS_DECLARE_FRAME_PROPERTY(EmbeddingLevelProperty, nullptr)
  2627   NS_DECLARE_FRAME_PROPERTY(ParagraphDepthProperty, nullptr)
  2629 #define NS_GET_BASE_LEVEL(frame) \
  2630 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::BaseLevelProperty()))
  2632 #define NS_GET_EMBEDDING_LEVEL(frame) \
  2633 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()))
  2635 #define NS_GET_PARAGRAPH_DEPTH(frame) \
  2636 NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty()))
  2638   /**
  2639    * Return true if and only if this frame obeys visibility:hidden.
  2640    * if it does not, then nsContainerFrame will hide its view even though
  2641    * this means children can't be made visible again.
  2642    */
  2643   virtual bool SupportsVisibilityHidden() { return true; }
  2645   /**
  2646    * Returns true if the frame has a valid clip rect set via the 'clip'
  2647    * property, and the 'clip' property applies to this frame. The 'clip'
  2648    * property applies to HTML frames if they are absolutely positioned. The
  2649    * 'clip' property applies to SVG frames regardless of the value of the
  2650    * 'position' property.
  2652    * If this method returns true, then we also set aRect to the computed clip
  2653    * rect, with coordinates relative to this frame's origin. aRect must not be
  2654    * null!
  2655    */
  2656   bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
  2657                            const nsSize& aSize) const;
  2659   /**
  2660    * Check if this frame is focusable and in the current tab order.
  2661    * Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
  2662    * For example, only the selected radio button in a group is in the 
  2663    * tab order, unless the radio group has no selection in which case
  2664    * all of the visible, non-disabled radio buttons in the group are 
  2665    * in the tab order. On the other hand, all of the visible, non-disabled 
  2666    * radio buttons are always focusable via clicking or script.
  2667    * Also, depending on the pref accessibility.tabfocus some widgets may be 
  2668    * focusable but removed from the tab order. This is the default on
  2669    * Mac OS X, where fewer items are focusable.
  2670    * @param  [in, optional] aTabIndex the computed tab index
  2671    *         < 0 if not tabbable
  2672    *         == 0 if in normal tab order
  2673    *         > 0 can be tabbed to in the order specified by this value
  2674    * @param  [in, optional] aWithMouse, is this focus query for mouse clicking
  2675    * @return whether the frame is focusable via mouse, kbd or script.
  2676    */
  2677   virtual bool IsFocusable(int32_t *aTabIndex = nullptr, bool aWithMouse = false);
  2679   // BOX LAYOUT METHODS
  2680   // These methods have been migrated from nsIBox and are in the process of
  2681   // being refactored. DO NOT USE OUTSIDE OF XUL.
  2682   bool IsBoxFrame() const
  2684     return IsFrameOfType(nsIFrame::eXULBox);
  2686   bool IsBoxWrapped() const
  2687   { return (!IsBoxFrame() && mParent && mParent->IsBoxFrame()); }
  2689   enum Halignment {
  2690     hAlign_Left,
  2691     hAlign_Right,
  2692     hAlign_Center
  2693   };
  2695   enum Valignment {
  2696     vAlign_Top,
  2697     vAlign_Middle,
  2698     vAlign_BaseLine,
  2699     vAlign_Bottom
  2700   };
  2702   /**
  2703    * This calculates the minimum size required for a box based on its state
  2704    * @param[in] aBoxLayoutState The desired state to calculate for
  2705    * @return The minimum size
  2706    */
  2707   virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) = 0;
  2709   /**
  2710    * This calculates the preferred size of a box based on its state
  2711    * @param[in] aBoxLayoutState The desired state to calculate for
  2712    * @return The preferred size
  2713    */
  2714   virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) = 0;
  2716   /**
  2717    * This calculates the maximum size for a box based on its state
  2718    * @param[in] aBoxLayoutState The desired state to calculate for
  2719    * @return The maximum size
  2720    */    
  2721   virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) = 0;
  2723   /**
  2724    * This returns the minimum size for the scroll area if this frame is
  2725    * being scrolled. Usually it's (0,0).
  2726    */
  2727   virtual nsSize GetMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) = 0;
  2729   // Implemented in nsBox, used in nsBoxFrame
  2730   uint32_t GetOrdinal();
  2732   virtual nscoord GetFlex(nsBoxLayoutState& aBoxLayoutState) = 0;
  2733   virtual nscoord GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) = 0;
  2734   virtual bool IsCollapsed() = 0;
  2735   // This does not alter the overflow area. If the caller is changing
  2736   // the box size, the caller is responsible for updating the overflow
  2737   // area. It's enough to just call Layout or SyncLayout on the
  2738   // box. You can pass true to aRemoveOverflowArea as a
  2739   // convenience.
  2740   virtual void SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
  2741                          bool aRemoveOverflowAreas = false) = 0;
  2742   NS_HIDDEN_(nsresult) Layout(nsBoxLayoutState& aBoxLayoutState);
  2743   nsIFrame* GetChildBox() const
  2745     // box layout ends at box-wrapped frames, so don't allow these frames
  2746     // to report child boxes.
  2747     return IsBoxFrame() ? GetFirstPrincipalChild() : nullptr;
  2749   nsIFrame* GetNextBox() const
  2751     return (mParent && mParent->IsBoxFrame()) ? mNextSibling : nullptr;
  2753   nsIFrame* GetParentBox() const
  2755     return (mParent && mParent->IsBoxFrame()) ? mParent : nullptr;
  2757   // Box methods.  Note that these do NOT just get the CSS border, padding,
  2758   // etc.  They also talk to nsITheme.
  2759   virtual nsresult GetBorderAndPadding(nsMargin& aBorderAndPadding);
  2760   virtual nsresult GetBorder(nsMargin& aBorder)=0;
  2761   virtual nsresult GetPadding(nsMargin& aBorderAndPadding)=0;
  2762   virtual nsresult GetMargin(nsMargin& aMargin)=0;
  2763   virtual void SetLayoutManager(nsBoxLayout* aLayout) { }
  2764   virtual nsBoxLayout* GetLayoutManager() { return nullptr; }
  2765   NS_HIDDEN_(nsresult) GetClientRect(nsRect& aContentRect);
  2767   // For nsSprocketLayout
  2768   virtual Valignment GetVAlign() const = 0;
  2769   virtual Halignment GetHAlign() const = 0;
  2771   bool IsHorizontal() const { return (mState & NS_STATE_IS_HORIZONTAL) != 0; }
  2772   bool IsNormalDirection() const { return (mState & NS_STATE_IS_DIRECTION_NORMAL) != 0; }
  2774   NS_HIDDEN_(nsresult) Redraw(nsBoxLayoutState& aState);
  2775   virtual nsresult RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIFrame* aChild)=0;
  2776   // XXX take this out after we've branched
  2777   virtual bool GetMouseThrough() const { return false; }
  2779 #ifdef DEBUG_LAYOUT
  2780   virtual nsresult SetDebug(nsBoxLayoutState& aState, bool aDebug)=0;
  2781   virtual nsresult GetDebug(bool& aDebug)=0;
  2783   virtual nsresult DumpBox(FILE* out)=0;
  2784 #endif
  2786   /**
  2787    * @return true if this text frame ends with a newline character.  It
  2788    * should return false if this is not a text frame.
  2789    */
  2790   virtual bool HasSignificantTerminalNewline() const;
  2792   static bool AddCSSPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
  2793   static bool AddCSSMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
  2794                             nsSize& aSize, bool& aWidth, bool& aHeightSet);
  2795   static bool AddCSSMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidth, bool& aHeightSet);
  2796   static bool AddCSSFlex(nsBoxLayoutState& aState, nsIFrame* aBox, nscoord& aFlex);
  2798   // END OF BOX LAYOUT METHODS
  2799   // The above methods have been migrated from nsIBox and are in the process of
  2800   // being refactored. DO NOT USE OUTSIDE OF XUL.
  2802   struct CaretPosition {
  2803     CaretPosition();
  2804     ~CaretPosition();
  2806     nsCOMPtr<nsIContent> mResultContent;
  2807     int32_t              mContentOffset;
  2808   };
  2810   /**
  2811    * gets the first or last possible caret position within the frame
  2813    * @param  [in] aStart
  2814    *         true  for getting the first possible caret position
  2815    *         false for getting the last possible caret position
  2816    * @return The caret position in a CaretPosition.
  2817    *         the returned value is a 'best effort' in case errors
  2818    *         are encountered rummaging through the frame.
  2819    */
  2820   CaretPosition GetExtremeCaretPosition(bool aStart);
  2822   /**
  2823    * Get a line iterator for this frame, if supported.
  2825    * @return nullptr if no line iterator is supported.
  2826    * @note dispose the line iterator using nsILineIterator::DisposeLineIterator
  2827    */
  2828   virtual nsILineIterator* GetLineIterator() = 0;
  2830   /**
  2831    * If this frame is a next-in-flow, and its prev-in-flow has something on its
  2832    * overflow list, pull those frames into the child list of this one.
  2833    */
  2834   virtual void PullOverflowsFromPrevInFlow() {}
  2836   /**
  2837    * Clear the list of child PresShells generated during the last paint
  2838    * so that we can begin generating a new one.
  2839    */  
  2840   void ClearPresShellsFromLastPaint() { 
  2841     PaintedPresShellList()->Clear(); 
  2844   /**
  2845    * Flag a child PresShell as painted so that it will get its paint count
  2846    * incremented during empty transactions.
  2847    */  
  2848   void AddPaintedPresShell(nsIPresShell* shell) { 
  2849     nsWeakPtr weakShell = do_GetWeakReference(shell);
  2850     PaintedPresShellList()->AppendElement(weakShell);
  2853   /**
  2854    * Increment the paint count of all child PresShells that were painted during
  2855    * the last repaint.
  2856    */  
  2857   void UpdatePaintCountForPaintedPresShells() {
  2858     nsTArray<nsWeakPtr> * list = PaintedPresShellList();
  2859     for (int i = 0, l = list->Length(); i < l; i++) {
  2860       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i));
  2862       if (shell) {
  2863         shell->IncrementPaintCount();
  2868   /**
  2869    * Accessors for the absolute containing block.
  2870    */
  2871   bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
  2872   bool HasAbsolutelyPositionedChildren() const;
  2873   nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
  2874   void MarkAsAbsoluteContainingBlock();
  2875   void MarkAsNotAbsoluteContainingBlock();
  2876   // Child frame types override this function to select their own child list name
  2877   virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
  2879   // Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
  2880   // clears this bit if so.
  2881   bool CheckAndClearPaintedState();
  2883   // CSS visibility just doesn't cut it because it doesn't inherit through
  2884   // documents. Also if this frame is in a hidden card of a deck then it isn't
  2885   // visible either and that isn't expressed using CSS visibility. Also if it
  2886   // is in a hidden view (there are a few cases left and they are hopefully
  2887   // going away soon).
  2888   // If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
  2889   // ignore the chrome/content boundary, otherwise we stop looking when we
  2890   // reach it.
  2891   enum {
  2892     VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY = 0x01
  2893   };
  2894   bool IsVisibleConsideringAncestors(uint32_t aFlags = 0) const;
  2896   struct FrameWithDistance
  2898     nsIFrame* mFrame;
  2899     nscoord mXDistance;
  2900     nscoord mYDistance;
  2901   };
  2903   /**
  2904    * Finds a frame that is closer to a specified point than a current
  2905    * distance.  Distance is measured as for text selection -- a closer x
  2906    * distance beats a closer y distance.
  2908    * Normally, this function will only check the distance between this
  2909    * frame's rectangle and the specified point.  SVGTextFrame overrides
  2910    * this so that it can manage all of its descendant frames and take
  2911    * into account any SVG text layout.
  2913    * If aPoint is closer to this frame's rectangle than aCurrentBestFrame
  2914    * indicates, then aCurrentBestFrame is updated with the distance between
  2915    * aPoint and this frame's rectangle, and with a pointer to this frame.
  2916    * If aPoint is not closer, then aCurrentBestFrame is left unchanged.
  2918    * @param aPoint The point to check for its distance to this frame.
  2919    * @param aCurrentBestFrame Pointer to a struct that will be updated with
  2920    *   a pointer to this frame and its distance to aPoint, if this frame
  2921    *   is indeed closer than the current distance in aCurrentBestFrame.
  2922    */
  2923   virtual void FindCloserFrameForSelection(nsPoint aPoint,
  2924                                            FrameWithDistance* aCurrentBestFrame);
  2926   /**
  2927    * Is this a flex item? (i.e. a non-abs-pos child of a flex container)
  2928    */
  2929   inline bool IsFlexItem() const;
  2931   inline bool IsBlockInside() const;
  2932   inline bool IsBlockOutside() const;
  2933   inline bool IsInlineOutside() const;
  2934   inline uint8_t GetDisplay() const;
  2935   inline bool IsFloating() const;
  2936   inline bool IsPositioned() const;
  2937   inline bool IsRelativelyPositioned() const;
  2938   inline bool IsAbsolutelyPositioned() const;
  2940   /**
  2941    * Returns the vertical-align value to be used for layout, if it is one
  2942    * of the enumerated values.  If this is an SVG text frame, it returns a value
  2943    * that corresponds to the value of dominant-baseline.  If the
  2944    * vertical-align property has length or percentage value, this returns
  2945    * eInvalidVerticalAlign.
  2946    */
  2947   uint8_t VerticalAlignEnum() const;
  2948   enum { eInvalidVerticalAlign = 0xFF };
  2950   bool IsSVGText() const { return mState & NS_FRAME_IS_SVG_TEXT; }
  2952   void CreateOwnLayerIfNeeded(nsDisplayListBuilder* aBuilder, nsDisplayList* aList);
  2954   /**
  2955    * Adds the NS_FRAME_IN_POPUP state bit to aFrame, and
  2956    * all descendant frames (including cross-doc ones).
  2957    */
  2958   static void AddInPopupStateBitToDescendants(nsIFrame* aFrame);
  2959   /**
  2960    * Removes the NS_FRAME_IN_POPUP state bit from aFrame and
  2961    * all descendant frames (including cross-doc ones), unless
  2962    * the frame is a popup itself.
  2963    */
  2964   static void RemoveInPopupStateBitFromDescendants(nsIFrame* aFrame);
  2966   /**
  2967    * Sorts the given nsFrameList, so that for every two adjacent frames in the
  2968    * list, the former is less than or equal to the latter, according to the
  2969    * templated IsLessThanOrEqual method.
  2971    * Note: this method uses a stable merge-sort algorithm.
  2972    */
  2973   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  2974   static void SortFrameList(nsFrameList& aFrameList);
  2976   /**
  2977    * Returns true if the given frame list is already sorted, according to the
  2978    * templated IsLessThanOrEqual function.
  2979    */
  2980   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  2981   static bool IsFrameListSorted(nsFrameList& aFrameList);
  2983   /**
  2984    * Return true if aFrame is in an {ib} split and is NOT one of the
  2985    * continuations of the first inline in it.
  2986    */
  2987   bool FrameIsNonFirstInIBSplit() const {
  2988     return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
  2989       FirstContinuation()->Properties().Get(nsIFrame::IBSplitPrevSibling());
  2992   /**
  2993    * Return true if aFrame is in an {ib} split and is NOT one of the
  2994    * continuations of the last inline in it.
  2995    */
  2996   bool FrameIsNonLastInIBSplit() const {
  2997     return (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
  2998       FirstContinuation()->Properties().Get(nsIFrame::IBSplitSibling());
  3001   /**
  3002    * Return whether this is a frame whose width is used when computing
  3003    * the font size inflation of its descendants.
  3004    */
  3005   bool IsContainerForFontSizeInflation() const {
  3006     return GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER;
  3009   /**
  3010    * Returns the content node within the anonymous content that this frame
  3011    * generated and which corresponds to the specified pseudo-element type,
  3012    * or nullptr if there is no such anonymous content.
  3013    */
  3014   virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType);
  3016 protected:
  3017   // Members
  3018   nsRect           mRect;
  3019   nsIContent*      mContent;
  3020   nsStyleContext*  mStyleContext;
  3021   nsIFrame*        mParent;
  3022 private:
  3023   nsIFrame*        mNextSibling;  // doubly-linked list of frames
  3024   nsIFrame*        mPrevSibling;  // Do not touch outside SetNextSibling!
  3026   void MarkAbsoluteFramesForDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect);
  3028   static void DestroyPaintedPresShellList(void* propertyValue) {
  3029     nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(propertyValue);
  3030     list->Clear();
  3031     delete list;
  3034   // Stores weak references to all the PresShells that were painted during
  3035   // the last paint event so that we can increment their paint count during
  3036   // empty transactions
  3037   NS_DECLARE_FRAME_PROPERTY(PaintedPresShellsProperty, DestroyPaintedPresShellList)
  3039   nsTArray<nsWeakPtr>* PaintedPresShellList() {
  3040     nsTArray<nsWeakPtr>* list = static_cast<nsTArray<nsWeakPtr>*>(
  3041       Properties().Get(PaintedPresShellsProperty())
  3042     );
  3044     if (!list) {
  3045       list = new nsTArray<nsWeakPtr>();
  3046       Properties().Set(PaintedPresShellsProperty(), list);
  3049     return list;
  3052 protected:
  3053   nsFrameState     mState;
  3055   // When there is an overflow area only slightly larger than mRect,
  3056   // we store a set of four 1-byte deltas from the edges of mRect
  3057   // rather than allocating a whole separate rectangle property.
  3058   // Note that these are unsigned values, all measured "outwards"
  3059   // from the edges of mRect, so /mLeft/ and /mTop/ are reversed from
  3060   // our normal coordinate system.
  3061   // If mOverflow.mType == NS_FRAME_OVERFLOW_LARGE, then the
  3062   // delta values are not meaningful and the overflow area is stored
  3063   // as a separate rect property.
  3064   struct VisualDeltas {
  3065     uint8_t mLeft;
  3066     uint8_t mTop;
  3067     uint8_t mRight;
  3068     uint8_t mBottom;
  3069     bool operator==(const VisualDeltas& aOther) const
  3071       return mLeft == aOther.mLeft && mTop == aOther.mTop &&
  3072              mRight == aOther.mRight && mBottom == aOther.mBottom;
  3074     bool operator!=(const VisualDeltas& aOther) const
  3076       return !(*this == aOther);
  3078   };
  3079   union {
  3080     uint32_t     mType;
  3081     VisualDeltas mVisualDeltas;
  3082   } mOverflow;
  3084   // Helpers
  3085   /**
  3086    * Can we stop inside this frame when we're skipping non-rendered whitespace?
  3087    * @param  aForward [in] Are we moving forward (or backward) in content order.
  3088    * @param  aOffset [in/out] At what offset into the frame to start looking.
  3089    *         on output - what offset was reached (whether or not we found a place to stop).
  3090    * @return STOP: An appropriate offset was found within this frame,
  3091    *         and is given by aOffset.
  3092    *         CONTINUE: Not found within this frame, need to try the next frame.
  3093    *         see enum FrameSearchResult for more details.
  3094    */
  3095   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) = 0;
  3097   /**
  3098    * Search the frame for the next character
  3099    * @param  aForward [in] Are we moving forward (or backward) in content order.
  3100    * @param  aOffset [in/out] At what offset into the frame to start looking.
  3101    *         on output - what offset was reached (whether or not we found a place to stop).
  3102    * @param  aRespectClusters [in] Whether to restrict result to valid cursor locations
  3103    *         (between grapheme clusters) - default TRUE maintains "normal" behavior,
  3104    *         FALSE is used for selection by "code unit" (instead of "character")
  3105    * @return STOP: An appropriate offset was found within this frame,
  3106    *         and is given by aOffset.
  3107    *         CONTINUE: Not found within this frame, need to try the next frame.
  3108    *         see enum FrameSearchResult for more details.
  3109    */
  3110   virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
  3111                                      bool aRespectClusters = true) = 0;
  3113   /**
  3114    * Search the frame for the next word boundary
  3115    * @param  aForward [in] Are we moving forward (or backward) in content order.
  3116    * @param  aWordSelectEatSpace [in] true: look for non-whitespace following
  3117    *         whitespace (in the direction of movement).
  3118    *         false: look for whitespace following non-whitespace (in the
  3119    *         direction  of movement).
  3120    * @param  aIsKeyboardSelect [in] Was the action initiated by a keyboard operation?
  3121    *         If true, punctuation immediately following a word is considered part
  3122    *         of that word. Otherwise, a sequence of punctuation is always considered
  3123    *         as a word on its own.
  3124    * @param  aOffset [in/out] At what offset into the frame to start looking.
  3125    *         on output - what offset was reached (whether or not we found a place to stop).
  3126    * @param  aState [in/out] the state that is carried from frame to frame
  3127    * @return true: An appropriate offset was found within this frame,
  3128    *         and is given by aOffset.
  3129    *         false: Not found within this frame, need to try the next frame.
  3130    */
  3131   struct PeekWordState {
  3132     // true when we're still at the start of the search, i.e., we can't return
  3133     // this point as a valid offset!
  3134     bool mAtStart;
  3135     // true when we've encountered at least one character of the pre-boundary type
  3136     // (whitespace if aWordSelectEatSpace is true, non-whitespace otherwise)
  3137     bool mSawBeforeType;
  3138     // true when the last character encountered was punctuation
  3139     bool mLastCharWasPunctuation;
  3140     // true when the last character encountered was whitespace
  3141     bool mLastCharWasWhitespace;
  3142     // true when we've seen non-punctuation since the last whitespace
  3143     bool mSeenNonPunctuationSinceWhitespace;
  3144     // text that's *before* the current frame when aForward is true, *after*
  3145     // the current frame when aForward is false. Only includes the text
  3146     // on the current line.
  3147     nsAutoString mContext;
  3149     PeekWordState() : mAtStart(true), mSawBeforeType(false),
  3150         mLastCharWasPunctuation(false), mLastCharWasWhitespace(false),
  3151         mSeenNonPunctuationSinceWhitespace(false) {}
  3152     void SetSawBeforeType() { mSawBeforeType = true; }
  3153     void Update(bool aAfterPunctuation, bool aAfterWhitespace) {
  3154       mLastCharWasPunctuation = aAfterPunctuation;
  3155       mLastCharWasWhitespace = aAfterWhitespace;
  3156       if (aAfterWhitespace) {
  3157         mSeenNonPunctuationSinceWhitespace = false;
  3158       } else if (!aAfterPunctuation) {
  3159         mSeenNonPunctuationSinceWhitespace = true;
  3161       mAtStart = false;
  3163   };
  3164   virtual FrameSearchResult PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect,
  3165                                 int32_t* aOffset, PeekWordState* aState) = 0;
  3167   /**
  3168    * Search for the first paragraph boundary before or after the given position
  3169    * @param  aPos See description in nsFrameSelection.h. The following fields are
  3170    *              used by this method: 
  3171    *              Input: mDirection
  3172    *              Output: mResultContent, mContentOffset
  3173    */
  3174   nsresult PeekOffsetParagraph(nsPeekOffsetStruct *aPos);
  3176 private:
  3177   nsOverflowAreas* GetOverflowAreasProperty();
  3178   nsRect GetVisualOverflowFromDeltas() const {
  3179     NS_ABORT_IF_FALSE(mOverflow.mType != NS_FRAME_OVERFLOW_LARGE,
  3180                       "should not be called when overflow is in a property");
  3181     // Calculate the rect using deltas from the frame's border rect.
  3182     // Note that the mOverflow.mDeltas fields are unsigned, but we will often
  3183     // need to return negative values for the left and top, so take care
  3184     // to cast away the unsigned-ness.
  3185     return nsRect(-(int32_t)mOverflow.mVisualDeltas.mLeft,
  3186                   -(int32_t)mOverflow.mVisualDeltas.mTop,
  3187                   mRect.width + mOverflow.mVisualDeltas.mRight +
  3188                                 mOverflow.mVisualDeltas.mLeft,
  3189                   mRect.height + mOverflow.mVisualDeltas.mBottom +
  3190                                  mOverflow.mVisualDeltas.mTop);
  3192   /**
  3193    * Returns true if any overflow changed.
  3194    */
  3195   bool SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
  3196   nsPoint GetOffsetToCrossDoc(const nsIFrame* aOther, const int32_t aAPD) const;
  3198   // Helper-functions for SortFrameList():
  3199   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  3200   static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
  3202   template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  3203   static nsIFrame* MergeSort(nsIFrame *aSource);
  3205   bool HasOpacityInternal(float aThreshold) const;
  3207 #ifdef DEBUG_FRAME_DUMP
  3208 public:
  3209   static void IndentBy(FILE* out, int32_t aIndent) {
  3210     while (--aIndent >= 0) fputs("  ", out);
  3212   void ListTag(FILE* out) const {
  3213     ListTag(out, this);
  3215   static void ListTag(FILE* out, const nsIFrame* aFrame) {
  3216     nsAutoCString t;
  3217     ListTag(t, aFrame);
  3218     fputs(t.get(), out);
  3220   void ListTag(nsACString& aTo) const;
  3221   static void ListTag(nsACString& aTo, const nsIFrame* aFrame);
  3222   void ListGeneric(nsACString& aTo, const char* aPrefix = "", uint32_t aFlags = 0) const;
  3223   enum {
  3224     TRAVERSE_SUBDOCUMENT_FRAMES = 0x01
  3225   };
  3226   virtual void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
  3227   /**
  3228    * lists the frames beginning from the root frame
  3229    * - calls root frame's List(...)
  3230    */
  3231   static void RootFrameList(nsPresContext* aPresContext,
  3232                             FILE* out = stderr, const char* aPrefix = "");
  3233   virtual void DumpFrameTree();
  3234   void DumpFrameTreeLimited();
  3236   virtual nsresult  GetFrameName(nsAString& aResult) const = 0;
  3237 #endif
  3239 #ifdef DEBUG
  3240 public:
  3241   virtual nsFrameState  GetDebugStateBits() const = 0;
  3242   virtual nsresult  DumpRegressionData(nsPresContext* aPresContext,
  3243                                        FILE* out, int32_t aIndent) = 0;
  3244 #endif
  3245 };
  3247 //----------------------------------------------------------------------
  3249 /**
  3250  * nsWeakFrame can be used to keep a reference to a nsIFrame in a safe way.
  3251  * Whenever an nsIFrame object is deleted, the nsWeakFrames pointing
  3252  * to it will be cleared.
  3254  * Create nsWeakFrame object when it is sure that nsIFrame object
  3255  * is alive and after some operations which may destroy the nsIFrame
  3256  * (for example any DOM modifications) use IsAlive() or GetFrame() methods to
  3257  * check whether it is safe to continue to use the nsIFrame object.
  3259  * @note The usage of this class should be kept to a minimum.
  3260  */
  3262 class nsWeakFrame {
  3263 public:
  3264   nsWeakFrame() : mPrev(nullptr), mFrame(nullptr) { }
  3266   nsWeakFrame(const nsWeakFrame& aOther) : mPrev(nullptr), mFrame(nullptr)
  3268     Init(aOther.GetFrame());
  3271   nsWeakFrame(nsIFrame* aFrame) : mPrev(nullptr), mFrame(nullptr)
  3273     Init(aFrame);
  3276   nsWeakFrame& operator=(nsWeakFrame& aOther) {
  3277     Init(aOther.GetFrame());
  3278     return *this;
  3281   nsWeakFrame& operator=(nsIFrame* aFrame) {
  3282     Init(aFrame);
  3283     return *this;
  3286   nsIFrame* operator->()
  3288     return mFrame;
  3291   operator nsIFrame*()
  3293     return mFrame;
  3296   void Clear(nsIPresShell* aShell) {
  3297     if (aShell) {
  3298       aShell->RemoveWeakFrame(this);
  3300     mFrame = nullptr;
  3301     mPrev = nullptr;
  3304   bool IsAlive() { return !!mFrame; }
  3306   nsIFrame* GetFrame() const { return mFrame; }
  3308   nsWeakFrame* GetPreviousWeakFrame() { return mPrev; }
  3310   void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; }
  3312   ~nsWeakFrame()
  3314     Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
  3316 private:
  3317   void Init(nsIFrame* aFrame);
  3319   nsWeakFrame*  mPrev;
  3320   nsIFrame*     mFrame;
  3321 };
  3323 inline bool
  3324 nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame)
  3326   MOZ_ASSERT(!aFrame->GetPrevSibling() || !aFrame->GetNextSibling(),
  3327              "Forgot to call StartRemoveFrame?");
  3328   if (aFrame == mLastChild) {
  3329     MOZ_ASSERT(!aFrame->GetNextSibling(), "broken frame list");
  3330     nsIFrame* prevSibling = aFrame->GetPrevSibling();
  3331     if (!prevSibling) {
  3332       MOZ_ASSERT(aFrame == mFirstChild, "broken frame list");
  3333       mFirstChild = mLastChild = nullptr;
  3334       return true;
  3336     MOZ_ASSERT(prevSibling->GetNextSibling() == aFrame, "Broken frame linkage");
  3337     prevSibling->SetNextSibling(nullptr);
  3338     mLastChild = prevSibling;
  3339     return true;
  3341   if (aFrame == mFirstChild) {
  3342     MOZ_ASSERT(!aFrame->GetPrevSibling(), "broken frame list");
  3343     mFirstChild = aFrame->GetNextSibling();
  3344     aFrame->SetNextSibling(nullptr);
  3345     MOZ_ASSERT(mFirstChild, "broken frame list");
  3346     return true;
  3348   return false;
  3351 inline bool
  3352 nsFrameList::StartRemoveFrame(nsIFrame* aFrame)
  3354   if (aFrame->GetPrevSibling() && aFrame->GetNextSibling()) {
  3355     UnhookFrameFromSiblings(aFrame);
  3356     return true;
  3358   return ContinueRemoveFrame(aFrame);
  3361 inline void
  3362 nsFrameList::Enumerator::Next()
  3364   NS_ASSERTION(!AtEnd(), "Should have checked AtEnd()!");
  3365   mFrame = mFrame->GetNextSibling();
  3368 inline
  3369 nsFrameList::FrameLinkEnumerator::
  3370 FrameLinkEnumerator(const nsFrameList& aList, nsIFrame* aPrevFrame)
  3371   : Enumerator(aList)
  3373   mPrev = aPrevFrame;
  3374   mFrame = aPrevFrame ? aPrevFrame->GetNextSibling() : aList.FirstChild();
  3377 inline void
  3378 nsFrameList::FrameLinkEnumerator::Next()
  3380   mPrev = mFrame;
  3381   Enumerator::Next();
  3384 // Helper-functions for nsIFrame::SortFrameList()
  3385 // ---------------------------------------------------
  3387 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  3388 /* static */ nsIFrame*
  3389 nsIFrame::SortedMerge(nsIFrame *aLeft, nsIFrame *aRight)
  3391   NS_PRECONDITION(aLeft && aRight, "SortedMerge must have non-empty lists");
  3393   nsIFrame *result;
  3394   // Unroll first iteration to avoid null-check 'result' inside the loop.
  3395   if (IsLessThanOrEqual(aLeft, aRight)) {
  3396     result = aLeft;
  3397     aLeft = aLeft->GetNextSibling();
  3398     if (!aLeft) {
  3399       result->SetNextSibling(aRight);
  3400       return result;
  3403   else {
  3404     result = aRight;
  3405     aRight = aRight->GetNextSibling();
  3406     if (!aRight) {
  3407       result->SetNextSibling(aLeft);
  3408       return result;
  3412   nsIFrame *last = result;
  3413   for (;;) {
  3414     if (IsLessThanOrEqual(aLeft, aRight)) {
  3415       last->SetNextSibling(aLeft);
  3416       last = aLeft;
  3417       aLeft = aLeft->GetNextSibling();
  3418       if (!aLeft) {
  3419         last->SetNextSibling(aRight);
  3420         return result;
  3423     else {
  3424       last->SetNextSibling(aRight);
  3425       last = aRight;
  3426       aRight = aRight->GetNextSibling();
  3427       if (!aRight) {
  3428         last->SetNextSibling(aLeft);
  3429         return result;
  3435 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  3436 /* static */ nsIFrame*
  3437 nsIFrame::MergeSort(nsIFrame *aSource)
  3439   NS_PRECONDITION(aSource, "MergeSort null arg");
  3441   nsIFrame *sorted[32] = { nullptr };
  3442   nsIFrame **fill = &sorted[0];
  3443   nsIFrame **left;
  3444   nsIFrame *rest = aSource;
  3446   do {
  3447     nsIFrame *current = rest;
  3448     rest = rest->GetNextSibling();
  3449     current->SetNextSibling(nullptr);
  3451     // Merge it with sorted[0] if present; then merge the result with sorted[1] etc.
  3452     // sorted[0] is a list of length 1 (or nullptr).
  3453     // sorted[1] is a list of length 2 (or nullptr).
  3454     // sorted[2] is a list of length 4 (or nullptr). etc.
  3455     for (left = &sorted[0]; left != fill && *left; ++left) {
  3456       current = SortedMerge<IsLessThanOrEqual>(*left, current);
  3457       *left = nullptr;
  3460     // Fill the empty slot that we couldn't merge with the last result.
  3461     *left = current;
  3463     if (left == fill)
  3464       ++fill;
  3465   } while (rest);
  3467   // Collect and merge the results.
  3468   nsIFrame *result = nullptr;
  3469   for (left = &sorted[0]; left != fill; ++left) {
  3470     if (*left) {
  3471       result = result ? SortedMerge<IsLessThanOrEqual>(*left, result) : *left;
  3474   return result;
  3477 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  3478 /* static */ void
  3479 nsIFrame::SortFrameList(nsFrameList& aFrameList)
  3481   nsIFrame* head = MergeSort<IsLessThanOrEqual>(aFrameList.FirstChild());
  3482   aFrameList = nsFrameList(head, nsLayoutUtils::GetLastSibling(head));
  3483   MOZ_ASSERT(IsFrameListSorted<IsLessThanOrEqual>(aFrameList),
  3484              "After we sort a frame list, it should be in sorted order...");
  3487 template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
  3488 /* static */ bool
  3489 nsIFrame::IsFrameListSorted(nsFrameList& aFrameList)
  3491   if (aFrameList.IsEmpty()) {
  3492     // empty lists are trivially sorted.
  3493     return true;
  3496   // We'll walk through the list with two iterators, one trailing behind the
  3497   // other. The list is sorted IFF trailingIter <= iter, across the whole list.
  3498   nsFrameList::Enumerator trailingIter(aFrameList);
  3499   nsFrameList::Enumerator iter(aFrameList);
  3500   iter.Next(); // Skip |iter| past first frame. (List is nonempty, so we can.)
  3502   // Now, advance the iterators in parallel, comparing each adjacent pair.
  3503   while (!iter.AtEnd()) {
  3504     MOZ_ASSERT(!trailingIter.AtEnd(), "trailing iter shouldn't finish first");
  3505     if (!IsLessThanOrEqual(trailingIter.get(), iter.get())) {
  3506       return false;
  3508     trailingIter.Next();
  3509     iter.Next();
  3512   // We made it to the end without returning early, so the list is sorted.
  3513   return true;
  3516 #endif /* nsIFrame_h___ */

mercurial