1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* base class #1 for rendering objects that have child lists */
8 
9 #ifndef nsContainerFrame_h___
10 #define nsContainerFrame_h___
11 
12 #include "mozilla/Attributes.h"
13 #include "nsSplittableFrame.h"
14 #include "nsFrameList.h"
15 #include "nsLayoutUtils.h"
16 #include "nsLineBox.h"
17 
18 class nsOverflowContinuationTracker;
19 
20 namespace mozilla {
21 class PresShell;
22 }  // namespace mozilla
23 
24 // Some macros for container classes to do sanity checking on
25 // width/height/x/y values computed during reflow.
26 // NOTE: AppUnitsPerCSSPixel value hardwired here to remove the
27 // dependency on nsDeviceContext.h.  It doesn't matter if it's a
28 // little off.
29 #ifdef DEBUG
30 // 10 million pixels, converted to app units. Note that this a bit larger
31 // than 1/4 of nscoord_MAX. So, if any content gets to be this large, we're
32 // definitely in danger of grazing up against nscoord_MAX; hence, it's CRAZY.
33 #  define CRAZY_COORD (10000000 * 60)
34 #  define CRAZY_SIZE(_x) (((_x) < -CRAZY_COORD) || ((_x) > CRAZY_COORD))
35 #endif
36 
37 /**
38  * Implementation of a container frame.
39  */
40 class nsContainerFrame : public nsSplittableFrame {
41  public:
42   NS_DECL_ABSTRACT_FRAME(nsContainerFrame)
43   NS_DECL_QUERYFRAME_TARGET(nsContainerFrame)
44   NS_DECL_QUERYFRAME
45 
46   // nsIFrame overrides
47   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
48                     nsIFrame* aPrevInFlow) override;
GetContentInsertionFrame()49   virtual nsContainerFrame* GetContentInsertionFrame() override { return this; }
50 
51   virtual const nsFrameList& GetChildList(ChildListID aList) const override;
52   virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
53   virtual void DestroyFrom(nsIFrame* aDestructRoot,
54                            PostDestroyData& aPostDestroyData) override;
55   virtual void ChildIsDirty(nsIFrame* aChild) override;
56 
57   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward,
58                                                int32_t* aOffset) override;
59   virtual FrameSearchResult PeekOffsetCharacter(
60       bool aForward, int32_t* aOffset,
61       PeekOffsetCharacterOptions aOptions =
62           PeekOffsetCharacterOptions()) override;
63 
64 #ifdef DEBUG_FRAME_DUMP
65   void List(FILE* out = stderr, const char* aPrefix = "",
66             ListFlags aFlags = ListFlags()) const override;
67   void ListWithMatchedRules(FILE* out = stderr,
68                             const char* aPrefix = "") const override;
69   virtual void ExtraContainerFrameInfo(nsACString& aTo) const;
70 #endif
71 
72   // nsContainerFrame methods
73 
74   /**
75    * Called to set the initial list of frames. This happens after the frame
76    * has been initialized.
77    *
78    * This is only called once for a given child list, and won't be called
79    * at all for child lists with no initial list of frames.
80    *
81    * @param   aListID the child list identifier.
82    * @param   aChildList list of child frames. Each of the frames has its
83    *            NS_FRAME_IS_DIRTY bit set.  Must not be empty.
84    *            This method cannot handle the child list returned by
85    *            GetAbsoluteListID().
86    * @see     #Init()
87    */
88   virtual void SetInitialChildList(ChildListID aListID,
89                                    nsFrameList& aChildList);
90 
91   /**
92    * This method is responsible for appending frames to the frame
93    * list.  The implementation should append the frames to the specified
94    * child list and then generate a reflow command.
95    *
96    * @param   aListID the child list identifier.
97    * @param   aFrameList list of child frames to append. Each of the frames has
98    *            its NS_FRAME_IS_DIRTY bit set.  Must not be empty.
99    */
100   virtual void AppendFrames(ChildListID aListID, nsFrameList& aFrameList);
101 
102   /**
103    * This method is responsible for inserting frames into the frame
104    * list.  The implementation should insert the new frames into the specified
105    * child list and then generate a reflow command.
106    *
107    * @param   aListID the child list identifier.
108    * @param   aPrevFrame the frame to insert frames <b>after</b>
109    * @param   aPrevFrameLine (optional) if present (i.e., not null), the line
110    *            box that aPrevFrame is part of.
111    * @param   aFrameList list of child frames to insert <b>after</b> aPrevFrame.
112    *            Each of the frames has its NS_FRAME_IS_DIRTY bit set
113    */
114   virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
115                             const nsLineList::iterator* aPrevFrameLine,
116                             nsFrameList& aFrameList);
117 
118   /**
119    * This method is responsible for removing a frame in the frame
120    * list.  The implementation should do something with the removed frame
121    * and then generate a reflow command. The implementation is responsible
122    * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
123    *
124    * @param   aListID the child list identifier.
125    * @param   aOldFrame the frame to remove
126    */
127   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
128 
129   /**
130    * Helper method to create next-in-flows if necessary. If aFrame
131    * already has a next-in-flow then this method does
132    * nothing. Otherwise, a new continuation frame is created and
133    * linked into the flow. In addition, the new frame is inserted
134    * into the principal child list after aFrame.
135    * @note calling this method on a block frame is illegal. Use
136    * nsBlockFrame::CreateContinuationFor() instead.
137    * @return the next-in-flow <b>if and only if</b> one is created. If
138    *         a next-in-flow already exists, nullptr will be returned.
139    */
140   nsIFrame* CreateNextInFlow(nsIFrame* aFrame);
141 
142   /**
143    * Delete aNextInFlow and its next-in-flows.
144    * @param aDeletingEmptyFrames if set, then the reflow for aNextInFlow's
145    * content was complete before aNextInFlow, so aNextInFlow and its
146    * next-in-flows no longer map any real content.
147    */
148   virtual void DeleteNextInFlowChild(nsIFrame* aNextInFlow,
149                                      bool aDeletingEmptyFrames);
150 
151   // Positions the frame's view based on the frame's origin
152   static void PositionFrameView(nsIFrame* aKidFrame);
153 
154   static nsresult ReparentFrameView(nsIFrame* aChildFrame,
155                                     nsIFrame* aOldParentFrame,
156                                     nsIFrame* aNewParentFrame);
157 
158   static void ReparentFrameViewList(const nsFrameList& aChildFrameList,
159                                     nsIFrame* aOldParentFrame,
160                                     nsIFrame* aNewParentFrame);
161 
162   /**
163    * Reparent aFrame from aOldParent to aNewParent.
164    */
165   static void ReparentFrame(nsIFrame* aFrame, nsContainerFrame* aOldParent,
166                             nsContainerFrame* aNewParent);
167 
168   /**
169    * Reparent all the frames in aFrameList from aOldParent to aNewParent.
170    *
171    * Note: Reparenting a large frame list can be have huge performance impact.
172    * For example, instead of using this method, nsInlineFrame uses a "lazy
173    * reparenting" technique that it reparents a child frame just before
174    * reflowing the child. (See InlineReflowInput::mSetParentPointer.)
175    */
176   static void ReparentFrames(nsFrameList& aFrameList,
177                              nsContainerFrame* aOldParent,
178                              nsContainerFrame* aNewParent);
179 
180   // Set the view's size and position after its frame has been reflowed.
181   static void SyncFrameViewAfterReflow(
182       nsPresContext* aPresContext, nsIFrame* aFrame, nsView* aView,
183       const nsRect& aVisualOverflowArea,
184       ReflowChildFlags aFlags = ReflowChildFlags::Default);
185 
186   // Syncs properties to the top level view and window, like transparency and
187   // shadow.
188   // The SET_ASYNC indicates that the actual nsIWidget calls to sync the window
189   // properties should be done async.
190   enum {
191     SET_ASYNC = 0x01,
192   };
193   static void SyncWindowProperties(nsPresContext* aPresContext,
194                                    nsIFrame* aFrame, nsView* aView,
195                                    gfxContext* aRC, uint32_t aFlags);
196 
197   /**
198    * Converts the minimum and maximum sizes given in inner window app units to
199    * outer window device pixel sizes and assigns these constraints to the
200    * widget.
201    *
202    * @param aPresContext pres context
203    * @param aWidget widget for this frame
204    * @param minimum size of the window in app units
205    * @param maxmimum size of the window in app units
206    */
207   static void SetSizeConstraints(nsPresContext* aPresContext,
208                                  nsIWidget* aWidget, const nsSize& aMinSize,
209                                  const nsSize& aMaxSize);
210 
211   // Used by both nsInlineFrame and nsFirstLetterFrame.
212   void DoInlineIntrinsicISize(gfxContext* aRenderingContext,
213                               InlineIntrinsicISizeData* aData,
214                               nsLayoutUtils::IntrinsicISizeType aType);
215 
216   /**
217    * This is the CSS block concept of computing 'auto' widths, which most
218    * classes derived from nsContainerFrame want.
219    */
220   virtual mozilla::LogicalSize ComputeAutoSize(
221       gfxContext* aRenderingContext, mozilla::WritingMode aWM,
222       const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
223       const mozilla::LogicalSize& aMargin, const mozilla::LogicalSize& aBorder,
224       const mozilla::LogicalSize& aPadding, ComputeSizeFlags aFlags) override;
225 
226   /**
227    * Positions aKidFrame and its view (if requested), and then calls Reflow().
228    * If the reflow status after reflowing the child is FullyComplete then any
229    * next-in-flows are deleted using DeleteNextInFlowChild().
230    *
231    * @param aReflowInput the reflow input for aKidFrame.
232    * @param aWM aPos's writing-mode (any writing mode will do).
233    * @param aPos Position of the aKidFrame to be moved, in terms of aWM.
234    * @param aContainerSize Size of the border-box of the containing frame.
235    *
236    * Note: If ReflowChildFlags::NoMoveFrame is requested, both aPos and
237    * aContainerSize are ignored.
238    */
239   void ReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext,
240                    ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
241                    const mozilla::WritingMode& aWM,
242                    const mozilla::LogicalPoint& aPos,
243                    const nsSize& aContainerSize, ReflowChildFlags aFlags,
244                    nsReflowStatus& aStatus,
245                    nsOverflowContinuationTracker* aTracker = nullptr);
246 
247   /**
248    * The second half of frame reflow. Does the following:
249    * - sets the frame's bounds
250    * - sizes and positions (if requested) the frame's view. If the frame's final
251    *   position differs from the current position and the frame itself does not
252    *   have a view, then any child frames with views are positioned so they stay
253    *   in sync
254    * - sets the view's visibility, opacity, content transparency, and clip
255    * - invoked the DidReflow() function
256    *
257    * @param aReflowInput the reflow input for aKidFrame.
258    * @param aWM aPos's writing-mode (any writing mode will do).
259    * @param aPos Position of the aKidFrame to be moved, in terms of aWM.
260    * @param aContainerSize Size of the border-box of the containing frame.
261    *
262    * Note: If ReflowChildFlags::NoMoveFrame is requested, both aPos and
263    * aContainerSize are ignored unless
264    * ReflowChildFlags::ApplyRelativePositioning is requested.
265    */
266   static void FinishReflowChild(
267       nsIFrame* aKidFrame, nsPresContext* aPresContext,
268       const ReflowOutput& aDesiredSize, const ReflowInput* aReflowInput,
269       const mozilla::WritingMode& aWM, const mozilla::LogicalPoint& aPos,
270       const nsSize& aContainerSize, ReflowChildFlags aFlags);
271 
272   // XXX temporary: hold on to a copy of the old physical versions of
273   //    ReflowChild and FinishReflowChild so that we can convert callers
274   //    incrementally.
275   void ReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext,
276                    ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
277                    nscoord aX, nscoord aY, ReflowChildFlags aFlags,
278                    nsReflowStatus& aStatus,
279                    nsOverflowContinuationTracker* aTracker = nullptr);
280 
281   static void FinishReflowChild(nsIFrame* aKidFrame,
282                                 nsPresContext* aPresContext,
283                                 const ReflowOutput& aDesiredSize,
284                                 const ReflowInput* aReflowInput, nscoord aX,
285                                 nscoord aY, ReflowChildFlags aFlags);
286 
287   static void PositionChildViews(nsIFrame* aFrame);
288 
289   // ==========================================================================
290   /* Overflow containers are continuation frames that hold overflow. They
291    * are created when the frame runs out of computed height, but still has
292    * too much content to fit in the availableHeight. The parent creates a
293    * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
294    * and adds it to its next-in-flow's overflow container list, either by
295    * adding it directly or by putting it in its own excess overflow containers
296    * list (to be drained by the next-in-flow when it calls
297    * ReflowOverflowContainerChildren). The parent continues reflow as if
298    * the frame was complete once it ran out of computed height, but returns a
299    * reflow status with either IsIncomplete() or IsOverflowIncomplete() equal
300    * to true to request a next-in-flow. The parent's next-in-flow is then
301    * responsible for calling ReflowOverflowContainerChildren to (drain and)
302    * reflow these overflow continuations. Overflow containers do not affect
303    * other frames' size or position during reflow (but do affect their
304    * parent's overflow area).
305    *
306    * Overflow container continuations are different from normal continuations
307    * in that
308    *   - more than one child of the frame can have its next-in-flow broken
309    *     off and pushed into the frame's next-in-flow
310    *   - new continuations may need to be spliced into the middle of the list
311    *     or deleted continuations slipped out
312    *     e.g. A, B, C are all fixed-size containers on one page, all have
313    *      overflow beyond availableHeight, and content is dynamically added
314    *      and removed from B
315    * As a result, it is not possible to simply prepend the new continuations
316    * to the old list as with the overflowProperty mechanism. To avoid
317    * complicated list splicing, the code assumes only one overflow containers
318    * list exists for a given frame: either its own overflowContainersProperty
319    * or its prev-in-flow's excessOverflowContainersProperty, not both.
320    *
321    * The nsOverflowContinuationTracker helper class should be used for tracking
322    * overflow containers and adding them to the appropriate list.
323    * See nsBlockFrame::Reflow for a sample implementation.
324    *
325    * For more information, see https://wiki.mozilla.org/Gecko:Continuation_Model
326    */
327 
328   friend class nsOverflowContinuationTracker;
329 
330   typedef void (*ChildFrameMerger)(nsFrameList& aDest, nsFrameList& aSrc,
331                                    nsContainerFrame* aParent);
DefaultChildFrameMerge(nsFrameList & aDest,nsFrameList & aSrc,nsContainerFrame * aParent)332   static inline void DefaultChildFrameMerge(nsFrameList& aDest,
333                                             nsFrameList& aSrc,
334                                             nsContainerFrame* aParent) {
335     aDest.AppendFrames(nullptr, aSrc);
336   }
337 
338   /**
339    * Reflow overflow container children. They are invisible to normal reflow
340    * (i.e. don't affect sizing or placement of other children) and inherit
341    * width and horizontal position from their prev-in-flow.
342    *
343    * This method
344    *   1. Pulls excess overflow containers from the prev-in-flow and adds
345    *      them to our overflow container list
346    *   2. Reflows all our overflow container kids
347    *   3. Expands aOverflowRect as necessary to accomodate these children.
348    *   4. Sets aStatus's mOverflowIncomplete flag (along with
349    *      mNextInFlowNeedsReflow as necessary) if any overflow children
350    *      are incomplete and
351    *   5. Prepends a list of their continuations to our excess overflow
352    *      container list, to be drained into our next-in-flow when it is
353    *      reflowed.
354    *
355    * The caller is responsible for tracking any new overflow container
356    * continuations it makes, removing them from its child list, and
357    * making sure they are stored properly in the overflow container lists.
358    * The nsOverflowContinuationTracker helper class should be used for this.
359    *
360    * @param aFlags is passed through to ReflowChild
361    * @param aMergeFunc is passed to DrainExcessOverflowContainersList
362    */
363   void ReflowOverflowContainerChildren(
364       nsPresContext* aPresContext, const ReflowInput& aReflowInput,
365       nsOverflowAreas& aOverflowRects, ReflowChildFlags aFlags,
366       nsReflowStatus& aStatus,
367       ChildFrameMerger aMergeFunc = DefaultChildFrameMerge);
368 
369   /**
370    * Move any frames on our overflow list to the end of our principal list.
371    * @return true if there were any overflow frames
372    */
373   virtual bool DrainSelfOverflowList() override;
374 
375   /**
376    * Move all frames on our prev-in-flow's and our own ExcessOverflowContainers
377    * lists to our OverflowContainers list.  If there are frames on multiple
378    * lists they are merged using aMergeFunc.
379    * @return a pointer to our OverflowContainers list, if any
380    */
381   nsFrameList* DrainExcessOverflowContainersList(
382       ChildFrameMerger aMergeFunc = DefaultChildFrameMerge);
383 
384   /**
385    * Removes aChild without destroying it and without requesting reflow.
386    * Continuations are not affected.  Checks the principal and overflow lists,
387    * and also the [excess] overflow containers lists if the frame bit
388    * NS_FRAME_IS_OVERFLOW_CONTAINER is set.  It does not check any other lists.
389    * Returns NS_ERROR_UNEXPECTED if aChild wasn't found on any of the lists
390    * mentioned above.
391    */
392   virtual nsresult StealFrame(nsIFrame* aChild);
393 
394   /**
395    * Removes the next-siblings of aChild without destroying them and without
396    * requesting reflow. Checks the principal and overflow lists (not
397    * overflow containers / excess overflow containers). Does not check any
398    * other auxiliary lists.
399    * @param aChild a child frame or nullptr
400    * @return If aChild is non-null, the next-siblings of aChild, if any.
401    *         If aChild is null, all child frames on the principal list, if any.
402    */
403   nsFrameList StealFramesAfter(nsIFrame* aChild);
404 
405   /**
406    * Add overflow containers to the display list
407    */
408   void DisplayOverflowContainers(nsDisplayListBuilder* aBuilder,
409                                  const nsDisplayListSet& aLists);
410 
411   /**
412    * Builds display lists for the children. The background
413    * of each child is placed in the Content() list (suitable for inline
414    * children and other elements that behave like inlines,
415    * but not for in-flow block children of blocks).  DOES NOT
416    * paint the background/borders/outline of this frame. This should
417    * probably be avoided and eventually removed. It's currently here
418    * to emulate what nsContainerFrame::Paint did.
419    */
420   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
421                                 const nsDisplayListSet& aLists) override;
422 
PlaceFrameView(nsIFrame * aFrame)423   static void PlaceFrameView(nsIFrame* aFrame) {
424     if (aFrame->HasView())
425       nsContainerFrame::PositionFrameView(aFrame);
426     else
427       nsContainerFrame::PositionChildViews(aFrame);
428   }
429 
430   /**
431    * Returns a CSS Box Alignment constant which the caller can use to align
432    * the absolutely-positioned child (whose ReflowInput is aChildRI) within
433    * a CSS Box Alignment area associated with this container.
434    *
435    * The lower 8 bits of the returned value are guaranteed to form a valid
436    * argument for CSSAlignUtils::AlignJustifySelf(). (The upper 8 bits may
437    * encode an <overflow-position>.)
438    *
439    * NOTE: This default nsContainerFrame implementation is a stub, and isn't
440    * meant to be called.  Subclasses must provide their own implementations, if
441    * they use CSS Box Alignment to determine the static position of their
442    * absolutely-positioned children. (Though: if subclasses share enough code,
443    * maybe this nsContainerFrame impl should include some shared code.)
444    *
445    * @param aChildRI A ReflowInput for the positioned child frame that's being
446    *                 aligned.
447    * @param aLogicalAxis The axis (of this container frame) in which the caller
448    *                     would like to align the child frame.
449    */
450   virtual mozilla::StyleAlignFlags CSSAlignmentForAbsPosChild(
451       const ReflowInput& aChildRI, mozilla::LogicalAxis aLogicalAxis) const;
452 
453 #define NS_DECLARE_FRAME_PROPERTY_FRAMELIST(prop) \
454   NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, nsFrameList)
455 
456   typedef PropertyDescriptor<nsFrameList> FrameListPropertyDescriptor;
457 
458   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowProperty)
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)459   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)
460   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(ExcessOverflowContainersProperty)
461   NS_DECLARE_FRAME_PROPERTY_FRAMELIST(BackdropProperty)
462 
463   // Only really used on nsBlockFrame instances, but the caller thinks it could
464   // have arbitrary nsContainerFrames.
465   NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(FirstLetterProperty, nsIFrame)
466 
467   void SetHasFirstLetterChild() { mHasFirstLetterChild = true; }
468 
ClearHasFirstLetterChild()469   void ClearHasFirstLetterChild() { mHasFirstLetterChild = false; }
470 
471 #ifdef DEBUG
472   // Use this to suppress the CRAZY_SIZE assertions.
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize,bool)473   NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize, bool)
474   bool IsCrazySizeAssertSuppressed() const {
475     return GetProperty(DebugReflowingWithInfiniteISize());
476   }
477 #endif
478 
479   // Incorporate the child overflow areas into aOverflowAreas.
480   // If the child does not have a overflow, use the child area.
481   void ConsiderChildOverflow(nsOverflowAreas& aOverflowAreas,
482                              nsIFrame* aChildFrame);
483 
484  protected:
nsContainerFrame(ComputedStyle * aStyle,nsPresContext * aPresContext,ClassID aID)485   nsContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
486                    ClassID aID)
487       : nsSplittableFrame(aStyle, aPresContext, aID) {}
488 
489   ~nsContainerFrame();
490 
491   /**
492    * Helper for DestroyFrom. DestroyAbsoluteFrames is called before
493    * destroying frames on lists that can contain placeholders.
494    * Derived classes must do that too, if they destroy such frame lists.
495    * See nsBlockFrame::DestroyFrom for an example.
496    */
497   void DestroyAbsoluteFrames(nsIFrame* aDestructRoot,
498                              PostDestroyData& aPostDestroyData);
499 
500   /**
501    * Helper for StealFrame.  Returns true if aChild was removed from its list.
502    */
503   bool MaybeStealOverflowContainerFrame(nsIFrame* aChild);
504 
505   /**
506    * Builds a display list for non-block children that behave like
507    * inlines. This puts the background of each child into the
508    * Content() list (suitable for inline children but not for
509    * in-flow block children of blocks).
510    * @param aForcePseudoStack forces each child into a pseudo-stacking-context
511    * so its background and all other display items (except for positioned
512    * display items) go into the Content() list.
513    */
514   void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
515                                            const nsDisplayListSet& aLists,
516                                            uint32_t aFlags = 0);
517 
518   /**
519    * A version of BuildDisplayList that use DISPLAY_CHILD_INLINE.
520    * Intended as a convenience for derived classes.
521    */
BuildDisplayListForInline(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)522   void BuildDisplayListForInline(nsDisplayListBuilder* aBuilder,
523                                  const nsDisplayListSet& aLists) {
524     DisplayBorderBackgroundOutline(aBuilder, aLists);
525     BuildDisplayListForNonBlockChildren(aBuilder, aLists, DISPLAY_CHILD_INLINE);
526   }
527 
528   // ==========================================================================
529   /* Overflow Frames are frames that did not fit and must be pulled by
530    * our next-in-flow during its reflow. (The same concept for overflow
531    * containers is called "excess frames". We should probably make the
532    * names match.)
533    */
534 
535   /**
536    * Get the frames on the overflow list.  Can return null if there are no
537    * overflow frames.  The caller does NOT take ownership of the list; it's
538    * still owned by this frame.  A non-null return value indicates that the
539    * list is nonempty.
540    */
541   inline nsFrameList* GetOverflowFrames() const;
542 
543   /**
544    * As GetOverflowFrames, but removes the overflow frames property.  The
545    * caller is responsible for deleting nsFrameList and either passing
546    * ownership of the frames to someone else or destroying the frames.
547    * A non-null return value indicates that the list is nonempty.  The
548    * recommended way to use this function it to assign its return value
549    * into an AutoFrameListPtr.
550    */
551   inline nsFrameList* StealOverflowFrames();
552 
553   /**
554    * Set the overflow list.  aOverflowFrames must not be an empty list.
555    */
556   void SetOverflowFrames(const nsFrameList& aOverflowFrames);
557 
558   /**
559    * Destroy the overflow list, which must be empty.
560    */
561   inline void DestroyOverflowList();
562 
563   /**
564    * Moves any frames on both the prev-in-flow's overflow list and the
565    * receiver's overflow to the receiver's child list.
566    *
567    * Resets the overlist pointers to nullptr, and updates the receiver's child
568    * count and content mapping.
569    *
570    * @return true if any frames were moved and false otherwise
571    */
572   bool MoveOverflowToChildList();
573 
574   /**
575    * Merge a sorted frame list into our overflow list. aList becomes empty after
576    * this call.
577    */
578   void MergeSortedOverflow(nsFrameList& aList);
579 
580   /**
581    * Merge a sorted frame list into our excess overflow containers list. aList
582    * becomes empty after this call.
583    */
584   void MergeSortedExcessOverflowContainers(nsFrameList& aList);
585 
586   /**
587    * Moves all frames from aSrc into aDest such that the resulting aDest
588    * is still sorted in document content order and continuation order. aSrc
589    * becomes empty after this call.
590    *
591    * Precondition: both |aSrc| and |aDest| must be sorted to begin with.
592    * @param aCommonAncestor a hint for nsLayoutUtils::CompareTreePosition
593    */
594   static void MergeSortedFrameLists(nsFrameList& aDest, nsFrameList& aSrc,
595                                     nsIContent* aCommonAncestor);
596 
597   /**
598    * This is intended to be used as a ChildFrameMerger argument for
599    * ReflowOverflowContainerChildren().
600    */
MergeSortedFrameListsFor(nsFrameList & aDest,nsFrameList & aSrc,nsContainerFrame * aParent)601   static inline void MergeSortedFrameListsFor(nsFrameList& aDest,
602                                               nsFrameList& aSrc,
603                                               nsContainerFrame* aParent) {
604     MergeSortedFrameLists(aDest, aSrc, aParent->GetContent());
605   }
606 
607   /**
608    * Basically same as MoveOverflowToChildList, except that this is for
609    * handling inline children where children of prev-in-flow can be
610    * pushed to overflow list even if a next-in-flow exists.
611    *
612    * @param aLineContainer the line container of the current frame.
613    *
614    * @return true if any frames were moved and false otherwise
615    */
616   bool MoveInlineOverflowToChildList(nsIFrame* aLineContainer);
617 
618   /**
619    * Push aFromChild and its next siblings to the overflow list.
620    *
621    * @param aFromChild the first child frame to push. It is disconnected
622    *          from aPrevSibling
623    * @param aPrevSibling aFrameChild's previous sibling. Must not be null.
624    *          It's an error to push a parent's first child frame.
625    */
626   void PushChildrenToOverflow(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
627 
628   /**
629    * Same as above, except that this pushes frames to the next-in-flow
630    * frame and changes the geometric parent of the pushed frames when
631    * there is a next-in-flow frame.
632    *
633    * Updates the next-in-flow's child count. Does <b>not</b> update the
634    * pusher's child count.
635    */
636   void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
637 
638   /**
639    * Iterate our children in our principal child list in the normal document
640    * order, and append them (or their next-in-flows) to either our overflow list
641    * or excess overflow container list according to their presence in
642    * aPushedItems, aIncompleteItems, or aOverflowIncompleteItems.
643    *
644    * Note: This method is only intended for Grid / Flex containers.
645    * aPushedItems, aIncompleteItems, and aOverflowIncompleteItems are expected
646    * to contain only Grid / Flex items. That is, they should contain only
647    * in-flow children.
648    *
649    * @return true if any items are moved; false otherwise.
650    */
651   using FrameHashtable = nsTHashtable<nsPtrHashKey<nsIFrame>>;
652   bool PushIncompleteChildren(const FrameHashtable& aPushedItems,
653                               const FrameHashtable& aIncompleteItems,
654                               const FrameHashtable& aOverflowIncompleteItems);
655 
656   /**
657    * Prepare our child lists so that they are ready to reflow by the following
658    * operations:
659    *
660    * - Merge overflow list from our prev-in-flow into our principal child list.
661    * - Merge our own overflow list into our principal child list,
662    * - Push any child's next-in-flows in our principal child list to our
663    *   overflow list.
664    * - Pull up any first-in-flow child we might have pushed from our
665    *   next-in-flows.
666    */
667   void NormalizeChildLists();
668 
669   /**
670    * Helper to implement AppendFrames / InsertFrames for flex / grid
671    * containers.
672    */
673   void NoteNewChildren(ChildListID aListID, const nsFrameList& aFrameList);
674 
675   /**
676    * Helper to implement DrainSelfOverflowList() for flex / grid containers.
677    */
678   bool DrainAndMergeSelfOverflowList();
679 
680   /**
681    * Reparent floats whose placeholders are inline descendants of aFrame from
682    * whatever block they're currently parented by to aOurBlock.
683    * @param aReparentSiblings if this is true, we follow aFrame's
684    * GetNextSibling chain reparenting them all
685    */
686   static void ReparentFloatsForInlineChild(nsIFrame* aOurBlock,
687                                            nsIFrame* aFrame,
688                                            bool aReparentSiblings);
689 
690   // ==========================================================================
691   /*
692    * Convenience methods for traversing continuations
693    */
694 
695   struct ContinuationTraversingState {
696     nsContainerFrame* mNextInFlow;
ContinuationTraversingStateContinuationTraversingState697     explicit ContinuationTraversingState(nsContainerFrame* aFrame)
698         : mNextInFlow(static_cast<nsContainerFrame*>(aFrame->GetNextInFlow())) {
699     }
700   };
701 
702   /**
703    * Find the first frame that is a child of this frame's next-in-flows,
704    * considering both their principal child lists and overflow lists.
705    */
706   nsIFrame* GetNextInFlowChild(ContinuationTraversingState& aState,
707                                bool* aIsInOverflow = nullptr);
708 
709   /**
710    * Remove the result of GetNextInFlowChild from its current parent and
711    * append it to this frame's principal child list.
712    */
713   nsIFrame* PullNextInFlowChild(ContinuationTraversingState& aState);
714 
715   // ==========================================================================
716   /*
717    * Convenience methods for nsFrameLists stored in the
718    * PresContext's proptable
719    */
720 
721   /**
722    * Get the PresContext-stored nsFrameList named aPropID for this frame.
723    * May return null.
724    */
725   nsFrameList* GetPropTableFrames(FrameListPropertyDescriptor aProperty) const;
726 
727   /**
728    * Remove and return the PresContext-stored nsFrameList named aPropID for
729    * this frame. May return null.
730    */
731   nsFrameList* RemovePropTableFrames(FrameListPropertyDescriptor aProperty);
732 
733   /**
734    * Set the PresContext-stored nsFrameList named aPropID for this frame
735    * to the given aFrameList, which must not be null.
736    */
737   void SetPropTableFrames(nsFrameList* aFrameList,
738                           FrameListPropertyDescriptor aProperty);
739 
740   /**
741    * Safely destroy the frames on the nsFrameList stored on aProp for this
742    * frame then remove the property and delete the frame list.
743    * Nothing happens if the property doesn't exist.
744    */
745   void SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
746                                   PostDestroyData& aPostDestroyData,
747                                   mozilla::PresShell* aPresShell,
748                                   FrameListPropertyDescriptor aProp);
749 
750   // ==========================================================================
751 
752   // Helper used by Progress and Meter frames. Returns true if the bar should
753   // be rendered vertically, based on writing-mode and -moz-orient properties.
754   bool ResolvedOrientationIsVertical();
755 
756   /**
757    * Calculate the used values for 'width' and 'height' for a replaced element.
758    *   http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
759    */
760   mozilla::LogicalSize ComputeSizeWithIntrinsicDimensions(
761       gfxContext* aRenderingContext, mozilla::WritingMode aWM,
762       const mozilla::IntrinsicSize& aIntrinsicSize,
763       const mozilla::AspectRatio& aIntrinsicRatio,
764       const mozilla::LogicalSize& aCBSize, const mozilla::LogicalSize& aMargin,
765       const mozilla::LogicalSize& aBorder, const mozilla::LogicalSize& aPadding,
766       ComputeSizeFlags aFlags);
767 
768   // Compute tight bounds assuming this frame honours its border, background
769   // and outline, its children's tight bounds, and nothing else.
770   nsRect ComputeSimpleTightBounds(mozilla::gfx::DrawTarget* aDrawTarget) const;
771 
772   /*
773    * If this frame is dirty, marks all absolutely-positioned children of this
774    * frame dirty. If this frame isn't dirty, or if there are no
775    * absolutely-positioned children, does nothing.
776    *
777    * It's necessary to use PushDirtyBitToAbsoluteFrames() when you plan to
778    * reflow this frame's absolutely-positioned children after the dirty bit on
779    * this frame has already been cleared, which prevents ReflowInput from
780    * propagating the dirty bit normally. This situation generally only arises
781    * when a multipass layout algorithm is used.
782    */
783   void PushDirtyBitToAbsoluteFrames();
784 
785   // Helper function that tests if the frame tree is too deep; if it is
786   // it marks the frame as "unflowable", zeroes out the metrics, sets
787   // the reflow status, and returns true. Otherwise, the frame is
788   // unmarked "unflowable" and the metrics and reflow status are not
789   // touched and false is returned.
790   bool IsFrameTreeTooDeep(const ReflowInput& aReflowInput,
791                           ReflowOutput& aMetrics, nsReflowStatus& aStatus);
792 
793   /**
794    * @return true if we should avoid a page/column break in this frame.
795    */
796   bool ShouldAvoidBreakInside(const ReflowInput& aReflowInput) const;
797 
798   /**
799    * To be called by |BuildDisplayLists| of this class or derived classes to add
800    * a translucent overlay if this frame's content is selected.
801    * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
802    * which kind of content this is for
803    */
804   void DisplaySelectionOverlay(
805       nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
806       uint16_t aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
807 
808   // ==========================================================================
809 
810 #ifdef DEBUG
811   // A helper for flex / grid container to sanity check child lists before
812   // reflow. Intended to be called after calling NormalizeChildLists().
813   void SanityCheckChildListsBeforeReflow() const;
814 
815   // A helper to set mDidPushItemsBitMayLie if needed. Intended to be called
816   // only in flex / grid container's RemoveFrame.
817   void SetDidPushItemsBitIfNeeded(ChildListID aListID, nsIFrame* aOldFrame);
818 
819   // A flag for flex / grid containers. If true, NS_STATE_GRID_DID_PUSH_ITEMS or
820   // NS_STATE_FLEX_DID_PUSH_ITEMS may be set even though all pushed frames may
821   // have been removed. This is used to suppress an assertion in case
822   // RemoveFrame removed all associated child frames.
823   bool mDidPushItemsBitMayLie{false};
824 #endif
825 
826   nsFrameList mFrames;
827 };
828 
829 // ==========================================================================
830 /* The out-of-flow-related code below is for a hacky way of splitting
831  * absolutely-positioned frames. Basically what we do is split the frame
832  * in nsAbsoluteContainingBlock and pretend the continuation is an overflow
833  * container. This isn't an ideal solution, but it lets us print the content
834  * at least. See bug 154892.
835  */
836 
837 #define IS_TRUE_OVERFLOW_CONTAINER(frame)                      \
838   ((frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) && \
839    !((frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&         \
840      frame->IsAbsolutelyPositioned()))
841 // XXXfr This check isn't quite correct, because it doesn't handle cases
842 //      where the out-of-flow has overflow.. but that's rare.
843 //      We'll need to revisit the way abspos continuations are handled later
844 //      for various reasons, this detail is one of them. See bug 154892
845 
846 /**
847  * Helper class for tracking overflow container continuations during reflow.
848  *
849  * A frame is related to two sets of overflow containers: those that /are/
850  * its own children, and those that are /continuations/ of its children.
851  * This tracker walks through those continuations (the frame's NIF's children)
852  * and their prev-in-flows (a subset of the frame's normal and overflow
853  * container children) in parallel. It allows the reflower to synchronously
854  * walk its overflow continuations while it loops through and reflows its
855  * children. This makes it possible to insert new continuations at the correct
856  * place in the overflow containers list.
857  *
858  * The reflower is expected to loop through its children in the same order it
859  * looped through them the last time (if there was a last time).
860  * For each child, the reflower should either
861  *   - call Skip for the child if was not reflowed in this pass
862  *   - call Insert for the overflow continuation if the child was reflowed
863  *     but has incomplete overflow
864  *   - call Finished for the child if it was reflowed in this pass but
865  *     is either complete or has a normal next-in-flow. This call can
866  *     be skipped if the child did not previously have an overflow
867  *     continuation.
868  */
869 class nsOverflowContinuationTracker {
870  public:
871   /**
872    * Initializes an nsOverflowContinuationTracker to help track overflow
873    * continuations of aFrame's children. Typically invoked on 'this'.
874    *
875    * aWalkOOFFrames determines whether the walker skips out-of-flow frames
876    * or skips non-out-of-flow frames.
877    *
878    * Don't set aSkipOverflowContainerChildren to false unless you plan
879    * to walk your own overflow container children. (Usually they are handled
880    * by calling ReflowOverflowContainerChildren.) aWalkOOFFrames is ignored
881    * if aSkipOverflowContainerChildren is false.
882    */
883   nsOverflowContinuationTracker(nsContainerFrame* aFrame, bool aWalkOOFFrames,
884                                 bool aSkipOverflowContainerChildren = true);
885   /**
886    * This function adds an overflow continuation to our running list and
887    * sets its NS_FRAME_IS_OVERFLOW_CONTAINER flag.
888    *
889    * aReflowStatus should preferably be specific to the recently-reflowed
890    * child and not influenced by any of its siblings' statuses. This
891    * function sets the NS_FRAME_IS_DIRTY bit on aOverflowCont if it needs
892    * to be reflowed. (Its need for reflow depends on changes to its
893    * prev-in-flow, not to its parent--for whom it is invisible, reflow-wise.)
894    *
895    * The caller MUST disconnect the frame from its parent's child list
896    * if it was not previously an NS_FRAME_IS_OVERFLOW_CONTAINER (because
897    * StealFrame is much more inefficient than disconnecting in place
898    * during Reflow, which the caller is able to do but we are not).
899    *
900    * The caller MUST NOT disconnect the frame from its parent's
901    * child list if it is already an NS_FRAME_IS_OVERFLOW_CONTAINER.
902    * (In this case we will disconnect and reconnect it ourselves.)
903    */
904   nsresult Insert(nsIFrame* aOverflowCont, nsReflowStatus& aReflowStatus);
905   /**
906    * Begin/EndFinish() must be called for each child that is reflowed
907    * but no longer has an overflow continuation. (It may be called for
908    * other children, but in that case has no effect.) It increments our
909    * walker and makes sure we drop any dangling pointers to its
910    * next-in-flow. This function MUST be called before stealing or
911    * deleting aChild's next-in-flow.
912    * The AutoFinish helper object does that for you. Use it like so:
913    * if (kidNextInFlow) {
914    *   nsOverflowContinuationTracker::AutoFinish fini(tracker, kid);
915    *   ... DeleteNextInFlowChild/StealFrame(kidNextInFlow) here ...
916    * }
917    */
918   class MOZ_RAII AutoFinish {
919    public:
AutoFinish(nsOverflowContinuationTracker * aTracker,nsIFrame * aChild)920     AutoFinish(nsOverflowContinuationTracker* aTracker, nsIFrame* aChild)
921         : mTracker(aTracker), mChild(aChild) {
922       if (mTracker) mTracker->BeginFinish(mChild);
923     }
~AutoFinish()924     ~AutoFinish() {
925       if (mTracker) mTracker->EndFinish(mChild);
926     }
927 
928    private:
929     nsOverflowContinuationTracker* mTracker;
930     nsIFrame* mChild;
931   };
932 
933   /**
934    * This function should be called for each child that isn't reflowed.
935    * It increments our walker and sets the mOverflowIncomplete
936    * reflow flag if it encounters an overflow continuation so that our
937    * next-in-flow doesn't get prematurely deleted. It MUST be called on
938    * each unreflowed child that has an overflow container continuation;
939    * it MAY be called on other children, but it isn't necessary (doesn't
940    * do anything).
941    */
Skip(nsIFrame * aChild,nsReflowStatus & aReflowStatus)942   void Skip(nsIFrame* aChild, nsReflowStatus& aReflowStatus) {
943     MOZ_ASSERT(aChild, "null ptr");
944     if (aChild == mSentry) {
945       StepForward();
946       if (aReflowStatus.IsComplete()) {
947         aReflowStatus.SetOverflowIncomplete();
948       }
949     }
950   }
951 
952  private:
953   /**
954    * @see class AutoFinish
955    */
956   void BeginFinish(nsIFrame* aChild);
957   void EndFinish(nsIFrame* aChild);
958 
959   void SetupOverflowContList();
960   void SetUpListWalker();
961   void StepForward();
962 
963   /* We hold a pointer to either the next-in-flow's overflow containers list
964      or, if that doesn't exist, our frame's excess overflow containers list.
965      We need to make sure that we drop that pointer if the list becomes
966      empty and is deleted elsewhere. */
967   nsFrameList* mOverflowContList;
968   /* We hold a pointer to the most recently-reflowed child that has an
969      overflow container next-in-flow. We do this because it's a known
970      good point; this pointer won't be deleted on us. We can use it to
971      recover our place in the list. */
972   nsIFrame* mPrevOverflowCont;
973   /* This is a pointer to the next overflow container's prev-in-flow, which
974      is (or should be) a child of our frame. When we hit this, we will need
975      to increment this walker to the next overflow container. */
976   nsIFrame* mSentry;
977   /* Parent of all frames in mOverflowContList. If our mOverflowContList
978      is an excessOverflowContainersProperty, or null, then this is our frame
979      (the frame that was passed in to our constructor). Otherwise this is
980      that frame's next-in-flow, and our mOverflowContList is mParent's
981      overflowContainersProperty */
982   nsContainerFrame* mParent;
983   /* Tells SetUpListWalker whether or not to walk us past any continuations
984      of overflow containers. aWalkOOFFrames is ignored when this is false. */
985   bool mSkipOverflowContainerChildren;
986   /* Tells us whether to pay attention to OOF frames or non-OOF frames */
987   bool mWalkOOFFrames;
988 };
989 
GetOverflowFrames()990 inline nsFrameList* nsContainerFrame::GetOverflowFrames() const {
991   nsFrameList* list = GetProperty(OverflowProperty());
992   NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
993   return list;
994 }
995 
StealOverflowFrames()996 inline nsFrameList* nsContainerFrame::StealOverflowFrames() {
997   nsFrameList* list = TakeProperty(OverflowProperty());
998   NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
999   return list;
1000 }
1001 
DestroyOverflowList()1002 inline void nsContainerFrame::DestroyOverflowList() {
1003   nsFrameList* list = RemovePropTableFrames(OverflowProperty());
1004   MOZ_ASSERT(list && list->IsEmpty());
1005   list->Delete(PresShell());
1006 }
1007 
1008 // Start Display Reflow Debugging
1009 #ifdef DEBUG
1010 
1011 struct DR_cookie {
1012   DR_cookie(nsPresContext* aPresContext, nsIFrame* aFrame,
1013             const mozilla::ReflowInput& aReflowInput,
1014             mozilla::ReflowOutput& aMetrics, nsReflowStatus& aStatus);
1015   ~DR_cookie();
1016   void Change() const;
1017 
1018   nsPresContext* mPresContext;
1019   nsIFrame* mFrame;
1020   const mozilla::ReflowInput& mReflowInput;
1021   mozilla::ReflowOutput& mMetrics;
1022   nsReflowStatus& mStatus;
1023   void* mValue;
1024 };
1025 
1026 struct DR_layout_cookie {
1027   explicit DR_layout_cookie(nsIFrame* aFrame);
1028   ~DR_layout_cookie();
1029 
1030   nsIFrame* mFrame;
1031   void* mValue;
1032 };
1033 
1034 struct DR_intrinsic_inline_size_cookie {
1035   DR_intrinsic_inline_size_cookie(nsIFrame* aFrame, const char* aType,
1036                                   nscoord& aResult);
1037   ~DR_intrinsic_inline_size_cookie();
1038 
1039   nsIFrame* mFrame;
1040   const char* mType;
1041   nscoord& mResult;
1042   void* mValue;
1043 };
1044 
1045 struct DR_intrinsic_size_cookie {
1046   DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
1047                            nsSize& aResult);
1048   ~DR_intrinsic_size_cookie();
1049 
1050   nsIFrame* mFrame;
1051   const char* mType;
1052   nsSize& mResult;
1053   void* mValue;
1054 };
1055 
1056 struct DR_init_constraints_cookie {
1057   DR_init_constraints_cookie(nsIFrame* aFrame, mozilla::ReflowInput* aState,
1058                              nscoord aCBWidth, nscoord aCBHeight,
1059                              const nsMargin* aMargin, const nsMargin* aPadding);
1060   ~DR_init_constraints_cookie();
1061 
1062   nsIFrame* mFrame;
1063   mozilla::ReflowInput* mState;
1064   void* mValue;
1065 };
1066 
1067 struct DR_init_offsets_cookie {
1068   DR_init_offsets_cookie(nsIFrame* aFrame,
1069                          mozilla::SizeComputationInput* aState,
1070                          nscoord aPercentBasis,
1071                          mozilla::WritingMode aCBWritingMode,
1072                          const nsMargin* aMargin, const nsMargin* aPadding);
1073   ~DR_init_offsets_cookie();
1074 
1075   nsIFrame* mFrame;
1076   mozilla::SizeComputationInput* mState;
1077   void* mValue;
1078 };
1079 
1080 struct DR_init_type_cookie {
1081   DR_init_type_cookie(nsIFrame* aFrame, mozilla::ReflowInput* aState);
1082   ~DR_init_type_cookie();
1083 
1084   nsIFrame* mFrame;
1085   mozilla::ReflowInput* mState;
1086   void* mValue;
1087 };
1088 
1089 #  define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state,               \
1090                          dr_rf_metrics, dr_rf_status)                          \
1091     DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, \
1092                         dr_rf_status);
1093 #  define DISPLAY_REFLOW_CHANGE() dr_cookie.Change();
1094 #  define DISPLAY_LAYOUT(dr_frame) DR_layout_cookie dr_cookie(dr_frame);
1095 #  define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
1096     DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Min", dr_result)
1097 #  define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
1098     DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
1099 #  define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
1100     DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
1101 #  define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
1102     DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
1103 #  define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
1104     DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
1105 #  define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \
1106                                    dr_pad)                                     \
1107     DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh,   \
1108                                          dr_bdr, dr_pad)
1109 #  define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
1110                                dr_pad)                                     \
1111     DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_cbwm,   \
1112                                      dr_bdr, dr_pad)
1113 #  define DISPLAY_INIT_TYPE(dr_frame, dr_result) \
1114     DR_init_type_cookie dr_cookie(dr_frame, dr_result)
1115 
1116 #else
1117 
1118 #  define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, \
1119                          dr_rf_metrics, dr_rf_status)
1120 #  define DISPLAY_REFLOW_CHANGE()
1121 #  define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
1122 #  define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
1123     PR_BEGIN_MACRO PR_END_MACRO
1124 #  define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
1125     PR_BEGIN_MACRO PR_END_MACRO
1126 #  define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1127 #  define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1128 #  define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1129 #  define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \
1130                                    dr_pad)                                     \
1131     PR_BEGIN_MACRO PR_END_MACRO
1132 #  define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
1133                                dr_pad)                                     \
1134     PR_BEGIN_MACRO PR_END_MACRO
1135 #  define DISPLAY_INIT_TYPE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
1136 
1137 #endif
1138 // End Display Reflow Debugging
1139 
1140 #endif /* nsContainerFrame_h___ */
1141