зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
3848f15987
Коммит
fc01a17366
|
@ -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,7 +888,6 @@ 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?
|
||||
|
@ -900,8 +900,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
|
|||
|
||||
// Reflow the floater
|
||||
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
|
||||
aFloaterCache->mMargins, aFloaterCache->mOffsets,
|
||||
aFloaterCache->mMaxElementWidth);
|
||||
aFloaterCache->mMargins, aFloaterCache->mOffsets);
|
||||
|
||||
// Get the floaters bounding box and margin information
|
||||
floater->GetRect(region);
|
||||
|
@ -911,9 +910,8 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
|
|||
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);
|
||||
printf(" (%d,%d,%d,%d)\n",
|
||||
region.x, region.y, region.width, region.height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -933,16 +931,14 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
|
|||
// 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;
|
||||
|
||||
if ((eCompatibility_NavQuirks != mode) ||
|
||||
(NS_STYLE_DISPLAY_TABLE != floaterDisplay->mDisplay)) {
|
||||
// Can the floater fit here?
|
||||
if (CanPlaceFloater(region, floaterDisplay->mFloats))
|
||||
break;
|
||||
|
||||
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,7 +888,6 @@ 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?
|
||||
|
@ -900,8 +900,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
|
|||
|
||||
// Reflow the floater
|
||||
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
|
||||
aFloaterCache->mMargins, aFloaterCache->mOffsets,
|
||||
aFloaterCache->mMaxElementWidth);
|
||||
aFloaterCache->mMargins, aFloaterCache->mOffsets);
|
||||
|
||||
// Get the floaters bounding box and margin information
|
||||
floater->GetRect(region);
|
||||
|
@ -911,9 +910,8 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
|
|||
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);
|
||||
printf(" (%d,%d,%d,%d)\n",
|
||||
region.x, region.y, region.width, region.height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -933,16 +931,14 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
|
|||
// 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;
|
||||
|
||||
if ((eCompatibility_NavQuirks != mode) ||
|
||||
(NS_STYLE_DISPLAY_TABLE != floaterDisplay->mDisplay)) {
|
||||
// Can the floater fit here?
|
||||
if (CanPlaceFloater(region, floaterDisplay->mFloats))
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче