diff --git a/layout/base/public/nsIFrame.h b/layout/base/public/nsIFrame.h index 5fd1b973b3d5..006f371241df 100644 --- a/layout/base/public/nsIFrame.h +++ b/layout/base/public/nsIFrame.h @@ -33,6 +33,7 @@ class nsISpaceManager; class nsIStyleContext; class nsIView; class nsIWidget; +class nsIFrame; class nsReflowCommand; struct nsPoint; @@ -76,33 +77,45 @@ enum nsReflowReason { }; /** - * Reflow state passed to a frame during reflow. + * Reflow state passed to a frame during reflow. The reflow states are linked + * together. The max size represents the available space on which to reflow + * your frame, and is computed as the parent frame's available content area + * minus any room for margins that your frame requests. * * @see #Reflow() */ struct nsReflowState { - nsReflowReason reason; // the reason for the reflow - nsReflowCommand* reflowCommand; // only used for incremental changes - nsSize maxSize; // the available space in which to reflow + nsReflowReason reason; // the reason for the reflow + nsReflowCommand* reflowCommand; // only used for incremental changes + nsSize maxSize; // the available space in which to reflow + const nsReflowState* parentReflowState; // pointer to parent's reflow state + nsIFrame* frame; // the frame being reflowed - // Construct a non-incremental reflow state - nsReflowState(nsReflowReason aReason, const nsSize& aMaxSize) { - reason = aReason; reflowCommand = nsnull; maxSize = aMaxSize; - } - // Construct a reflow state for an incremental change - nsReflowState(nsReflowCommand* aReflowCommand, const nsSize& aMaxSize) { - reason = eReflowReason_Incremental; - reflowCommand = aReflowCommand; - maxSize = aMaxSize; - } + // Constructs an initial reflow state (no parent reflow state) for a + // non-incremental reflow command + nsReflowState(nsIFrame* aFrame, + nsReflowReason aReason, + const nsSize& aMaxSize); - // Construct a reflow state similar to an existing reflow state except that - // it has a different max size - nsReflowState(const nsReflowState& aReflowState, const nsSize& aMaxSize) { - reason = aReflowState.reason; - reflowCommand = aReflowState.reflowCommand; - maxSize = aMaxSize; - } + // Constructs an initial reflow state (no parent reflow state) for an + // incremental reflow command + nsReflowState(nsIFrame* aFrame, + nsReflowCommand& aReflowCommand, + const nsSize& aMaxSize); + + // Construct a reflow state for the given frame, parent reflow state, and + // max size. Uses the reflow reason and reflow command from the parent's + // reflow state + nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize); + + // Constructs a reflow state that overrides the reflow reason of the parent + // reflow state. Sets the reflow command to NULL + nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize, + nsReflowReason aReflowReason); }; //---------------------------------------------------------------------- @@ -320,28 +333,34 @@ public: /** * The frame is given a maximum size and asked for its desired size. - * size. This is the frame's opportunity to reflow its children. + * This is the frame's opportunity to reflow its children. * * @param aDesiredSize out parameter where you should return the * desired size and ascent/descent info. You should include any * space you want for border/padding in the desired size you return. * - * @param aMaxSize the available space in which to lay out. Each - * dimension can either be constrained or unconstrained (a - * value of NS_UNCONSTRAINEDSIZE). If constrained you - * should choose a value that's less than or equal to the - * constrained size. If unconstrained you can choose as - * large a value as you like. - * * It's okay to return a desired size that exceeds the max * size if that's the smallest you can be, i.e. it's your * minimum size. * - * @param aMaxElementSize an optional parameter for returning your + * maxElementSize is an optional parameter for returning your * maximum element size. If may be null in which case you * don't have to compute a maximum element size. The * maximum element size must be less than or equal to your * desired size. + * + * @param aReflowState information about your reflow including the reason + * for the reflow and the available space in which to lay out. Each + * dimension of the available space can either be constrained or + * unconstrained (a value of NS_UNCONSTRAINEDSIZE). If constrained + * you should choose a value that's less than or equal to the + * constrained size. If unconstrained you can choose as + * large a value as you like. + * + * Note that the available space can be negative. In this case you + * still must return an accurate desired size. If you're a container + * you must always reflow at least one frame regardless of the + * available space */ NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, @@ -563,4 +582,69 @@ protected: static NS_LAYOUT PRLogModuleInfo* gLogModule; }; +// Constructs an initial reflow state (no parent reflow state) for a +// non-incremental reflow command +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + nsReflowReason aReason, + const nsSize& aMaxSize) +{ + NS_PRECONDITION(aReason != eReflowReason_Incremental, "unexpected reflow reason"); +#ifdef NS_DEBUG + nsIFrame* parent; + aFrame->GetGeometricParent(parent); + NS_PRECONDITION(nsnull == parent, "not root frame"); +#endif + reason = aReason; + reflowCommand = nsnull; + maxSize = aMaxSize; + parentReflowState = nsnull; + frame = aFrame; +} + +// Constructs an initial reflow state (no parent reflow state) for an +// incremental reflow command +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + nsReflowCommand& aReflowCommand, + const nsSize& aMaxSize) +{ +#ifdef NS_DEBUG + nsIFrame* parent; + aFrame->GetGeometricParent(parent); + NS_PRECONDITION(nsnull == parent, "not root frame"); +#endif + reason = eReflowReason_Incremental; + reflowCommand = &aReflowCommand; + maxSize = aMaxSize; + parentReflowState = nsnull; + frame = aFrame; +} + +// Construct a reflow state for the given frame, parent reflow state, and +// max size. Uses the reflow reason and reflow command from the parent's +// reflow state +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize) +{ + reason = aParentReflowState.reason; + reflowCommand = aParentReflowState.reflowCommand; + maxSize = aMaxSize; + parentReflowState = &aParentReflowState; + frame = aFrame; +} + +// Constructs a reflow state that overrides the reflow reason of the parent +// reflow state. Sets the reflow command to NULL +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize, + nsReflowReason aReflowReason) +{ + reason = aReflowReason; + reflowCommand = nsnull; + maxSize = aMaxSize; + parentReflowState = &aParentReflowState; + frame = aFrame; +} + #endif /* nsIFrame_h___ */ diff --git a/layout/base/src/nsContainerFrame.cpp b/layout/base/src/nsContainerFrame.cpp index 840da4231b8d..de53f402019e 100644 --- a/layout/base/src/nsContainerFrame.cpp +++ b/layout/base/src/nsContainerFrame.cpp @@ -448,6 +448,7 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, { nsReflowStatus status; + NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state"); #ifdef NS_DEBUG nsFrameState kidFrameState; @@ -482,16 +483,17 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, * used to reflow the child; otherwise interface nsIFrame is used. If the * child is splittable then runaround is done using continuing frames. */ -nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, - nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsRect& aDesiredRect) +nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, + nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + nsReflowMetrics& aDesiredSize, + nsReflowState& aReflowState, + nsRect& aDesiredRect) { nsIRunaround* reflowRunaround; nsReflowStatus status; + NS_PRECONDITION(aReflowState.frame == aKidFrame, "bad reflow state"); #ifdef NS_DEBUG nsFrameState kidFrameState; @@ -509,7 +511,6 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, nsBandTrapezoid trapezoids[12]; nsBandTrapezoid* trapezoid = trapezoids; nsRect availBand; - nsSize availSize = aReflowState.maxSize; bandData.trapezoids = trapezoids; bandData.size = 12; @@ -561,15 +562,14 @@ nsReflowStatus nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, (void**)&reflowRunaround)) { // Yes, the child frame wants to interact directly with the space // manager. - nsReflowState reflowState(aReflowState, availSize); - reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, reflowState, + reflowRunaround->Reflow(aPresContext, aSpaceManager, aDesiredSize, aReflowState, aDesiredRect, status); } else { // No, use interface nsIFrame instead. if (aReflowState.maxSize.width != NS_UNCONSTRAINEDSIZE) { if ((availBand.x > 0) || (availBand.XMost() < aReflowState.maxSize.width)) { // There are left/right floaters. - availSize.width = availBand.width; + aReflowState.maxSize.width = availBand.width; } } diff --git a/layout/base/src/nsContainerFrame.h b/layout/base/src/nsContainerFrame.h index 26cdf75d8fa6..9ae385667301 100644 --- a/layout/base/src/nsContainerFrame.h +++ b/layout/base/src/nsContainerFrame.h @@ -237,12 +237,12 @@ protected: * * @see nsIRunaround */ - nsReflowStatus ReflowChild(nsIFrame* aKidFrame, - nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsRect& aDesiredRect); + nsReflowStatus ReflowChild(nsIFrame* aKidFrame, + nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + nsReflowMetrics& aDesiredSize, + nsReflowState& aReflowState, + nsRect& aDesiredRect); /** * Moves any frames on both the prev-in-flow's overflow list and the receiver's diff --git a/layout/base/src/nsPresShell.cpp b/layout/base/src/nsPresShell.cpp index 59cc34e433fe..e65a0a868833 100644 --- a/layout/base/src/nsPresShell.cpp +++ b/layout/base/src/nsPresShell.cpp @@ -414,7 +414,7 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) nsSize maxSize(bounds.width, bounds.height); nsReflowMetrics desiredSize(nsnull); nsReflowStatus status; - nsReflowState reflowState(reflowReason, maxSize); + nsReflowState reflowState(mRootFrame, reflowReason, maxSize); mRootFrame->Reflow(mPresContext, desiredSize, reflowState, status); mRootFrame->SizeTo(desiredSize.width, desiredSize.height); diff --git a/layout/base/src/nsReflowCommand.cpp b/layout/base/src/nsReflowCommand.cpp index 374737bb56c8..9633f2648740 100644 --- a/layout/base/src/nsReflowCommand.cpp +++ b/layout/base/src/nsReflowCommand.cpp @@ -76,7 +76,7 @@ void nsReflowCommand::Dispatch(nsReflowMetrics& aDesiredSize, if (nsnull != root) { mPath.RemoveElementAt(mPath.Count() - 1); - nsReflowState reflowState(this, aMaxSize); + nsReflowState reflowState(root, *this, aMaxSize); nsReflowStatus status; root->Reflow(mPresContext, aDesiredSize, reflowState, status); } diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a0d7301816c2..e7ab36b63c9a 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -101,7 +101,7 @@ nsBlockReflowState::~nsBlockReflowState() nsresult nsBlockReflowState::Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock) { @@ -114,10 +114,11 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext, mListPositionOutside = PR_FALSE; mCurrentLine = nsnull; mPrevKidFrame = nsnull; + reflowState = &aReflowState; mX = 0; mY = 0; - mAvailSize = aMaxSize; + mAvailSize = reflowState->maxSize; mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE); mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE); mMaxElementSizePointer = aMaxElementSize; @@ -447,7 +448,7 @@ nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) { @@ -955,15 +956,15 @@ done: } nsresult -nsBlockFrame::InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState) +nsBlockFrame::InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState) { nsresult rv; rv = aState.Initialize(aPresContext, aSpaceManager, - aMaxSize, aMaxElementSize, this); + aReflowState, aMaxElementSize, this); // Apply border and padding adjustments for regular frames only if (!aState.mBlockIsPseudo) { @@ -1173,7 +1174,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - rv = InitializeState(aPresContext, aSpaceManager, aReflowState.maxSize, + rv = InitializeState(aPresContext, aSpaceManager, aReflowState, aDesiredSize.maxElementSize, state); NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d", diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 684644e442ae..3138e67d6abc 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -59,7 +59,7 @@ struct nsBlockReflowState { nsresult Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock); @@ -86,6 +86,7 @@ struct nsBlockReflowState { PRPackedBool mUnconstrainedHeight; nsSize* mMaxElementSizePointer; nscoord mKidXMost; + const nsReflowState* reflowState; // Change in width since last reflow nscoord mDeltaWidth; @@ -216,7 +217,7 @@ public: nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus); @@ -234,11 +235,11 @@ protected: virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow); - nsresult InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState); + nsresult InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState); void ComputeDesiredRect(nsBlockReflowState& aState, const nsSize& aMaxSize, diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index a0d7301816c2..e7ab36b63c9a 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -101,7 +101,7 @@ nsBlockReflowState::~nsBlockReflowState() nsresult nsBlockReflowState::Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock) { @@ -114,10 +114,11 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext, mListPositionOutside = PR_FALSE; mCurrentLine = nsnull; mPrevKidFrame = nsnull; + reflowState = &aReflowState; mX = 0; mY = 0; - mAvailSize = aMaxSize; + mAvailSize = reflowState->maxSize; mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE); mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE); mMaxElementSizePointer = aMaxElementSize; @@ -447,7 +448,7 @@ nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) { @@ -955,15 +956,15 @@ done: } nsresult -nsBlockFrame::InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState) +nsBlockFrame::InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState) { nsresult rv; rv = aState.Initialize(aPresContext, aSpaceManager, - aMaxSize, aMaxElementSize, this); + aReflowState, aMaxElementSize, this); // Apply border and padding adjustments for regular frames only if (!aState.mBlockIsPseudo) { @@ -1173,7 +1174,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - rv = InitializeState(aPresContext, aSpaceManager, aReflowState.maxSize, + rv = InitializeState(aPresContext, aSpaceManager, aReflowState, aDesiredSize.maxElementSize, state); NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d", diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index a0d7301816c2..e7ab36b63c9a 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -101,7 +101,7 @@ nsBlockReflowState::~nsBlockReflowState() nsresult nsBlockReflowState::Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock) { @@ -114,10 +114,11 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext, mListPositionOutside = PR_FALSE; mCurrentLine = nsnull; mPrevKidFrame = nsnull; + reflowState = &aReflowState; mX = 0; mY = 0; - mAvailSize = aMaxSize; + mAvailSize = reflowState->maxSize; mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE); mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE); mMaxElementSizePointer = aMaxElementSize; @@ -447,7 +448,7 @@ nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) { @@ -955,15 +956,15 @@ done: } nsresult -nsBlockFrame::InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState) +nsBlockFrame::InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState) { nsresult rv; rv = aState.Initialize(aPresContext, aSpaceManager, - aMaxSize, aMaxElementSize, this); + aReflowState, aMaxElementSize, this); // Apply border and padding adjustments for regular frames only if (!aState.mBlockIsPseudo) { @@ -1173,7 +1174,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - rv = InitializeState(aPresContext, aSpaceManager, aReflowState.maxSize, + rv = InitializeState(aPresContext, aSpaceManager, aReflowState, aDesiredSize.maxElementSize, state); NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d", diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 5fd1b973b3d5..006f371241df 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -33,6 +33,7 @@ class nsISpaceManager; class nsIStyleContext; class nsIView; class nsIWidget; +class nsIFrame; class nsReflowCommand; struct nsPoint; @@ -76,33 +77,45 @@ enum nsReflowReason { }; /** - * Reflow state passed to a frame during reflow. + * Reflow state passed to a frame during reflow. The reflow states are linked + * together. The max size represents the available space on which to reflow + * your frame, and is computed as the parent frame's available content area + * minus any room for margins that your frame requests. * * @see #Reflow() */ struct nsReflowState { - nsReflowReason reason; // the reason for the reflow - nsReflowCommand* reflowCommand; // only used for incremental changes - nsSize maxSize; // the available space in which to reflow + nsReflowReason reason; // the reason for the reflow + nsReflowCommand* reflowCommand; // only used for incremental changes + nsSize maxSize; // the available space in which to reflow + const nsReflowState* parentReflowState; // pointer to parent's reflow state + nsIFrame* frame; // the frame being reflowed - // Construct a non-incremental reflow state - nsReflowState(nsReflowReason aReason, const nsSize& aMaxSize) { - reason = aReason; reflowCommand = nsnull; maxSize = aMaxSize; - } - // Construct a reflow state for an incremental change - nsReflowState(nsReflowCommand* aReflowCommand, const nsSize& aMaxSize) { - reason = eReflowReason_Incremental; - reflowCommand = aReflowCommand; - maxSize = aMaxSize; - } + // Constructs an initial reflow state (no parent reflow state) for a + // non-incremental reflow command + nsReflowState(nsIFrame* aFrame, + nsReflowReason aReason, + const nsSize& aMaxSize); - // Construct a reflow state similar to an existing reflow state except that - // it has a different max size - nsReflowState(const nsReflowState& aReflowState, const nsSize& aMaxSize) { - reason = aReflowState.reason; - reflowCommand = aReflowState.reflowCommand; - maxSize = aMaxSize; - } + // Constructs an initial reflow state (no parent reflow state) for an + // incremental reflow command + nsReflowState(nsIFrame* aFrame, + nsReflowCommand& aReflowCommand, + const nsSize& aMaxSize); + + // Construct a reflow state for the given frame, parent reflow state, and + // max size. Uses the reflow reason and reflow command from the parent's + // reflow state + nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize); + + // Constructs a reflow state that overrides the reflow reason of the parent + // reflow state. Sets the reflow command to NULL + nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize, + nsReflowReason aReflowReason); }; //---------------------------------------------------------------------- @@ -320,28 +333,34 @@ public: /** * The frame is given a maximum size and asked for its desired size. - * size. This is the frame's opportunity to reflow its children. + * This is the frame's opportunity to reflow its children. * * @param aDesiredSize out parameter where you should return the * desired size and ascent/descent info. You should include any * space you want for border/padding in the desired size you return. * - * @param aMaxSize the available space in which to lay out. Each - * dimension can either be constrained or unconstrained (a - * value of NS_UNCONSTRAINEDSIZE). If constrained you - * should choose a value that's less than or equal to the - * constrained size. If unconstrained you can choose as - * large a value as you like. - * * It's okay to return a desired size that exceeds the max * size if that's the smallest you can be, i.e. it's your * minimum size. * - * @param aMaxElementSize an optional parameter for returning your + * maxElementSize is an optional parameter for returning your * maximum element size. If may be null in which case you * don't have to compute a maximum element size. The * maximum element size must be less than or equal to your * desired size. + * + * @param aReflowState information about your reflow including the reason + * for the reflow and the available space in which to lay out. Each + * dimension of the available space can either be constrained or + * unconstrained (a value of NS_UNCONSTRAINEDSIZE). If constrained + * you should choose a value that's less than or equal to the + * constrained size. If unconstrained you can choose as + * large a value as you like. + * + * Note that the available space can be negative. In this case you + * still must return an accurate desired size. If you're a container + * you must always reflow at least one frame regardless of the + * available space */ NS_IMETHOD Reflow(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, @@ -563,4 +582,69 @@ protected: static NS_LAYOUT PRLogModuleInfo* gLogModule; }; +// Constructs an initial reflow state (no parent reflow state) for a +// non-incremental reflow command +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + nsReflowReason aReason, + const nsSize& aMaxSize) +{ + NS_PRECONDITION(aReason != eReflowReason_Incremental, "unexpected reflow reason"); +#ifdef NS_DEBUG + nsIFrame* parent; + aFrame->GetGeometricParent(parent); + NS_PRECONDITION(nsnull == parent, "not root frame"); +#endif + reason = aReason; + reflowCommand = nsnull; + maxSize = aMaxSize; + parentReflowState = nsnull; + frame = aFrame; +} + +// Constructs an initial reflow state (no parent reflow state) for an +// incremental reflow command +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + nsReflowCommand& aReflowCommand, + const nsSize& aMaxSize) +{ +#ifdef NS_DEBUG + nsIFrame* parent; + aFrame->GetGeometricParent(parent); + NS_PRECONDITION(nsnull == parent, "not root frame"); +#endif + reason = eReflowReason_Incremental; + reflowCommand = &aReflowCommand; + maxSize = aMaxSize; + parentReflowState = nsnull; + frame = aFrame; +} + +// Construct a reflow state for the given frame, parent reflow state, and +// max size. Uses the reflow reason and reflow command from the parent's +// reflow state +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize) +{ + reason = aParentReflowState.reason; + reflowCommand = aParentReflowState.reflowCommand; + maxSize = aMaxSize; + parentReflowState = &aParentReflowState; + frame = aFrame; +} + +// Constructs a reflow state that overrides the reflow reason of the parent +// reflow state. Sets the reflow command to NULL +inline nsReflowState::nsReflowState(nsIFrame* aFrame, + const nsReflowState& aParentReflowState, + const nsSize& aMaxSize, + nsReflowReason aReflowReason) +{ + reason = aReflowReason; + reflowCommand = nsnull; + maxSize = aMaxSize; + parentReflowState = &aParentReflowState; + frame = aFrame; +} + #endif /* nsIFrame_h___ */ diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 0c273a040032..53605fe46489 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -53,31 +53,33 @@ NS_DEF_PTR(nsIContentDelegate); class nsInlineState { public: - nsStyleFont* font; // style font - nsMargin borderPadding; // inner margin - nsSize mStyleSize; - PRIntn mStyleSizeFlags; - nsSize availSize; // available space in which to reflow (starts as max size minus insets) - nsSize* maxElementSize; // maximum element size (may be null) - nscoord x; // running x-offset (starts at left inner edge) - const nscoord y; // y-offset (top inner edge) - nscoord maxAscent; // max child ascent - nscoord maxDescent; // max child descent - nscoord* ascents; // ascent information for each child - PRBool unconstrainedWidth; - PRBool unconstrainedHeight; - nsLineLayout* lineLayout; - PRBool atBreakPoint; + nsStyleFont* font; // style font + nsMargin borderPadding; // inner margin + nsSize mStyleSize; + PRIntn mStyleSizeFlags; + nsSize availSize; // available space in which to reflow (starts as max size minus insets) + nsSize* maxElementSize; // maximum element size (may be null) + nscoord x; // running x-offset (starts at left inner edge) + const nscoord y; // y-offset (top inner edge) + nscoord maxAscent; // max child ascent + nscoord maxDescent; // max child descent + nscoord* ascents; // ascent information for each child + PRBool unconstrainedWidth; + PRBool unconstrainedHeight; + nsLineLayout* lineLayout; + PRBool atBreakPoint; + const nsReflowState& reflowState; // Constructor - nsInlineState(nsIPresContext* aPresContext, - nsIFrame* aInlineFrame, - nsStyleFont* aStyleFont, - const nsMargin& aBorderPadding, - const nsSize& aMaxSize, - nsSize* aMaxElementSize) + nsInlineState(nsIPresContext* aPresContext, + nsIFrame* aInlineFrame, + nsStyleFont* aStyleFont, + const nsMargin& aBorderPadding, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize) : x(aBorderPadding.left), // determined by inner edge - y(aBorderPadding.top) // determined by inner edge + y(aBorderPadding.top), // determined by inner edge + reflowState(aReflowState) { nsBlockReflowState* brs = nsBlockFrame::FindBlockReflowState(aPresContext, aInlineFrame); @@ -87,16 +89,16 @@ public: font = aStyleFont; borderPadding = aBorderPadding; - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); // If we're constrained adjust the available size so it excludes space // needed for border/padding - availSize.width = aMaxSize.width; + availSize.width = reflowState.maxSize.width; if (PR_FALSE == unconstrainedWidth) { availSize.width -= aBorderPadding.left + aBorderPadding.right; } - availSize.height = aMaxSize.height; + availSize.height = reflowState.maxSize.height; if (PR_FALSE == unconstrainedHeight) { availSize.height -= aBorderPadding.top + aBorderPadding.bottom; } @@ -276,7 +278,8 @@ PRBool nsInlineFrame::ReflowMappedChildrenFrom(nsIPresContext* aPresContext, for (nsIFrame* kidFrame = aChildFrame; nsnull != kidFrame; ) { nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); nsReflowStatus status; // Reflow the child into the available space @@ -462,7 +465,8 @@ PRBool nsInlineFrame::PullUpChildren(nsIPresContext* aPresContext, } #endif - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -716,7 +720,8 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext, // Try to reflow the child into the available space. It might not // fit or might need continuing. nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -828,7 +833,7 @@ NS_METHOD nsInlineFrame::Reflow(nsIPresContext* aPresContext, nsMargin borderPadding; styleSpacing->CalcBorderPaddingFor(this, borderPadding); nsInlineState state(aPresContext, this, styleFont, borderPadding, - aReflowState.maxSize, aDesiredSize.maxElementSize); + aReflowState, aDesiredSize.maxElementSize); InitializeState(aPresContext, state); state.SetNumAscents(mContent->ChildCount() - mFirstContentOffset); @@ -851,7 +856,7 @@ NS_METHOD nsInlineFrame::Reflow(nsIPresContext* aPresContext, // The command is passing through us. Get the next frame in the reflow chain nsIFrame* kidFrame = aReflowState.reflowCommand->GetNext(); nsReflowMetrics kidSize(aDesiredSize.maxElementSize); - nsReflowState kidReflowState(aReflowState.reflowCommand, state.availSize); + nsReflowState kidReflowState(kidFrame, aReflowState, state.availSize); // Restore our state as if nextFrame is the next frame to reflow PRInt32 kidIndex = RecoverState(aPresContext, state, kidFrame); diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index 7b90d68edab5..64b769fd83ab 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -677,7 +677,8 @@ nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand, } } - nsReflowState kidReflowState(kidReason, kidAvailSize); + nsReflowState kidReflowState(kidFrame, *mBlockReflowState.reflowState, + kidAvailSize, kidReason); kidReflowState.reflowCommand = aReflowCommand; mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE; nscoord dx = mState.mX + kidMargin.left; diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index db3be25bcba8..b05f70384eaf 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -78,9 +78,9 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, // Dispatch the reflow command to our content child. Allow it to be as high // as it wants nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE); - nsReflowState reflowState(aReflowState.reflowCommand, maxSize); + nsReflowState kidReflowState(mFirstChild, aReflowState, maxSize); - aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, reflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState); // Place and size the child. Make sure the child is at least as // tall as our max size (the containing window) @@ -119,9 +119,11 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, // Resize our frame allowing it only to be as big as we are // XXX Pay attention to the page's border and padding... if (nsnull != mFirstChild) { + nsReflowState kidReflowState(mFirstChild, aReflowState, aReflowState.maxSize); + // Get the child's desired size mFirstChild->WillReflow(*aPresContext); - aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, aReflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState); mLastContentIsComplete = NS_FRAME_IS_COMPLETE(aStatus); // Make sure the child is at least as tall as our max size (the containing window) diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index 0b0bfeeb7b6f..8f897c6e8990 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -79,7 +79,8 @@ NS_METHOD nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext, // Resize reflow the anchored item into the available space // XXX Check for complete? nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Initial, aReflowState.maxSize); + nsReflowState reflowState(mAnchoredItem, aReflowState, aReflowState.maxSize, + eReflowReason_Initial); mAnchoredItem->WillReflow(*aPresContext); mAnchoredItem->Reflow(aPresContext, desiredSize, reflowState, aStatus); mAnchoredItem->SizeTo(desiredSize.width, desiredSize.height); @@ -94,7 +95,8 @@ NS_METHOD nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext, // of the incremental reflow methods and propagating things down // properly to the contained frame. nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Resize, aReflowState.maxSize); + nsReflowState reflowState(mAnchoredItem, aReflowState, aReflowState.maxSize, + eReflowReason_Resize); mAnchoredItem->WillReflow(*aPresContext); mAnchoredItem->Reflow(aPresContext, desiredSize, reflowState, aStatus); mAnchoredItem->SizeTo(desiredSize.width, desiredSize.height); diff --git a/layout/html/base/src/nsAbsoluteFrame.cpp b/layout/html/base/src/nsAbsoluteFrame.cpp index e7193e2c411c..b01cba1064fb 100644 --- a/layout/html/base/src/nsAbsoluteFrame.cpp +++ b/layout/html/base/src/nsAbsoluteFrame.cpp @@ -325,7 +325,7 @@ NS_METHOD nsAbsoluteFrame::Reflow(nsIPresContext* aPresContext, } nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Initial, availSize); + nsReflowState reflowState(mFrame, aReflowState, availSize, eReflowReason_Initial); mFrame->WillReflow(*aPresContext); mFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index a0d7301816c2..e7ab36b63c9a 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -101,7 +101,7 @@ nsBlockReflowState::~nsBlockReflowState() nsresult nsBlockReflowState::Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock) { @@ -114,10 +114,11 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext, mListPositionOutside = PR_FALSE; mCurrentLine = nsnull; mPrevKidFrame = nsnull; + reflowState = &aReflowState; mX = 0; mY = 0; - mAvailSize = aMaxSize; + mAvailSize = reflowState->maxSize; mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE); mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE); mMaxElementSizePointer = aMaxElementSize; @@ -447,7 +448,7 @@ nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) { @@ -955,15 +956,15 @@ done: } nsresult -nsBlockFrame::InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState) +nsBlockFrame::InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState) { nsresult rv; rv = aState.Initialize(aPresContext, aSpaceManager, - aMaxSize, aMaxElementSize, this); + aReflowState, aMaxElementSize, this); // Apply border and padding adjustments for regular frames only if (!aState.mBlockIsPseudo) { @@ -1173,7 +1174,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - rv = InitializeState(aPresContext, aSpaceManager, aReflowState.maxSize, + rv = InitializeState(aPresContext, aSpaceManager, aReflowState, aDesiredSize.maxElementSize, state); NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d", diff --git a/layout/html/base/src/nsBlockFrame.h b/layout/html/base/src/nsBlockFrame.h index 684644e442ae..3138e67d6abc 100644 --- a/layout/html/base/src/nsBlockFrame.h +++ b/layout/html/base/src/nsBlockFrame.h @@ -59,7 +59,7 @@ struct nsBlockReflowState { nsresult Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock); @@ -86,6 +86,7 @@ struct nsBlockReflowState { PRPackedBool mUnconstrainedHeight; nsSize* mMaxElementSizePointer; nscoord mKidXMost; + const nsReflowState* reflowState; // Change in width since last reflow nscoord mDeltaWidth; @@ -216,7 +217,7 @@ public: nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus); @@ -234,11 +235,11 @@ protected: virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow); - nsresult InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState); + nsresult InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState); void ComputeDesiredRect(nsBlockReflowState& aState, const nsSize& aMaxSize, diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index a0d7301816c2..e7ab36b63c9a 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -101,7 +101,7 @@ nsBlockReflowState::~nsBlockReflowState() nsresult nsBlockReflowState::Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock) { @@ -114,10 +114,11 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext, mListPositionOutside = PR_FALSE; mCurrentLine = nsnull; mPrevKidFrame = nsnull; + reflowState = &aReflowState; mX = 0; mY = 0; - mAvailSize = aMaxSize; + mAvailSize = reflowState->maxSize; mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE); mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE); mMaxElementSizePointer = aMaxElementSize; @@ -447,7 +448,7 @@ nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) { @@ -955,15 +956,15 @@ done: } nsresult -nsBlockFrame::InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState) +nsBlockFrame::InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState) { nsresult rv; rv = aState.Initialize(aPresContext, aSpaceManager, - aMaxSize, aMaxElementSize, this); + aReflowState, aMaxElementSize, this); // Apply border and padding adjustments for regular frames only if (!aState.mBlockIsPseudo) { @@ -1173,7 +1174,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - rv = InitializeState(aPresContext, aSpaceManager, aReflowState.maxSize, + rv = InitializeState(aPresContext, aSpaceManager, aReflowState, aDesiredSize.maxElementSize, state); NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d", diff --git a/layout/html/base/src/nsBlockReflowState.h b/layout/html/base/src/nsBlockReflowState.h index a0d7301816c2..e7ab36b63c9a 100644 --- a/layout/html/base/src/nsBlockReflowState.h +++ b/layout/html/base/src/nsBlockReflowState.h @@ -101,7 +101,7 @@ nsBlockReflowState::~nsBlockReflowState() nsresult nsBlockReflowState::Initialize(nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, nsBlockFrame* aBlock) { @@ -114,10 +114,11 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext, mListPositionOutside = PR_FALSE; mCurrentLine = nsnull; mPrevKidFrame = nsnull; + reflowState = &aReflowState; mX = 0; mY = 0; - mAvailSize = aMaxSize; + mAvailSize = reflowState->maxSize; mUnconstrainedWidth = PRBool(mAvailSize.width == NS_UNCONSTRAINEDSIZE); mUnconstrainedHeight = PRBool(mAvailSize.height == NS_UNCONSTRAINEDSIZE); mMaxElementSizePointer = aMaxElementSize; @@ -447,7 +448,7 @@ nsBlockFrame::ReflowBlockChild(nsIFrame* aKidFrame, nsIPresContext* aPresContext, nsISpaceManager* aSpaceManager, nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, + nsReflowState& aReflowState, nsRect& aDesiredRect, nsReflowStatus& aStatus) { @@ -955,15 +956,15 @@ done: } nsresult -nsBlockFrame::InitializeState(nsIPresContext* aPresContext, - nsISpaceManager* aSpaceManager, - const nsSize& aMaxSize, - nsSize* aMaxElementSize, - nsBlockReflowState& aState) +nsBlockFrame::InitializeState(nsIPresContext* aPresContext, + nsISpaceManager* aSpaceManager, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize, + nsBlockReflowState& aState) { nsresult rv; rv = aState.Initialize(aPresContext, aSpaceManager, - aMaxSize, aMaxElementSize, this); + aReflowState, aMaxElementSize, this); // Apply border and padding adjustments for regular frames only if (!aState.mBlockIsPseudo) { @@ -1173,7 +1174,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, } aStatus = NS_FRAME_COMPLETE; - rv = InitializeState(aPresContext, aSpaceManager, aReflowState.maxSize, + rv = InitializeState(aPresContext, aSpaceManager, aReflowState, aDesiredSize.maxElementSize, state); NS_FRAME_TRACE_MSG(("enter nsBlockFrame::Reflow: reason=%d deltaWidth=%d", diff --git a/layout/html/base/src/nsBodyFrame.cpp b/layout/html/base/src/nsBodyFrame.cpp index 1e00b3c0cc11..2507e7ab1ced 100644 --- a/layout/html/base/src/nsBodyFrame.cpp +++ b/layout/html/base/src/nsBodyFrame.cpp @@ -181,7 +181,7 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext, // It's a floating frame that's the target. Reflow the body making it // look like a resize occured. This will reflow the placeholder which will // resize the floating frame... - nsReflowState reflowState(eReflowReason_Resize, aReflowState.maxSize); + nsReflowState reflowState(next, aReflowState, aReflowState.maxSize, eReflowReason_Resize); return Reflow(aPresContext, aDesiredSize, reflowState, aStatus); } } @@ -207,7 +207,7 @@ NS_METHOD nsBodyFrame::Reflow(nsIPresContext* aPresContext, // Get the column's desired rect nsIRunaround* reflowRunaround; - nsReflowState reflowState(aReflowState, kidMaxSize); + nsReflowState reflowState(mFirstChild, aReflowState, kidMaxSize); nsRect desiredRect; mFirstChild->WillReflow(*aPresContext); diff --git a/layout/html/base/src/nsInlineFrame.cpp b/layout/html/base/src/nsInlineFrame.cpp index 0c273a040032..53605fe46489 100644 --- a/layout/html/base/src/nsInlineFrame.cpp +++ b/layout/html/base/src/nsInlineFrame.cpp @@ -53,31 +53,33 @@ NS_DEF_PTR(nsIContentDelegate); class nsInlineState { public: - nsStyleFont* font; // style font - nsMargin borderPadding; // inner margin - nsSize mStyleSize; - PRIntn mStyleSizeFlags; - nsSize availSize; // available space in which to reflow (starts as max size minus insets) - nsSize* maxElementSize; // maximum element size (may be null) - nscoord x; // running x-offset (starts at left inner edge) - const nscoord y; // y-offset (top inner edge) - nscoord maxAscent; // max child ascent - nscoord maxDescent; // max child descent - nscoord* ascents; // ascent information for each child - PRBool unconstrainedWidth; - PRBool unconstrainedHeight; - nsLineLayout* lineLayout; - PRBool atBreakPoint; + nsStyleFont* font; // style font + nsMargin borderPadding; // inner margin + nsSize mStyleSize; + PRIntn mStyleSizeFlags; + nsSize availSize; // available space in which to reflow (starts as max size minus insets) + nsSize* maxElementSize; // maximum element size (may be null) + nscoord x; // running x-offset (starts at left inner edge) + const nscoord y; // y-offset (top inner edge) + nscoord maxAscent; // max child ascent + nscoord maxDescent; // max child descent + nscoord* ascents; // ascent information for each child + PRBool unconstrainedWidth; + PRBool unconstrainedHeight; + nsLineLayout* lineLayout; + PRBool atBreakPoint; + const nsReflowState& reflowState; // Constructor - nsInlineState(nsIPresContext* aPresContext, - nsIFrame* aInlineFrame, - nsStyleFont* aStyleFont, - const nsMargin& aBorderPadding, - const nsSize& aMaxSize, - nsSize* aMaxElementSize) + nsInlineState(nsIPresContext* aPresContext, + nsIFrame* aInlineFrame, + nsStyleFont* aStyleFont, + const nsMargin& aBorderPadding, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize) : x(aBorderPadding.left), // determined by inner edge - y(aBorderPadding.top) // determined by inner edge + y(aBorderPadding.top), // determined by inner edge + reflowState(aReflowState) { nsBlockReflowState* brs = nsBlockFrame::FindBlockReflowState(aPresContext, aInlineFrame); @@ -87,16 +89,16 @@ public: font = aStyleFont; borderPadding = aBorderPadding; - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); // If we're constrained adjust the available size so it excludes space // needed for border/padding - availSize.width = aMaxSize.width; + availSize.width = reflowState.maxSize.width; if (PR_FALSE == unconstrainedWidth) { availSize.width -= aBorderPadding.left + aBorderPadding.right; } - availSize.height = aMaxSize.height; + availSize.height = reflowState.maxSize.height; if (PR_FALSE == unconstrainedHeight) { availSize.height -= aBorderPadding.top + aBorderPadding.bottom; } @@ -276,7 +278,8 @@ PRBool nsInlineFrame::ReflowMappedChildrenFrom(nsIPresContext* aPresContext, for (nsIFrame* kidFrame = aChildFrame; nsnull != kidFrame; ) { nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); nsReflowStatus status; // Reflow the child into the available space @@ -462,7 +465,8 @@ PRBool nsInlineFrame::PullUpChildren(nsIPresContext* aPresContext, } #endif - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -716,7 +720,8 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext, // Try to reflow the child into the available space. It might not // fit or might need continuing. nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -828,7 +833,7 @@ NS_METHOD nsInlineFrame::Reflow(nsIPresContext* aPresContext, nsMargin borderPadding; styleSpacing->CalcBorderPaddingFor(this, borderPadding); nsInlineState state(aPresContext, this, styleFont, borderPadding, - aReflowState.maxSize, aDesiredSize.maxElementSize); + aReflowState, aDesiredSize.maxElementSize); InitializeState(aPresContext, state); state.SetNumAscents(mContent->ChildCount() - mFirstContentOffset); @@ -851,7 +856,7 @@ NS_METHOD nsInlineFrame::Reflow(nsIPresContext* aPresContext, // The command is passing through us. Get the next frame in the reflow chain nsIFrame* kidFrame = aReflowState.reflowCommand->GetNext(); nsReflowMetrics kidSize(aDesiredSize.maxElementSize); - nsReflowState kidReflowState(aReflowState.reflowCommand, state.availSize); + nsReflowState kidReflowState(kidFrame, aReflowState, state.availSize); // Restore our state as if nextFrame is the next frame to reflow PRInt32 kidIndex = RecoverState(aPresContext, state, kidFrame); diff --git a/layout/html/base/src/nsLineLayout.cpp b/layout/html/base/src/nsLineLayout.cpp index 7b90d68edab5..64b769fd83ab 100644 --- a/layout/html/base/src/nsLineLayout.cpp +++ b/layout/html/base/src/nsLineLayout.cpp @@ -677,7 +677,8 @@ nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand, } } - nsReflowState kidReflowState(kidReason, kidAvailSize); + nsReflowState kidReflowState(kidFrame, *mBlockReflowState.reflowState, + kidAvailSize, kidReason); kidReflowState.reflowCommand = aReflowCommand; mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE; nscoord dx = mState.mX + kidMargin.left; diff --git a/layout/html/base/src/nsPageFrame.cpp b/layout/html/base/src/nsPageFrame.cpp index db3be25bcba8..b05f70384eaf 100644 --- a/layout/html/base/src/nsPageFrame.cpp +++ b/layout/html/base/src/nsPageFrame.cpp @@ -78,9 +78,9 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, // Dispatch the reflow command to our content child. Allow it to be as high // as it wants nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE); - nsReflowState reflowState(aReflowState.reflowCommand, maxSize); + nsReflowState kidReflowState(mFirstChild, aReflowState, maxSize); - aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, reflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState); // Place and size the child. Make sure the child is at least as // tall as our max size (the containing window) @@ -119,9 +119,11 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, // Resize our frame allowing it only to be as big as we are // XXX Pay attention to the page's border and padding... if (nsnull != mFirstChild) { + nsReflowState kidReflowState(mFirstChild, aReflowState, aReflowState.maxSize); + // Get the child's desired size mFirstChild->WillReflow(*aPresContext); - aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, aReflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState); mLastContentIsComplete = NS_FRAME_IS_COMPLETE(aStatus); // Make sure the child is at least as tall as our max size (the containing window) diff --git a/layout/html/base/src/nsPlaceholderFrame.cpp b/layout/html/base/src/nsPlaceholderFrame.cpp index 0b0bfeeb7b6f..8f897c6e8990 100644 --- a/layout/html/base/src/nsPlaceholderFrame.cpp +++ b/layout/html/base/src/nsPlaceholderFrame.cpp @@ -79,7 +79,8 @@ NS_METHOD nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext, // Resize reflow the anchored item into the available space // XXX Check for complete? nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Initial, aReflowState.maxSize); + nsReflowState reflowState(mAnchoredItem, aReflowState, aReflowState.maxSize, + eReflowReason_Initial); mAnchoredItem->WillReflow(*aPresContext); mAnchoredItem->Reflow(aPresContext, desiredSize, reflowState, aStatus); mAnchoredItem->SizeTo(desiredSize.width, desiredSize.height); @@ -94,7 +95,8 @@ NS_METHOD nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext, // of the incremental reflow methods and propagating things down // properly to the contained frame. nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Resize, aReflowState.maxSize); + nsReflowState reflowState(mAnchoredItem, aReflowState, aReflowState.maxSize, + eReflowReason_Resize); mAnchoredItem->WillReflow(*aPresContext); mAnchoredItem->Reflow(aPresContext, desiredSize, reflowState, aStatus); mAnchoredItem->SizeTo(desiredSize.width, desiredSize.height); diff --git a/layout/html/base/src/nsRootPart.cpp b/layout/html/base/src/nsRootPart.cpp index 0c3824f910cc..5504c812b074 100644 --- a/layout/html/base/src/nsRootPart.cpp +++ b/layout/html/base/src/nsRootPart.cpp @@ -112,11 +112,12 @@ NS_METHOD RootFrame::Reflow(nsIPresContext* aPresContext, // Reflow our pseudo frame. It will choose whetever height its child frame // wants - nsReflowMetrics desiredSize(nsnull); - if (nsnull != mFirstChild) { + nsReflowMetrics desiredSize(nsnull); + nsReflowState kidReflowState(mFirstChild, aReflowState, aReflowState.maxSize); + mFirstChild->WillReflow(*aPresContext); - aStatus = ReflowChild(mFirstChild, aPresContext, desiredSize, aReflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, desiredSize, kidReflowState); // Place and size the child nsRect rect(0, 0, desiredSize.width, desiredSize.height); @@ -279,17 +280,17 @@ NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext, NS_ASSERTION(aReflowState.reflowCommand->GetTarget() != this, "root content frame is reflow command target"); - nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE); - nsReflowState reflowState(aReflowState.reflowCommand, maxSize); - // Verify the next frame in the reflow chain is our child frame nsIFrame* next = aReflowState.reflowCommand->GetNext(); NS_ASSERTION(next == mFirstChild, "unexpected next reflow command frame"); + nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE); + nsReflowState kidReflowState(next, aReflowState, maxSize); + // Dispatch the reflow command to our child frame. Allow it to be as high // as it wants mFirstChild->WillReflow(*aPresContext); - aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, reflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState); // Place and size the child. Make sure the child is at least as // tall as our max size (the containing window) @@ -315,11 +316,11 @@ NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext, nsReflowMetrics kidSize(aDesiredSize.maxElementSize); nsSize pageSize(aPresContext->GetPageWidth(), aPresContext->GetPageHeight()); - nsReflowState reflowState(aReflowState.reason, pageSize); // Tile the pages vertically for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) { // Reflow the page + nsReflowState kidReflowState(kidFrame, aReflowState, pageSize); nsReflowStatus status; // Place and size the page. If the page is narrower than our max width then @@ -332,7 +333,7 @@ NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext, kidFrame->WillReflow(*aPresContext); kidFrame->MoveTo(x, y); - status = ReflowChild(kidFrame, aPresContext, kidSize, reflowState); + status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); kidFrame->SetRect(nsRect(x, y, kidSize.width, kidSize.height)); kidFrame->DidReflow(*aPresContext, NS_FRAME_REFLOW_FINISHED); @@ -380,12 +381,12 @@ NS_METHOD RootContentFrame::Reflow(nsIPresContext* aPresContext, // Allow the frame to be as wide as our max width, and as high // as it wants to be. nsSize maxSize(aReflowState.maxSize.width, NS_UNCONSTRAINEDSIZE); - nsReflowState reflowState(aReflowState.reason, maxSize); + nsReflowState kidReflowState(mFirstChild, aReflowState, maxSize); // Get the child's desired size. Our child's desired height is our // desired size mFirstChild->WillReflow(*aPresContext); - aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, reflowState); + aStatus = ReflowChild(mFirstChild, aPresContext, aDesiredSize, kidReflowState); NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); // Place and size the child. Make sure the child is at least as diff --git a/layout/html/forms/src/nsInputFile.cpp b/layout/html/forms/src/nsInputFile.cpp index 55bb6847173e..acea87a1438c 100644 --- a/layout/html/forms/src/nsInputFile.cpp +++ b/layout/html/forms/src/nsInputFile.cpp @@ -181,7 +181,7 @@ NS_IMETHODIMP nsInputFileFrame::Reflow(nsIPresContext* aCX, aDesiredSize.height = 0; childFrame = mFirstChild; while (nsnull != childFrame) { - nsReflowState reflowState(aReflowState, maxSize); + nsReflowState reflowState(childFrame, aReflowState, maxSize); nsresult result = childFrame->Reflow(aCX, desiredSize, reflowState, aStatus); // XXX check aStatus ?? if (NS_OK != result) { diff --git a/layout/html/table/src/nsTableCellFrame.cpp b/layout/html/table/src/nsTableCellFrame.cpp index 774c9aee6d5b..fcc777cbb83d 100644 --- a/layout/html/table/src/nsTableCellFrame.cpp +++ b/layout/html/table/src/nsTableCellFrame.cpp @@ -300,7 +300,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, printf(" nsTableCellFrame::ResizeReflow calling ReflowChild with availSize=%d,%d\n", availSize.width, availSize.height); nsReflowMetrics kidSize(pMaxElementSize); - nsReflowState kidReflowState(aReflowState, availSize); + nsReflowState kidReflowState(mFirstChild, aReflowState, availSize); mFirstChild->WillReflow(*aPresContext); aStatus = ReflowChild(mFirstChild, aPresContext, kidSize, kidReflowState); diff --git a/layout/html/table/src/nsTableColGroupFrame.cpp b/layout/html/table/src/nsTableColGroupFrame.cpp index 274f410686ee..4a1b85720c5a 100644 --- a/layout/html/table/src/nsTableColGroupFrame.cpp +++ b/layout/html/table/src/nsTableColGroupFrame.cpp @@ -89,7 +89,7 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext* aPresContext, // give the child frame a chance to reflow, even though we know it'll have 0 size nsReflowMetrics kidSize(nsnull); - nsReflowState kidReflowState(eReflowReason_Initial, nsSize(0,0)); + nsReflowState kidReflowState(kidFrame, aReflowState, nsSize(0,0), eReflowReason_Initial); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame,aPresContext, kidSize, kidReflowState); diff --git a/layout/html/table/src/nsTableFrame.cpp b/layout/html/table/src/nsTableFrame.cpp index 04969bb77828..301cf4dd80a3 100644 --- a/layout/html/table/src/nsTableFrame.cpp +++ b/layout/html/table/src/nsTableFrame.cpp @@ -73,6 +73,9 @@ struct InnerTableReflowState { // The body's style molecule + // Our reflow state + const nsReflowState& reflowState; + // The body's available size (computed from the body's parent) nsSize availSize; @@ -98,23 +101,24 @@ struct InnerTableReflowState { // cache the total height of the footers for placing body rows nscoord footerHeight; - InnerTableReflowState(nsIPresContext* aPresContext, - const nsSize& aMaxSize, - const nsMargin& aBorderPadding) + InnerTableReflowState(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + const nsMargin& aBorderPadding) + : reflowState(aReflowState) { prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; y=0; // border/padding/margin??? - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - availSize.width = aMaxSize.width; + unconstrainedWidth = PRBool(aReflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + availSize.width = aReflowState.maxSize.width; if (!unconstrainedWidth) { availSize.width -= aBorderPadding.left + aBorderPadding.right; } leftInset = aBorderPadding.left; - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); - availSize.height = aMaxSize.height; + unconstrainedHeight = PRBool(aReflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); + availSize.height = aReflowState.maxSize.height; if (!unconstrainedHeight) { availSize.height -= aBorderPadding.top + aBorderPadding.bottom; } @@ -518,8 +522,8 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, if (PR_FALSE==IsFirstPassValid()) { // we treat the table as if we've never seen the layout data before mPass = kPASS_FIRST; - aStatus = ResizeReflowPass1(aPresContext, aDesiredSize, - aReflowState.maxSize, aDesiredSize.maxElementSize); + aStatus = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, + aDesiredSize.maxElementSize); // check result } mPass = kPASS_SECOND; @@ -530,7 +534,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, // assign table width SetTableWidth(aPresContext); - aStatus = ResizeReflowPass2(aPresContext, aDesiredSize, aReflowState.maxSize, + aStatus = ResizeReflowPass2(aPresContext, aDesiredSize, aReflowState, aDesiredSize.maxElementSize, 0, 0); if (gsTiming) { @@ -563,14 +567,17 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, */ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize) { + NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); + NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, + "bad parent reflow state"); NS_ASSERTION(nsnull!=aPresContext, "bad pres context param"); NS_ASSERTION(nsnull==mPrevInFlow, "illegal call, cannot call pass 1 on a continuing frame."); if (gsDebug==PR_TRUE) printf("nsTableFrame::ResizeReflow Pass1: maxSize=%d,%d\n", - aMaxSize.width, aMaxSize.height); + aReflowState.maxSize.width, aReflowState.maxSize.height); if (PR_TRUE==gsDebug) printf ("*** tableframe reflow pass1\t\t%d\n", this); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -684,7 +691,8 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, } nsSize maxKidElementSize; - nsReflowState kidReflowState(eReflowReason_Resize, availSize); + nsReflowState kidReflowState(kidFrame, aReflowState, availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); result = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -763,15 +771,18 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, */ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, PRInt32 aMinCaptionWidth, PRInt32 mMaxCaptionWidth) { + NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); + NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, + "bad parent reflow state"); if (PR_TRUE==gsDebug) printf ("***tableframe reflow pass2\t\t%d\n", this); if (gsDebug==PR_TRUE) printf("nsTableFrame::ResizeReflow Pass2: maxSize=%d,%d\n", - aMaxSize.width, aMaxSize.height); + aReflowState.maxSize.width, aReflowState.maxSize.height); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -805,7 +816,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, nsMargin myBorderPadding; mySpacing->CalcBorderPaddingFor(this, myBorderPadding); - InnerTableReflowState state(aPresContext, aMaxSize, myBorderPadding); + InnerTableReflowState state(aPresContext, aReflowState, myBorderPadding); // Reflow the existing frames if (nsnull != mFirstChild) { @@ -852,7 +863,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, // Return our desired rect //NS_ASSERTION(0WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -1279,7 +1291,8 @@ PRBool nsTableFrame::PullUpChildren(nsIPresContext* aPresContext, mLastContentIsComplete = prevLastContentIsComplete; break; } - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -1494,7 +1507,8 @@ nsTableFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext, // Try to reflow the child into the available space. It might not // fit or might need continuing. nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Initial, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Initial); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame,aPresContext, kidSize, kidReflowState); diff --git a/layout/html/table/src/nsTableFrame.h b/layout/html/table/src/nsTableFrame.h index 51dea15ef249..c29f38d78c4d 100644 --- a/layout/html/table/src/nsTableFrame.h +++ b/layout/html/table/src/nsTableFrame.h @@ -183,10 +183,10 @@ protected: * * @see ResizeReflow */ - virtual nsReflowStatus ResizeReflowPass1(nsIPresContext* aPresContext, - nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, - nsSize* aMaxElementSize); + virtual nsReflowStatus ResizeReflowPass1(nsIPresContext* aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize); /** second pass of ResizeReflow. * lays out all table content with aMaxSize(computed_table_width, given_table_height) @@ -201,7 +201,7 @@ protected: */ virtual nsReflowStatus ResizeReflowPass2(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, PRInt32 aMinCaptionWidth, PRInt32 mMaxCaptionWidth); diff --git a/layout/html/table/src/nsTableOuterFrame.cpp b/layout/html/table/src/nsTableOuterFrame.cpp index 0d04baeffa9c..7be446af5d64 100644 --- a/layout/html/table/src/nsTableOuterFrame.cpp +++ b/layout/html/table/src/nsTableOuterFrame.cpp @@ -53,6 +53,9 @@ struct OuterTableReflowState { // The presentation context nsIPresContext *pc; + // Our reflow state + const nsReflowState& reflowState; + // The total available size (computed from the parent) nsSize availSize; // The available size for the inner table frame @@ -73,17 +76,18 @@ struct OuterTableReflowState { PRBool firstRowGroup; PRBool processingCaption; - OuterTableReflowState(nsIPresContext* aPresContext, - const nsSize& aMaxSize) + OuterTableReflowState(nsIPresContext* aPresContext, + const nsReflowState& aReflowState) + : reflowState(aReflowState) { pc = aPresContext; - availSize.width = aMaxSize.width; - availSize.height = aMaxSize.height; + availSize.width = reflowState.maxSize.width; + availSize.height = reflowState.maxSize.height; prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; y=0; // border/padding/margin??? - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(aReflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(aReflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); firstRowGroup = PR_TRUE; processingCaption = PR_FALSE; } @@ -206,13 +210,13 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, return NS_OK; } - OuterTableReflowState state(aPresContext, aReflowState.maxSize); + OuterTableReflowState state(aPresContext, aReflowState); // lay out captions pass 1, if necessary if (PR_FALSE==IsFirstPassValid()) { mFirstPassValid = PR_TRUE; - aStatus = ResizeReflowCaptionsPass1(aPresContext); + aStatus = ResizeReflowCaptionsPass1(aPresContext, state); } @@ -222,7 +226,9 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, // we treat the table as if we've never seen the layout data before mInnerTableFrame->SetReflowPass(nsTableFrame::kPASS_FIRST); - aStatus = mInnerTableFrame->ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.maxSize, + nsReflowState innerTableReflowState(mInnerTableFrame, aReflowState, aReflowState.maxSize); + aStatus = mInnerTableFrame->ResizeReflowPass1(aPresContext, aDesiredSize, + innerTableReflowState, &innerTableMaxElementSize); mInnerTableFrame->RecalcLayoutData(); @@ -897,20 +903,21 @@ nsTableOuterFrame::ReflowChild( nsIFrame* aKidFrame, if (PR_TRUE==gsDebug) printf("reflowChild called with a bottom caption\n"); status = ResizeReflowBottomCaptionsPass2(aPresContext, aDesiredSize, aMaxSize, aMaxElementSize, - aState.y); + aState.y, aState); } else { if (PR_TRUE==gsDebug) printf("reflowChild called with a top caption\n"); status = ResizeReflowTopCaptionsPass2(aPresContext, aDesiredSize, - aMaxSize, aMaxElementSize); + aMaxSize, aMaxElementSize, aState); } } else { if (PR_TRUE==gsDebug) printf("reflowChild called with a table body\n"); - status = ((nsTableFrame*)aKidFrame)->ResizeReflowPass2(aPresContext, aDesiredSize, aState.innerTableMaxSize, - aMaxElementSize, + nsReflowState kidReflowState(aKidFrame, aState.reflowState, aState.innerTableMaxSize); + status = ((nsTableFrame*)aKidFrame)->ResizeReflowPass2(aPresContext, aDesiredSize, + kidReflowState, aMaxElementSize, mMinCaptionWidth, mMaxCaptionWidth); } if (PR_TRUE==gsDebug) @@ -1015,7 +1022,8 @@ void nsTableOuterFrame::CreateChildFrames(nsIPresContext* aPresContext) nsReflowStatus -nsTableOuterFrame::ResizeReflowCaptionsPass1(nsIPresContext* aPresContext) +nsTableOuterFrame::ResizeReflowCaptionsPass1(nsIPresContext* aPresContext, + OuterTableReflowState& aState) { if (nsnull!=mCaptionFrames) { @@ -1027,7 +1035,7 @@ nsTableOuterFrame::ResizeReflowCaptionsPass1(nsIPresContext* aPresContext) nsReflowMetrics desiredSize(&maxElementSize); nsTableCaptionFrame *captionFrame = (nsTableCaptionFrame *)mCaptionFrames->ElementAt(captionIndex); nsReflowStatus status; - nsReflowState reflowState(eReflowReason_Resize, maxSize); + nsReflowState reflowState(captionFrame, aState.reflowState, maxSize, eReflowReason_Resize); captionFrame->WillReflow(*aPresContext); captionFrame->Reflow(aPresContext, desiredSize, reflowState, status); if (mMinCaptionWidthWillReflow(*aPresContext); result = nsContainerFrame::ReflowChild(captionFrame, aPresContext, desiredSize, reflowState); // place the caption @@ -1114,7 +1123,8 @@ nsTableOuterFrame::ResizeReflowBottomCaptionsPass2(nsIPresContext* aPresContext nsReflowMetrics& aDesiredSize, const nsSize& aMaxSize, nsSize* aMaxElementSize, - nscoord aYOffset) + nscoord aYOffset, + OuterTableReflowState& aState) { nsReflowStatus result = NS_FRAME_COMPLETE; nscoord bottomCaptionY = aYOffset; @@ -1137,7 +1147,7 @@ nsTableOuterFrame::ResizeReflowBottomCaptionsPass2(nsIPresContext* aPresContext */ // reflow the caption nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Resize, aMaxSize); + nsReflowState reflowState(captionFrame, aState.reflowState, aMaxSize, eReflowReason_Resize); captionFrame->WillReflow(*aPresContext); result = nsContainerFrame::ReflowChild(captionFrame, aPresContext, desiredSize, reflowState); diff --git a/layout/html/table/src/nsTableOuterFrame.h b/layout/html/table/src/nsTableOuterFrame.h index 1084e1568eaa..daef7706a8e3 100644 --- a/layout/html/table/src/nsTableOuterFrame.h +++ b/layout/html/table/src/nsTableOuterFrame.h @@ -125,7 +125,8 @@ protected: /** reflow the captions in an infinite space, caching the min/max sizes for each */ - virtual nsReflowStatus ResizeReflowCaptionsPass1(nsIPresContext* aPresContext); + virtual nsReflowStatus ResizeReflowCaptionsPass1(nsIPresContext* aPresContext, + OuterTableReflowState& aState); /** reflow the top captions in a space constrained by the computed table width * and the heigth given to us by our parent. Top captions are laid down @@ -134,7 +135,8 @@ protected: virtual nsReflowStatus ResizeReflowTopCaptionsPass2(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, const nsSize& aMaxSize, - nsSize* aMaxElementSize); + nsSize* aMaxElementSize, + OuterTableReflowState& aState); /** reflow the bottom captions in a space constrained by the computed table width * and the heigth given to us by our parent. Bottom captions are laid down @@ -144,7 +146,8 @@ protected: nsReflowMetrics& aDesiredSize, const nsSize& aMaxSize, nsSize* aMaxElementSize, - nscoord aYOffset); + nscoord aYOffset, + OuterTableReflowState& aState); nscoord GetTopMarginFor(nsIPresContext* aCX, OuterTableReflowState& aState, diff --git a/layout/html/table/src/nsTableRowFrame.cpp b/layout/html/table/src/nsTableRowFrame.cpp index 9257f2639930..d3214f838881 100644 --- a/layout/html/table/src/nsTableRowFrame.cpp +++ b/layout/html/table/src/nsTableRowFrame.cpp @@ -41,6 +41,9 @@ static const PRBool gsDebug2 = PR_FALSE; /* ----------- RowReflowState ---------- */ struct RowReflowState { + // Our reflow state + const nsReflowState& reflowState; + // The body's available size (computed from the body's parent) nsSize availSize; @@ -64,16 +67,17 @@ struct RowReflowState { nsTableFrame *tableFrame; - RowReflowState( nsIPresContext* aPresContext, - const nsSize& aMaxSize) + RowReflowState( nsIPresContext* aPresContext, + const nsReflowState& aReflowState) + : reflowState(aReflowState) { - availSize.width = aMaxSize.width; - availSize.height = aMaxSize.height; + availSize.width = reflowState.maxSize.width; + availSize.height = reflowState.maxSize.height; prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; x=0; - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); maxCellHeight=0; maxCellVertSpace=0; maxCellHorzSpace=0; @@ -343,7 +347,8 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, if (NS_UNCONSTRAINEDSIZE == aState.availSize.width) { // Reflow the child into the available space - nsReflowState kidReflowState(eReflowReason_Resize, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -360,7 +365,8 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan); kidAvailSize.width = availWidth; - nsReflowState kidReflowState(eReflowReason_Resize, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); } @@ -633,7 +639,8 @@ PRBool nsTableRowFrame::PullUpChildren(nsIPresContext* aPresContext, availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan); NS_ASSERTION(0WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); if (nsnull!=pKidMaxElementSize) @@ -897,7 +904,8 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext, nsReflowStatus status; if (NS_UNCONSTRAINEDSIZE == aState.availSize.width) { - nsReflowState kidReflowState(eReflowReason_Initial, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Initial); // Reflow the child into the available space kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -914,7 +922,7 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext, availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan); NS_ASSERTION(0WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); } @@ -1029,7 +1037,7 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext, // Check for an overflow list MoveOverflowToChildList(); - RowReflowState state(aPresContext, aReflowState.maxSize); + RowReflowState state(aPresContext, aReflowState); mContentParent->GetContentParent((nsIFrame*&)(state.tableFrame)); // Reflow the existing frames diff --git a/layout/html/table/src/nsTableRowGroupFrame.cpp b/layout/html/table/src/nsTableRowGroupFrame.cpp index 5bfd5dba5126..4849095711e7 100644 --- a/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -43,6 +43,9 @@ NS_DEF_PTR(nsIContent); /* ----------- RowGroupReflowState ---------- */ struct RowGroupReflowState { + // Our reflow state + const nsReflowState& reflowState; + // The body's available size (computed from the body's parent) nsSize availSize; @@ -63,16 +66,17 @@ struct RowGroupReflowState { // Remember the height of the first row, because it's our maxElementHeight (plus header/footers) nscoord firstRowHeight; - RowGroupReflowState(nsIPresContext* aPresContext, - const nsSize& aMaxSize) + RowGroupReflowState(nsIPresContext* aPresContext, + const nsReflowState& aReflowState) + : reflowState(aReflowState) { - availSize.width = aMaxSize.width; - availSize.height = aMaxSize.height; + availSize.width = reflowState.maxSize.width; + availSize.height = reflowState.maxSize.height; prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; y=0; // border/padding/margin??? - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); firstRow = PR_TRUE; firstRowHeight=0; } @@ -296,7 +300,8 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon } // Reflow the child into the available space - nsReflowState kidReflowState(eReflowReason_Resize, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -531,7 +536,8 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext, mLastContentIsComplete = prevLastContentIsComplete; break; } - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -760,7 +766,8 @@ nsTableRowGroupFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext, // Try to reflow the child into the available space. It might not // fit or might need continuing. nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Initial, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Initial); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame,aPresContext, kidSize, kidReflowState); @@ -847,7 +854,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext, // Check for an overflow list MoveOverflowToChildList(); - RowGroupReflowState state(aPresContext, aReflowState.maxSize); + RowGroupReflowState state(aPresContext, aReflowState); // Reflow the existing frames if (nsnull != mFirstChild) { diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 774c9aee6d5b..fcc777cbb83d 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -300,7 +300,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, printf(" nsTableCellFrame::ResizeReflow calling ReflowChild with availSize=%d,%d\n", availSize.width, availSize.height); nsReflowMetrics kidSize(pMaxElementSize); - nsReflowState kidReflowState(aReflowState, availSize); + nsReflowState kidReflowState(mFirstChild, aReflowState, availSize); mFirstChild->WillReflow(*aPresContext); aStatus = ReflowChild(mFirstChild, aPresContext, kidSize, kidReflowState); diff --git a/layout/tables/nsTableColGroupFrame.cpp b/layout/tables/nsTableColGroupFrame.cpp index 274f410686ee..4a1b85720c5a 100644 --- a/layout/tables/nsTableColGroupFrame.cpp +++ b/layout/tables/nsTableColGroupFrame.cpp @@ -89,7 +89,7 @@ NS_METHOD nsTableColGroupFrame::Reflow(nsIPresContext* aPresContext, // give the child frame a chance to reflow, even though we know it'll have 0 size nsReflowMetrics kidSize(nsnull); - nsReflowState kidReflowState(eReflowReason_Initial, nsSize(0,0)); + nsReflowState kidReflowState(kidFrame, aReflowState, nsSize(0,0), eReflowReason_Initial); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame,aPresContext, kidSize, kidReflowState); diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 04969bb77828..301cf4dd80a3 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -73,6 +73,9 @@ struct InnerTableReflowState { // The body's style molecule + // Our reflow state + const nsReflowState& reflowState; + // The body's available size (computed from the body's parent) nsSize availSize; @@ -98,23 +101,24 @@ struct InnerTableReflowState { // cache the total height of the footers for placing body rows nscoord footerHeight; - InnerTableReflowState(nsIPresContext* aPresContext, - const nsSize& aMaxSize, - const nsMargin& aBorderPadding) + InnerTableReflowState(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + const nsMargin& aBorderPadding) + : reflowState(aReflowState) { prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; y=0; // border/padding/margin??? - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - availSize.width = aMaxSize.width; + unconstrainedWidth = PRBool(aReflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + availSize.width = aReflowState.maxSize.width; if (!unconstrainedWidth) { availSize.width -= aBorderPadding.left + aBorderPadding.right; } leftInset = aBorderPadding.left; - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); - availSize.height = aMaxSize.height; + unconstrainedHeight = PRBool(aReflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); + availSize.height = aReflowState.maxSize.height; if (!unconstrainedHeight) { availSize.height -= aBorderPadding.top + aBorderPadding.bottom; } @@ -518,8 +522,8 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, if (PR_FALSE==IsFirstPassValid()) { // we treat the table as if we've never seen the layout data before mPass = kPASS_FIRST; - aStatus = ResizeReflowPass1(aPresContext, aDesiredSize, - aReflowState.maxSize, aDesiredSize.maxElementSize); + aStatus = ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState, + aDesiredSize.maxElementSize); // check result } mPass = kPASS_SECOND; @@ -530,7 +534,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, // assign table width SetTableWidth(aPresContext); - aStatus = ResizeReflowPass2(aPresContext, aDesiredSize, aReflowState.maxSize, + aStatus = ResizeReflowPass2(aPresContext, aDesiredSize, aReflowState, aDesiredSize.maxElementSize, 0, 0); if (gsTiming) { @@ -563,14 +567,17 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, */ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize) { + NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); + NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, + "bad parent reflow state"); NS_ASSERTION(nsnull!=aPresContext, "bad pres context param"); NS_ASSERTION(nsnull==mPrevInFlow, "illegal call, cannot call pass 1 on a continuing frame."); if (gsDebug==PR_TRUE) printf("nsTableFrame::ResizeReflow Pass1: maxSize=%d,%d\n", - aMaxSize.width, aMaxSize.height); + aReflowState.maxSize.width, aReflowState.maxSize.height); if (PR_TRUE==gsDebug) printf ("*** tableframe reflow pass1\t\t%d\n", this); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -684,7 +691,8 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, } nsSize maxKidElementSize; - nsReflowState kidReflowState(eReflowReason_Resize, availSize); + nsReflowState kidReflowState(kidFrame, aReflowState, availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); result = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -763,15 +771,18 @@ nsReflowStatus nsTableFrame::ResizeReflowPass1(nsIPresContext* aPresContext, */ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, PRInt32 aMinCaptionWidth, PRInt32 mMaxCaptionWidth) { + NS_PRECONDITION(aReflowState.frame == this, "bad reflow state"); + NS_PRECONDITION(aReflowState.parentReflowState->frame == mGeometricParent, + "bad parent reflow state"); if (PR_TRUE==gsDebug) printf ("***tableframe reflow pass2\t\t%d\n", this); if (gsDebug==PR_TRUE) printf("nsTableFrame::ResizeReflow Pass2: maxSize=%d,%d\n", - aMaxSize.width, aMaxSize.height); + aReflowState.maxSize.width, aReflowState.maxSize.height); nsReflowStatus result = NS_FRAME_COMPLETE; @@ -805,7 +816,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, nsMargin myBorderPadding; mySpacing->CalcBorderPaddingFor(this, myBorderPadding); - InnerTableReflowState state(aPresContext, aMaxSize, myBorderPadding); + InnerTableReflowState state(aPresContext, aReflowState, myBorderPadding); // Reflow the existing frames if (nsnull != mFirstChild) { @@ -852,7 +863,7 @@ nsReflowStatus nsTableFrame::ResizeReflowPass2(nsIPresContext* aPresContext, // Return our desired rect //NS_ASSERTION(0WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -1279,7 +1291,8 @@ PRBool nsTableFrame::PullUpChildren(nsIPresContext* aPresContext, mLastContentIsComplete = prevLastContentIsComplete; break; } - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -1494,7 +1507,8 @@ nsTableFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext, // Try to reflow the child into the available space. It might not // fit or might need continuing. nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Initial, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Initial); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame,aPresContext, kidSize, kidReflowState); diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index 51dea15ef249..c29f38d78c4d 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -183,10 +183,10 @@ protected: * * @see ResizeReflow */ - virtual nsReflowStatus ResizeReflowPass1(nsIPresContext* aPresContext, - nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, - nsSize* aMaxElementSize); + virtual nsReflowStatus ResizeReflowPass1(nsIPresContext* aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsSize* aMaxElementSize); /** second pass of ResizeReflow. * lays out all table content with aMaxSize(computed_table_width, given_table_height) @@ -201,7 +201,7 @@ protected: */ virtual nsReflowStatus ResizeReflowPass2(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, - const nsSize& aMaxSize, + const nsReflowState& aReflowState, nsSize* aMaxElementSize, PRInt32 aMinCaptionWidth, PRInt32 mMaxCaptionWidth); diff --git a/layout/tables/nsTableOuterFrame.cpp b/layout/tables/nsTableOuterFrame.cpp index 0d04baeffa9c..7be446af5d64 100644 --- a/layout/tables/nsTableOuterFrame.cpp +++ b/layout/tables/nsTableOuterFrame.cpp @@ -53,6 +53,9 @@ struct OuterTableReflowState { // The presentation context nsIPresContext *pc; + // Our reflow state + const nsReflowState& reflowState; + // The total available size (computed from the parent) nsSize availSize; // The available size for the inner table frame @@ -73,17 +76,18 @@ struct OuterTableReflowState { PRBool firstRowGroup; PRBool processingCaption; - OuterTableReflowState(nsIPresContext* aPresContext, - const nsSize& aMaxSize) + OuterTableReflowState(nsIPresContext* aPresContext, + const nsReflowState& aReflowState) + : reflowState(aReflowState) { pc = aPresContext; - availSize.width = aMaxSize.width; - availSize.height = aMaxSize.height; + availSize.width = reflowState.maxSize.width; + availSize.height = reflowState.maxSize.height; prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; y=0; // border/padding/margin??? - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(aReflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(aReflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); firstRowGroup = PR_TRUE; processingCaption = PR_FALSE; } @@ -206,13 +210,13 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, return NS_OK; } - OuterTableReflowState state(aPresContext, aReflowState.maxSize); + OuterTableReflowState state(aPresContext, aReflowState); // lay out captions pass 1, if necessary if (PR_FALSE==IsFirstPassValid()) { mFirstPassValid = PR_TRUE; - aStatus = ResizeReflowCaptionsPass1(aPresContext); + aStatus = ResizeReflowCaptionsPass1(aPresContext, state); } @@ -222,7 +226,9 @@ NS_METHOD nsTableOuterFrame::Reflow(nsIPresContext* aPresContext, // we treat the table as if we've never seen the layout data before mInnerTableFrame->SetReflowPass(nsTableFrame::kPASS_FIRST); - aStatus = mInnerTableFrame->ResizeReflowPass1(aPresContext, aDesiredSize, aReflowState.maxSize, + nsReflowState innerTableReflowState(mInnerTableFrame, aReflowState, aReflowState.maxSize); + aStatus = mInnerTableFrame->ResizeReflowPass1(aPresContext, aDesiredSize, + innerTableReflowState, &innerTableMaxElementSize); mInnerTableFrame->RecalcLayoutData(); @@ -897,20 +903,21 @@ nsTableOuterFrame::ReflowChild( nsIFrame* aKidFrame, if (PR_TRUE==gsDebug) printf("reflowChild called with a bottom caption\n"); status = ResizeReflowBottomCaptionsPass2(aPresContext, aDesiredSize, aMaxSize, aMaxElementSize, - aState.y); + aState.y, aState); } else { if (PR_TRUE==gsDebug) printf("reflowChild called with a top caption\n"); status = ResizeReflowTopCaptionsPass2(aPresContext, aDesiredSize, - aMaxSize, aMaxElementSize); + aMaxSize, aMaxElementSize, aState); } } else { if (PR_TRUE==gsDebug) printf("reflowChild called with a table body\n"); - status = ((nsTableFrame*)aKidFrame)->ResizeReflowPass2(aPresContext, aDesiredSize, aState.innerTableMaxSize, - aMaxElementSize, + nsReflowState kidReflowState(aKidFrame, aState.reflowState, aState.innerTableMaxSize); + status = ((nsTableFrame*)aKidFrame)->ResizeReflowPass2(aPresContext, aDesiredSize, + kidReflowState, aMaxElementSize, mMinCaptionWidth, mMaxCaptionWidth); } if (PR_TRUE==gsDebug) @@ -1015,7 +1022,8 @@ void nsTableOuterFrame::CreateChildFrames(nsIPresContext* aPresContext) nsReflowStatus -nsTableOuterFrame::ResizeReflowCaptionsPass1(nsIPresContext* aPresContext) +nsTableOuterFrame::ResizeReflowCaptionsPass1(nsIPresContext* aPresContext, + OuterTableReflowState& aState) { if (nsnull!=mCaptionFrames) { @@ -1027,7 +1035,7 @@ nsTableOuterFrame::ResizeReflowCaptionsPass1(nsIPresContext* aPresContext) nsReflowMetrics desiredSize(&maxElementSize); nsTableCaptionFrame *captionFrame = (nsTableCaptionFrame *)mCaptionFrames->ElementAt(captionIndex); nsReflowStatus status; - nsReflowState reflowState(eReflowReason_Resize, maxSize); + nsReflowState reflowState(captionFrame, aState.reflowState, maxSize, eReflowReason_Resize); captionFrame->WillReflow(*aPresContext); captionFrame->Reflow(aPresContext, desiredSize, reflowState, status); if (mMinCaptionWidthWillReflow(*aPresContext); result = nsContainerFrame::ReflowChild(captionFrame, aPresContext, desiredSize, reflowState); // place the caption @@ -1114,7 +1123,8 @@ nsTableOuterFrame::ResizeReflowBottomCaptionsPass2(nsIPresContext* aPresContext nsReflowMetrics& aDesiredSize, const nsSize& aMaxSize, nsSize* aMaxElementSize, - nscoord aYOffset) + nscoord aYOffset, + OuterTableReflowState& aState) { nsReflowStatus result = NS_FRAME_COMPLETE; nscoord bottomCaptionY = aYOffset; @@ -1137,7 +1147,7 @@ nsTableOuterFrame::ResizeReflowBottomCaptionsPass2(nsIPresContext* aPresContext */ // reflow the caption nsReflowMetrics desiredSize(nsnull); - nsReflowState reflowState(eReflowReason_Resize, aMaxSize); + nsReflowState reflowState(captionFrame, aState.reflowState, aMaxSize, eReflowReason_Resize); captionFrame->WillReflow(*aPresContext); result = nsContainerFrame::ReflowChild(captionFrame, aPresContext, desiredSize, reflowState); diff --git a/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index 1084e1568eaa..daef7706a8e3 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/layout/tables/nsTableOuterFrame.h @@ -125,7 +125,8 @@ protected: /** reflow the captions in an infinite space, caching the min/max sizes for each */ - virtual nsReflowStatus ResizeReflowCaptionsPass1(nsIPresContext* aPresContext); + virtual nsReflowStatus ResizeReflowCaptionsPass1(nsIPresContext* aPresContext, + OuterTableReflowState& aState); /** reflow the top captions in a space constrained by the computed table width * and the heigth given to us by our parent. Top captions are laid down @@ -134,7 +135,8 @@ protected: virtual nsReflowStatus ResizeReflowTopCaptionsPass2(nsIPresContext* aPresContext, nsReflowMetrics& aDesiredSize, const nsSize& aMaxSize, - nsSize* aMaxElementSize); + nsSize* aMaxElementSize, + OuterTableReflowState& aState); /** reflow the bottom captions in a space constrained by the computed table width * and the heigth given to us by our parent. Bottom captions are laid down @@ -144,7 +146,8 @@ protected: nsReflowMetrics& aDesiredSize, const nsSize& aMaxSize, nsSize* aMaxElementSize, - nscoord aYOffset); + nscoord aYOffset, + OuterTableReflowState& aState); nscoord GetTopMarginFor(nsIPresContext* aCX, OuterTableReflowState& aState, diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 9257f2639930..d3214f838881 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -41,6 +41,9 @@ static const PRBool gsDebug2 = PR_FALSE; /* ----------- RowReflowState ---------- */ struct RowReflowState { + // Our reflow state + const nsReflowState& reflowState; + // The body's available size (computed from the body's parent) nsSize availSize; @@ -64,16 +67,17 @@ struct RowReflowState { nsTableFrame *tableFrame; - RowReflowState( nsIPresContext* aPresContext, - const nsSize& aMaxSize) + RowReflowState( nsIPresContext* aPresContext, + const nsReflowState& aReflowState) + : reflowState(aReflowState) { - availSize.width = aMaxSize.width; - availSize.height = aMaxSize.height; + availSize.width = reflowState.maxSize.width; + availSize.height = reflowState.maxSize.height; prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; x=0; - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); maxCellHeight=0; maxCellVertSpace=0; maxCellHorzSpace=0; @@ -343,7 +347,8 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, if (NS_UNCONSTRAINEDSIZE == aState.availSize.width) { // Reflow the child into the available space - nsReflowState kidReflowState(eReflowReason_Resize, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -360,7 +365,8 @@ PRBool nsTableRowFrame::ReflowMappedChildren(nsIPresContext* aPresContext, availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan); kidAvailSize.width = availWidth; - nsReflowState kidReflowState(eReflowReason_Resize, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); } @@ -633,7 +639,8 @@ PRBool nsTableRowFrame::PullUpChildren(nsIPresContext* aPresContext, availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan); NS_ASSERTION(0WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); if (nsnull!=pKidMaxElementSize) @@ -897,7 +904,8 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext, nsReflowStatus status; if (NS_UNCONSTRAINEDSIZE == aState.availSize.width) { - nsReflowState kidReflowState(eReflowReason_Initial, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Initial); // Reflow the child into the available space kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -914,7 +922,7 @@ nsTableRowFrame::ReflowUnmappedChildren( nsIPresContext* aPresContext, availWidth += aState.tableFrame->GetColumnWidth(cellStartingCol+numColSpan); NS_ASSERTION(0WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); } @@ -1029,7 +1037,7 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext, // Check for an overflow list MoveOverflowToChildList(); - RowReflowState state(aPresContext, aReflowState.maxSize); + RowReflowState state(aPresContext, aReflowState); mContentParent->GetContentParent((nsIFrame*&)(state.tableFrame)); // Reflow the existing frames diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 5bfd5dba5126..4849095711e7 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -43,6 +43,9 @@ NS_DEF_PTR(nsIContent); /* ----------- RowGroupReflowState ---------- */ struct RowGroupReflowState { + // Our reflow state + const nsReflowState& reflowState; + // The body's available size (computed from the body's parent) nsSize availSize; @@ -63,16 +66,17 @@ struct RowGroupReflowState { // Remember the height of the first row, because it's our maxElementHeight (plus header/footers) nscoord firstRowHeight; - RowGroupReflowState(nsIPresContext* aPresContext, - const nsSize& aMaxSize) + RowGroupReflowState(nsIPresContext* aPresContext, + const nsReflowState& aReflowState) + : reflowState(aReflowState) { - availSize.width = aMaxSize.width; - availSize.height = aMaxSize.height; + availSize.width = reflowState.maxSize.width; + availSize.height = reflowState.maxSize.height; prevMaxPosBottomMargin = 0; prevMaxNegBottomMargin = 0; y=0; // border/padding/margin??? - unconstrainedWidth = PRBool(aMaxSize.width == NS_UNCONSTRAINEDSIZE); - unconstrainedHeight = PRBool(aMaxSize.height == NS_UNCONSTRAINEDSIZE); + unconstrainedWidth = PRBool(reflowState.maxSize.width == NS_UNCONSTRAINEDSIZE); + unconstrainedHeight = PRBool(reflowState.maxSize.height == NS_UNCONSTRAINEDSIZE); firstRow = PR_TRUE; firstRowHeight=0; } @@ -296,7 +300,8 @@ PRBool nsTableRowGroupFrame::ReflowMappedChildren( nsIPresContext* aPresCon } // Reflow the child into the available space - nsReflowState kidReflowState(eReflowReason_Resize, kidAvailSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, kidAvailSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState); @@ -531,7 +536,8 @@ PRBool nsTableRowGroupFrame::PullUpChildren(nsIPresContext* aPresContext, mLastContentIsComplete = prevLastContentIsComplete; break; } - nsReflowState kidReflowState(eReflowReason_Resize, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Resize); kidFrame->WillReflow(*aPresContext); status = ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState); @@ -760,7 +766,8 @@ nsTableRowGroupFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext, // Try to reflow the child into the available space. It might not // fit or might need continuing. nsReflowMetrics kidSize(pKidMaxElementSize); - nsReflowState kidReflowState(eReflowReason_Initial, aState.availSize); + nsReflowState kidReflowState(kidFrame, aState.reflowState, aState.availSize, + eReflowReason_Initial); kidFrame->WillReflow(*aPresContext); nsReflowStatus status = ReflowChild(kidFrame,aPresContext, kidSize, kidReflowState); @@ -847,7 +854,7 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext, // Check for an overflow list MoveOverflowToChildList(); - RowGroupReflowState state(aPresContext, aReflowState.maxSize); + RowGroupReflowState state(aPresContext, aReflowState); // Reflow the existing frames if (nsnull != mFirstChild) {