layout/base/nsCSSFrameConstructor.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 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * construction of a frame tree that is nearly isomorphic to the content
     8  * tree and updating of that tree in response to dynamic changes
     9  */
    11 #ifndef nsCSSFrameConstructor_h___
    12 #define nsCSSFrameConstructor_h___
    14 #include "mozilla/Attributes.h"
    16 #include "nsCOMPtr.h"
    17 #include "nsILayoutHistoryState.h"
    18 #include "nsQuoteList.h"
    19 #include "nsCounterManager.h"
    20 #include "nsCSSPseudoElements.h"
    21 #include "nsIAnonymousContentCreator.h"
    22 #include "nsFrameManager.h"
    23 #include "nsIDocument.h"
    25 struct nsFrameItems;
    26 struct nsAbsoluteItems;
    27 class nsStyleContext;
    28 struct nsStyleDisplay;
    29 class nsIDOMHTMLSelectElement;
    30 struct nsGenConInitializer;
    32 class nsICSSAnonBoxPseudo;
    33 class nsPageContentFrame;
    34 struct PendingBinding;
    35 class nsGenericDOMDataNode;
    37 class nsFrameConstructorState;
    38 class nsFrameConstructorSaveState;
    40 namespace mozilla {
    42 class RestyleManager;
    44 namespace dom {
    46 class FlattenedChildIterator;
    48 }
    49 }
    51 class nsCSSFrameConstructor : public nsFrameManager
    52 {
    53 public:
    54   typedef mozilla::dom::Element Element;
    56   friend class mozilla::RestyleManager;
    58   nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell,
    59                         nsStyleSet* aStyleSet);
    60   ~nsCSSFrameConstructor(void) {
    61     NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
    62   }
    64   // get the alternate text for a content node
    65   static void GetAlternateTextFor(nsIContent*    aContent,
    66                                   nsIAtom*       aTag,  // content object's tag
    67                                   nsXPIDLString& aAltText);
    69 private:
    70   nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
    71   nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
    73 public:
    74   mozilla::RestyleManager* RestyleManager() const
    75     { return mPresShell->GetPresContext()->RestyleManager(); }
    77   nsIFrame* ConstructRootFrame();
    79   nsresult ReconstructDocElementHierarchy();
    81   // Create frames for content nodes that are marked as needing frames. This
    82   // should be called before ProcessPendingRestyles.
    83   // Note: It's the caller's responsibility to make sure to wrap a
    84   // CreateNeededFrames call in a view update batch and a script blocker.
    85   void CreateNeededFrames();
    87 private:
    88   void CreateNeededFrames(nsIContent* aContent);
    90   enum Operation {
    91     CONTENTAPPEND,
    92     CONTENTINSERT
    93   };
    95   // aChild is the child being inserted for inserts, and the first
    96   // child being appended for appends.
    97   bool MaybeConstructLazily(Operation aOperation,
    98                               nsIContent* aContainer,
    99                               nsIContent* aChild);
   101   // Issues a single ContentInserted for each child of aContainer in the range
   102   // [aStartChild, aEndChild).
   103   void IssueSingleInsertNofications(nsIContent* aContainer,
   104                                     nsIContent* aStartChild,
   105                                     nsIContent* aEndChild,
   106                                     bool aAllowLazyConstruction);
   108   // Checks if the children of aContainer in the range [aStartChild, aEndChild)
   109   // can be inserted/appended to one insertion point together. If so, returns
   110   // that insertion point. If not, returns null and issues single
   111   // ContentInserted calls for each child.  aEndChild = nullptr indicates that we
   112   // are dealing with an append.
   113   nsIFrame* GetRangeInsertionPoint(nsIContent* aContainer,
   114                                    nsIContent* aStartChild,
   115                                    nsIContent* aEndChild,
   116                                    bool aAllowLazyConstruction);
   118   // Returns true if parent was recreated due to frameset child, false otherwise.
   119   bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
   120                                   nsIContent* aStartChild,
   121                                   nsIContent* aEndChild);
   123 public:
   124   /**
   125    * Lazy frame construction is controlled by the aAllowLazyConstruction bool
   126    * parameter of nsCSSFrameConstructor::ContentAppended/Inserted. It is true
   127    * for all inserts/appends as passed from the presshell, except for the
   128    * insert of the root element, which is always non-lazy. Even if the
   129    * aAllowLazyConstruction passed to ContentAppended/Inserted is true we still
   130    * may not be able to construct lazily, so we call MaybeConstructLazily.
   131    * MaybeConstructLazily does not allow lazy construction if any of the
   132    * following are true:
   133    *  -we are in chrome
   134    *  -the container is in a native anonymous subtree
   135    *  -the container is XUL
   136    *  -is any of the appended/inserted nodes are XUL or editable
   137    *  -(for inserts) the child is anonymous.  In the append case this function
   138    *   must not be called with anonymous children.
   139    * The XUL and chrome checks are because XBL bindings only get applied at
   140    * frame construction time and some things depend on the bindings getting
   141    * attached synchronously. The editable checks are because the editor seems
   142    * to expect frames to be constructed synchronously.
   143    *
   144    * If MaybeConstructLazily returns false we construct as usual, but if it
   145    * returns true then it adds NODE_NEEDS_FRAME bits to the newly
   146    * inserted/appended nodes and adds NODE_DESCENDANTS_NEED_FRAMES bits to the
   147    * container and up along the parent chain until it hits the root or another
   148    * node with that bit set. Then it posts a restyle event to ensure that a
   149    * flush happens to construct those frames.
   150    *
   151    * When the flush happens the presshell calls
   152    * nsCSSFrameConstructor::CreateNeededFrames. CreateNeededFrames follows any
   153    * nodes with NODE_DESCENDANTS_NEED_FRAMES set down the content tree looking
   154    * for nodes with NODE_NEEDS_FRAME set. It calls ContentAppended for any runs
   155    * of nodes with NODE_NEEDS_FRAME set that are at the end of their childlist,
   156    * and ContentRangeInserted for any other runs that aren't.
   157    *
   158    * If a node is removed from the document then we don't bother unsetting any
   159    * of the lazy bits that might be set on it, its descendants, or any of its
   160    * ancestor nodes because that is a slow operation, the work might be wasted
   161    * if another node gets inserted in its place, and we can clear the bits
   162    * quicker by processing the content tree from top down the next time we call
   163    * CreateNeededFrames. (We do clear the bits when BindToTree is called on any
   164    * nsIContent; so any nodes added to the document will not have any lazy bits
   165    * set.)
   166    */
   168   // If aAllowLazyConstruction is true then frame construction of the new
   169   // children can be done lazily.
   170   nsresult ContentAppended(nsIContent* aContainer,
   171                            nsIContent* aFirstNewContent,
   172                            bool        aAllowLazyConstruction);
   174   // If aAllowLazyConstruction is true then frame construction of the new child
   175   // can be done lazily.
   176   nsresult ContentInserted(nsIContent*            aContainer,
   177                            nsIContent*            aChild,
   178                            nsILayoutHistoryState* aFrameState,
   179                            bool                   aAllowLazyConstruction);
   181   // Like ContentInserted but handles inserting the children of aContainer in
   182   // the range [aStartChild, aEndChild).  aStartChild must be non-null.
   183   // aEndChild may be null to indicate the range includes all kids after
   184   // aStartChild.  If aAllowLazyConstruction is true then frame construction of
   185   // the new children can be done lazily. It is only allowed to be true when
   186   // inserting a single node.
   187   nsresult ContentRangeInserted(nsIContent*            aContainer,
   188                                 nsIContent*            aStartChild,
   189                                 nsIContent*            aEndChild,
   190                                 nsILayoutHistoryState* aFrameState,
   191                                 bool                   aAllowLazyConstruction);
   193   enum RemoveFlags { REMOVE_CONTENT, REMOVE_FOR_RECONSTRUCTION };
   194   nsresult ContentRemoved(nsIContent* aContainer,
   195                           nsIContent* aChild,
   196                           nsIContent* aOldNextSibling,
   197                           RemoveFlags aFlags,
   198                           bool*     aDidReconstruct);
   200   nsresult CharacterDataChanged(nsIContent* aContent,
   201                                 CharacterDataChangeInfo* aInfo);
   203   // If aContent is a text node that has been optimized away due to being
   204   // whitespace next to a block boundary (or for some other reason), stop
   205   // doing that and create a frame for it if it should have one. This recreates
   206   // frames so be careful (although this should not change actual layout).
   207   // Returns the frame for aContent if there is one.
   208   nsIFrame* EnsureFrameForTextNode(nsGenericDOMDataNode* aContent);
   210   // generate the child frames and process bindings
   211   nsresult GenerateChildFrames(nsIFrame* aFrame);
   213   // Should be called when a frame is going to be destroyed and
   214   // WillDestroyFrameTree hasn't been called yet.
   215   void NotifyDestroyingFrame(nsIFrame* aFrame);
   217   void BeginUpdate();
   218   void EndUpdate();
   219   void RecalcQuotesAndCounters();
   221   // Gets called when the presshell is destroying itself and also
   222   // when we tear down our frame tree to reconstruct it
   223   void WillDestroyFrameTree();
   225   // Request to create a continuing frame.  This method never returns null.
   226   nsIFrame* CreateContinuingFrame(nsPresContext* aPresContext,
   227                                   nsIFrame*       aFrame,
   228                                   nsIFrame*       aParentFrame,
   229                                   bool            aIsFluid = true);
   231   // Copy over fixed frames from aParentFrame's prev-in-flow
   232   nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
   234   // Get the XBL insertion point for a child
   235   nsIFrame* GetInsertionPoint(nsIContent* aContainer,
   236                               nsIContent* aChildContent,
   237                               bool*       aMultiple = nullptr);
   239   nsresult CreateListBoxContent(nsPresContext* aPresContext,
   240                                 nsIFrame*       aParentFrame,
   241                                 nsIFrame*       aPrevFrame,
   242                                 nsIContent*     aChild,
   243                                 nsIFrame**      aResult,
   244                                 bool            aIsAppend,
   245                                 bool            aIsScrollbar,
   246                                 nsILayoutHistoryState* aFrameState);
   248   // GetInitialContainingBlock() is deprecated in favor of GetRootElementFrame();
   249   // nsIFrame* GetInitialContainingBlock() { return mRootElementFrame; }
   250   // This returns the outermost frame for the root element
   251   nsIFrame* GetRootElementFrame() { return mRootElementFrame; }
   252   // This returns the frame for the root element that does not
   253   // have a psuedo-element style
   254   nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
   255   nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
   257   // Get the frame that is the parent of the root element.
   258   nsIFrame* GetDocElementContainingBlock()
   259     { return mDocElementContainingBlock; }
   261 private:
   262   struct FrameConstructionItem;
   263   class FrameConstructionItemList;
   265   nsIFrame* ConstructPageFrame(nsIPresShell*  aPresShell,
   266                                nsPresContext* aPresContext,
   267                                nsIFrame*      aParentFrame,
   268                                nsIFrame*      aPrevPageFrame,
   269                                nsIFrame*&     aCanvasFrame);
   271   void InitAndRestoreFrame (const nsFrameConstructorState& aState,
   272                             nsIContent*                    aContent,
   273                             nsIFrame*                      aParentFrame,
   274                             nsIFrame*                      aNewFrame,
   275                             bool                           aAllowCounters = true);
   277   // aState can be null if not available; it's used as an optimization.
   278   // XXXbz IsValidSibling is the only caller that doesn't pass a state here!
   279   already_AddRefed<nsStyleContext>
   280   ResolveStyleContext(nsIFrame*         aParentFrame,
   281                       nsIContent*       aContent,
   282                       nsFrameConstructorState* aState);
   283   already_AddRefed<nsStyleContext>
   284   ResolveStyleContext(nsStyleContext* aParentStyleContext,
   285                       nsIContent* aContent,
   286                       nsFrameConstructorState* aState);
   288   // Add the frame construction items for the given aContent and aParentFrame
   289   // to the list.  This might add more than one item in some rare cases.
   290   // If aSuppressWhiteSpaceOptimizations is true, optimizations that
   291   // may suppress the construction of white-space-only text frames
   292   // must be skipped for these items and items around them.
   293   void AddFrameConstructionItems(nsFrameConstructorState& aState,
   294                                  nsIContent*              aContent,
   295                                  bool                     aSuppressWhiteSpaceOptimizations,
   296                                  nsIFrame*                aParentFrame,
   297                                  FrameConstructionItemList& aItems);
   299   // Construct the frames for the document element.  This can return null if the
   300   // document element is display:none, or if the document element has a
   301   // not-yet-loaded XBL binding, or if it's an SVG element that's not <svg>.
   302   nsIFrame* ConstructDocElementFrame(Element*                 aDocElement,
   303                                      nsILayoutHistoryState*   aFrameState);
   305   // Set up our mDocElementContainingBlock correctly for the given root
   306   // content.
   307   void SetUpDocElementContainingBlock(nsIContent* aDocElement);
   309   /**
   310    * CreateAttributeContent creates a single content/frame combination for an
   311    * |attr(foo)| generated content.
   312    *
   313    * @param aParentContent the parent content for the generated content
   314    * @param aParentFrame the parent frame for the generated frame
   315    * @param aAttrNamespace the namespace of the attribute in question
   316    * @param aAttrName the localname of the attribute
   317    * @param aStyleContext the style context to use
   318    * @param aGeneratedContent the array of generated content to append the
   319    *                          created content to.
   320    * @param [out] aNewContent the content node we create
   321    * @param [out] aNewFrame the new frame we create
   322    */
   323   nsresult CreateAttributeContent(nsIContent* aParentContent,
   324                                   nsIFrame* aParentFrame,
   325                                   int32_t aAttrNamespace,
   326                                   nsIAtom* aAttrName,
   327                                   nsStyleContext* aStyleContext,
   328                                   nsCOMArray<nsIContent>& aGeneratedContent,
   329                                   nsIContent** aNewContent,
   330                                   nsIFrame** aNewFrame);
   332   /**
   333    * Create a text node containing the given string. If aText is non-null
   334    * then we also set aText to the returned node.
   335    */
   336   already_AddRefed<nsIContent> CreateGenConTextNode(nsFrameConstructorState& aState,
   337                                                     const nsString& aString,
   338                                                     nsCOMPtr<nsIDOMCharacterData>* aText,
   339                                                     nsGenConInitializer* aInitializer);
   341   /**
   342    * Create a content node for the given generated content style.
   343    * The caller takes care of making it SetIsNativeAnonymousRoot, binding it
   344    * to the document, and creating frames for it.
   345    * @param aParentContent is the node that has the before/after style
   346    * @param aStyleContext is the 'before' or 'after' pseudo-element
   347    * style context
   348    * @param aContentIndex is the index of the content item to create
   349    */
   350   already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
   351                                                       nsIContent*     aParentContent,
   352                                                       nsStyleContext* aStyleContext,
   353                                                       uint32_t        aContentIndex);
   355   // aFrame may be null; this method doesn't use it directly in any case.
   356   void CreateGeneratedContentItem(nsFrameConstructorState&   aState,
   357                                   nsIFrame*                  aFrame,
   358                                   nsIContent*                aContent,
   359                                   nsStyleContext*            aStyleContext,
   360                                   nsCSSPseudoElements::Type  aPseudoElement,
   361                                   FrameConstructionItemList& aItems);
   363   // This method can change aFrameList: it can chop off the beginning and put
   364   // it in aParentFrame while putting the remainder into a ib-split sibling of
   365   // aParentFrame.  aPrevSibling must be the frame after which aFrameList is to
   366   // be placed on aParentFrame's principal child list.  It may be null if
   367   // aFrameList is being added at the beginning of the child list.
   368   nsresult AppendFramesToParent(nsFrameConstructorState&       aState,
   369                                 nsIFrame*                      aParentFrame,
   370                                 nsFrameItems&                  aFrameList,
   371                                 nsIFrame*                      aPrevSibling,
   372                                 bool                           aIsRecursiveCall = false);
   374   // BEGIN TABLE SECTION
   375   /**
   376    * Construct an outer table frame.  This is the FrameConstructionData
   377    * callback used for the job.
   378    */
   379   nsIFrame* ConstructTable(nsFrameConstructorState& aState,
   380                            FrameConstructionItem&   aItem,
   381                            nsIFrame*                aParentFrame,
   382                            const nsStyleDisplay*    aDisplay,
   383                            nsFrameItems&            aFrameItems);
   385   /**
   386    * FrameConstructionData callback for constructing table rows and row groups.
   387    */
   388   nsIFrame* ConstructTableRowOrRowGroup(nsFrameConstructorState& aState,
   389                                         FrameConstructionItem&   aItem,
   390                                         nsIFrame*                aParentFrame,
   391                                         const nsStyleDisplay*    aStyleDisplay,
   392                                         nsFrameItems&            aFrameItems);
   394   /**
   395    * FrameConstructionData callback used for constructing table columns.
   396    */
   397   nsIFrame* ConstructTableCol(nsFrameConstructorState& aState,
   398                               FrameConstructionItem&   aItem,
   399                               nsIFrame*                aParentFrame,
   400                               const nsStyleDisplay*    aStyleDisplay,
   401                               nsFrameItems&            aFrameItems);
   403   /**
   404    * FrameConstructionData callback used for constructing table cells.
   405    */
   406   nsIFrame* ConstructTableCell(nsFrameConstructorState& aState,
   407                                FrameConstructionItem&   aItem,
   408                                nsIFrame*                aParentFrame,
   409                                const nsStyleDisplay*    aStyleDisplay,
   410                                nsFrameItems&            aFrameItems);
   412 private:
   413   /* An enum of possible parent types for anonymous table object construction */
   414   enum ParentType {
   415     eTypeBlock = 0, /* This includes all non-table-related frames */
   416     eTypeRow,
   417     eTypeRowGroup,
   418     eTypeColGroup,
   419     eTypeTable,
   420     eParentTypeCount
   421   };
   423   /* 3 bits is enough to handle our ParentType values */
   424 #define FCDATA_PARENT_TYPE_OFFSET 29
   425   /* Macro to get the desired parent type out of an mBits member of
   426      FrameConstructionData */
   427 #define FCDATA_DESIRED_PARENT_TYPE(_bits)           \
   428   ParentType((_bits) >> FCDATA_PARENT_TYPE_OFFSET)
   429   /* Macro to create FrameConstructionData bits out of a desired parent type */
   430 #define FCDATA_DESIRED_PARENT_TYPE_TO_BITS(_type)     \
   431   (((uint32_t)(_type)) << FCDATA_PARENT_TYPE_OFFSET)
   433   /* Get the parent type that aParentFrame has. */
   434   static ParentType GetParentType(nsIFrame* aParentFrame) {
   435     return GetParentType(aParentFrame->GetType());
   436   }
   438   /* Get the parent type for the given nsIFrame type atom */
   439   static ParentType GetParentType(nsIAtom* aFrameType);
   441   /* A constructor function that just creates an nsIFrame object.  The caller
   442      is responsible for initializing the object, adding it to frame lists,
   443      constructing frames for the children, etc.
   445      @param nsIPresShell the presshell whose arena should be used to allocate
   446                          the frame.
   447      @param nsStyleContext the style context to use for the frame. */
   448   typedef nsIFrame* (* FrameCreationFunc)(nsIPresShell*, nsStyleContext*);
   450   /* A function that can be used to get a FrameConstructionData.  Such
   451      a function is allowed to return null.
   453      @param nsIContent the node for which the frame is being constructed.
   454      @param nsStyleContext the style context to be used for the frame.
   455   */
   456   struct FrameConstructionData;
   457   typedef const FrameConstructionData*
   458     (* FrameConstructionDataGetter)(Element*, nsStyleContext*);
   460   /* A constructor function that's used for complicated construction tasks.
   461      This is expected to create the new frame, initialize it, add whatever
   462      needs to be added to aFrameItems (XXXbz is that really necessary?  Could
   463      caller add?  Might there be cases when the returned frame or its
   464      placeholder is not the thing that ends up in aFrameItems?  If not, would
   465      it be safe to do the add into the frame construction state after
   466      processing kids?  Look into this as a followup!), process children as
   467      needed, etc.  It is NOT expected to deal with setting the frame on the
   468      content.
   470      @param aState the frame construction state to use.
   471      @param aItem the frame construction item to use
   472      @param aParentFrame the frame to set as the parent of the
   473                          newly-constructed frame.
   474      @param aStyleDisplay the display struct from aItem's mStyleContext
   475      @param aFrameItems the frame list to add the new frame (or its
   476                         placeholder) to.
   477      @return the frame that was constructed.  This frame is what the caller
   478              will set as the frame on the content.  Guaranteed non-null.
   479   */
   480   typedef nsIFrame*
   481     (nsCSSFrameConstructor::* FrameFullConstructor)(nsFrameConstructorState& aState,
   482                                                     FrameConstructionItem& aItem,
   483                                                     nsIFrame* aParentFrame,
   484                                                     const nsStyleDisplay* aStyleDisplay,
   485                                                     nsFrameItems& aFrameItems);
   487   /* Bits that modify the way a FrameConstructionData is handled */
   489   /* If the FCDATA_SKIP_FRAMESET bit is set, then the frame created should not
   490      be set as the primary frame on the content node.  This should only be used
   491      in very rare cases when we create more than one frame for a given content
   492      node. */
   493 #define FCDATA_SKIP_FRAMESET 0x1
   494   /* If the FCDATA_FUNC_IS_DATA_GETTER bit is set, then the mFunc of the
   495      FrameConstructionData is a getter function that can be used to get the
   496      actual FrameConstructionData to use. */
   497 #define FCDATA_FUNC_IS_DATA_GETTER 0x2
   498   /* If the FCDATA_FUNC_IS_FULL_CTOR bit is set, then the FrameConstructionData
   499      has an mFullConstructor.  In this case, there is no relevant mData or
   500      mFunc */
   501 #define FCDATA_FUNC_IS_FULL_CTOR 0x4
   502   /* If FCDATA_DISALLOW_OUT_OF_FLOW is set, do not allow the frame to
   503      float or be absolutely positioned.  This can also be used with
   504      FCDATA_FUNC_IS_FULL_CTOR to indicate what the full-constructor
   505      function will do. */
   506 #define FCDATA_DISALLOW_OUT_OF_FLOW 0x8
   507   /* If FCDATA_FORCE_NULL_ABSPOS_CONTAINER is set, make sure to push a
   508      null absolute containing block before processing children for this
   509      frame.  If this is not set, the frame will be pushed as the
   510      absolute containing block as needed, based on its style */
   511 #define FCDATA_FORCE_NULL_ABSPOS_CONTAINER 0x10
   512   /* If FCDATA_WRAP_KIDS_IN_BLOCKS is set, the inline kids of the frame
   513      will be wrapped in blocks.  This is only usable for MathML at the
   514      moment. */
   515 #define FCDATA_WRAP_KIDS_IN_BLOCKS 0x20
   516   /* If FCDATA_SUPPRESS_FRAME is set, no frame should be created for the
   517      content.  If this bit is set, nothing else in the struct needs to be
   518      set. */
   519 #define FCDATA_SUPPRESS_FRAME 0x40
   520   /* If FCDATA_MAY_NEED_SCROLLFRAME is set, the new frame should be wrapped in
   521      a scrollframe if its overflow type so requires. */
   522 #define FCDATA_MAY_NEED_SCROLLFRAME 0x80
   523 #ifdef MOZ_XUL
   524   /* If FCDATA_IS_POPUP is set, the new frame is a XUL popup frame.  These need
   525      some really weird special handling.  */
   526 #define FCDATA_IS_POPUP 0x100
   527 #endif /* MOZ_XUL */
   528   /* If FCDATA_SKIP_ABSPOS_PUSH is set, don't push this frame as an
   529      absolute containing block, no matter what its style says. */
   530 #define FCDATA_SKIP_ABSPOS_PUSH 0x200
   531   /* If FCDATA_DISALLOW_GENERATED_CONTENT is set, then don't allow generated
   532      content when processing kids of this frame.  This should not be used with
   533      FCDATA_FUNC_IS_FULL_CTOR */
   534 #define FCDATA_DISALLOW_GENERATED_CONTENT 0x400
   535   /* If FCDATA_IS_TABLE_PART is set, then the frame is some sort of
   536      table-related thing and we should not attempt to fetch a table-cell parent
   537      for it if it's inside another table-related frame. */
   538 #define FCDATA_IS_TABLE_PART 0x800
   539   /* If FCDATA_IS_INLINE is set, then the frame is a non-replaced CSS
   540      inline box. */
   541 #define FCDATA_IS_INLINE 0x1000
   542   /* If FCDATA_IS_LINE_PARTICIPANT is set, the frame is something that will
   543      return true for IsFrameOfType(nsIFrame::eLineParticipant) */
   544 #define FCDATA_IS_LINE_PARTICIPANT 0x2000
   545   /* If FCDATA_IS_LINE_BREAK is set, the frame is something that will
   546      induce a line break boundary before and after itself. */
   547 #define FCDATA_IS_LINE_BREAK 0x4000
   548   /* If FCDATA_ALLOW_BLOCK_STYLES is set, allow block styles when processing
   549      children.  This should not be used with FCDATA_FUNC_IS_FULL_CTOR. */
   550 #define FCDATA_ALLOW_BLOCK_STYLES 0x8000
   551   /* If FCDATA_USE_CHILD_ITEMS is set, then use the mChildItems in the relevant
   552      FrameConstructionItem instead of trying to process the content's children.
   553      This can be used with or without FCDATA_FUNC_IS_FULL_CTOR.
   554      The child items might still need table pseudo processing. */
   555 #define FCDATA_USE_CHILD_ITEMS 0x10000
   556   /* If FCDATA_FORCED_NON_SCROLLABLE_BLOCK is set, then this block
   557      would have been scrollable but has been forced to be
   558      non-scrollable due to being in a paginated context. */
   559 #define FCDATA_FORCED_NON_SCROLLABLE_BLOCK 0x20000
   560   /* If FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, then create a
   561      block formatting context wrapper around the kids of this frame
   562      using the FrameConstructionData's mPseudoAtom for its anonymous
   563      box type. */
   564 #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
   565   /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
   566      an SVG text frame. */
   567 #define FCDATA_IS_SVG_TEXT 0x80000
   569   /* Structure representing information about how a frame should be
   570      constructed.  */
   571   struct FrameConstructionData {
   572     // Flag bits that can modify the way the construction happens
   573     uint32_t mBits;
   574     // We have exactly one of three types of functions, so use a union for
   575     // better cache locality for the ones that aren't pointer-to-member.  That
   576     // one needs to be separate, because we can't cast between it and the
   577     // others and hence wouldn't be able to initialize the union without a
   578     // constructor and all the resulting generated code.  See documentation
   579     // above for FrameCreationFunc, FrameConstructionDataGetter, and
   580     // FrameFullConstructor to see what the functions would do.
   581     union Func {
   582       FrameCreationFunc mCreationFunc;
   583       FrameConstructionDataGetter mDataGetter;
   584     } mFunc;
   585     FrameFullConstructor mFullConstructor;
   586     // For cases when FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, the
   587     // anonymous box type to use for that wrapper.
   588     nsICSSAnonBoxPseudo * const * const mAnonBoxPseudo;
   589   };
   591   /* Structure representing a mapping of an atom to a FrameConstructionData.
   592      This can be used with non-static atoms, assuming that the nsIAtom* is
   593      stored somewhere that this struct can point to (that is, a static
   594      nsIAtom*) and that it's allocated before the struct is ever used. */
   595   struct FrameConstructionDataByTag {
   596     // Pointer to nsIAtom* is used because we want to initialize this
   597     // statically, so before our atom tables are set up.
   598     const nsIAtom * const * const mTag;
   599     const FrameConstructionData mData;
   600   };
   602   /* Structure representing a mapping of an integer to a
   603      FrameConstructionData. There are no magic integer values here. */
   604   struct FrameConstructionDataByInt {
   605     /* Could be used for display or whatever else */
   606     const int32_t mInt;
   607     const FrameConstructionData mData;
   608   };
   610   /* Structure that has a FrameConstructionData and style context pseudo-type
   611      for a table pseudo-frame */
   612   struct PseudoParentData {
   613     const FrameConstructionData mFCData;
   614     nsICSSAnonBoxPseudo * const * const mPseudoType;
   615   };
   616   /* Array of such structures that we use to properly construct table
   617      pseudo-frames as needed */
   618   static const PseudoParentData sPseudoParentData[eParentTypeCount];
   620   /* A function that takes an integer, content, style context, and array of
   621      FrameConstructionDataByInts and finds the appropriate frame construction
   622      data to use and returns it.  This can return null if none of the integers
   623      match or if the matching integer has a FrameConstructionDataGetter that
   624      returns null. */
   625   static const FrameConstructionData*
   626     FindDataByInt(int32_t aInt, Element* aElement,
   627                   nsStyleContext* aStyleContext,
   628                   const FrameConstructionDataByInt* aDataPtr,
   629                   uint32_t aDataLength);
   631   /* A function that takes a tag, content, style context, and array of
   632      FrameConstructionDataByTags and finds the appropriate frame construction
   633      data to use and returns it.  This can return null if none of the tags
   634      match or if the matching tag has a FrameConstructionDataGetter that
   635      returns null. */
   636   static const FrameConstructionData*
   637     FindDataByTag(nsIAtom* aTag, Element* aElement,
   638                   nsStyleContext* aStyleContext,
   639                   const FrameConstructionDataByTag* aDataPtr,
   640                   uint32_t aDataLength);
   642   /* A class representing a list of FrameConstructionItems */
   643   class FrameConstructionItemList {
   644   public:
   645     FrameConstructionItemList() :
   646       mInlineCount(0),
   647       mBlockCount(0),
   648       mLineParticipantCount(0),
   649       mItemCount(0),
   650       mLineBoundaryAtStart(false),
   651       mLineBoundaryAtEnd(false),
   652       mParentHasNoXBLChildren(false),
   653       mTriedConstructingFrames(false)
   654     {
   655       PR_INIT_CLIST(&mItems);
   656       memset(mDesiredParentCounts, 0, sizeof(mDesiredParentCounts));
   657     }
   659     ~FrameConstructionItemList() {
   660       PRCList* cur = PR_NEXT_LINK(&mItems);
   661       while (cur != &mItems) {
   662         PRCList* next = PR_NEXT_LINK(cur);
   663         delete ToItem(cur);
   664         cur = next;
   665       }
   667       // Leaves our mItems pointing to deleted memory in both directions,
   668       // but that's OK at this point.
   670       // Create the undisplayed entries for our mUndisplayedItems, if any, but
   671       // only if we have tried constructing frames for this item list.  If we
   672       // haven't, then we're just throwing it away and will probably try again.
   673       if (!mUndisplayedItems.IsEmpty() && mTriedConstructingFrames) {
   674         // We could store the frame manager in a member, but just
   675         // getting it off the style context is not too bad.
   676         nsFrameManager *mgr =
   677           mUndisplayedItems[0].mStyleContext->PresContext()->FrameManager();
   678         for (uint32_t i = 0; i < mUndisplayedItems.Length(); ++i) {
   679           UndisplayedItem& item = mUndisplayedItems[i];
   680           mgr->SetUndisplayedContent(item.mContent, item.mStyleContext);
   681         }
   682       }
   683     }
   685     void SetLineBoundaryAtStart(bool aBoundary) { mLineBoundaryAtStart = aBoundary; }
   686     void SetLineBoundaryAtEnd(bool aBoundary) { mLineBoundaryAtEnd = aBoundary; }
   687     void SetParentHasNoXBLChildren(bool aHasNoXBLChildren) {
   688       mParentHasNoXBLChildren = aHasNoXBLChildren;
   689     }
   690     void SetTriedConstructingFrames() { mTriedConstructingFrames = true; }
   691     bool HasLineBoundaryAtStart() { return mLineBoundaryAtStart; }
   692     bool HasLineBoundaryAtEnd() { return mLineBoundaryAtEnd; }
   693     bool ParentHasNoXBLChildren() { return mParentHasNoXBLChildren; }
   694     bool IsEmpty() const { return PR_CLIST_IS_EMPTY(&mItems); }
   695     bool AnyItemsNeedBlockParent() const { return mLineParticipantCount != 0; }
   696     bool AreAllItemsInline() const { return mInlineCount == mItemCount; }
   697     bool AreAllItemsBlock() const { return mBlockCount == mItemCount; }
   698     bool AllWantParentType(ParentType aDesiredParentType) const {
   699       return mDesiredParentCounts[aDesiredParentType] == mItemCount;
   700     }
   702     // aSuppressWhiteSpaceOptimizations is true if optimizations that
   703     // skip constructing whitespace frames for this item or items
   704     // around it cannot be performed.
   705     FrameConstructionItem* AppendItem(const FrameConstructionData* aFCData,
   706                                       nsIContent* aContent,
   707                                       nsIAtom* aTag,
   708                                       int32_t aNameSpaceID,
   709                                       PendingBinding* aPendingBinding,
   710                                       already_AddRefed<nsStyleContext>&& aStyleContext,
   711                                       bool aSuppressWhiteSpaceOptimizations,
   712                                       nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren)
   713     {
   714       FrameConstructionItem* item =
   715         new FrameConstructionItem(aFCData, aContent, aTag, aNameSpaceID,
   716                                   aPendingBinding, aStyleContext,
   717                                   aSuppressWhiteSpaceOptimizations,
   718                                   aAnonChildren);
   719       PR_APPEND_LINK(item, &mItems);
   720       ++mItemCount;
   721       ++mDesiredParentCounts[item->DesiredParentType()];
   722       return item;
   723     }
   725     void AppendUndisplayedItem(nsIContent* aContent,
   726                                nsStyleContext* aStyleContext) {
   727       mUndisplayedItems.AppendElement(UndisplayedItem(aContent, aStyleContext));
   728     }
   730     void InlineItemAdded() { ++mInlineCount; }
   731     void BlockItemAdded() { ++mBlockCount; }
   732     void LineParticipantItemAdded() { ++mLineParticipantCount; }
   734     class Iterator;
   735     friend class Iterator;
   737     class Iterator {
   738     public:
   739       Iterator(FrameConstructionItemList& list) :
   740         mCurrent(PR_NEXT_LINK(&list.mItems)),
   741         mEnd(&list.mItems),
   742         mList(list)
   743       {}
   744       Iterator(const Iterator& aOther) :
   745         mCurrent(aOther.mCurrent),
   746         mEnd(aOther.mEnd),
   747         mList(aOther.mList)
   748       {}
   750       bool operator==(const Iterator& aOther) const {
   751         NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
   752         return mCurrent == aOther.mCurrent;
   753       }
   754       bool operator!=(const Iterator& aOther) const {
   755         return !(*this == aOther);
   756       }
   757       Iterator& operator=(const Iterator& aOther) {
   758         NS_ASSERTION(mEnd == aOther.mEnd, "Iterators for different lists?");
   759         mCurrent = aOther.mCurrent;
   760         return *this;
   761       }
   763       FrameConstructionItemList* List() {
   764         return &mList;
   765       }
   767       operator FrameConstructionItem& () {
   768         return item();
   769       }
   771       FrameConstructionItem& item() {
   772         return *FrameConstructionItemList::ToItem(mCurrent);
   773       }
   774       bool IsDone() const { return mCurrent == mEnd; }
   775       bool AtStart() const { return mCurrent == PR_NEXT_LINK(mEnd); }
   776       void Next() {
   777         NS_ASSERTION(!IsDone(), "Should have checked IsDone()!");
   778         mCurrent = PR_NEXT_LINK(mCurrent);
   779       }
   780       void Prev() {
   781         NS_ASSERTION(!AtStart(), "Should have checked AtStart()!");
   782         mCurrent = PR_PREV_LINK(mCurrent);
   783       }
   784       void SetToEnd() { mCurrent = mEnd; }
   786       // Skip over all items that want a parent type different from the given
   787       // one.  Return whether the iterator is done after doing that.  The
   788       // iterator must not be done when this is called.
   789       inline bool SkipItemsWantingParentType(ParentType aParentType);
   791       // Skip over non-replaced inline frames and positioned frames.
   792       // Return whether the iterator is done after doing that.
   793       // The iterator must not be done when this is called.
   794       inline bool SkipItemsThatNeedAnonFlexItem(
   795         const nsFrameConstructorState& aState);
   797       // Skip to the first frame that is a non-replaced inline or is
   798       // positioned.  Return whether the iterator is done after doing that.
   799       // The iterator must not be done when this is called.
   800       inline bool SkipItemsThatDontNeedAnonFlexItem(
   801         const nsFrameConstructorState& aState);
   803       // Skip over whitespace.  Return whether the iterator is done after doing
   804       // that.  The iterator must not be done, and must be pointing to a
   805       // whitespace item when this is called.
   806       inline bool SkipWhitespace(nsFrameConstructorState& aState);
   808       // Remove the item pointed to by this iterator from its current list and
   809       // Append it to aTargetList.  This iterator is advanced to point to the
   810       // next item in its list.  aIter must not be done.  aOther must not be
   811       // the list this iterator is iterating over..
   812       void AppendItemToList(FrameConstructionItemList& aTargetList);
   814       // As above, but moves all items starting with this iterator until we
   815       // get to aEnd; the item pointed to by aEnd is not stolen.  This method
   816       // might have optimizations over just looping and doing StealItem for
   817       // some special cases.  After this method returns, this iterator will
   818       // point to the item aEnd points to now; aEnd is not modified.
   819       // aTargetList must not be the list this iterator is iterating over.
   820       void AppendItemsToList(const Iterator& aEnd,
   821                              FrameConstructionItemList& aTargetList);
   823       // Insert aItem in this iterator's list right before the item pointed to
   824       // by this iterator.  After the insertion, this iterator will continue to
   825       // point to the item it now points to (the one just after the
   826       // newly-inserted item).  This iterator is allowed to be done; in that
   827       // case this call just appends the given item to the list.
   828       void InsertItem(FrameConstructionItem* aItem);
   830       // Delete the items between this iterator and aEnd, including the item
   831       // this iterator currently points to but not including the item pointed
   832       // to by aEnd.  When this returns, this iterator will point to the same
   833       // item as aEnd.  This iterator must not equal aEnd when this method is
   834       // called.
   835       void DeleteItemsTo(const Iterator& aEnd);
   837     private:
   838       PRCList* mCurrent;
   839       PRCList* mEnd;
   840       FrameConstructionItemList& mList;
   841     };
   843   private:
   844     static FrameConstructionItem* ToItem(PRCList* item) {
   845       return static_cast<FrameConstructionItem*>(item);
   846     }
   848     struct UndisplayedItem {
   849       UndisplayedItem(nsIContent* aContent, nsStyleContext* aStyleContext) :
   850         mContent(aContent), mStyleContext(aStyleContext)
   851       {}
   853       nsIContent * const mContent;
   854       nsRefPtr<nsStyleContext> mStyleContext;
   855     };
   857     // Adjust our various counts for aItem being added or removed.  aDelta
   858     // should be either +1 or -1 depending on which is happening.
   859     void AdjustCountsForItem(FrameConstructionItem* aItem, int32_t aDelta);
   861     PRCList mItems;
   862     uint32_t mInlineCount;
   863     uint32_t mBlockCount;
   864     uint32_t mLineParticipantCount;
   865     uint32_t mItemCount;
   866     uint32_t mDesiredParentCounts[eParentTypeCount];
   867     // True if there is guaranteed to be a line boundary before the
   868     // frames created by these items
   869     bool mLineBoundaryAtStart;
   870     // True if there is guaranteed to be a line boundary after the
   871     // frames created by these items
   872     bool mLineBoundaryAtEnd;
   873     // True if the parent is guaranteed to have no XBL anonymous children
   874     bool mParentHasNoXBLChildren;
   875     // True if we have tried constructing frames from this list
   876     bool mTriedConstructingFrames;
   878     nsTArray<UndisplayedItem> mUndisplayedItems;
   879   };
   881   typedef FrameConstructionItemList::Iterator FCItemIterator;
   883   /* A struct representing an item for which frames might need to be
   884    * constructed.  This contains all the information needed to construct the
   885    * frame other than the parent frame and whatever would be stored in the
   886    * frame constructor state. */
   887   struct FrameConstructionItem : public PRCList {
   888     // No need to PR_INIT_CLIST in the constructor because the only
   889     // place that creates us immediately appends us.
   890     FrameConstructionItem(const FrameConstructionData* aFCData,
   891                           nsIContent* aContent,
   892                           nsIAtom* aTag,
   893                           int32_t aNameSpaceID,
   894                           PendingBinding* aPendingBinding,
   895                           already_AddRefed<nsStyleContext>& aStyleContext,
   896                           bool aSuppressWhiteSpaceOptimizations,
   897                           nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren) :
   898       mFCData(aFCData), mContent(aContent), mTag(aTag),
   899       mNameSpaceID(aNameSpaceID),
   900       mPendingBinding(aPendingBinding), mStyleContext(aStyleContext),
   901       mSuppressWhiteSpaceOptimizations(aSuppressWhiteSpaceOptimizations),
   902       mIsText(false), mIsGeneratedContent(false),
   903       mIsAnonymousContentCreatorContent(false),
   904       mIsRootPopupgroup(false), mIsAllInline(false), mIsBlock(false),
   905       mHasInlineEnds(false), mIsPopup(false),
   906       mIsLineParticipant(false), mIsForSVGAElement(false)
   907     {
   908       if (aAnonChildren) {
   909         NS_ASSERTION(!(mFCData->mBits & FCDATA_FUNC_IS_FULL_CTOR) ||
   910                      mFCData->mFullConstructor ==
   911                        &nsCSSFrameConstructor::ConstructInline,
   912                      "This is going to fail");
   913         NS_ASSERTION(!(mFCData->mBits & FCDATA_USE_CHILD_ITEMS),
   914                      "nsIAnonymousContentCreator::CreateAnonymousContent "
   915                      "implementations should not output a list where the "
   916                      "items have children in this case");
   917         mAnonChildren.SwapElements(*aAnonChildren);
   918       }
   919     }
   920     ~FrameConstructionItem() {
   921       if (mIsGeneratedContent) {
   922         mContent->UnbindFromTree();
   923         NS_RELEASE(mContent);
   924       }
   925     }
   927     ParentType DesiredParentType() {
   928       return FCDATA_DESIRED_PARENT_TYPE(mFCData->mBits);
   929     }
   931     // Indicates whether (when in a flexbox container) this item needs to be
   932     // wrapped in an anonymous block.
   933     bool NeedsAnonFlexItem(const nsFrameConstructorState& aState);
   935     // Don't call this unless the frametree really depends on the answer!
   936     // Especially so for generated content, where we don't want to reframe
   937     // things.
   938     bool IsWhitespace(nsFrameConstructorState& aState) const;
   940     bool IsLineBoundary() const {
   941       return mIsBlock || (mFCData->mBits & FCDATA_IS_LINE_BREAK);
   942     }
   944     // The FrameConstructionData to use.
   945     const FrameConstructionData* mFCData;
   946     // The nsIContent node to use when initializing the new frame.
   947     nsIContent* mContent;
   948     // The XBL-resolved tag name to use for frame construction.
   949     nsIAtom* mTag;
   950     // The XBL-resolved namespace to use for frame construction.
   951     int32_t mNameSpaceID;
   952     // The PendingBinding for this frame construction item, if any.  May be
   953     // null.  We maintain a list of PendingBindings in the frame construction
   954     // state in the order in which AddToAttachedQueue should be called on them:
   955     // depth-first, post-order traversal order.  Since we actually traverse the
   956     // DOM in a mix of breadth-first and depth-first, it is the responsibility
   957     // of whoever constructs FrameConstructionItem kids of a given
   958     // FrameConstructionItem to push its mPendingBinding as the current
   959     // insertion point before doing so and pop it afterward.
   960     PendingBinding* mPendingBinding;
   961     // The style context to use for creating the new frame.
   962     nsRefPtr<nsStyleContext> mStyleContext;
   963     // Whether optimizations to skip constructing textframes around
   964     // this content need to be suppressed.
   965     bool mSuppressWhiteSpaceOptimizations;
   966     // Whether this is a text content item.
   967     bool mIsText;
   968     // Whether this is a generated content container.
   969     // If it is, mContent is a strong pointer.
   970     bool mIsGeneratedContent;
   971     // Whether this is an item for nsIAnonymousContentCreator content.
   972     bool mIsAnonymousContentCreatorContent;
   973     // Whether this is an item for the root popupgroup.
   974     bool mIsRootPopupgroup;
   975     // Whether construction from this item will create only frames that are
   976     // IsInlineOutside() in the principal child list.  This is not precise, but
   977     // conservative: if true the frames will really be inline, whereas if false
   978     // they might still all be inline.
   979     bool mIsAllInline;
   980     // Whether construction from this item will create only frames that are
   981     // IsBlockOutside() in the principal child list.  This is not precise, but
   982     // conservative: if true the frames will really be blocks, whereas if false
   983     // they might still be blocks (and in particular, out-of-flows that didn't
   984     // find a containing block).
   985     bool mIsBlock;
   986     // Whether construction from this item will give leading and trailing
   987     // inline frames.  This is equal to mIsAllInline, except for inline frame
   988     // items, where it's always true, whereas mIsAllInline might be false due
   989     // to {ib} splits.
   990     bool mHasInlineEnds;
   991     // Whether construction from this item will create a popup that needs to
   992     // go into the global popup items.
   993     bool mIsPopup;
   994     // Whether this item should be treated as a line participant
   995     bool mIsLineParticipant;
   996     // Whether this item is for an SVG <a> element
   997     bool mIsForSVGAElement;
   999     // Child frame construction items.
  1000     FrameConstructionItemList mChildItems;
  1002     // ContentInfo list for children that have yet to have
  1003     // FrameConstructionItem objects created for them. This exists because
  1004     // AddFrameConstructionItemsInternal needs a valid frame, but in the case
  1005     // that nsIAnonymousContentCreator::CreateAnonymousContent returns items
  1006     // that have their own children (so we have a tree of ContentInfo objects
  1007     // rather than a flat list) we don't yet have a frame to provide to
  1008     // AddFrameConstructionItemsInternal in order to create the items for the
  1009     // grandchildren. That prevents FrameConstructionItems from being created
  1010     // for these grandchildren (and any descendants that they may have),
  1011     // otherwise they could have been added to the mChildItems member of their
  1012     // parent FrameConstructionItem. As it is, the grandchildren ContentInfo
  1013     // list has to be stored in this mAnonChildren member in order to delay
  1014     // construction of the FrameConstructionItems for the grandchildren until
  1015     // a frame has been created for their parent item.
  1016     nsTArray<nsIAnonymousContentCreator::ContentInfo> mAnonChildren;
  1018   private:
  1019     FrameConstructionItem(const FrameConstructionItem& aOther) MOZ_DELETE; /* not implemented */
  1020   };
  1022   /**
  1023    * Function to create the anonymous flex items that we need.
  1024    * If aParentFrame is not a nsFlexContainerFrame then this method is a NOP.
  1025    * @param aItems the child frame construction items before pseudo creation
  1026    * @param aParentFrame the parent frame
  1027    */
  1028   void CreateNeededAnonFlexItems(nsFrameConstructorState& aState,
  1029                                     FrameConstructionItemList& aItems,
  1030                                     nsIFrame* aParentFrame);
  1032   /**
  1033    * Function to create the table pseudo items we need.
  1034    * @param aItems the child frame construction items before pseudo creation
  1035    * @param aParentFrame the parent frame we're creating pseudos for
  1036    */
  1037   inline void CreateNeededTablePseudos(nsFrameConstructorState& aState,
  1038                                        FrameConstructionItemList& aItems,
  1039                                        nsIFrame* aParentFrame);
  1041   /**
  1042    * Function to adjust aParentFrame to deal with captions.
  1043    * @param aParentFrame the frame we think should be the parent.  This will be
  1044    *        adjusted to point to the right parent frame.
  1045    * @param aFCData the FrameConstructionData that would be used for frame
  1046    *        construction.
  1047    * @param aStyleContext the style context for aChildContent
  1048    */
  1049   // XXXbz this function should really go away once we rework pseudo-frame
  1050   // handling to be better. This should simply be part of the job of
  1051   // GetGeometricParent, and stuff like the frameitems and parent frame should
  1052   // be kept track of in the state...
  1053   void AdjustParentFrame(nsIFrame* &                  aParentFrame,
  1054                          const FrameConstructionData* aFCData,
  1055                          nsStyleContext*              aStyleContext);
  1057   // END TABLE SECTION
  1059 protected:
  1060   static nsIFrame* CreatePlaceholderFrameFor(nsIPresShell*    aPresShell,
  1061                                              nsIContent*      aContent,
  1062                                              nsIFrame*        aFrame,
  1063                                              nsStyleContext*  aStyleContext,
  1064                                              nsIFrame*        aParentFrame,
  1065                                              nsIFrame*        aPrevInFlow,
  1066                                              nsFrameState     aTypeBit);
  1068 private:
  1069   // ConstructSelectFrame puts the new frame in aFrameItems and
  1070   // handles the kids of the select.
  1071   nsIFrame* ConstructSelectFrame(nsFrameConstructorState& aState,
  1072                                  FrameConstructionItem&   aItem,
  1073                                  nsIFrame*                aParentFrame,
  1074                                  const nsStyleDisplay*    aStyleDisplay,
  1075                                  nsFrameItems&            aFrameItems);
  1077   // ConstructFieldSetFrame puts the new frame in aFrameItems and
  1078   // handles the kids of the fieldset
  1079   nsIFrame* ConstructFieldSetFrame(nsFrameConstructorState& aState,
  1080                                    FrameConstructionItem&   aItem,
  1081                                    nsIFrame*                aParentFrame,
  1082                                    const nsStyleDisplay*    aStyleDisplay,
  1083                                    nsFrameItems&            aFrameItems);
  1085   // aParentFrame might be null.  If it is, that means it was an
  1086   // inline frame.
  1087   static const FrameConstructionData* FindTextData(nsIFrame* aParentFrame);
  1089   void ConstructTextFrame(const FrameConstructionData* aData,
  1090                           nsFrameConstructorState& aState,
  1091                           nsIContent*              aContent,
  1092                           nsIFrame*                aParentFrame,
  1093                           nsStyleContext*          aStyleContext,
  1094                           nsFrameItems&            aFrameItems);
  1096   // If aPossibleTextContent is a text node and doesn't have a frame, append a
  1097   // frame construction item for it to aItems.
  1098   void AddTextItemIfNeeded(nsFrameConstructorState& aState,
  1099                            nsIFrame* aParentFrame,
  1100                            nsIContent* aPossibleTextContent,
  1101                            FrameConstructionItemList& aItems);
  1103   // If aParentContent's child aContent is a text node and
  1104   // doesn't have a frame, try to create a frame for it.
  1105   void ReframeTextIfNeeded(nsIContent* aParentContent,
  1106                            nsIContent* aContent);
  1108   void AddPageBreakItem(nsIContent* aContent,
  1109                         nsStyleContext* aMainStyleContext,
  1110                         FrameConstructionItemList& aItems);
  1112   // Function to find FrameConstructionData for aElement.  Will return
  1113   // null if aElement is not HTML.
  1114   // aParentFrame might be null.  If it is, that means it was an
  1115   // inline frame.
  1116   static const FrameConstructionData* FindHTMLData(Element* aContent,
  1117                                                    nsIAtom* aTag,
  1118                                                    int32_t aNameSpaceID,
  1119                                                    nsIFrame* aParentFrame,
  1120                                                    nsStyleContext* aStyleContext);
  1121   // HTML data-finding helper functions
  1122   static const FrameConstructionData*
  1123     FindImgData(Element* aElement, nsStyleContext* aStyleContext);
  1124   static const FrameConstructionData*
  1125     FindImgControlData(Element* aElement, nsStyleContext* aStyleContext);
  1126   static const FrameConstructionData*
  1127     FindInputData(Element* aElement, nsStyleContext* aStyleContext);
  1128   static const FrameConstructionData*
  1129     FindObjectData(Element* aElement, nsStyleContext* aStyleContext);
  1130   static const FrameConstructionData*
  1131     FindCanvasData(Element* aElement, nsStyleContext* aStyleContext);
  1133   /* Construct a frame from the given FrameConstructionItem.  This function
  1134      will handle adding the frame to frame lists, processing children, setting
  1135      the frame as the primary frame for the item's content, and so forth.
  1137      @param aItem the FrameConstructionItem to use.
  1138      @param aState the frame construction state to use.
  1139      @param aParentFrame the frame to set as the parent of the
  1140                          newly-constructed frame.
  1141      @param aFrameItems the frame list to add the new frame (or its
  1142                         placeholder) to.
  1143   */
  1144   void ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
  1145                                       nsFrameConstructorState& aState,
  1146                                       nsIFrame* aParentFrame,
  1147                                       nsFrameItems& aFrameItems);
  1149   // possible flags for AddFrameConstructionItemInternal's aFlags argument
  1150   /* Allow xbl:base to affect the tag/namespace used. */
  1151 #define ITEM_ALLOW_XBL_BASE 0x1
  1152   /* Allow page-break before and after items to be created if the
  1153      style asks for them. */
  1154 #define ITEM_ALLOW_PAGE_BREAK 0x2
  1155   /* The item is a generated content item. */
  1156 #define ITEM_IS_GENERATED_CONTENT 0x4
  1157   /* The item is within an SVG text block frame. */
  1158 #define ITEM_IS_WITHIN_SVG_TEXT 0x8
  1159   /* The item allows items to be created for SVG <textPath> children. */
  1160 #define ITEM_ALLOWS_TEXT_PATH_CHILD 0x10
  1161   /* The item is content created by an nsIAnonymousContentCreator frame */
  1162 #define ITEM_IS_ANONYMOUSCONTENTCREATOR_CONTENT 0x20
  1163   // The guts of AddFrameConstructionItems
  1164   // aParentFrame might be null.  If it is, that means it was an
  1165   // inline frame.
  1166   void AddFrameConstructionItemsInternal(nsFrameConstructorState& aState,
  1167                                          nsIContent*              aContent,
  1168                                          nsIFrame*                aParentFrame,
  1169                                          nsIAtom*                 aTag,
  1170                                          int32_t                  aNameSpaceID,
  1171                                          bool                     aSuppressWhiteSpaceOptimizations,
  1172                                          nsStyleContext*          aStyleContext,
  1173                                          uint32_t                 aFlags,
  1174                                          nsTArray<nsIAnonymousContentCreator::ContentInfo>* aAnonChildren,
  1175                                          FrameConstructionItemList& aItems);
  1177   /**
  1178    * Construct frames for the given item list and parent frame, and put the
  1179    * resulting frames in aFrameItems.
  1180    */
  1181   void ConstructFramesFromItemList(nsFrameConstructorState& aState,
  1182                                    FrameConstructionItemList& aItems,
  1183                                    nsIFrame* aParentFrame,
  1184                                    nsFrameItems& aFrameItems);
  1185   void ConstructFramesFromItem(nsFrameConstructorState& aState,
  1186                                FCItemIterator& aItem,
  1187                                nsIFrame* aParentFrame,
  1188                                nsFrameItems& aFrameItems);
  1189   static bool AtLineBoundary(FCItemIterator& aIter);
  1191   nsresult CreateAnonymousFrames(nsFrameConstructorState& aState,
  1192                                  nsIContent*              aParent,
  1193                                  nsIFrame*                aParentFrame,
  1194                                  PendingBinding  *        aPendingBinding,
  1195                                  nsFrameItems&            aChildItems);
  1197   nsresult GetAnonymousContent(nsIContent* aParent,
  1198                                nsIFrame* aParentFrame,
  1199                                nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonContent);
  1201 //MathML Mod - RBS
  1202   /**
  1203    * Takes the frames in aBlockItems and wraps them in a new anonymous block
  1204    * frame whose content is aContent and whose parent will be aParentFrame.
  1205    * The anonymous block is added to aNewItems and aBlockItems is cleared.
  1206    */
  1207   void FlushAccumulatedBlock(nsFrameConstructorState& aState,
  1208                              nsIContent* aContent,
  1209                              nsIFrame* aParentFrame,
  1210                              nsFrameItems& aBlockItems,
  1211                              nsFrameItems& aNewItems);
  1213   // Function to find FrameConstructionData for aContent.  Will return
  1214   // null if aContent is not MathML.
  1215   static const FrameConstructionData* FindMathMLData(Element* aElement,
  1216                                                      nsIAtom* aTag,
  1217                                                      int32_t aNameSpaceID,
  1218                                                      nsStyleContext* aStyleContext);
  1220   // Function to find FrameConstructionData for aContent.  Will return
  1221   // null if aContent is not XUL.
  1222   static const FrameConstructionData* FindXULTagData(Element* aElement,
  1223                                                      nsIAtom* aTag,
  1224                                                      int32_t aNameSpaceID,
  1225                                                      nsStyleContext* aStyleContext);
  1226   // XUL data-finding helper functions and structures
  1227 #ifdef MOZ_XUL
  1228   static const FrameConstructionData*
  1229     FindPopupGroupData(Element* aElement, nsStyleContext* aStyleContext);
  1230   // sXULTextBoxData used for both labels and descriptions
  1231   static const FrameConstructionData sXULTextBoxData;
  1232   static const FrameConstructionData*
  1233     FindXULLabelData(Element* aElement, nsStyleContext* aStyleContext);
  1234   static const FrameConstructionData*
  1235     FindXULDescriptionData(Element* aElement, nsStyleContext* aStyleContext);
  1236 #ifdef XP_MACOSX
  1237   static const FrameConstructionData*
  1238     FindXULMenubarData(Element* aElement, nsStyleContext* aStyleContext);
  1239 #endif /* XP_MACOSX */
  1240   static const FrameConstructionData*
  1241     FindXULListBoxBodyData(Element* aElement, nsStyleContext* aStyleContext);
  1242   static const FrameConstructionData*
  1243     FindXULListItemData(Element* aElement, nsStyleContext* aStyleContext);
  1244 #endif /* MOZ_XUL */
  1246   // Function to find FrameConstructionData for aContent using one of the XUL
  1247   // display types.  Will return null if aDisplay doesn't have a XUL display
  1248   // type.  This function performs no other checks, so should only be called if
  1249   // we know for sure that the content is not something that should get a frame
  1250   // constructed by tag.
  1251   static const FrameConstructionData*
  1252     FindXULDisplayData(const nsStyleDisplay* aDisplay,
  1253                        Element* aElement,
  1254                        nsStyleContext* aStyleContext);
  1256   /**
  1257    * Constructs an outer frame, an anonymous child that wraps its real
  1258    * children, and its descendant frames.  This is used by both ConstructOuterSVG
  1259    * and ConstructMarker, which both want an anonymous block child for their
  1260    * children to go in to.
  1261    */
  1262   nsIFrame* ConstructFrameWithAnonymousChild(
  1263                                   nsFrameConstructorState& aState,
  1264                                   FrameConstructionItem&   aItem,
  1265                                   nsIFrame*                aParentFrame,
  1266                                   const nsStyleDisplay*    aDisplay,
  1267                                   nsFrameItems&            aFrameItems,
  1268                                   FrameCreationFunc        aConstructor,
  1269                                   FrameCreationFunc        aInnerConstructor,
  1270                                   nsICSSAnonBoxPseudo*     aInnerPseudo,
  1271                                   bool                     aCandidateRootFrame);
  1273   /**
  1274    * Construct an nsSVGOuterSVGFrame.
  1275    */
  1276   nsIFrame* ConstructOuterSVG(nsFrameConstructorState& aState,
  1277                               FrameConstructionItem&   aItem,
  1278                               nsIFrame*                aParentFrame,
  1279                               const nsStyleDisplay*    aDisplay,
  1280                               nsFrameItems&            aFrameItems);
  1282   /**
  1283    * Construct an nsSVGMarkerFrame.
  1284    */
  1285   nsIFrame* ConstructMarker(nsFrameConstructorState& aState,
  1286                             FrameConstructionItem&   aItem,
  1287                             nsIFrame*                aParentFrame,
  1288                             const nsStyleDisplay*    aDisplay,
  1289                             nsFrameItems&            aFrameItems);
  1291   static const FrameConstructionData* FindSVGData(Element* aElement,
  1292                                                   nsIAtom* aTag,
  1293                                                   int32_t aNameSpaceID,
  1294                                                   nsIFrame* aParentFrame,
  1295                                                   bool aIsWithinSVGText,
  1296                                                   bool aAllowsTextPathChild,
  1297                                                   nsStyleContext* aStyleContext);
  1299   /* Not static because it does PropagateScrollToViewport.  If this
  1300      changes, make this static */
  1301   const FrameConstructionData*
  1302     FindDisplayData(const nsStyleDisplay* aDisplay, Element* aElement,
  1303                     nsIFrame* aParentFrame, nsStyleContext* aStyleContext);
  1305   /**
  1306    * Construct a scrollable block frame
  1307    */
  1308   nsIFrame* ConstructScrollableBlock(nsFrameConstructorState& aState,
  1309                                      FrameConstructionItem&   aItem,
  1310                                      nsIFrame*                aParentFrame,
  1311                                      const nsStyleDisplay*    aDisplay,
  1312                                      nsFrameItems&            aFrameItems);
  1314   /**
  1315    * Construct a non-scrollable block frame
  1316    */
  1317   nsIFrame* ConstructNonScrollableBlock(nsFrameConstructorState& aState,
  1318                                         FrameConstructionItem&   aItem,
  1319                                         nsIFrame*                aParentFrame,
  1320                                         const nsStyleDisplay*    aDisplay,
  1321                                         nsFrameItems&            aFrameItems);
  1323   /**
  1324    * This adds FrameConstructionItem objects to aItemsToConstruct for the
  1325    * anonymous content returned by an nsIAnonymousContentCreator::
  1326    * CreateAnonymousContent implementation.
  1327    */
  1328   void AddFCItemsForAnonymousContent(
  1329             nsFrameConstructorState& aState,
  1330             nsIFrame* aFrame,
  1331             nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
  1332             FrameConstructionItemList& aItemsToConstruct,
  1333             uint32_t aExtraFlags = 0);
  1335   /**
  1336    * Construct the frames for the children of aContent.  "children" is defined
  1337    * as "whatever FlattenedChildIterator returns for aContent".  This means we're
  1338    * basically operating on children in the "flattened tree" per sXBL/XBL2.
  1339    * This method will also handle constructing ::before, ::after,
  1340    * ::first-letter, and ::first-line frames, as needed and if allowed.
  1342    * If the parent is a float containing block, this method will handle pushing
  1343    * it as the float containing block in aState (so there's no need for callers
  1344    * to push it themselves).
  1346    * @param aState the frame construction state
  1347    * @param aContent the content node whose children need frames
  1348    * @param aStyleContext the style context for aContent
  1349    * @param aFrame the frame to use as the parent frame for the new in-flow
  1350    *        kids. Note that this must be its own content insertion frame, but
  1351    *        need not be be the primary frame for aContent.  This frame will be
  1352    *        pushed as the float containing block, as needed.  aFrame is also
  1353    *        used to find the parent style context for the kids' style contexts
  1354    *        (not necessary aFrame's style context).
  1355    * @param aCanHaveGeneratedContent Whether to allow :before and
  1356    *        :after styles on the parent.
  1357    * @param aFrameItems the list in which we should place the in-flow children
  1358    * @param aAllowBlockStyles Whether to allow first-letter and first-line
  1359    *        styles on the parent.
  1360    * @param aPendingBinding Make sure to push this into aState before doing any
  1361    *        child item construction.
  1362    * @param aPossiblyLeafFrame if non-null, this should be used for the isLeaf
  1363    *        test and the anonymous content creation.  If null, aFrame will be
  1364    *        used.
  1365    */
  1366   void ProcessChildren(nsFrameConstructorState& aState,
  1367                        nsIContent*              aContent,
  1368                        nsStyleContext*          aStyleContext,
  1369                        nsIFrame*                aFrame,
  1370                        const bool               aCanHaveGeneratedContent,
  1371                        nsFrameItems&            aFrameItems,
  1372                        const bool               aAllowBlockStyles,
  1373                        PendingBinding*          aPendingBinding,
  1374                        nsIFrame*                aPossiblyLeafFrame = nullptr);
  1376   nsIFrame* GetFrameFor(nsIContent* aContent);
  1378   /**
  1379    * These two functions are used when we start frame creation from a non-root
  1380    * element. They should recreate the same state that we would have
  1381    * arrived at if we had built frames from the root frame to aFrame.
  1382    * Therefore, any calls to PushFloatContainingBlock and
  1383    * PushAbsoluteContainingBlock during frame construction should get
  1384    * corresponding logic in these functions.
  1385    */
  1386 public:
  1387   enum ContainingBlockType {
  1388     ABS_POS,
  1389     FIXED_POS
  1390   };
  1391   nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame, ContainingBlockType aType);
  1392   nsIFrame* GetFloatContainingBlock(nsIFrame* aFrame);
  1394 private:
  1395   nsIContent* PropagateScrollToViewport();
  1397   // Build a scroll frame:
  1398   //  Calls BeginBuildingScrollFrame, InitAndRestoreFrame, and then FinishBuildingScrollFrame.
  1399   // @param aNewFrame the created scrollframe --- output only
  1400   // @param aParentFrame the geometric parent that the scrollframe will have.
  1401   nsresult
  1402   BuildScrollFrame(nsFrameConstructorState& aState,
  1403                    nsIContent*              aContent,
  1404                    nsStyleContext*          aContentStyle,
  1405                    nsIFrame*                aScrolledFrame,
  1406                    nsIFrame*                aParentFrame,
  1407                    nsIFrame*&               aNewFrame);
  1409   // Builds the initial ScrollFrame
  1410   already_AddRefed<nsStyleContext>
  1411   BeginBuildingScrollFrame(nsFrameConstructorState& aState,
  1412                            nsIContent*              aContent,
  1413                            nsStyleContext*          aContentStyle,
  1414                            nsIFrame*                aParentFrame,
  1415                            nsIAtom*                 aScrolledPseudo,
  1416                            bool                     aIsRoot,
  1417                            nsIFrame*&               aNewFrame);
  1419   // Completes the building of the scrollframe:
  1420   // Creates a view for the scrolledframe and makes it the child of the scrollframe.
  1421   void
  1422   FinishBuildingScrollFrame(nsIFrame* aScrollFrame,
  1423                             nsIFrame* aScrolledFrame);
  1425   // InitializeSelectFrame puts scrollFrame in aFrameItems if aBuildCombobox is false
  1426   // aBuildCombobox indicates if we are building a combobox that has a dropdown
  1427   // popup widget or not.
  1428   nsresult
  1429   InitializeSelectFrame(nsFrameConstructorState& aState,
  1430                         nsIFrame*                scrollFrame,
  1431                         nsIFrame*                scrolledFrame,
  1432                         nsIContent*              aContent,
  1433                         nsIFrame*                aParentFrame,
  1434                         nsStyleContext*          aStyleContext,
  1435                         bool                     aBuildCombobox,
  1436                         PendingBinding*          aPendingBinding,
  1437                         nsFrameItems&            aFrameItems);
  1439   nsresult MaybeRecreateFramesForElement(Element* aElement);
  1441   // If aAsyncInsert is true then a restyle event will be posted to handle the
  1442   // required ContentInserted call instead of doing it immediately.
  1443   nsresult RecreateFramesForContent(nsIContent* aContent, bool aAsyncInsert);
  1445   // If removal of aFrame from the frame tree requires reconstruction of some
  1446   // containing block (either of aFrame or of its parent) due to {ib} splits or
  1447   // table pseudo-frames, recreate the relevant frame subtree.  The return value
  1448   // indicates whether this happened.  If this method returns true, *aResult is
  1449   // the return value of ReframeContainingBlock or RecreateFramesForContent.  If
  1450   // this method returns false, the value of *aResult is not affected.  aFrame
  1451   // and aResult must not be null.  aFrame must be the result of a
  1452   // GetPrimaryFrame() call on a content node (which means its parent is also
  1453   // not null).
  1454   bool MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame,
  1455                                                nsresult* aResult);
  1457   nsIFrame* CreateContinuingOuterTableFrame(nsIPresShell*    aPresShell,
  1458                                             nsPresContext*  aPresContext,
  1459                                             nsIFrame*        aFrame,
  1460                                             nsIFrame*        aParentFrame,
  1461                                             nsIContent*      aContent,
  1462                                             nsStyleContext*  aStyleContext);
  1464   nsIFrame* CreateContinuingTableFrame(nsIPresShell*    aPresShell,
  1465                                        nsPresContext*  aPresContext,
  1466                                        nsIFrame*        aFrame,
  1467                                        nsIFrame*        aParentFrame,
  1468                                        nsIContent*      aContent,
  1469                                        nsStyleContext*  aStyleContext);
  1471   //----------------------------------------
  1473   // Methods support creating block frames and their children
  1475   already_AddRefed<nsStyleContext>
  1476   GetFirstLetterStyle(nsIContent*      aContent,
  1477                       nsStyleContext*  aStyleContext);
  1479   already_AddRefed<nsStyleContext>
  1480   GetFirstLineStyle(nsIContent*      aContent,
  1481                     nsStyleContext*  aStyleContext);
  1483   bool ShouldHaveFirstLetterStyle(nsIContent*      aContent,
  1484                                     nsStyleContext*  aStyleContext);
  1486   // Check whether a given block has first-letter style.  Make sure to
  1487   // only pass in blocks!  And don't pass in null either.
  1488   bool HasFirstLetterStyle(nsIFrame* aBlockFrame);
  1490   bool ShouldHaveFirstLineStyle(nsIContent*      aContent,
  1491                                   nsStyleContext*  aStyleContext);
  1493   void ShouldHaveSpecialBlockStyle(nsIContent*      aContent,
  1494                                    nsStyleContext*  aStyleContext,
  1495                                    bool*          aHaveFirstLetterStyle,
  1496                                    bool*          aHaveFirstLineStyle);
  1498   // |aContentParentFrame| should be null if it's really the same as
  1499   // |aParentFrame|.
  1500   // @param aFrameItems where we want to put the block in case it's in-flow.
  1501   // @param aNewFrame an in/out parameter. On input it is the block to be
  1502   // constructed. On output it is reset to the outermost
  1503   // frame constructed (e.g. if we need to wrap the block in an
  1504   // nsColumnSetFrame.
  1505   // @param aParentFrame is the desired parent for the (possibly wrapped)
  1506   // block
  1507   // @param aContentParent is the parent the block would have if it
  1508   // were in-flow
  1509   // @param aPositionedFrameForAbsPosContainer if non-null, then the new
  1510   // block should be an abs-pos container and aPositionedFrameForAbsPosContainer
  1511   // is the frame whose style is making this block an abs-pos container.
  1512   // @param aPendingBinding the pending binding  from this block's frame
  1513   // construction item.
  1514   void ConstructBlock(nsFrameConstructorState& aState,
  1515                       const nsStyleDisplay*    aDisplay,
  1516                       nsIContent*              aContent,
  1517                       nsIFrame*                aParentFrame,
  1518                       nsIFrame*                aContentParentFrame,
  1519                       nsStyleContext*          aStyleContext,
  1520                       nsIFrame**               aNewFrame,
  1521                       nsFrameItems&            aFrameItems,
  1522                       nsIFrame*                aPositionedFrameForAbsPosContainer,
  1523                       PendingBinding*          aPendingBinding);
  1525   nsIFrame* ConstructInline(nsFrameConstructorState& aState,
  1526                             FrameConstructionItem&   aItem,
  1527                             nsIFrame*                aParentFrame,
  1528                             const nsStyleDisplay*    aDisplay,
  1529                             nsFrameItems&            aFrameItems);
  1531   /**
  1532    * Create any additional {ib} siblings needed to contain aChildItems and put
  1533    * them in aSiblings.
  1535    * @param aState the frame constructor state
  1536    * @param aInitialInline is an already-existing inline frame that will be
  1537    *                       part of this {ib} split and come before everything
  1538    *                       in aSiblings.
  1539    * @param aIsPositioned true if aInitialInline is positioned.
  1540    * @param aChildItems is a child list starting with a block; this method
  1541    *                    assumes that the inline has already taken all the
  1542    *                    children it wants.  When the method returns aChildItems
  1543    *                    will be empty.
  1544    * @param aSiblings the nsFrameItems to put the newly-created siblings into.
  1546    * This method is responsible for making any SetFrameIsIBSplit calls that are
  1547    * needed.
  1548    */
  1549   void CreateIBSiblings(nsFrameConstructorState& aState,
  1550                         nsIFrame* aInitialInline,
  1551                         bool aIsPositioned,
  1552                         nsFrameItems& aChildItems,
  1553                         nsFrameItems& aSiblings);
  1555   /**
  1556    * For an inline aParentItem, construct its list of child
  1557    * FrameConstructionItems and set its mIsAllInline flag appropriately.
  1558    */
  1559   void BuildInlineChildItems(nsFrameConstructorState& aState,
  1560                              FrameConstructionItem& aParentItem,
  1561                              bool aItemIsWithinSVGText,
  1562                              bool aItemAllowsTextPathChild);
  1564   // Determine whether we need to wipe out what we just did and start over
  1565   // because we're doing something like adding block kids to an inline frame
  1566   // (and therefore need an {ib} split).  aPrevSibling must be correct, even in
  1567   // aIsAppend cases.  Passing aIsAppend false even when an append is happening
  1568   // is ok in terms of correctness, but can lead to unnecessary reframing.  If
  1569   // aIsAppend is true, then the caller MUST call
  1570   // nsCSSFrameConstructor::AppendFrames (as opposed to
  1571   // nsFrameManager::InsertFrames directly) to add the new frames.
  1572   // @return true if we reconstructed the containing block, false
  1573   // otherwise
  1574   bool WipeContainingBlock(nsFrameConstructorState& aState,
  1575                              nsIFrame*                aContainingBlock,
  1576                              nsIFrame*                aFrame,
  1577                              FrameConstructionItemList& aItems,
  1578                              bool                     aIsAppend,
  1579                              nsIFrame*                aPrevSibling);
  1581   nsresult ReframeContainingBlock(nsIFrame* aFrame);
  1583   //----------------------------------------
  1585   // Methods support :first-letter style
  1587   void CreateFloatingLetterFrame(nsFrameConstructorState& aState,
  1588                                  nsIFrame*                aBlockFrame,
  1589                                  nsIContent*              aTextContent,
  1590                                  nsIFrame*                aTextFrame,
  1591                                  nsIContent*              aBlockContent,
  1592                                  nsIFrame*                aParentFrame,
  1593                                  nsStyleContext*          aStyleContext,
  1594                                  nsFrameItems&            aResult);
  1596   void CreateLetterFrame(nsIFrame*                aBlockFrame,
  1597                          nsIFrame*                aBlockContinuation,
  1598                          nsIContent*              aTextContent,
  1599                          nsIFrame*                aParentFrame,
  1600                          nsFrameItems&            aResult);
  1602   void WrapFramesInFirstLetterFrame(nsIContent*   aBlockContent,
  1603                                     nsIFrame*     aBlockFrame,
  1604                                     nsFrameItems& aBlockFrames);
  1606   /**
  1607    * Looks in the block aBlockFrame for a text frame that contains the
  1608    * first-letter of the block and creates the necessary first-letter frames
  1609    * and returns them in aLetterFrames.
  1611    * @param aBlockFrame the (first-continuation of) the block we are creating a
  1612    *                    first-letter frame for
  1613    * @param aBlockContinuation the current continuation of the block that we
  1614    *                           are looking in for a textframe with suitable
  1615    *                           contents for first-letter
  1616    * @param aParentFrame the current frame whose children we are looking at for
  1617    *                     a suitable first-letter textframe
  1618    * @param aParentFrameList the first child of aParentFrame
  1619    * @param aModifiedParent returns the parent of the textframe that contains
  1620    *                        the first-letter
  1621    * @param aTextFrame returns the textframe that had the first-letter
  1622    * @param aPrevFrame returns the previous sibling of aTextFrame
  1623    * @param aLetterFrames returns the frames that were created
  1624    * @param aStopLooking returns whether we should stop looking for a
  1625    *                     first-letter either because it was found or won't be
  1626    *                     found
  1627    */
  1628   void WrapFramesInFirstLetterFrame(nsIFrame*     aBlockFrame,
  1629                                     nsIFrame*     aBlockContinuation,
  1630                                     nsIFrame*     aParentFrame,
  1631                                     nsIFrame*     aParentFrameList,
  1632                                     nsIFrame**    aModifiedParent,
  1633                                     nsIFrame**    aTextFrame,
  1634                                     nsIFrame**    aPrevFrame,
  1635                                     nsFrameItems& aLetterFrames,
  1636                                     bool*       aStopLooking);
  1638   void RecoverLetterFrames(nsIFrame* aBlockFrame);
  1640   //
  1641   nsresult RemoveLetterFrames(nsPresContext*  aPresContext,
  1642                               nsIPresShell*    aPresShell,
  1643                               nsIFrame*        aBlockFrame);
  1645   // Recursive helper for RemoveLetterFrames
  1646   nsresult RemoveFirstLetterFrames(nsPresContext*  aPresContext,
  1647                                    nsIPresShell*    aPresShell,
  1648                                    nsIFrame*        aFrame,
  1649                                    nsIFrame*        aBlockFrame,
  1650                                    bool*          aStopLooking);
  1652   // Special remove method for those pesky floating first-letter frames
  1653   nsresult RemoveFloatingFirstLetterFrames(nsPresContext*  aPresContext,
  1654                                            nsIPresShell*    aPresShell,
  1655                                            nsIFrame*        aBlockFrame,
  1656                                            bool*          aStopLooking);
  1658   // Capture state for the frame tree rooted at the frame associated with the
  1659   // content object, aContent
  1660   void CaptureStateForFramesOf(nsIContent* aContent,
  1661                                nsILayoutHistoryState* aHistoryState);
  1663   //----------------------------------------
  1665   // Methods support :first-line style
  1667   // This method chops the initial inline-outside frames out of aFrameItems.
  1668   // If aLineFrame is non-null, it appends them to that frame.  Otherwise, it
  1669   // creates a new line frame, sets the inline frames as its initial child
  1670   // list, and inserts that line frame at the front of what's left of
  1671   // aFrameItems.  In both cases, the kids are reparented to the line frame.
  1672   // After this call, aFrameItems holds the frames that need to become kids of
  1673   // the block (possibly including line frames).
  1674   void WrapFramesInFirstLineFrame(nsFrameConstructorState& aState,
  1675                                   nsIContent*              aBlockContent,
  1676                                   nsIFrame*                aBlockFrame,
  1677                                   nsIFrame*                aLineFrame,
  1678                                   nsFrameItems&            aFrameItems);
  1680   // Handle the case when a block with first-line style is appended to (by
  1681   // possibly calling WrapFramesInFirstLineFrame as needed).
  1682   void AppendFirstLineFrames(nsFrameConstructorState& aState,
  1683                              nsIContent*              aContent,
  1684                              nsIFrame*                aBlockFrame,
  1685                              nsFrameItems&            aFrameItems);
  1687   nsresult InsertFirstLineFrames(nsFrameConstructorState& aState,
  1688                                  nsIContent*              aContent,
  1689                                  nsIFrame*                aBlockFrame,
  1690                                  nsIFrame**               aParentFrame,
  1691                                  nsIFrame*                aPrevSibling,
  1692                                  nsFrameItems&            aFrameItems);
  1694   // Find the right frame to use for aContent when looking for sibling
  1695   // frames for aTargetContent.  If aPrevSibling is true, this
  1696   // will look for last continuations, etc, as necessary.  This calls
  1697   // IsValidSibling as needed; if that returns false it returns null.
  1698   //
  1699   // @param aTargetContentDisplay the CSS display enum for aTargetContent if
  1700   // already known, UNSET_DISPLAY otherwise. It will be filled in if needed.
  1701   nsIFrame* FindFrameForContentSibling(nsIContent* aContent,
  1702                                        nsIContent* aTargetContent,
  1703                                        uint8_t& aTargetContentDisplay,
  1704                                        bool aPrevSibling);
  1706   // Find the ``rightmost'' frame for the content immediately preceding the one
  1707   // aIter points to, following continuations if necessary.  aIter is passed by
  1708   // value on purpose, so as not to modify the caller's iterator.
  1709   nsIFrame* FindPreviousSibling(mozilla::dom::FlattenedChildIterator aIter,
  1710                                 uint8_t& aTargetContentDisplay);
  1712   // Find the frame for the content node immediately following the one aIter
  1713   // points to, following continuations if necessary.  aIter is passed by value
  1714   // on purpose, so as not to modify the caller's iterator.
  1715   nsIFrame* FindNextSibling(mozilla::dom::FlattenedChildIterator aIter,
  1716                             uint8_t& aTargetContentDisplay);
  1718   // Find the right previous sibling for an insertion.  This also updates the
  1719   // parent frame to point to the correct continuation of the parent frame to
  1720   // use, and returns whether this insertion is to be treated as an append.
  1721   // aChild is the child being inserted.
  1722   // aIsRangeInsertSafe returns whether it is safe to do a range insert with
  1723   // aChild being the first child in the range. It is the callers'
  1724   // responsibility to check whether a range insert is safe with regards to
  1725   // fieldsets.
  1726   // The skip parameters are used to ignore a range of children when looking
  1727   // for a sibling. All nodes starting from aStartSkipChild and up to but not
  1728   // including aEndSkipChild will be skipped over when looking for sibling
  1729   // frames. Skipping a range can deal with XBL but not when there are multiple
  1730   // insertion points.
  1731   nsIFrame* GetInsertionPrevSibling(nsIFrame*& aParentFrame, /* inout */
  1732                                     nsIContent* aContainer,
  1733                                     nsIContent* aChild,
  1734                                     bool* aIsAppend,
  1735                                     bool* aIsRangeInsertSafe,
  1736                                     nsIContent* aStartSkipChild = nullptr,
  1737                                     nsIContent *aEndSkipChild = nullptr);
  1739   // see if aContent and aSibling are legitimate siblings due to restrictions
  1740   // imposed by table columns
  1741   // XXXbz this code is generally wrong, since the frame for aContent
  1742   // may be constructed based on tag, not based on aDisplay!
  1743   bool IsValidSibling(nsIFrame*              aSibling,
  1744                         nsIContent*            aContent,
  1745                         uint8_t&               aDisplay);
  1747   void QuotesDirty() {
  1748     NS_PRECONDITION(mUpdateCount != 0, "Instant quote updates are bad news");
  1749     mQuotesDirty = true;
  1750     mDocument->SetNeedLayoutFlush();
  1753   void CountersDirty() {
  1754     NS_PRECONDITION(mUpdateCount != 0, "Instant counter updates are bad news");
  1755     mCountersDirty = true;
  1756     mDocument->SetNeedLayoutFlush();
  1759   /**
  1760    * Add the pair (aContent, aStyleContext) to the undisplayed items
  1761    * in aList as needed.  This method enforces the invariant that all
  1762    * style contexts in the undisplayed content map must be non-pseudo
  1763    * contexts and also handles unbinding undisplayed generated content
  1764    * as needed.
  1765    */
  1766   static void SetAsUndisplayedContent(FrameConstructionItemList& aList,
  1767                                       nsIContent* aContent,
  1768                                       nsStyleContext* aStyleContext,
  1769                                       bool aIsGeneratedContent);
  1771 public:
  1773   friend class nsFrameConstructorState;
  1775 private:
  1777   nsIDocument*        mDocument;  // Weak ref
  1779   // See the comment at the start of ConstructRootFrame for more details
  1780   // about the following frames.
  1782   // This is just the outermost frame for the root element.
  1783   nsIFrame*           mRootElementFrame;
  1784   // This is the frame for the root element that has no pseudo-element style.
  1785   nsIFrame*           mRootElementStyleFrame;
  1786   // This is the containing block for fixed-pos frames --- the
  1787   // viewport or page frame
  1788   nsIFrame*           mFixedContainingBlock;
  1789   // This is the containing block that contains the root element ---
  1790   // the real "initial containing block" according to CSS 2.1.
  1791   nsIFrame*           mDocElementContainingBlock;
  1792   nsIFrame*           mGfxScrollFrame;
  1793   nsIFrame*           mPageSequenceFrame;
  1794   nsQuoteList         mQuoteList;
  1795   nsCounterManager    mCounterManager;
  1796   // Current ProcessChildren depth.
  1797   uint16_t            mCurrentDepth;
  1798   uint16_t            mUpdateCount;
  1799   bool                mQuotesDirty : 1;
  1800   bool                mCountersDirty : 1;
  1801   bool                mIsDestroyingFrameTree : 1;
  1802   // This is true if mDocElementContainingBlock supports absolute positioning
  1803   bool                mHasRootAbsPosContainingBlock : 1;
  1804   bool                mAlwaysCreateFramesForIgnorableWhitespace : 1;
  1806   nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
  1807 };
  1809 #endif /* nsCSSFrameConstructor_h___ */

mercurial