Make the width of floats with |width: auto| depend only on the width of the containing block and the contents of the float and not on the available space. Remove the loop calling ReflowFloater at different positions that is no longer needed, and remove the caching of the max element size for that loop that was not being invalidated correctly between reflows. Fix handling of margin, border, and padding for computation of available width for |width: auto| floaters. r=attinasi sr=waterson b= 85876, 82314, 82315, 85216, 85874, 86746

This commit is contained in:
dbaron%fas.harvard.edu 2001-07-19 02:33:43 +00:00
Родитель 3848f15987
Коммит fc01a17366
12 изменённых файлов: 130 добавлений и 180 удалений

Просмотреть файл

@ -4779,8 +4779,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nscoord& aMaxElementWidthResult)
nsMargin& aComputedOffsetsResult)
{
// Reflow the floater.
nsIFrame* floater = aPlaceholder->GetOutOfFlowFrame();
@ -4794,39 +4793,25 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
#endif
// Compute the available width. By default, assume the width of the
// available space rect.
nscoord availWidth = aState.mAvailSpaceRect.width;
// containing block.
nscoord availWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)
? NS_UNCONSTRAINEDSIZE
: aState.mContentArea.width;
// If the floater's width is automatic, we can't let the floater's
// width shrink below its maxElementSize.
const nsStylePosition* position;
GetStyleData(eStyleStruct_Position, NS_REINTERPRET_CAST(const nsStyleStruct*&, position));
floater->GetStyleData(eStyleStruct_Position,
NS_REINTERPRET_CAST(const nsStyleStruct*&, position));
PRBool isAutoWidth = (eStyleUnit_Auto == position->mWidth.GetUnit());
if (isAutoWidth) {
// It's auto-width. Have we computed a max element size yet? (If
// not, the floater cache will have NS_UNCONSTRAINEDSIZE as the
// initial value.) If we _have_ computed a max element size, and
// its larger then the available width, pin the avaiable width to
// the maxElementSize.
if ((NS_UNCONSTRAINEDSIZE != aMaxElementWidthResult) &&
(aMaxElementWidthResult > availWidth)) {
availWidth = aMaxElementWidthResult;
}
}
// We'll need to compute the max element size if either 1) we're
// auto-width and we've not yet cached the value, or 2) the state
// wanted us to compute it anyway.
// auto-width or 2) the state wanted us to compute it anyway.
PRBool computeMaxElementSize =
(isAutoWidth && (NS_UNCONSTRAINEDSIZE == aMaxElementWidthResult)) ||
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
isAutoWidth || aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
// XXX Why do we have to add in our border/padding?
// XXXldb Shouldn't the width of this rect be
// availWidth - aState.BorderPadding().left - aState.BorderPadding().right ?
nsRect availSpace(aState.mAvailSpaceRect.x + aState.BorderPadding().left,
aState.mAvailSpaceRect.y + aState.BorderPadding().top,
nsRect availSpace(aState.BorderPadding().left,
aState.BorderPadding().top,
availWidth, NS_UNCONSTRAINEDSIZE);
// Setup a block reflow state to reflow the floater.
@ -4843,17 +4828,13 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsresult rv = brc.ReflowBlock(floater, availSpace, PR_TRUE, 0, isAdjacentWithTop,
aComputedOffsetsResult, frameReflowStatus);
if (NS_SUCCEEDED(rv) && isAutoWidth && (NS_UNCONSTRAINEDSIZE == aMaxElementWidthResult)) {
// We've just flowed an auto-width floater, but have not yet cached
// the maxElementSize. Do so now.
nsSize maxElementSize = brc.GetMaxElementSize();
aMaxElementWidthResult = maxElementSize.width;
if (aMaxElementWidthResult > availSpace.width) {
if (NS_SUCCEEDED(rv) && isAutoWidth) {
nscoord maxElementWidth = brc.GetMaxElementSize().width;
if (maxElementWidth > availSpace.width) {
// The floater's maxElementSize is larger than the available
// width. Reflow it again, this time pinning the width to the
// maxElementSize.
availSpace.width = aMaxElementWidthResult;
availSpace.width = maxElementWidth;
rv = brc.ReflowBlock(floater, availSpace, PR_TRUE, 0, isAdjacentWithTop,
aComputedOffsetsResult, frameReflowStatus);
}
@ -4898,7 +4879,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
// If we computed it, then stash away the max-element-size for later
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
if (computeMaxElementSize) {
nsSize mes = brc.GetMaxElementSize();
mes.SizeBy(aMarginResult.left + aMarginResult.right,
aMarginResult.top + aMarginResult.bottom);

Просмотреть файл

@ -353,8 +353,7 @@ protected:
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nscoord& aMaxElementWidthResult);
nsMargin& aComputedOffsetsResult);
//----------------------------------------
// Methods for pushing/pulling lines/frames

Просмотреть файл

@ -771,6 +771,7 @@ nsBlockReflowState::CanPlaceFloater(const nsRect& aFloaterRect,
// then by definition the floater fits.
PRBool result = PR_TRUE;
if (0 != mBand.GetFloaterCount()) {
// XXX We should allow overflow by up to half a pixel here (bug 21193).
if (mAvailSpaceRect.width < aFloaterRect.width) {
// The available width is too narrow (and its been impacted by a
// prior floater)
@ -887,62 +888,57 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// ``above'' another float that preceded it in the flow.
mY = NS_MAX(mLastFloaterY, mY);
while (1) {
// See if the floater should clear any preceeding floaters...
if (NS_STYLE_CLEAR_NONE != floaterDisplay->mBreakType) {
// XXXldb Does this handle vertical margins correctly?
ClearFloaters(mY, floaterDisplay->mBreakType);
}
else {
// Get the band of available space
GetAvailableSpace();
}
// See if the floater should clear any preceeding floaters...
if (NS_STYLE_CLEAR_NONE != floaterDisplay->mBreakType) {
// XXXldb Does this handle vertical margins correctly?
ClearFloaters(mY, floaterDisplay->mBreakType);
}
else {
// Get the band of available space
GetAvailableSpace();
}
// Reflow the floater
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets,
aFloaterCache->mMaxElementWidth);
// Reflow the floater
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets);
// Get the floaters bounding box and margin information
floater->GetRect(region);
// Get the floaters bounding box and margin information
floater->GetRect(region);
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("flowed floater: ");
nsFrame::ListTag(stdout, floater);
printf(" (%d,%d,%d,%d), max-element-width=%d\n",
region.x, region.y, region.width, region.height,
aFloaterCache->mMaxElementWidth);
}
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("flowed floater: ");
nsFrame::ListTag(stdout, floater);
printf(" (%d,%d,%d,%d)\n",
region.x, region.y, region.width, region.height);
}
#endif
// Adjust the floater size by its margin. That's the area that will
// impact the space manager.
region.width += aFloaterCache->mMargins.left + aFloaterCache->mMargins.right;
region.height += aFloaterCache->mMargins.top + aFloaterCache->mMargins.bottom;
// Adjust the floater size by its margin. That's the area that will
// impact the space manager.
region.width += aFloaterCache->mMargins.left + aFloaterCache->mMargins.right;
region.height += aFloaterCache->mMargins.top + aFloaterCache->mMargins.bottom;
// Find a place to place the floater. The CSS2 spec doesn't want
// floaters overlapping each other or sticking out of the containing
// block if possible (CSS2 spec section 9.5.1, see the rule list).
NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) ||
(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats),
"invalid float type");
// In backwards compatibility mode, we don't bother to see if a
// floated table can ``really'' fit: in old browsers, floating
// tables are horizontally stacked regardless of available space.
// (See bug 43086 about tables vs. non-tables.)
if ((eCompatibility_NavQuirks == mode) &&
(NS_STYLE_DISPLAY_TABLE == floaterDisplay->mDisplay))
break;
// Find a place to place the floater. The CSS2 spec doesn't want
// floaters overlapping each other or sticking out of the containing
// block if possible (CSS2 spec section 9.5.1, see the rule list).
NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) ||
(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats),
"invalid float type");
// In backwards compatibility mode, we don't bother to see if a
// floated table can ``really'' fit: in old browsers, floating
// tables are horizontally stacked regardless of available space.
// (See bug 43086 about tables vs. non-tables.)
if ((eCompatibility_NavQuirks != mode) ||
(NS_STYLE_DISPLAY_TABLE != floaterDisplay->mDisplay)) {
// Can the floater fit here?
if (CanPlaceFloater(region, floaterDisplay->mFloats))
break;
// Nope. Advance to the next band.
mY += mAvailSpaceRect.height;
while (! CanPlaceFloater(region, floaterDisplay->mFloats)) {
// Nope. Advance to the next band.
mY += mAvailSpaceRect.height;
GetAvailableSpace();
}
}
// Assign an x and y coordinate to the floater. Note that the x,y

