summaryrefslogtreecommitdiffstats
path: root/layout/generic/nsContainerFrame.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /layout/generic/nsContainerFrame.h
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--layout/generic/nsContainerFrame.h1212
1 files changed, 1212 insertions, 0 deletions
diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h
new file mode 100644
index 0000000000..7495ca0d0b
--- /dev/null
+++ b/layout/generic/nsContainerFrame.h
@@ -0,0 +1,1212 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* base class #1 for rendering objects that have child lists */
+
+#ifndef nsContainerFrame_h___
+#define nsContainerFrame_h___
+
+#include "mozilla/Attributes.h"
+#include "LayoutConstants.h"
+#include "nsISelectionDisplay.h"
+#include "nsSplittableFrame.h"
+#include "nsFrameList.h"
+#include "nsLineBox.h"
+
+class nsOverflowContinuationTracker;
+
+namespace mozilla {
+class PresShell;
+} // namespace mozilla
+
+// Some macros for container classes to do sanity checking on
+// width/height/x/y values computed during reflow.
+// NOTE: AppUnitsPerCSSPixel value hardwired here to remove the
+// dependency on nsDeviceContext.h. It doesn't matter if it's a
+// little off.
+#ifdef DEBUG
+// 10 million pixels, converted to app units. Note that this a bit larger
+// than 1/4 of nscoord_MAX. So, if any content gets to be this large, we're
+// definitely in danger of grazing up against nscoord_MAX; hence, it's ABSURD.
+# define ABSURD_COORD (10000000 * 60)
+# define ABSURD_SIZE(_x) (((_x) < -ABSURD_COORD) || ((_x) > ABSURD_COORD))
+#endif
+
+/**
+ * Implementation of a container frame.
+ */
+class nsContainerFrame : public nsSplittableFrame {
+ public:
+ NS_DECL_ABSTRACT_FRAME(nsContainerFrame)
+ NS_DECL_QUERYFRAME_TARGET(nsContainerFrame)
+ NS_DECL_QUERYFRAME
+
+ // nsIFrame overrides
+ virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
+ nsIFrame* aPrevInFlow) override;
+ virtual nsContainerFrame* GetContentInsertionFrame() override { return this; }
+
+ virtual const nsFrameList& GetChildList(ChildListID aList) const override;
+ virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
+ virtual void DestroyFrom(nsIFrame* aDestructRoot,
+ PostDestroyData& aPostDestroyData) override;
+ virtual void ChildIsDirty(nsIFrame* aChild) override;
+
+ virtual FrameSearchResult PeekOffsetNoAmount(bool aForward,
+ int32_t* aOffset) override;
+ virtual FrameSearchResult PeekOffsetCharacter(
+ bool aForward, int32_t* aOffset,
+ PeekOffsetCharacterOptions aOptions =
+ PeekOffsetCharacterOptions()) override;
+
+#ifdef DEBUG_FRAME_DUMP
+ void List(FILE* out = stderr, const char* aPrefix = "",
+ ListFlags aFlags = ListFlags()) const override;
+ void ListWithMatchedRules(FILE* out = stderr,
+ const char* aPrefix = "") const override;
+ void ListChildLists(FILE* aOut, const char* aPrefix, ListFlags aFlags,
+ ChildListIDs aSkippedListIDs) const;
+ virtual void ExtraContainerFrameInfo(nsACString& aTo) const;
+#endif
+
+ // nsContainerFrame methods
+
+ /**
+ * Called to set the initial list of frames. This happens after the frame
+ * has been initialized.
+ *
+ * This is only called once for a given child list, and won't be called
+ * at all for child lists with no initial list of frames.
+ *
+ * @param aListID the child list identifier.
+ * @param aChildList list of child frames. Each of the frames has its
+ * NS_FRAME_IS_DIRTY bit set. Must not be empty.
+ * This method cannot handle the child list returned by
+ * GetAbsoluteListID().
+ * @see #Init()
+ */
+ virtual void SetInitialChildList(ChildListID aListID,
+ nsFrameList& aChildList);
+
+ /**
+ * This method is responsible for appending frames to the frame
+ * list. The implementation should append the frames to the specified
+ * child list and then generate a reflow command.
+ *
+ * @param aListID the child list identifier.
+ * @param aFrameList list of child frames to append. Each of the frames has
+ * its NS_FRAME_IS_DIRTY bit set. Must not be empty.
+ */
+ virtual void AppendFrames(ChildListID aListID, nsFrameList& aFrameList);
+
+ /**
+ * This method is responsible for inserting frames into the frame
+ * list. The implementation should insert the new frames into the specified
+ * child list and then generate a reflow command.
+ *
+ * @param aListID the child list identifier.
+ * @param aPrevFrame the frame to insert frames <b>after</b>
+ * @param aPrevFrameLine (optional) if present (i.e., not null), the line
+ * box that aPrevFrame is part of.
+ * @param aFrameList list of child frames to insert <b>after</b> aPrevFrame.
+ * Each of the frames has its NS_FRAME_IS_DIRTY bit set
+ */
+ virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
+ const nsLineList::iterator* aPrevFrameLine,
+ nsFrameList& aFrameList);
+
+ /**
+ * This method is responsible for removing a frame in the frame
+ * list. The implementation should do something with the removed frame
+ * and then generate a reflow command. The implementation is responsible
+ * for destroying aOldFrame (the caller mustn't destroy aOldFrame).
+ *
+ * @param aListID the child list identifier.
+ * @param aOldFrame the frame to remove
+ */
+ virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
+
+ /**
+ * Helper method to create next-in-flows if necessary. If aFrame
+ * already has a next-in-flow then this method does
+ * nothing. Otherwise, a new continuation frame is created and
+ * linked into the flow. In addition, the new frame is inserted
+ * into the principal child list after aFrame.
+ * @note calling this method on a block frame is illegal. Use
+ * nsBlockFrame::CreateContinuationFor() instead.
+ * @return the next-in-flow <b>if and only if</b> one is created. If
+ * a next-in-flow already exists, nullptr will be returned.
+ */
+ nsIFrame* CreateNextInFlow(nsIFrame* aFrame);
+
+ /**
+ * Delete aNextInFlow and its next-in-flows.
+ * @param aDeletingEmptyFrames if set, then the reflow for aNextInFlow's
+ * content was complete before aNextInFlow, so aNextInFlow and its
+ * next-in-flows no longer map any real content.
+ */
+ virtual void DeleteNextInFlowChild(nsIFrame* aNextInFlow,
+ bool aDeletingEmptyFrames);
+
+ // Positions the frame's view based on the frame's origin
+ static void PositionFrameView(nsIFrame* aKidFrame);
+
+ static nsresult ReparentFrameView(nsIFrame* aChildFrame,
+ nsIFrame* aOldParentFrame,
+ nsIFrame* aNewParentFrame);
+
+ static void ReparentFrameViewList(const nsFrameList& aChildFrameList,
+ nsIFrame* aOldParentFrame,
+ nsIFrame* aNewParentFrame);
+
+ /**
+ * Reparent aFrame from aOldParent to aNewParent.
+ */
+ static void ReparentFrame(nsIFrame* aFrame, nsContainerFrame* aOldParent,
+ nsContainerFrame* aNewParent);
+
+ /**
+ * Reparent all the frames in aFrameList from aOldParent to aNewParent.
+ *
+ * Note: Reparenting a large frame list can be have huge performance impact.
+ * For example, instead of using this method, nsInlineFrame uses a "lazy
+ * reparenting" technique that it reparents a child frame just before
+ * reflowing the child. (See InlineReflowInput::mSetParentPointer.)
+ */
+ static void ReparentFrames(nsFrameList& aFrameList,
+ nsContainerFrame* aOldParent,
+ nsContainerFrame* aNewParent);
+
+ // Set the view's size and position after its frame has been reflowed.
+ static void SyncFrameViewAfterReflow(
+ nsPresContext* aPresContext, nsIFrame* aFrame, nsView* aView,
+ const nsRect& aInkOverflowArea,
+ ReflowChildFlags aFlags = ReflowChildFlags::Default);
+
+ // Syncs properties to the top level view and window, like transparency and
+ // shadow.
+ // The SET_ASYNC indicates that the actual nsIWidget calls to sync the window
+ // properties should be done async.
+ enum {
+ SET_ASYNC = 0x01,
+ };
+ static void SyncWindowProperties(nsPresContext* aPresContext,
+ nsIFrame* aFrame, nsView* aView,
+ gfxContext* aRC, uint32_t aFlags);
+
+ /**
+ * Converts the minimum and maximum sizes given in inner window app units to
+ * outer window device pixel sizes and assigns these constraints to the
+ * widget.
+ *
+ * @param aPresContext pres context
+ * @param aWidget widget for this frame
+ * @param minimum size of the window in app units
+ * @param maxmimum size of the window in app units
+ */
+ static void SetSizeConstraints(nsPresContext* aPresContext,
+ nsIWidget* aWidget, const nsSize& aMinSize,
+ const nsSize& aMaxSize);
+
+ // Used by both nsInlineFrame and nsFirstLetterFrame.
+ void DoInlineIntrinsicISize(gfxContext* aRenderingContext,
+ InlineIntrinsicISizeData* aData,
+ mozilla::IntrinsicISizeType aType);
+
+ /**
+ * This is the CSS block concept of computing 'auto' widths, which most
+ * classes derived from nsContainerFrame want.
+ */
+ virtual mozilla::LogicalSize ComputeAutoSize(
+ gfxContext* aRenderingContext, mozilla::WritingMode aWM,
+ const mozilla::LogicalSize& aCBSize, nscoord aAvailableISize,
+ const mozilla::LogicalSize& aMargin,
+ const mozilla::LogicalSize& aBorderPadding,
+ mozilla::ComputeSizeFlags aFlags) override;
+
+ /**
+ * Positions aKidFrame and its view (if requested), and then calls Reflow().
+ * If the reflow status after reflowing the child is FullyComplete then any
+ * next-in-flows are deleted using DeleteNextInFlowChild().
+ *
+ * @param aReflowInput the reflow input for aKidFrame.
+ * @param aWM aPos's writing-mode (any writing mode will do).
+ * @param aPos Position of the aKidFrame to be moved, in terms of aWM.
+ * @param aContainerSize Size of the border-box of the containing frame.
+ *
+ * Note: If ReflowChildFlags::NoMoveFrame is requested, both aPos and
+ * aContainerSize are ignored.
+ */
+ void ReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext,
+ ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
+ const mozilla::WritingMode& aWM,
+ const mozilla::LogicalPoint& aPos,
+ const nsSize& aContainerSize, ReflowChildFlags aFlags,
+ nsReflowStatus& aStatus,
+ nsOverflowContinuationTracker* aTracker = nullptr);
+
+ /**
+ * The second half of frame reflow. Does the following:
+ * - sets the frame's bounds
+ * - sizes and positions (if requested) the frame's view. If the frame's final
+ * position differs from the current position and the frame itself does not
+ * have a view, then any child frames with views are positioned so they stay
+ * in sync
+ * - sets the view's visibility, opacity, content transparency, and clip
+ * - invoked the DidReflow() function
+ *
+ * @param aReflowInput the reflow input for aKidFrame.
+ * @param aWM aPos's writing-mode (any writing mode will do).
+ * @param aPos Position of the aKidFrame to be moved, in terms of aWM.
+ * @param aContainerSize Size of the border-box of the containing frame.
+ *
+ * Note: If ReflowChildFlags::NoMoveFrame is requested, both aPos and
+ * aContainerSize are ignored unless
+ * ReflowChildFlags::ApplyRelativePositioning is requested.
+ */
+ static void FinishReflowChild(
+ nsIFrame* aKidFrame, nsPresContext* aPresContext,
+ const ReflowOutput& aDesiredSize, const ReflowInput* aReflowInput,
+ const mozilla::WritingMode& aWM, const mozilla::LogicalPoint& aPos,
+ const nsSize& aContainerSize, ReflowChildFlags aFlags);
+
+ // XXX temporary: hold on to a copy of the old physical versions of
+ // ReflowChild and FinishReflowChild so that we can convert callers
+ // incrementally.
+ void ReflowChild(nsIFrame* aKidFrame, nsPresContext* aPresContext,
+ ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput,
+ nscoord aX, nscoord aY, ReflowChildFlags aFlags,
+ nsReflowStatus& aStatus,
+ nsOverflowContinuationTracker* aTracker = nullptr);
+
+ static void FinishReflowChild(nsIFrame* aKidFrame,
+ nsPresContext* aPresContext,
+ const ReflowOutput& aDesiredSize,
+ const ReflowInput* aReflowInput, nscoord aX,
+ nscoord aY, ReflowChildFlags aFlags);
+
+ static void PositionChildViews(nsIFrame* aFrame);
+
+ // ==========================================================================
+ /* Overflow containers are continuation frames that hold overflow. They
+ * are created when the frame runs out of computed block-size, but still has
+ * too much content to fit in the AvailableBSize. The parent creates a
+ * continuation as usual, but marks it as NS_FRAME_IS_OVERFLOW_CONTAINER
+ * and adds it to its next-in-flow's overflow container list, either by
+ * adding it directly or by putting it in its own excess overflow containers
+ * list (to be drained by the next-in-flow when it calls
+ * ReflowOverflowContainerChildren). The parent continues reflow as if
+ * the frame was complete once it ran out of computed block-size, but returns
+ * a reflow status with either IsIncomplete() or IsOverflowIncomplete() equal
+ * to true to request a next-in-flow. The parent's next-in-flow is then
+ * responsible for calling ReflowOverflowContainerChildren to (drain and)
+ * reflow these overflow continuations. Overflow containers do not affect
+ * other frames' size or position during reflow (but do affect their
+ * parent's overflow area).
+ *
+ * Overflow container continuations are different from normal continuations
+ * in that
+ * - more than one child of the frame can have its next-in-flow broken
+ * off and pushed into the frame's next-in-flow
+ * - new continuations may need to be spliced into the middle of the list
+ * or deleted continuations slipped out
+ * e.g. A, B, C are all fixed-size containers on one page, all have
+ * overflow beyond AvailableBSize, and content is dynamically added
+ * and removed from B
+ * As a result, it is not possible to simply prepend the new continuations
+ * to the old list as with the OverflowProperty mechanism. To avoid
+ * complicated list splicing, the code assumes only one overflow containers
+ * list exists for a given frame: either its own OverflowContainersProperty
+ * or its prev-in-flow's ExcessOverflowContainersProperty, not both.
+ *
+ * The nsOverflowContinuationTracker helper class should be used for tracking
+ * overflow containers and adding them to the appropriate list.
+ * See nsBlockFrame::Reflow for a sample implementation.
+ *
+ * For more information, see https://wiki.mozilla.org/Gecko:Continuation_Model
+ *
+ * Note that Flex/GridContainerFrame doesn't use nsOverflowContinuationTracker
+ * so the above doesn't apply. Flex/Grid containers may have items that
+ * aren't in document order between fragments, due to the 'order' property,
+ * but they do maintain the invariant that children in the same nsFrameList
+ * are in document order. This means that when pushing/pulling items or
+ * merging lists, the result needs to be sorted to restore the order.
+ * However, given that lists are individually sorted, it's a simple merge
+ * operation of the two lists to make the result sorted.
+ * DrainExcessOverflowContainersList takes a merging function to perform that
+ * operation. (By "document order" here we mean normal frame tree order,
+ * which is approximately flattened DOM tree order.)
+ */
+
+ friend class nsOverflowContinuationTracker;
+
+ typedef void (*ChildFrameMerger)(nsFrameList& aDest, nsFrameList& aSrc,
+ nsContainerFrame* aParent);
+ static inline void DefaultChildFrameMerge(nsFrameList& aDest,
+ nsFrameList& aSrc,
+ nsContainerFrame* aParent) {
+ aDest.AppendFrames(nullptr, aSrc);
+ }
+
+ /**
+ * Reflow overflow container children. They are invisible to normal reflow
+ * (i.e. don't affect sizing or placement of other children) and inherit
+ * width and horizontal position from their prev-in-flow.
+ *
+ * This method
+ * 1. Pulls excess overflow containers from the prev-in-flow and adds
+ * them to our overflow container list
+ * 2. Reflows all our overflow container kids
+ * 3. Expands aOverflowRect as necessary to accomodate these children.
+ * 4. Sets aStatus's mOverflowIncomplete flag (along with
+ * mNextInFlowNeedsReflow as necessary) if any overflow children
+ * are incomplete and
+ * 5. Prepends a list of their continuations to our excess overflow
+ * container list, to be drained into our next-in-flow when it is
+ * reflowed.
+ *
+ * The caller is responsible for tracking any new overflow container
+ * continuations it makes, removing them from its child list, and
+ * making sure they are stored properly in the overflow container lists.
+ * The nsOverflowContinuationTracker helper class should be used for this.
+ *
+ * @param aFlags is passed through to ReflowChild
+ * @param aMergeFunc is passed to DrainExcessOverflowContainersList
+ * @param aContainerSize is used only for converting logical coordinate to
+ * physical coordinate. If a tentative container size is used, caller
+ * may need to adjust the position of our overflow container children
+ * once the real size is known if our writing mode is vertical-rl.
+ */
+ void ReflowOverflowContainerChildren(
+ nsPresContext* aPresContext, const ReflowInput& aReflowInput,
+ mozilla::OverflowAreas& aOverflowRects, ReflowChildFlags aFlags,
+ nsReflowStatus& aStatus,
+ ChildFrameMerger aMergeFunc = DefaultChildFrameMerge,
+ Maybe<nsSize> aContainerSize = Nothing());
+
+ /**
+ * Move any frames on our overflow list to the end of our principal list.
+ * @return true if there were any overflow frames
+ */
+ virtual bool DrainSelfOverflowList() override;
+
+ /**
+ * Move all frames on our prev-in-flow's and our own ExcessOverflowContainers
+ * lists to our OverflowContainers list. If there are frames on multiple
+ * lists they are merged using aMergeFunc.
+ * @return a pointer to our OverflowContainers list, if any
+ */
+ nsFrameList* DrainExcessOverflowContainersList(
+ ChildFrameMerger aMergeFunc = DefaultChildFrameMerge);
+
+ /**
+ * Removes aChild without destroying it and without requesting reflow.
+ * Continuations are not affected. Checks the principal and overflow lists,
+ * and also the [excess] overflow containers lists if the frame bit
+ * NS_FRAME_IS_OVERFLOW_CONTAINER is set. It does not check any other lists.
+ * aChild must be in one of the above mentioned lists, or an assertion is
+ * triggered.
+ *
+ * Note: This method can destroy either overflow list or [excess] overflow
+ * containers list if aChild is the only child in the list. Any pointer to the
+ * list obtained prior to calling this method shouldn't be used.
+ */
+ virtual void StealFrame(nsIFrame* aChild);
+
+ /**
+ * Removes the next-siblings of aChild without destroying them and without
+ * requesting reflow. Checks the principal and overflow lists (not
+ * overflow containers / excess overflow containers). Does not check any
+ * other auxiliary lists.
+ * @param aChild a child frame or nullptr
+ * @return If aChild is non-null, the next-siblings of aChild, if any.
+ * If aChild is null, all child frames on the principal list, if any.
+ */
+ nsFrameList StealFramesAfter(nsIFrame* aChild);
+
+ /**
+ * Add overflow containers to the display list
+ */
+ void DisplayOverflowContainers(nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists);
+
+ /**
+ * Builds display lists for the children. The background
+ * of each child is placed in the Content() list (suitable for inline
+ * children and other elements that behave like inlines,
+ * but not for in-flow block children of blocks). DOES NOT
+ * paint the background/borders/outline of this frame. This should
+ * probably be avoided and eventually removed. It's currently here
+ * to emulate what nsContainerFrame::Paint did.
+ */
+ virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists) override;
+
+ static void PlaceFrameView(nsIFrame* aFrame) {
+ if (aFrame->HasView())
+ nsContainerFrame::PositionFrameView(aFrame);
+ else
+ nsContainerFrame::PositionChildViews(aFrame);
+ }
+
+ /**
+ * Returns a CSS Box Alignment constant which the caller can use to align
+ * the absolutely-positioned child (whose ReflowInput is aChildRI) within
+ * a CSS Box Alignment area associated with this container.
+ *
+ * The lower 8 bits of the returned value are guaranteed to form a valid
+ * argument for CSSAlignUtils::AlignJustifySelf(). (The upper 8 bits may
+ * encode an <overflow-position>.)
+ *
+ * NOTE: This default nsContainerFrame implementation is a stub, and isn't
+ * meant to be called. Subclasses must provide their own implementations, if
+ * they use CSS Box Alignment to determine the static position of their
+ * absolutely-positioned children. (Though: if subclasses share enough code,
+ * maybe this nsContainerFrame impl should include some shared code.)
+ *
+ * @param aChildRI A ReflowInput for the positioned child frame that's being
+ * aligned.
+ * @param aLogicalAxis The axis (of this container frame) in which the caller
+ * would like to align the child frame.
+ */
+ virtual mozilla::StyleAlignFlags CSSAlignmentForAbsPosChild(
+ const ReflowInput& aChildRI, mozilla::LogicalAxis aLogicalAxis) const;
+
+#define NS_DECLARE_FRAME_PROPERTY_FRAMELIST(prop) \
+ NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, nsFrameList)
+
+ using FrameListPropertyDescriptor =
+ mozilla::FrameProperties::Descriptor<nsFrameList>;
+
+ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowProperty)
+ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowContainersProperty)
+ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(ExcessOverflowContainersProperty)
+ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(BackdropProperty)
+
+ // Only really used on nsBlockFrame instances, but the caller thinks it could
+ // have arbitrary nsContainerFrames.
+ NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(FirstLetterProperty, nsIFrame)
+
+ void SetHasFirstLetterChild() { mHasFirstLetterChild = true; }
+
+ void ClearHasFirstLetterChild() { mHasFirstLetterChild = false; }
+
+#ifdef DEBUG
+ // Use this to suppress the ABSURD_SIZE assertions.
+ NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize, bool)
+ bool IsAbsurdSizeAssertSuppressed() const {
+ return GetProperty(DebugReflowingWithInfiniteISize());
+ }
+#endif
+
+ // Incorporate the child overflow areas into aOverflowAreas.
+ // If the child does not have a overflow, use the child area.
+ void ConsiderChildOverflow(mozilla::OverflowAreas& aOverflowAreas,
+ nsIFrame* aChildFrame);
+
+ protected:
+ nsContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
+ ClassID aID)
+ : nsSplittableFrame(aStyle, aPresContext, aID) {}
+
+ ~nsContainerFrame();
+
+ /**
+ * Helper for DestroyFrom. DestroyAbsoluteFrames is called before
+ * destroying frames on lists that can contain placeholders.
+ * Derived classes must do that too, if they destroy such frame lists.
+ * See nsBlockFrame::DestroyFrom for an example.
+ */
+ void DestroyAbsoluteFrames(nsIFrame* aDestructRoot,
+ PostDestroyData& aPostDestroyData);
+
+ /**
+ * Helper for StealFrame. Returns true if aChild was removed from its list.
+ */
+ bool MaybeStealOverflowContainerFrame(nsIFrame* aChild);
+
+ /**
+ * Builds a display list for non-block children that behave like
+ * inlines. This puts the background of each child into the
+ * Content() list (suitable for inline children but not for
+ * in-flow block children of blocks).
+ * @param aForcePseudoStack forces each child into a pseudo-stacking-context
+ * so its background and all other display items (except for positioned
+ * display items) go into the Content() list.
+ */
+ void BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists,
+ DisplayChildFlags aFlags = {});
+
+ /**
+ * A version of BuildDisplayList that use DisplayChildFlag::Inline.
+ * Intended as a convenience for derived classes.
+ */
+ void BuildDisplayListForInline(nsDisplayListBuilder* aBuilder,
+ const nsDisplayListSet& aLists) {
+ DisplayBorderBackgroundOutline(aBuilder, aLists);
+ BuildDisplayListForNonBlockChildren(aBuilder, aLists,
+ DisplayChildFlag::Inline);
+ }
+
+ // ==========================================================================
+ /* Overflow Frames are frames that did not fit and must be pulled by
+ * our next-in-flow during its reflow. (The same concept for overflow
+ * containers is called "excess frames". We should probably make the
+ * names match.)
+ */
+
+ /**
+ * Get the frames on the overflow list, overflow containers list, or excess
+ * overflow containers list. Can return null if there are no frames in the
+ * list.
+ *
+ * The caller does NOT take ownership of the list; it's still owned by this
+ * frame. A non-null return value indicates that the list is non-empty.
+ */
+ [[nodiscard]] nsFrameList* GetOverflowFrames() const {
+ nsFrameList* list = GetProperty(OverflowProperty());
+ NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
+ return list;
+ }
+ [[nodiscard]] nsFrameList* GetOverflowContainers() const {
+ nsFrameList* list = GetProperty(OverflowContainersProperty());
+ NS_ASSERTION(!list || !list->IsEmpty(),
+ "Unexpected empty overflow containers list");
+ return list;
+ }
+ [[nodiscard]] nsFrameList* GetExcessOverflowContainers() const {
+ nsFrameList* list = GetProperty(ExcessOverflowContainersProperty());
+ NS_ASSERTION(!list || !list->IsEmpty(),
+ "Unexpected empty overflow containers list");
+ return list;
+ }
+
+ /**
+ * Same as the Get methods above, but also remove and the property from this
+ * frame.
+ *
+ * The caller is responsible for deleting nsFrameList and either passing
+ * ownership of the frames to someone else or destroying the frames. A
+ * non-null return value indicates that the list is non-empty. The recommended
+ * way to use this function it to assign its return value into an
+ * AutoFrameListPtr.
+ */
+ [[nodiscard]] nsFrameList* StealOverflowFrames() {
+ nsFrameList* list = TakeProperty(OverflowProperty());
+ NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
+ return list;
+ }
+ [[nodiscard]] nsFrameList* StealOverflowContainers() {
+ nsFrameList* list = TakeProperty(OverflowContainersProperty());
+ NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
+ return list;
+ }
+ [[nodiscard]] nsFrameList* StealExcessOverflowContainers() {
+ nsFrameList* list = TakeProperty(ExcessOverflowContainersProperty());
+ NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list");
+ return list;
+ }
+
+ /**
+ * Set the overflow list, overflow containers list, or excess overflow
+ * containers list. The argument must be a *non-empty* list.
+ *
+ * After this operation, the argument becomes an empty list.
+ *
+ * @return the frame list associated with the property.
+ */
+ nsFrameList* SetOverflowFrames(nsFrameList&& aOverflowFrames) {
+ MOZ_ASSERT(aOverflowFrames.NotEmpty(), "Shouldn't be called");
+ auto* list = new (PresShell()) nsFrameList(std::move(aOverflowFrames));
+ SetProperty(OverflowProperty(), list);
+ return list;
+ }
+ nsFrameList* SetOverflowContainers(nsFrameList&& aOverflowContainers) {
+ MOZ_ASSERT(aOverflowContainers.NotEmpty(), "Shouldn't set an empty list!");
+ MOZ_ASSERT(!GetProperty(OverflowContainersProperty()),
+ "Shouldn't override existing list!");
+ MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
+ "This type of frame can't have overflow containers!");
+ auto* list = new (PresShell()) nsFrameList(std::move(aOverflowContainers));
+ SetProperty(OverflowContainersProperty(), list);
+ return list;
+ }
+ nsFrameList* SetExcessOverflowContainers(
+ nsFrameList&& aExcessOverflowContainers) {
+ MOZ_ASSERT(aExcessOverflowContainers.NotEmpty(),
+ "Shouldn't set an empty list!");
+ MOZ_ASSERT(!GetProperty(ExcessOverflowContainersProperty()),
+ "Shouldn't override existing list!");
+ MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
+ "This type of frame can't have overflow containers!");
+ auto* list =
+ new (PresShell()) nsFrameList(std::move(aExcessOverflowContainers));
+ SetProperty(ExcessOverflowContainersProperty(), list);
+ return list;
+ }
+
+ /**
+ * Destroy the overflow list, overflow containers list, or excess overflow
+ * containers list.
+ *
+ * The list to be destroyed must be empty. That is, the caller is responsible
+ * for either passing ownership of the frames to someone else or destroying
+ * the frames before calling these methods.
+ */
+ void DestroyOverflowList() {
+ nsFrameList* list = TakeProperty(OverflowProperty());
+ MOZ_ASSERT(list && list->IsEmpty());
+ list->Delete(PresShell());
+ }
+ void DestroyOverflowContainers() {
+ nsFrameList* list = TakeProperty(OverflowContainersProperty());
+ MOZ_ASSERT(list && list->IsEmpty());
+ list->Delete(PresShell());
+ }
+ void DestroyExcessOverflowContainers() {
+ nsFrameList* list = TakeProperty(ExcessOverflowContainersProperty());
+ MOZ_ASSERT(list && list->IsEmpty());
+ list->Delete(PresShell());
+ }
+
+ /**
+ * Moves any frames on both the prev-in-flow's overflow list and the
+ * receiver's overflow to the receiver's child list.
+ *
+ * Resets the overlist pointers to nullptr, and updates the receiver's child
+ * count and content mapping.
+ *
+ * @return true if any frames were moved and false otherwise
+ */
+ bool MoveOverflowToChildList();
+
+ /**
+ * Merge a sorted frame list into our overflow list. aList becomes empty after
+ * this call.
+ */
+ void MergeSortedOverflow(nsFrameList& aList);
+
+ /**
+ * Merge a sorted frame list into our excess overflow containers list. aList
+ * becomes empty after this call.
+ */
+ void MergeSortedExcessOverflowContainers(nsFrameList& aList);
+
+ /**
+ * Moves all frames from aSrc into aDest such that the resulting aDest
+ * is still sorted in document content order and continuation order. aSrc
+ * becomes empty after this call.
+ *
+ * Precondition: both |aSrc| and |aDest| must be sorted to begin with.
+ * @param aCommonAncestor a hint for nsLayoutUtils::CompareTreePosition
+ */
+ static void MergeSortedFrameLists(nsFrameList& aDest, nsFrameList& aSrc,
+ nsIContent* aCommonAncestor);
+
+ /**
+ * This is intended to be used as a ChildFrameMerger argument for
+ * ReflowOverflowContainerChildren() and DrainExcessOverflowContainersList().
+ */
+ static inline void MergeSortedFrameListsFor(nsFrameList& aDest,
+ nsFrameList& aSrc,
+ nsContainerFrame* aParent) {
+ MergeSortedFrameLists(aDest, aSrc, aParent->GetContent());
+ }
+
+ /**
+ * Basically same as MoveOverflowToChildList, except that this is for
+ * handling inline children where children of prev-in-flow can be
+ * pushed to overflow list even if a next-in-flow exists.
+ *
+ * @param aLineContainer the line container of the current frame.
+ *
+ * @return true if any frames were moved and false otherwise
+ */
+ bool MoveInlineOverflowToChildList(nsIFrame* aLineContainer);
+
+ /**
+ * Push aFromChild and its next siblings to the overflow list.
+ *
+ * @param aFromChild the first child frame to push. It is disconnected
+ * from aPrevSibling
+ * @param aPrevSibling aFrameChild's previous sibling. Must not be null.
+ * It's an error to push a parent's first child frame.
+ */
+ void PushChildrenToOverflow(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
+
+ /**
+ * Same as above, except that this pushes frames to the next-in-flow
+ * frame and changes the geometric parent of the pushed frames when
+ * there is a next-in-flow frame.
+ *
+ * Updates the next-in-flow's child count. Does <b>not</b> update the
+ * pusher's child count.
+ */
+ void PushChildren(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
+
+ /**
+ * Iterate our children in our principal child list in the normal document
+ * order, and append them (or their next-in-flows) to either our overflow list
+ * or excess overflow container list according to their presence in
+ * aPushedItems, aIncompleteItems, or aOverflowIncompleteItems.
+ *
+ * Note: This method is only intended for Grid / Flex containers.
+ * aPushedItems, aIncompleteItems, and aOverflowIncompleteItems are expected
+ * to contain only Grid / Flex items. That is, they should contain only
+ * in-flow children.
+ *
+ * @return true if any items are moved; false otherwise.
+ */
+ using FrameHashtable = nsTHashtable<nsPtrHashKey<nsIFrame>>;
+ bool PushIncompleteChildren(const FrameHashtable& aPushedItems,
+ const FrameHashtable& aIncompleteItems,
+ const FrameHashtable& aOverflowIncompleteItems);
+
+ /**
+ * Prepare our child lists so that they are ready to reflow by the following
+ * operations:
+ *
+ * - Merge overflow list from our prev-in-flow into our principal child list.
+ * - Merge our own overflow list into our principal child list,
+ * - Push any child's next-in-flows in our principal child list to our
+ * overflow list.
+ * - Pull up any first-in-flow child we might have pushed from our
+ * next-in-flows.
+ */
+ void NormalizeChildLists();
+
+ /**
+ * Helper to implement AppendFrames / InsertFrames for flex / grid
+ * containers.
+ */
+ void NoteNewChildren(ChildListID aListID, const nsFrameList& aFrameList);
+
+ /**
+ * Helper to implement DrainSelfOverflowList() for flex / grid containers.
+ */
+ bool DrainAndMergeSelfOverflowList();
+
+ /**
+ * Helper to find the first non-anonymous-box frame in the subtree rooted at
+ * aFrame.
+ */
+ static nsIFrame* GetFirstNonAnonBoxInSubtree(nsIFrame* aFrame);
+
+ /**
+ * Reparent floats whose placeholders are inline descendants of aFrame from
+ * whatever block they're currently parented by to aOurBlock.
+ * @param aReparentSiblings if this is true, we follow aFrame's
+ * GetNextSibling chain reparenting them all
+ */
+ static void ReparentFloatsForInlineChild(nsIFrame* aOurBlock,
+ nsIFrame* aFrame,
+ bool aReparentSiblings);
+
+ /**
+ * Try to remove aChildToRemove from the frame list stored in aProp.
+ * If aChildToRemove was removed from the aProp list and that list became
+ * empty, then aProp is removed from this frame and deleted.
+ * @note if aChildToRemove isn't on the aProp frame list, it might still be
+ * removed from whatever list it happens to be on, so use this method
+ * carefully. This method is primarily meant for removing frames from the
+ * [Excess]OverflowContainers lists.
+ * @return true if aChildToRemove was removed from some list
+ */
+ bool TryRemoveFrame(FrameListPropertyDescriptor aProp,
+ nsIFrame* aChildToRemove);
+
+ // ==========================================================================
+ /*
+ * Convenience methods for traversing continuations
+ */
+
+ struct ContinuationTraversingState {
+ nsContainerFrame* mNextInFlow;
+ explicit ContinuationTraversingState(nsContainerFrame* aFrame)
+ : mNextInFlow(static_cast<nsContainerFrame*>(aFrame->GetNextInFlow())) {
+ }
+ };
+
+ /**
+ * Find the first frame that is a child of this frame's next-in-flows,
+ * considering both their principal child lists and overflow lists.
+ */
+ nsIFrame* GetNextInFlowChild(ContinuationTraversingState& aState,
+ bool* aIsInOverflow = nullptr);
+
+ /**
+ * Remove the result of GetNextInFlowChild from its current parent and
+ * append it to this frame's principal child list.
+ */
+ nsIFrame* PullNextInFlowChild(ContinuationTraversingState& aState);
+
+ /**
+ * Safely destroy the frames on the nsFrameList stored on aProp for this
+ * frame then remove the property and delete the frame list.
+ * Nothing happens if the property doesn't exist.
+ */
+ void SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
+ PostDestroyData& aPostDestroyData,
+ mozilla::PresShell* aPresShell,
+ FrameListPropertyDescriptor aProp);
+
+ // ==========================================================================
+
+ // Helper used by Progress and Meter frames. Returns true if the bar should
+ // be rendered vertically, based on writing-mode and -moz-orient properties.
+ bool ResolvedOrientationIsVertical();
+
+ /**
+ * Calculate the used values for 'width' and 'height' for a replaced element.
+ * http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
+ *
+ * @param aAspectRatio the aspect ratio calculated by GetAspectRatio().
+ */
+ mozilla::LogicalSize ComputeSizeWithIntrinsicDimensions(
+ gfxContext* aRenderingContext, mozilla::WritingMode aWM,
+ const mozilla::IntrinsicSize& aIntrinsicSize,
+ const mozilla::AspectRatio& aAspectRatio,
+ const mozilla::LogicalSize& aCBSize, const mozilla::LogicalSize& aMargin,
+ const mozilla::LogicalSize& aBorderPadding,
+ mozilla::ComputeSizeFlags aFlags);
+
+ // Compute tight bounds assuming this frame honours its border, background
+ // and outline, its children's tight bounds, and nothing else.
+ nsRect ComputeSimpleTightBounds(mozilla::gfx::DrawTarget* aDrawTarget) const;
+
+ /*
+ * If this frame is dirty, marks all absolutely-positioned children of this
+ * frame dirty. If this frame isn't dirty, or if there are no
+ * absolutely-positioned children, does nothing.
+ *
+ * It's necessary to use PushDirtyBitToAbsoluteFrames() when you plan to
+ * reflow this frame's absolutely-positioned children after the dirty bit on
+ * this frame has already been cleared, which prevents ReflowInput from
+ * propagating the dirty bit normally. This situation generally only arises
+ * when a multipass layout algorithm is used.
+ */
+ void PushDirtyBitToAbsoluteFrames();
+
+ // Helper function that tests if the frame tree is too deep; if it is
+ // it marks the frame as "unflowable", zeroes out the metrics, sets
+ // the reflow status, and returns true. Otherwise, the frame is
+ // unmarked "unflowable" and the metrics and reflow status are not
+ // touched and false is returned.
+ bool IsFrameTreeTooDeep(const ReflowInput& aReflowInput,
+ ReflowOutput& aMetrics, nsReflowStatus& aStatus);
+
+ /**
+ * @return true if we should avoid a page/column break in this frame.
+ */
+ bool ShouldAvoidBreakInside(const ReflowInput& aReflowInput) const;
+
+ /**
+ * To be called by |BuildDisplayLists| of this class or derived classes to add
+ * a translucent overlay if this frame's content is selected.
+ * @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
+ * which kind of content this is for
+ */
+ void DisplaySelectionOverlay(
+ nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
+ uint16_t aContentType = nsISelectionDisplay::DISPLAY_FRAMES);
+
+ // ==========================================================================
+
+#ifdef DEBUG
+ // A helper for flex / grid container to sanity check child lists before
+ // reflow. Intended to be called after calling NormalizeChildLists().
+ void SanityCheckChildListsBeforeReflow() const;
+
+ // A helper to set mDidPushItemsBitMayLie if needed. Intended to be called
+ // only in flex / grid container's RemoveFrame.
+ void SetDidPushItemsBitIfNeeded(ChildListID aListID, nsIFrame* aOldFrame);
+
+ // A flag for flex / grid containers. If true, NS_STATE_GRID_DID_PUSH_ITEMS or
+ // NS_STATE_FLEX_DID_PUSH_ITEMS may be set even though all pushed frames may
+ // have been removed. This is used to suppress an assertion in case
+ // RemoveFrame removed all associated child frames.
+ bool mDidPushItemsBitMayLie{false};
+#endif
+
+ nsFrameList mFrames;
+};
+
+// ==========================================================================
+/* The out-of-flow-related code below is for a hacky way of splitting
+ * absolutely-positioned frames. Basically what we do is split the frame
+ * in nsAbsoluteContainingBlock and pretend the continuation is an overflow
+ * container. This isn't an ideal solution, but it lets us print the content
+ * at least. See bug 154892.
+ */
+
+/**
+ * Helper class for tracking overflow container continuations during reflow.
+ *
+ * A frame is related to two sets of overflow containers: those that /are/
+ * its own children, and those that are /continuations/ of its children.
+ * This tracker walks through those continuations (the frame's NIF's children)
+ * and their prev-in-flows (a subset of the frame's normal and overflow
+ * container children) in parallel. It allows the reflower to synchronously
+ * walk its overflow continuations while it loops through and reflows its
+ * children. This makes it possible to insert new continuations at the correct
+ * place in the overflow containers list.
+ *
+ * The reflower is expected to loop through its children in the same order it
+ * looped through them the last time (if there was a last time).
+ * For each child, the reflower should either
+ * - call Skip for the child if was not reflowed in this pass
+ * - call Insert for the overflow continuation if the child was reflowed
+ * but has incomplete overflow
+ * - call Finished for the child if it was reflowed in this pass but
+ * is either complete or has a normal next-in-flow. This call can
+ * be skipped if the child did not previously have an overflow
+ * continuation.
+ */
+class nsOverflowContinuationTracker {
+ public:
+ /**
+ * Initializes an nsOverflowContinuationTracker to help track overflow
+ * continuations of aFrame's children. Typically invoked on 'this'.
+ *
+ * aWalkOOFFrames determines whether the walker skips out-of-flow frames
+ * or skips non-out-of-flow frames.
+ *
+ * Don't set aSkipOverflowContainerChildren to false unless you plan
+ * to walk your own overflow container children. (Usually they are handled
+ * by calling ReflowOverflowContainerChildren.) aWalkOOFFrames is ignored
+ * if aSkipOverflowContainerChildren is false.
+ */
+ nsOverflowContinuationTracker(nsContainerFrame* aFrame, bool aWalkOOFFrames,
+ bool aSkipOverflowContainerChildren = true);
+ /**
+ * This function adds an overflow continuation to our running list and
+ * sets its NS_FRAME_IS_OVERFLOW_CONTAINER flag.
+ *
+ * aReflowStatus should preferably be specific to the recently-reflowed
+ * child and not influenced by any of its siblings' statuses. This
+ * function sets the NS_FRAME_IS_DIRTY bit on aOverflowCont if it needs
+ * to be reflowed. (Its need for reflow depends on changes to its
+ * prev-in-flow, not to its parent--for whom it is invisible, reflow-wise.)
+ *
+ * The caller MUST disconnect the frame from its parent's child list
+ * if it was not previously an NS_FRAME_IS_OVERFLOW_CONTAINER (because
+ * StealFrame is much more inefficient than disconnecting in place
+ * during Reflow, which the caller is able to do but we are not).
+ *
+ * The caller MUST NOT disconnect the frame from its parent's
+ * child list if it is already an NS_FRAME_IS_OVERFLOW_CONTAINER.
+ * (In this case we will disconnect and reconnect it ourselves.)
+ */
+ nsresult Insert(nsIFrame* aOverflowCont, nsReflowStatus& aReflowStatus);
+ /**
+ * Begin/EndFinish() must be called for each child that is reflowed
+ * but no longer has an overflow continuation. (It may be called for
+ * other children, but in that case has no effect.) It increments our
+ * walker and makes sure we drop any dangling pointers to its
+ * next-in-flow. This function MUST be called before stealing or
+ * deleting aChild's next-in-flow.
+ * The AutoFinish helper object does that for you. Use it like so:
+ * if (kidNextInFlow) {
+ * nsOverflowContinuationTracker::AutoFinish fini(tracker, kid);
+ * ... DeleteNextInFlowChild/StealFrame(kidNextInFlow) here ...
+ * }
+ */
+ class MOZ_RAII AutoFinish {
+ public:
+ AutoFinish(nsOverflowContinuationTracker* aTracker, nsIFrame* aChild)
+ : mTracker(aTracker), mChild(aChild) {
+ if (mTracker) mTracker->BeginFinish(mChild);
+ }
+ ~AutoFinish() {
+ if (mTracker) mTracker->EndFinish(mChild);
+ }
+
+ private:
+ nsOverflowContinuationTracker* mTracker;
+ nsIFrame* mChild;
+ };
+
+ /**
+ * This function should be called for each child that isn't reflowed.
+ * It increments our walker and sets the mOverflowIncomplete
+ * reflow flag if it encounters an overflow continuation so that our
+ * next-in-flow doesn't get prematurely deleted. It MUST be called on
+ * each unreflowed child that has an overflow container continuation;
+ * it MAY be called on other children, but it isn't necessary (doesn't
+ * do anything).
+ */
+ void Skip(nsIFrame* aChild, nsReflowStatus& aReflowStatus) {
+ MOZ_ASSERT(aChild, "null ptr");
+ if (aChild == mSentry) {
+ StepForward();
+ if (aReflowStatus.IsComplete()) {
+ aReflowStatus.SetOverflowIncomplete();
+ }
+ }
+ }
+
+ private:
+ /**
+ * @see class AutoFinish
+ */
+ void BeginFinish(nsIFrame* aChild);
+ void EndFinish(nsIFrame* aChild);
+
+ void SetupOverflowContList();
+ void SetUpListWalker();
+ void StepForward();
+
+ /* We hold a pointer to either the next-in-flow's overflow containers list
+ or, if that doesn't exist, our frame's excess overflow containers list.
+ We need to make sure that we drop that pointer if the list becomes
+ empty and is deleted elsewhere. */
+ nsFrameList* mOverflowContList;
+ /* We hold a pointer to the most recently-reflowed child that has an
+ overflow container next-in-flow. We do this because it's a known
+ good point; this pointer won't be deleted on us. We can use it to
+ recover our place in the list. */
+ nsIFrame* mPrevOverflowCont;
+ /* This is a pointer to the next overflow container's prev-in-flow, which
+ is (or should be) a child of our frame. When we hit this, we will need
+ to increment this walker to the next overflow container. */
+ nsIFrame* mSentry;
+ /* Parent of all frames in mOverflowContList. If our mOverflowContList
+ is an excessOverflowContainersProperty, or null, then this is our frame
+ (the frame that was passed in to our constructor). Otherwise this is
+ that frame's next-in-flow, and our mOverflowContList is mParent's
+ overflowContainersProperty */
+ nsContainerFrame* mParent;
+ /* Tells SetUpListWalker whether or not to walk us past any continuations
+ of overflow containers. aWalkOOFFrames is ignored when this is false. */
+ bool mSkipOverflowContainerChildren;
+ /* Tells us whether to pay attention to OOF frames or non-OOF frames */
+ bool mWalkOOFFrames;
+};
+
+// Start Display Reflow Debugging
+#ifdef DEBUG
+
+struct DR_cookie {
+ DR_cookie(nsPresContext* aPresContext, nsIFrame* aFrame,
+ const mozilla::ReflowInput& aReflowInput,
+ mozilla::ReflowOutput& aMetrics, nsReflowStatus& aStatus);
+ ~DR_cookie();
+ void Change() const;
+
+ nsPresContext* mPresContext;
+ nsIFrame* mFrame;
+ const mozilla::ReflowInput& mReflowInput;
+ mozilla::ReflowOutput& mMetrics;
+ nsReflowStatus& mStatus;
+ void* mValue;
+};
+
+struct DR_layout_cookie {
+ explicit DR_layout_cookie(nsIFrame* aFrame);
+ ~DR_layout_cookie();
+
+ nsIFrame* mFrame;
+ void* mValue;
+};
+
+struct DR_intrinsic_inline_size_cookie {
+ DR_intrinsic_inline_size_cookie(nsIFrame* aFrame, const char* aType,
+ nscoord& aResult);
+ ~DR_intrinsic_inline_size_cookie();
+
+ nsIFrame* mFrame;
+ const char* mType;
+ nscoord& mResult;
+ void* mValue;
+};
+
+struct DR_intrinsic_size_cookie {
+ DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
+ nsSize& aResult);
+ ~DR_intrinsic_size_cookie();
+
+ nsIFrame* mFrame;
+ const char* mType;
+ nsSize& mResult;
+ void* mValue;
+};
+
+struct DR_init_constraints_cookie {
+ DR_init_constraints_cookie(
+ nsIFrame* aFrame, mozilla::ReflowInput* aState, nscoord aCBWidth,
+ nscoord aCBHeight, const mozilla::Maybe<mozilla::LogicalMargin> aBorder,
+ const mozilla::Maybe<mozilla::LogicalMargin> aPadding);
+ ~DR_init_constraints_cookie();
+
+ nsIFrame* mFrame;
+ mozilla::ReflowInput* mState;
+ void* mValue;
+};
+
+struct DR_init_offsets_cookie {
+ DR_init_offsets_cookie(nsIFrame* aFrame,
+ mozilla::SizeComputationInput* aState,
+ nscoord aPercentBasis,
+ mozilla::WritingMode aCBWritingMode,
+ const mozilla::Maybe<mozilla::LogicalMargin> aBorder,
+ const mozilla::Maybe<mozilla::LogicalMargin> aPadding);
+ ~DR_init_offsets_cookie();
+
+ nsIFrame* mFrame;
+ mozilla::SizeComputationInput* mState;
+ void* mValue;
+};
+
+# define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, \
+ dr_rf_metrics, dr_rf_status) \
+ DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, \
+ dr_rf_status);
+# define DISPLAY_REFLOW_CHANGE() dr_cookie.Change();
+# define DISPLAY_LAYOUT(dr_frame) DR_layout_cookie dr_cookie(dr_frame);
+# define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
+ DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Min", dr_result)
+# define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
+ DR_intrinsic_inline_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
+# define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
+ DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
+# define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
+ DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
+# define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
+ DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
+# define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \
+ dr_pad) \
+ DR_init_constraints_cookie dr_cookie(dr_frame, dr_state, dr_cbw, dr_cbh, \
+ dr_bdr, dr_pad)
+# define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
+ dr_pad) \
+ DR_init_offsets_cookie dr_cookie(dr_frame, dr_state, dr_pb, dr_cbwm, \
+ dr_bdr, dr_pad)
+
+#else
+
+# define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, \
+ dr_rf_metrics, dr_rf_status)
+# define DISPLAY_REFLOW_CHANGE()
+# define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_MIN_INLINE_SIZE(dr_frame, dr_result) \
+ PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_PREF_INLINE_SIZE(dr_frame, dr_result) \
+ PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_INIT_CONSTRAINTS(dr_frame, dr_state, dr_cbw, dr_cbh, dr_bdr, \
+ dr_pad) \
+ PR_BEGIN_MACRO PR_END_MACRO
+# define DISPLAY_INIT_OFFSETS(dr_frame, dr_state, dr_pb, dr_cbwm, dr_bdr, \
+ dr_pad) \
+ PR_BEGIN_MACRO PR_END_MACRO
+
+#endif
+// End Display Reflow Debugging
+
+#endif /* nsContainerFrame_h___ */