Added nsHTMLReflowState constructor that allows containing block width

and height to be specified. This is needed for relatively positioned
block elements
This commit is contained in:
troy%netscape.com 1999-09-16 14:33:19 +00:00
parent a308b98b00
commit 410a37f467
11 changed files with 301 additions and 100 deletions

View File

@ -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

View File

@ -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);

View File

@ -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",

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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",

View File

@ -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);
}
}
}

View File

@ -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
* <B>parent</B> 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,

View File

@ -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;