Просмотреть файл

@ -1654,8 +1654,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
mComputedWidth = NS_SHRINKWRAPWIDTH;
// Limnit the width to the containing block width
if (mComputedMaxWidth > aContainingBlockWidth) {
mComputedMaxWidth = aContainingBlockWidth;
nscoord widthFromCB = aContainingBlockWidth -
mComputedBorderPadding.left - mComputedBorderPadding.right -
mComputedMargin.left - mComputedMargin.right;
if (mComputedMaxWidth > widthFromCB) {
mComputedMaxWidth = widthFromCB;
}
}

Просмотреть файл

@ -1097,7 +1097,6 @@ nsFloaterCache::nsFloaterCache()
mMargins(0, 0, 0, 0),
mOffsets(0, 0, 0, 0),
mCombinedArea(0, 0, 0, 0),
mMaxElementWidth(NS_UNCONSTRAINEDSIZE),
mNext(nsnull)
{
MOZ_COUNT_CTOR(nsFloaterCache);

Просмотреть файл

@ -67,9 +67,6 @@ public:
// the containing block frame.
nsRect mCombinedArea;
// The max element size for the floater.
nscoord mMaxElementWidth;
protected:
nsFloaterCache* mNext;

Просмотреть файл

@ -4779,8 +4779,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nscoord& aMaxElementWidthResult)
nsMargin& aComputedOffsetsResult)
{
// Reflow the floater.
nsIFrame* floater = aPlaceholder->GetOutOfFlowFrame();
@ -4794,39 +4793,25 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
#endif
// Compute the available width. By default, assume the width of the
// available space rect.
nscoord availWidth = aState.mAvailSpaceRect.width;
// containing block.
nscoord availWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)
? NS_UNCONSTRAINEDSIZE
: aState.mContentArea.width;
// If the floater's width is automatic, we can't let the floater's
// width shrink below its maxElementSize.
const nsStylePosition* position;
GetStyleData(eStyleStruct_Position, NS_REINTERPRET_CAST(const nsStyleStruct*&, position));
floater->GetStyleData(eStyleStruct_Position,
NS_REINTERPRET_CAST(const nsStyleStruct*&, position));
PRBool isAutoWidth = (eStyleUnit_Auto == position->mWidth.GetUnit());
if (isAutoWidth) {
// It's auto-width. Have we computed a max element size yet? (If
// not, the floater cache will have NS_UNCONSTRAINEDSIZE as the
// initial value.) If we _have_ computed a max element size, and
// its larger then the available width, pin the avaiable width to
// the maxElementSize.
if ((NS_UNCONSTRAINEDSIZE != aMaxElementWidthResult) &&
(aMaxElementWidthResult > availWidth)) {
availWidth = aMaxElementWidthResult;
}
}
// We'll need to compute the max element size if either 1) we're
// auto-width and we've not yet cached the value, or 2) the state
// wanted us to compute it anyway.
// auto-width or 2) the state wanted us to compute it anyway.
PRBool computeMaxElementSize =
(isAutoWidth && (NS_UNCONSTRAINEDSIZE == aMaxElementWidthResult)) ||
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
isAutoWidth || aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
// XXX Why do we have to add in our border/padding?
// XXXldb Shouldn't the width of this rect be
// availWidth - aState.BorderPadding().left - aState.BorderPadding().right ?
nsRect availSpace(aState.mAvailSpaceRect.x + aState.BorderPadding().left,
aState.mAvailSpaceRect.y + aState.BorderPadding().top,
nsRect availSpace(aState.BorderPadding().left,
aState.BorderPadding().top,
availWidth, NS_UNCONSTRAINEDSIZE);
// Setup a block reflow state to reflow the floater.
@ -4843,17 +4828,13 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsresult rv = brc.ReflowBlock(floater, availSpace, PR_TRUE, 0, isAdjacentWithTop,
aComputedOffsetsResult, frameReflowStatus);
if (NS_SUCCEEDED(rv) && isAutoWidth && (NS_UNCONSTRAINEDSIZE == aMaxElementWidthResult)) {
// We've just flowed an auto-width floater, but have not yet cached
// the maxElementSize. Do so now.
nsSize maxElementSize = brc.GetMaxElementSize();
aMaxElementWidthResult = maxElementSize.width;
if (aMaxElementWidthResult > availSpace.width) {
if (NS_SUCCEEDED(rv) && isAutoWidth) {
nscoord maxElementWidth = brc.GetMaxElementSize().width;
if (maxElementWidth > availSpace.width) {
// The floater's maxElementSize is larger than the available
// width. Reflow it again, this time pinning the width to the
// maxElementSize.
availSpace.width = aMaxElementWidthResult;
availSpace.width = maxElementWidth;
rv = brc.ReflowBlock(floater, availSpace, PR_TRUE, 0, isAdjacentWithTop,
aComputedOffsetsResult, frameReflowStatus);
}
@ -4898,7 +4879,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
// If we computed it, then stash away the max-element-size for later
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
if (computeMaxElementSize) {
nsSize mes = brc.GetMaxElementSize();
mes.SizeBy(aMarginResult.left + aMarginResult.right,
aMarginResult.top + aMarginResult.bottom);

Просмотреть файл

@ -353,8 +353,7 @@ protected:
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nscoord& aMaxElementWidthResult);
nsMargin& aComputedOffsetsResult);
//----------------------------------------
// Methods for pushing/pulling lines/frames

Просмотреть файл

@ -771,6 +771,7 @@ nsBlockReflowState::CanPlaceFloater(const nsRect& aFloaterRect,
// then by definition the floater fits.
PRBool result = PR_TRUE;
if (0 != mBand.GetFloaterCount()) {
// XXX We should allow overflow by up to half a pixel here (bug 21193).
if (mAvailSpaceRect.width < aFloaterRect.width) {
// The available width is too narrow (and its been impacted by a
// prior floater)
@ -887,62 +888,57 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// ``above'' another float that preceded it in the flow.
mY = NS_MAX(mLastFloaterY, mY);
while (1) {
// See if the floater should clear any preceeding floaters...
if (NS_STYLE_CLEAR_NONE != floaterDisplay->mBreakType) {
// XXXldb Does this handle vertical margins correctly?
ClearFloaters(mY, floaterDisplay->mBreakType);
}
else {
// Get the band of available space
GetAvailableSpace();
}
// See if the floater should clear any preceeding floaters...
if (NS_STYLE_CLEAR_NONE != floaterDisplay->mBreakType) {
// XXXldb Does this handle vertical margins correctly?
ClearFloaters(mY, floaterDisplay->mBreakType);
}
else {
// Get the band of available space
GetAvailableSpace();
}
// Reflow the floater
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets,
aFloaterCache->mMaxElementWidth);
// Reflow the floater
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets);
// Get the floaters bounding box and margin information
floater->GetRect(region);
// Get the floaters bounding box and margin information
floater->GetRect(region);
#ifdef DEBUG
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("flowed floater: ");
nsFrame::ListTag(stdout, floater);
printf(" (%d,%d,%d,%d), max-element-width=%d\n",
region.x, region.y, region.width, region.height,
aFloaterCache->mMaxElementWidth);
}
if (nsBlockFrame::gNoisyReflow) {
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
printf("flowed floater: ");
nsFrame::ListTag(stdout, floater);
printf(" (%d,%d,%d,%d)\n",
region.x, region.y, region.width, region.height);
}
#endif
// Adjust the floater size by its margin. That's the area that will
// impact the space manager.
region.width += aFloaterCache->mMargins.left + aFloaterCache->mMargins.right;
region.height += aFloaterCache->mMargins.top + aFloaterCache->mMargins.bottom;
// Adjust the floater size by its margin. That's the area that will
// impact the space manager.
region.width += aFloaterCache->mMargins.left + aFloaterCache->mMargins.right;
region.height += aFloaterCache->mMargins.top + aFloaterCache->mMargins.bottom;
// Find a place to place the floater. The CSS2 spec doesn't want
// floaters overlapping each other or sticking out of the containing
// block if possible (CSS2 spec section 9.5.1, see the rule list).
NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) ||
(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats),
"invalid float type");
// In backwards compatibility mode, we don't bother to see if a
// floated table can ``really'' fit: in old browsers, floating
// tables are horizontally stacked regardless of available space.
// (See bug 43086 about tables vs. non-tables.)
if ((eCompatibility_NavQuirks == mode) &&
(NS_STYLE_DISPLAY_TABLE == floaterDisplay->mDisplay))
break;
// Find a place to place the floater. The CSS2 spec doesn't want
// floaters overlapping each other or sticking out of the containing
// block if possible (CSS2 spec section 9.5.1, see the rule list).
NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) ||
(NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats),
"invalid float type");
// In backwards compatibility mode, we don't bother to see if a
// floated table can ``really'' fit: in old browsers, floating
// tables are horizontally stacked regardless of available space.
// (See bug 43086 about tables vs. non-tables.)
if ((eCompatibility_NavQuirks != mode) ||
(NS_STYLE_DISPLAY_TABLE != floaterDisplay->mDisplay)) {
// Can the floater fit here?
if (CanPlaceFloater(region, floaterDisplay->mFloats))
break;
// Nope. Advance to the next band.
mY += mAvailSpaceRect.height;
while (! CanPlaceFloater(region, floaterDisplay->mFloats)) {
// Nope. Advance to the next band.
mY += mAvailSpaceRect.height;
GetAvailableSpace();
}
}
// Assign an x and y coordinate to the floater. Note that the x,y

Просмотреть файл

@ -1654,8 +1654,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
mComputedWidth = NS_SHRINKWRAPWIDTH;
// Limnit the width to the containing block width
if (mComputedMaxWidth > aContainingBlockWidth) {
mComputedMaxWidth = aContainingBlockWidth;
nscoord widthFromCB = aContainingBlockWidth -
mComputedBorderPadding.left - mComputedBorderPadding.right -
mComputedMargin.left - mComputedMargin.right;
if (mComputedMaxWidth > widthFromCB) {
mComputedMaxWidth = widthFromCB;
}
}

Просмотреть файл

@ -1097,7 +1097,6 @@ nsFloaterCache::nsFloaterCache()
mMargins(0, 0, 0, 0),
mOffsets(0, 0, 0, 0),
mCombinedArea(0, 0, 0, 0),
mMaxElementWidth(NS_UNCONSTRAINEDSIZE),
mNext(nsnull)
{
MOZ_COUNT_CTOR(nsFloaterCache);

Просмотреть файл

@ -67,9 +67,6 @@ public:
// the containing block frame.
nsRect mCombinedArea;
// The max element size for the floater.
nscoord mMaxElementWidth;
protected:
nsFloaterCache* mNext;