From 4d5ed09a1f8273dfb72883c4889eb89b90867d26 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Thu, 16 Sep 1999 14:33:19 +0000 Subject: [PATCH] Added nsHTMLReflowState constructor that allows containing block width and height to be specified. This is needed for relatively positioned block elements git-svn-id: svn://10.0.0.236/trunk@47787 18797224-902f-48f8-a5cc-f745e15eee43 --- .../generic/nsAbsoluteContainingBlock.cpp | 21 +++-- .../generic/nsAbsoluteContainingBlock.h | 8 +- mozilla/layout/generic/nsAreaFrame.cpp | 58 ++++++++++-- mozilla/layout/generic/nsHTMLReflowState.cpp | 93 ++++++++++++------- mozilla/layout/generic/nsInlineFrame.cpp | 12 ++- .../base/src/nsAbsoluteContainingBlock.cpp | 21 +++-- .../html/base/src/nsAbsoluteContainingBlock.h | 8 +- mozilla/layout/html/base/src/nsAreaFrame.cpp | 58 ++++++++++-- .../html/base/src/nsHTMLReflowState.cpp | 93 ++++++++++++------- mozilla/layout/html/base/src/nsIHTMLReflow.h | 17 +++- .../layout/html/base/src/nsInlineFrame.cpp | 12 ++- 11 files changed, 301 insertions(+), 100 deletions(-) diff --git a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp index bf363490ff2..3c6cec3b5d2 100644 --- a/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/generic/nsAbsoluteContainingBlock.cpp @@ -126,7 +126,9 @@ nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, nsresult nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, - const nsHTMLReflowState& aReflowState) + const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) { // Make a copy of the reflow state. If the reason is eReflowReason_Incremental, // then change it to eReflowReason_Resize @@ -139,8 +141,8 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, for (kidFrame = mAbsoluteFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) { // Reflow the frame nsReflowStatus kidStatus; - ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, kidFrame, - PR_FALSE, kidStatus); + ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth, + aContainingBlockHeight, kidFrame, PR_FALSE, kidStatus); } return NS_OK; } @@ -149,6 +151,8 @@ nsresult nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, PRBool& aWasHandled) { // Initialize the OUT paremeter @@ -189,7 +193,8 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin // just been inserted or appended NS_ASSERTION(frameState & NS_FRAME_FIRST_REFLOW, "unexpected frame state"); ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, - f, PR_TRUE, status); + aContainingBlockWidth, aContainingBlockHeight, f, + PR_TRUE, status); } } @@ -210,7 +215,8 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, - nextFrame, PR_FALSE, kidStatus); + aContainingBlockWidth, aContainingBlockHeight, nextFrame, + PR_FALSE, kidStatus); // We don't need to invalidate anything because the frame should // invalidate any area within its frame that needs repainting, and // because it has a view if it changes size the view manager will @@ -236,6 +242,8 @@ nsresult nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, nsIFrame* aKidFrame, PRBool aInitialReflow, nsReflowStatus& aStatus) @@ -256,7 +264,8 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat nsSize availSize(aReflowState.mComputedWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowMetrics kidDesiredSize(nsnull); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, - availSize); + availSize, aContainingBlockWidth, + aContainingBlockHeight); // If it's the initial reflow, then override the reflow reason. This is // used when frames are inserted incrementally diff --git a/mozilla/layout/generic/nsAbsoluteContainingBlock.h b/mozilla/layout/generic/nsAbsoluteContainingBlock.h index 5839d46022a..83fe0155dd4 100644 --- a/mozilla/layout/generic/nsAbsoluteContainingBlock.h +++ b/mozilla/layout/generic/nsAbsoluteContainingBlock.h @@ -71,7 +71,9 @@ public: // 'auto' for an offset, or a percentage based width or height nsresult Reflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, - const nsHTMLReflowState& aReflowState); + const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight); // Called only for a reflow reason of eReflowReason_Incremental. The // aWasHandled return value indicates whether the reflow command was @@ -80,6 +82,8 @@ public: nsresult IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, PRBool& aWasHandled); void DestroyFrames(nsIFrame* aDelegatingFrame, @@ -93,6 +97,8 @@ protected: nsresult ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, nsIFrame* aKidFrame, PRBool aInitialReflow, nsReflowStatus& aStatus); diff --git a/mozilla/layout/generic/nsAreaFrame.cpp b/mozilla/layout/generic/nsAreaFrame.cpp index c3a8e63980b..bc8c8e04914 100644 --- a/mozilla/layout/generic/nsAreaFrame.cpp +++ b/mozilla/layout/generic/nsAreaFrame.cpp @@ -305,6 +305,34 @@ nsAreaFrame::GetSpaceManager(nsISpaceManager** aSpaceManagerResult) return NS_OK; } +static void +CalculateContainingBlock(const nsHTMLReflowState& aReflowState, + nscoord aFrameWidth, + nscoord aFrameHeight, + nscoord& aContainingBlockWidth, + nscoord& aContainingBlockHeight) +{ + aContainingBlockWidth = -1; // have reflow state calculate + aContainingBlockHeight = -1; // have reflow state calculate + + // We should probably do this for all frames, but for the time being just + // do this for relatively positioned block frames. The issue there is that + // for a 'height' of 'auto' the reflow state code won't know how to calculate + // the containing block height + if (NS_STYLE_POSITION_RELATIVE == aReflowState.mStylePosition->mPosition) { + aContainingBlockWidth = aFrameWidth; + aContainingBlockHeight = aFrameHeight; + + // Containing block is relative to the padding edge + nsMargin border; + if (!aReflowState.mStyleSpacing->GetBorder(border)) { + NS_NOTYETIMPLEMENTED("percentage border"); + } + aContainingBlockWidth -= border.left + border.right; + aContainingBlockHeight -= border.top + border.bottom; + } +} + NS_IMETHODIMP nsAreaFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -322,9 +350,16 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, // See if it's an incremental reflow command if (eReflowReason_Incremental == aReflowState.reason) { // Give the absolute positioning code a chance to handle it + nscoord containingBlockWidth; + nscoord containingBlockHeight; PRBool handled; + + CalculateContainingBlock(aReflowState, mRect.width, mRect.height, + containingBlockWidth, containingBlockHeight); - mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, handled); + mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight, + handled); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done @@ -374,13 +409,6 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, } #endif - // Let the absolutely positioned container reflow any absolutely positioned - // child frames that need to be reflowed, e.g., elements with a percentage - // based width/height - if (NS_SUCCEEDED(rv)) { - rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState); - } - if (mFlags & NS_AREA_WRAP_SIZE) { // When the area frame is supposed to wrap around all in-flow // children, make sure its big enough to include those that stick @@ -397,6 +425,20 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, } } + // Let the absolutely positioned container reflow any absolutely positioned + // child frames that need to be reflowed, e.g., elements with a percentage + // based width/height + if (NS_SUCCEEDED(rv)) { + nscoord containingBlockWidth; + nscoord containingBlockHeight; + + CalculateContainingBlock(aReflowState, aDesiredSize.width, aDesiredSize.height, + containingBlockWidth, containingBlockHeight); + + rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight); + } + #ifdef NOISY_MAX_ELEMENT_SIZE ListTag(stdout); printf(": maxElementSize=%d,%d desiredSize=%d,%d\n", diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp index 44ff8e2ce24..a95aa4077ad 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.cpp +++ b/mozilla/layout/generic/nsHTMLReflowState.cpp @@ -133,8 +133,34 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext& aPresContext, Init(aPresContext); } +// Version that species the containing block width and height +nsHTMLReflowState::nsHTMLReflowState(nsIPresContext& aPresContext, + const nsHTMLReflowState& aParentReflowState, + nsIFrame* aFrame, + const nsSize& aAvailableSpace, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) + : mReflowDepth(aParentReflowState.mReflowDepth + 1) +{ + parentReflowState = &aParentReflowState; + frame = aFrame; + reason = aParentReflowState.reason; + reflowCommand = aParentReflowState.reflowCommand; + availableWidth = aAvailableSpace.width; + availableHeight = aAvailableSpace.height; + + rendContext = aParentReflowState.rendContext; + mSpaceManager = aParentReflowState.mSpaceManager; + mLineLayout = aParentReflowState.mLineLayout; + isTopOfPage = aParentReflowState.isTopOfPage; + + Init(aPresContext, aContainingBlockWidth, aContainingBlockHeight); +} + void -nsHTMLReflowState::Init(nsIPresContext& aPresContext) +nsHTMLReflowState::Init(nsIPresContext& aPresContext, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) { mCompactMarginWidth = 0; mAlignCharOffset = 0; @@ -147,7 +173,7 @@ nsHTMLReflowState::Init(nsIPresContext& aPresContext) frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)mStyleSpacing); mFrameType = DetermineFrameType(frame, mStylePosition, mStyleDisplay); - InitConstraints(aPresContext); + InitConstraints(aPresContext, aContainingBlockWidth, aContainingBlockHeight); } const nsHTMLReflowState* @@ -801,7 +827,9 @@ nsHTMLReflowState::ComputeContainingBlockRectangle(const nsHTMLReflowState* aCon // we are computing: width,height,line-height; margin; offsets void -nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) +nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) { // If this is the root frame, then set the computed width and // height equal to the available space @@ -820,14 +848,15 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) GetContainingBlockReflowState(parentReflowState); NS_ASSERTION(nsnull != cbrs, "no containing block"); - // Compute the containing block rectangle for the element - nscoord containingBlockWidth; - nscoord containingBlockHeight; - ComputeContainingBlockRectangle(cbrs, containingBlockWidth, containingBlockHeight); + // If we weren't given a containing block width and height, then + // compute one + if (aContainingBlockWidth == -1) { + ComputeContainingBlockRectangle(cbrs, aContainingBlockWidth, aContainingBlockHeight); + } // See if the element is relatively positioned if (NS_STYLE_POSITION_RELATIVE == mStylePosition->mPosition) { - ComputeRelativeOffsets(cbrs, containingBlockWidth, containingBlockHeight); + ComputeRelativeOffsets(cbrs, aContainingBlockWidth, aContainingBlockHeight); } else { // Initialize offsets to 0 mComputedOffsets.SizeTo(0, 0, 0, 0); @@ -835,12 +864,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) #if 0 nsFrame::ListTag(stdout, frame); printf(": cb="); - nsFrame::ListTag(stdout, cbrs->frame); printf(" size=%d,%d\n", containingBlockWidth, containingBlockHeight); + nsFrame::ListTag(stdout, cbrs->frame); printf(" size=%d,%d\n", aContainingBlockWidth, aContainingBlockHeight); #endif // See if the containing block height is based on the size of its // content - if (NS_AUTOHEIGHT == containingBlockHeight) { + if (NS_AUTOHEIGHT == aContainingBlockHeight) { // See if the containing block is a scrolled frame, i.e. its // parent is a scroll frame. The presence of the intervening // frame (that the scroll frame scrolls) needs to be hidden from @@ -852,7 +881,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) f->GetFrameType(&cbFrameType); if (nsLayoutAtoms::scrollFrame == cbFrameType) { // Use the scroll frame's computed height instead - containingBlockHeight = + aContainingBlockHeight = ((nsHTMLReflowState*)cbrs->parentReflowState)->mComputedHeight; } NS_IF_RELEASE(cbFrameType); @@ -863,8 +892,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // become the default computed values, and may be adjusted below // XXX fix to provide 0,0 for the top&bottom margins for // inline-non-replaced elements - ComputeMargin(containingBlockWidth, cbrs); - ComputePadding(containingBlockWidth, cbrs); + ComputeMargin(aContainingBlockWidth, cbrs); + ComputePadding(aContainingBlockWidth, cbrs); if (!mStyleSpacing->GetBorder(mComputedBorderPadding)) { // CSS2 has no percentage borders mComputedBorderPadding.SizeTo(0, 0, 0, 0); @@ -877,7 +906,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Check for a percentage based width and an unconstrained containing // block width if (eStyleUnit_Percent == widthUnit) { - if (NS_UNCONSTRAINEDSIZE == containingBlockWidth) { + if (NS_UNCONSTRAINEDSIZE == aContainingBlockWidth) { // Interpret the width like 'auto' widthUnit = eStyleUnit_Auto; } @@ -885,14 +914,14 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Check for a percentage based height and a containing block height // that depends on the content height if (eStyleUnit_Percent == heightUnit) { - if (NS_AUTOHEIGHT == containingBlockHeight) { + if (NS_AUTOHEIGHT == aContainingBlockHeight) { // Interpret the height like 'auto' heightUnit = eStyleUnit_Auto; } } // Calculate the computed values for min and max properties - ComputeMinMaxValues(containingBlockWidth, containingBlockHeight, cbrs); + ComputeMinMaxValues(aContainingBlockWidth, aContainingBlockHeight, cbrs); // Calculate the computed width and height. This varies by frame type if ((NS_FRAME_REPLACED(NS_CSS_FRAME_TYPE_INLINE) == mFrameType) || @@ -900,12 +929,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Inline replaced element and floating replaced element are basically // treated the same. First calculate the computed width if (eStyleUnit_Inherit == widthUnit) { - mComputedWidth = containingBlockWidth; + mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { // A specified value of 'auto' uses the element's intrinsic width mComputedWidth = NS_INTRINSICSIZE; } else { - ComputeHorizontalValue(containingBlockWidth, widthUnit, + ComputeHorizontalValue(aContainingBlockWidth, widthUnit, mStylePosition->mWidth, mComputedWidth); } @@ -929,12 +958,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Now calculate the computed height if (eStyleUnit_Inherit == heightUnit) { - mComputedHeight = containingBlockHeight; + mComputedHeight = aContainingBlockHeight; } else if (eStyleUnit_Auto == heightUnit) { // A specified value of 'auto' uses the element's intrinsic height mComputedHeight = NS_INTRINSICSIZE; } else { - ComputeVerticalValue(containingBlockHeight, heightUnit, + ComputeVerticalValue(aContainingBlockHeight, heightUnit, mStylePosition->mHeight, mComputedHeight); } @@ -959,12 +988,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) } else if (NS_CSS_FRAME_TYPE_FLOATING == mFrameType) { // Floating non-replaced element. First calculate the computed width if (eStyleUnit_Inherit == widthUnit) { - mComputedWidth = containingBlockWidth; + mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { // A specified value of 'auto' becomes a computed width of 0 mComputedWidth = 0; } else { - ComputeHorizontalValue(containingBlockWidth, widthUnit, + ComputeHorizontalValue(aContainingBlockWidth, widthUnit, mStylePosition->mWidth, mComputedWidth); } @@ -988,11 +1017,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Now calculate the computed height if (eStyleUnit_Inherit == heightUnit) { - mComputedHeight = containingBlockHeight; + mComputedHeight = aContainingBlockHeight; } else if (eStyleUnit_Auto == heightUnit) { mComputedHeight = NS_AUTOHEIGHT; // let it choose its height } else { - ComputeVerticalValue(containingBlockHeight, heightUnit, + ComputeVerticalValue(aContainingBlockHeight, heightUnit, mStylePosition->mHeight, mComputedHeight); } @@ -1024,7 +1053,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) } if (eStyleUnit_Inherit == widthUnit) { - mComputedWidth = containingBlockWidth; + mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { mComputedWidth = availableWidth; @@ -1036,7 +1065,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) } } else { - ComputeHorizontalValue(containingBlockWidth, widthUnit, + ComputeHorizontalValue(aContainingBlockWidth, widthUnit, mStylePosition->mWidth, mComputedWidth); } @@ -1048,11 +1077,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) heightUnit = eStyleUnit_Auto; } if (eStyleUnit_Inherit == heightUnit) { - mComputedHeight = containingBlockHeight; + mComputedHeight = aContainingBlockHeight; } else if (eStyleUnit_Auto == heightUnit) { mComputedHeight = NS_AUTOHEIGHT; } else { - ComputeVerticalValue(containingBlockHeight, heightUnit, + ComputeVerticalValue(aContainingBlockHeight, heightUnit, mStylePosition->mHeight, mComputedHeight); } @@ -1067,8 +1096,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) nsIAtom* targetFrameType; frame->GetFrameType(&targetFrameType); if (nsLayoutAtoms::htmlFrameInnerFrame != targetFrameType) { - InitAbsoluteConstraints(aPresContext, cbrs, containingBlockWidth, - containingBlockHeight); + InitAbsoluteConstraints(aPresContext, cbrs, aContainingBlockWidth, + aContainingBlockHeight); } NS_IF_RELEASE(targetFrameType); } else if (NS_CSS_FRAME_TYPE_INLINE == mFrameType) { @@ -1082,8 +1111,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) mComputedMaxWidth = mComputedMaxHeight = NS_UNCONSTRAINEDSIZE; } else { ComputeBlockBoxData(aPresContext, cbrs, widthUnit, heightUnit, - containingBlockWidth, - containingBlockHeight); + aContainingBlockWidth, + aContainingBlockHeight); } } } diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index f4588002717..c5e8f525e46 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -188,8 +188,12 @@ nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext, if (eReflowReason_Incremental == aReflowState.reason) { // Give the absolute positioning code a chance to handle it PRBool handled; + nscoord containingBlockWidth = -1; + nscoord containingBlockHeight = -1; - mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, handled); + mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight, + handled); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done @@ -210,7 +214,11 @@ nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext, // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed if (NS_SUCCEEDED(rv)) { - rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState); + nscoord containingBlockWidth = -1; + nscoord containingBlockHeight = -1; + + rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight); } return rv; diff --git a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp index bf363490ff2..3c6cec3b5d2 100644 --- a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -126,7 +126,9 @@ nsAbsoluteContainingBlock::RemoveFrame(nsIFrame* aDelegatingFrame, nsresult nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, - const nsHTMLReflowState& aReflowState) + const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) { // Make a copy of the reflow state. If the reason is eReflowReason_Incremental, // then change it to eReflowReason_Resize @@ -139,8 +141,8 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, for (kidFrame = mAbsoluteFrames.FirstChild(); nsnull != kidFrame; kidFrame->GetNextSibling(&kidFrame)) { // Reflow the frame nsReflowStatus kidStatus; - ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, kidFrame, - PR_FALSE, kidStatus); + ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth, + aContainingBlockHeight, kidFrame, PR_FALSE, kidStatus); } return NS_OK; } @@ -149,6 +151,8 @@ nsresult nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, PRBool& aWasHandled) { // Initialize the OUT paremeter @@ -189,7 +193,8 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin // just been inserted or appended NS_ASSERTION(frameState & NS_FRAME_FIRST_REFLOW, "unexpected frame state"); ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, - f, PR_TRUE, status); + aContainingBlockWidth, aContainingBlockHeight, f, + PR_TRUE, status); } } @@ -210,7 +215,8 @@ nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatin nsReflowStatus kidStatus; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, - nextFrame, PR_FALSE, kidStatus); + aContainingBlockWidth, aContainingBlockHeight, nextFrame, + PR_FALSE, kidStatus); // We don't need to invalidate anything because the frame should // invalidate any area within its frame that needs repainting, and // because it has a view if it changes size the view manager will @@ -236,6 +242,8 @@ nsresult nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, nsIFrame* aKidFrame, PRBool aInitialReflow, nsReflowStatus& aStatus) @@ -256,7 +264,8 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat nsSize availSize(aReflowState.mComputedWidth, NS_UNCONSTRAINEDSIZE); nsHTMLReflowMetrics kidDesiredSize(nsnull); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, - availSize); + availSize, aContainingBlockWidth, + aContainingBlockHeight); // If it's the initial reflow, then override the reflow reason. This is // used when frames are inserted incrementally diff --git a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h index 5839d46022a..83fe0155dd4 100644 --- a/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h +++ b/mozilla/layout/html/base/src/nsAbsoluteContainingBlock.h @@ -71,7 +71,9 @@ public: // 'auto' for an offset, or a percentage based width or height nsresult Reflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, - const nsHTMLReflowState& aReflowState); + const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight); // Called only for a reflow reason of eReflowReason_Incremental. The // aWasHandled return value indicates whether the reflow command was @@ -80,6 +82,8 @@ public: nsresult IncrementalReflow(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, PRBool& aWasHandled); void DestroyFrames(nsIFrame* aDelegatingFrame, @@ -93,6 +97,8 @@ protected: nsresult ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight, nsIFrame* aKidFrame, PRBool aInitialReflow, nsReflowStatus& aStatus); diff --git a/mozilla/layout/html/base/src/nsAreaFrame.cpp b/mozilla/layout/html/base/src/nsAreaFrame.cpp index c3a8e63980b..bc8c8e04914 100644 --- a/mozilla/layout/html/base/src/nsAreaFrame.cpp +++ b/mozilla/layout/html/base/src/nsAreaFrame.cpp @@ -305,6 +305,34 @@ nsAreaFrame::GetSpaceManager(nsISpaceManager** aSpaceManagerResult) return NS_OK; } +static void +CalculateContainingBlock(const nsHTMLReflowState& aReflowState, + nscoord aFrameWidth, + nscoord aFrameHeight, + nscoord& aContainingBlockWidth, + nscoord& aContainingBlockHeight) +{ + aContainingBlockWidth = -1; // have reflow state calculate + aContainingBlockHeight = -1; // have reflow state calculate + + // We should probably do this for all frames, but for the time being just + // do this for relatively positioned block frames. The issue there is that + // for a 'height' of 'auto' the reflow state code won't know how to calculate + // the containing block height + if (NS_STYLE_POSITION_RELATIVE == aReflowState.mStylePosition->mPosition) { + aContainingBlockWidth = aFrameWidth; + aContainingBlockHeight = aFrameHeight; + + // Containing block is relative to the padding edge + nsMargin border; + if (!aReflowState.mStyleSpacing->GetBorder(border)) { + NS_NOTYETIMPLEMENTED("percentage border"); + } + aContainingBlockWidth -= border.left + border.right; + aContainingBlockHeight -= border.top + border.bottom; + } +} + NS_IMETHODIMP nsAreaFrame::Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -322,9 +350,16 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, // See if it's an incremental reflow command if (eReflowReason_Incremental == aReflowState.reason) { // Give the absolute positioning code a chance to handle it + nscoord containingBlockWidth; + nscoord containingBlockHeight; PRBool handled; + + CalculateContainingBlock(aReflowState, mRect.width, mRect.height, + containingBlockWidth, containingBlockHeight); - mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, handled); + mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight, + handled); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done @@ -374,13 +409,6 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, } #endif - // Let the absolutely positioned container reflow any absolutely positioned - // child frames that need to be reflowed, e.g., elements with a percentage - // based width/height - if (NS_SUCCEEDED(rv)) { - rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState); - } - if (mFlags & NS_AREA_WRAP_SIZE) { // When the area frame is supposed to wrap around all in-flow // children, make sure its big enough to include those that stick @@ -397,6 +425,20 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, } } + // Let the absolutely positioned container reflow any absolutely positioned + // child frames that need to be reflowed, e.g., elements with a percentage + // based width/height + if (NS_SUCCEEDED(rv)) { + nscoord containingBlockWidth; + nscoord containingBlockHeight; + + CalculateContainingBlock(aReflowState, aDesiredSize.width, aDesiredSize.height, + containingBlockWidth, containingBlockHeight); + + rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight); + } + #ifdef NOISY_MAX_ELEMENT_SIZE ListTag(stdout); printf(": maxElementSize=%d,%d desiredSize=%d,%d\n", diff --git a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp index 44ff8e2ce24..a95aa4077ad 100644 --- a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp +++ b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp @@ -133,8 +133,34 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext& aPresContext, Init(aPresContext); } +// Version that species the containing block width and height +nsHTMLReflowState::nsHTMLReflowState(nsIPresContext& aPresContext, + const nsHTMLReflowState& aParentReflowState, + nsIFrame* aFrame, + const nsSize& aAvailableSpace, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) + : mReflowDepth(aParentReflowState.mReflowDepth + 1) +{ + parentReflowState = &aParentReflowState; + frame = aFrame; + reason = aParentReflowState.reason; + reflowCommand = aParentReflowState.reflowCommand; + availableWidth = aAvailableSpace.width; + availableHeight = aAvailableSpace.height; + + rendContext = aParentReflowState.rendContext; + mSpaceManager = aParentReflowState.mSpaceManager; + mLineLayout = aParentReflowState.mLineLayout; + isTopOfPage = aParentReflowState.isTopOfPage; + + Init(aPresContext, aContainingBlockWidth, aContainingBlockHeight); +} + void -nsHTMLReflowState::Init(nsIPresContext& aPresContext) +nsHTMLReflowState::Init(nsIPresContext& aPresContext, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) { mCompactMarginWidth = 0; mAlignCharOffset = 0; @@ -147,7 +173,7 @@ nsHTMLReflowState::Init(nsIPresContext& aPresContext) frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)mStyleSpacing); mFrameType = DetermineFrameType(frame, mStylePosition, mStyleDisplay); - InitConstraints(aPresContext); + InitConstraints(aPresContext, aContainingBlockWidth, aContainingBlockHeight); } const nsHTMLReflowState* @@ -801,7 +827,9 @@ nsHTMLReflowState::ComputeContainingBlockRectangle(const nsHTMLReflowState* aCon // we are computing: width,height,line-height; margin; offsets void -nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) +nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight) { // If this is the root frame, then set the computed width and // height equal to the available space @@ -820,14 +848,15 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) GetContainingBlockReflowState(parentReflowState); NS_ASSERTION(nsnull != cbrs, "no containing block"); - // Compute the containing block rectangle for the element - nscoord containingBlockWidth; - nscoord containingBlockHeight; - ComputeContainingBlockRectangle(cbrs, containingBlockWidth, containingBlockHeight); + // If we weren't given a containing block width and height, then + // compute one + if (aContainingBlockWidth == -1) { + ComputeContainingBlockRectangle(cbrs, aContainingBlockWidth, aContainingBlockHeight); + } // See if the element is relatively positioned if (NS_STYLE_POSITION_RELATIVE == mStylePosition->mPosition) { - ComputeRelativeOffsets(cbrs, containingBlockWidth, containingBlockHeight); + ComputeRelativeOffsets(cbrs, aContainingBlockWidth, aContainingBlockHeight); } else { // Initialize offsets to 0 mComputedOffsets.SizeTo(0, 0, 0, 0); @@ -835,12 +864,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) #if 0 nsFrame::ListTag(stdout, frame); printf(": cb="); - nsFrame::ListTag(stdout, cbrs->frame); printf(" size=%d,%d\n", containingBlockWidth, containingBlockHeight); + nsFrame::ListTag(stdout, cbrs->frame); printf(" size=%d,%d\n", aContainingBlockWidth, aContainingBlockHeight); #endif // See if the containing block height is based on the size of its // content - if (NS_AUTOHEIGHT == containingBlockHeight) { + if (NS_AUTOHEIGHT == aContainingBlockHeight) { // See if the containing block is a scrolled frame, i.e. its // parent is a scroll frame. The presence of the intervening // frame (that the scroll frame scrolls) needs to be hidden from @@ -852,7 +881,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) f->GetFrameType(&cbFrameType); if (nsLayoutAtoms::scrollFrame == cbFrameType) { // Use the scroll frame's computed height instead - containingBlockHeight = + aContainingBlockHeight = ((nsHTMLReflowState*)cbrs->parentReflowState)->mComputedHeight; } NS_IF_RELEASE(cbFrameType); @@ -863,8 +892,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // become the default computed values, and may be adjusted below // XXX fix to provide 0,0 for the top&bottom margins for // inline-non-replaced elements - ComputeMargin(containingBlockWidth, cbrs); - ComputePadding(containingBlockWidth, cbrs); + ComputeMargin(aContainingBlockWidth, cbrs); + ComputePadding(aContainingBlockWidth, cbrs); if (!mStyleSpacing->GetBorder(mComputedBorderPadding)) { // CSS2 has no percentage borders mComputedBorderPadding.SizeTo(0, 0, 0, 0); @@ -877,7 +906,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Check for a percentage based width and an unconstrained containing // block width if (eStyleUnit_Percent == widthUnit) { - if (NS_UNCONSTRAINEDSIZE == containingBlockWidth) { + if (NS_UNCONSTRAINEDSIZE == aContainingBlockWidth) { // Interpret the width like 'auto' widthUnit = eStyleUnit_Auto; } @@ -885,14 +914,14 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Check for a percentage based height and a containing block height // that depends on the content height if (eStyleUnit_Percent == heightUnit) { - if (NS_AUTOHEIGHT == containingBlockHeight) { + if (NS_AUTOHEIGHT == aContainingBlockHeight) { // Interpret the height like 'auto' heightUnit = eStyleUnit_Auto; } } // Calculate the computed values for min and max properties - ComputeMinMaxValues(containingBlockWidth, containingBlockHeight, cbrs); + ComputeMinMaxValues(aContainingBlockWidth, aContainingBlockHeight, cbrs); // Calculate the computed width and height. This varies by frame type if ((NS_FRAME_REPLACED(NS_CSS_FRAME_TYPE_INLINE) == mFrameType) || @@ -900,12 +929,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Inline replaced element and floating replaced element are basically // treated the same. First calculate the computed width if (eStyleUnit_Inherit == widthUnit) { - mComputedWidth = containingBlockWidth; + mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { // A specified value of 'auto' uses the element's intrinsic width mComputedWidth = NS_INTRINSICSIZE; } else { - ComputeHorizontalValue(containingBlockWidth, widthUnit, + ComputeHorizontalValue(aContainingBlockWidth, widthUnit, mStylePosition->mWidth, mComputedWidth); } @@ -929,12 +958,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Now calculate the computed height if (eStyleUnit_Inherit == heightUnit) { - mComputedHeight = containingBlockHeight; + mComputedHeight = aContainingBlockHeight; } else if (eStyleUnit_Auto == heightUnit) { // A specified value of 'auto' uses the element's intrinsic height mComputedHeight = NS_INTRINSICSIZE; } else { - ComputeVerticalValue(containingBlockHeight, heightUnit, + ComputeVerticalValue(aContainingBlockHeight, heightUnit, mStylePosition->mHeight, mComputedHeight); } @@ -959,12 +988,12 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) } else if (NS_CSS_FRAME_TYPE_FLOATING == mFrameType) { // Floating non-replaced element. First calculate the computed width if (eStyleUnit_Inherit == widthUnit) { - mComputedWidth = containingBlockWidth; + mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { // A specified value of 'auto' becomes a computed width of 0 mComputedWidth = 0; } else { - ComputeHorizontalValue(containingBlockWidth, widthUnit, + ComputeHorizontalValue(aContainingBlockWidth, widthUnit, mStylePosition->mWidth, mComputedWidth); } @@ -988,11 +1017,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) // Now calculate the computed height if (eStyleUnit_Inherit == heightUnit) { - mComputedHeight = containingBlockHeight; + mComputedHeight = aContainingBlockHeight; } else if (eStyleUnit_Auto == heightUnit) { mComputedHeight = NS_AUTOHEIGHT; // let it choose its height } else { - ComputeVerticalValue(containingBlockHeight, heightUnit, + ComputeVerticalValue(aContainingBlockHeight, heightUnit, mStylePosition->mHeight, mComputedHeight); } @@ -1024,7 +1053,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) } if (eStyleUnit_Inherit == widthUnit) { - mComputedWidth = containingBlockWidth; + mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { mComputedWidth = availableWidth; @@ -1036,7 +1065,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) } } else { - ComputeHorizontalValue(containingBlockWidth, widthUnit, + ComputeHorizontalValue(aContainingBlockWidth, widthUnit, mStylePosition->mWidth, mComputedWidth); } @@ -1048,11 +1077,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) heightUnit = eStyleUnit_Auto; } if (eStyleUnit_Inherit == heightUnit) { - mComputedHeight = containingBlockHeight; + mComputedHeight = aContainingBlockHeight; } else if (eStyleUnit_Auto == heightUnit) { mComputedHeight = NS_AUTOHEIGHT; } else { - ComputeVerticalValue(containingBlockHeight, heightUnit, + ComputeVerticalValue(aContainingBlockHeight, heightUnit, mStylePosition->mHeight, mComputedHeight); } @@ -1067,8 +1096,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) nsIAtom* targetFrameType; frame->GetFrameType(&targetFrameType); if (nsLayoutAtoms::htmlFrameInnerFrame != targetFrameType) { - InitAbsoluteConstraints(aPresContext, cbrs, containingBlockWidth, - containingBlockHeight); + InitAbsoluteConstraints(aPresContext, cbrs, aContainingBlockWidth, + aContainingBlockHeight); } NS_IF_RELEASE(targetFrameType); } else if (NS_CSS_FRAME_TYPE_INLINE == mFrameType) { @@ -1082,8 +1111,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext) mComputedMaxWidth = mComputedMaxHeight = NS_UNCONSTRAINEDSIZE; } else { ComputeBlockBoxData(aPresContext, cbrs, widthUnit, heightUnit, - containingBlockWidth, - containingBlockHeight); + aContainingBlockWidth, + aContainingBlockHeight); } } } diff --git a/mozilla/layout/html/base/src/nsIHTMLReflow.h b/mozilla/layout/html/base/src/nsIHTMLReflow.h index 40a2628713a..a05dfbd5900 100644 --- a/mozilla/layout/html/base/src/nsIHTMLReflow.h +++ b/mozilla/layout/html/base/src/nsIHTMLReflow.h @@ -237,6 +237,15 @@ struct nsHTMLReflowState : nsReflowState { nsIFrame* aFrame, const nsSize& aAvailableSpace); + // Used when you want to override the default containing block + // width and height. Used by absolute positioning code + nsHTMLReflowState(nsIPresContext& aPresContext, + const nsHTMLReflowState& aParentReflowState, + nsIFrame* aFrame, + const nsSize& aAvailableSpace, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight); + /** * Get the containing block reflow state, starting from a frames * parent reflow state (the parent reflow state may or may not end @@ -291,9 +300,13 @@ struct nsHTMLReflowState : nsReflowState { protected: // This method initializes various data members. It is automatically // called by the various constructors - void Init(nsIPresContext& aPresContext); + void Init(nsIPresContext& aPresContext, + nscoord aContainingBlockWidth = -1, + nscoord aContainingBlockHeight = -1); - void InitConstraints(nsIPresContext& aPresContext); + void InitConstraints(nsIPresContext& aPresContext, + nscoord aContainingBlockWidth, + nscoord aContainingBlockHeight); void InitAbsoluteConstraints(nsIPresContext& aPresContext, const nsHTMLReflowState* cbrs, diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp index f4588002717..c5e8f525e46 100644 --- a/mozilla/layout/html/base/src/nsInlineFrame.cpp +++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp @@ -188,8 +188,12 @@ nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext, if (eReflowReason_Incremental == aReflowState.reason) { // Give the absolute positioning code a chance to handle it PRBool handled; + nscoord containingBlockWidth = -1; + nscoord containingBlockHeight = -1; - mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, handled); + mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight, + handled); // If the incremental reflow command was handled by the absolute positioning // code, then we're all done @@ -210,7 +214,11 @@ nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext, // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed if (NS_SUCCEEDED(rv)) { - rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState); + nscoord containingBlockWidth = -1; + nscoord containingBlockHeight = -1; + + rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, + containingBlockWidth, containingBlockHeight); } return rv;