Change the way we calculate max-element-width for blocks with floaters: stop trying (and sometimes failing) to ensure that there can always be text next to the floater. b=186593 r+sr=roc+moz

This commit is contained in:
dbaron%dbaron.org 2003-02-22 16:19:31 +00:00
parent 4b4f8625f1
commit 0ec06d045f
14 changed files with 70 additions and 476 deletions

View File

@ -351,137 +351,6 @@ nsBlockBandData::ClearFloaters(nscoord aY, PRUint8 aBreakType)
return aY;
}
//----------------------------------------------------------------------
static void
MaxElementWidthPropertyDtor(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
nscoord* size = (nscoord*) aPropertyValue;
delete size;
}
void
nsBlockBandData::StoreMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord aMaxElementWidth)
{
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> mgr;
shell->GetFrameManager(getter_AddRefs(mgr));
if (mgr) {
nscoord* size = new nscoord(aMaxElementWidth);
if (size) {
mgr->SetFrameProperty(aFrame, nsLayoutAtoms::maxElementWidthProperty,
size, MaxElementWidthPropertyDtor);
}
}
}
}
void
nsBlockBandData::RecoverMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord* aResult)
{
if (!aResult) return;
nscoord answer = 0;
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> mgr;
shell->GetFrameManager(getter_AddRefs(mgr));
if (mgr) {
nscoord* width = nsnull;
mgr->GetFrameProperty(aFrame, nsLayoutAtoms::maxElementWidthProperty,
0, (void**) &width);
if (width) {
answer = *width;
}
}
}
*aResult = answer;
}
void
nsBlockBandData::GetMaxElementWidth(nsIPresContext* aPresContext,
nscoord* aResult) const
{
nsCOMPtr<nsIFrameManager> mgr;
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
shell->GetFrameManager(getter_AddRefs(mgr));
}
nsRect r;
nscoord maxWidth = 0;
for (PRInt32 i = 0; i < mCount; i++) {
const nsBandTrapezoid* trap = &mTrapezoids[i];
if (trap->mState != nsBandTrapezoid::Available) {
// Note: get the total height of the frame to compute the maxHeight,
// not just the height that is part of this band.
if (nsBandTrapezoid::OccupiedMultiple == trap->mState) {
PRBool usedBackupValue = PR_FALSE;
PRInt32 j, numFrames = trap->mFrames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (j = 0; j < numFrames; j++) {
PRBool useBackupValue = PR_TRUE;
nsIFrame* f = (nsIFrame*) trap->mFrames->ElementAt(j);
if (mgr) {
nscoord* maxElementWidth = nsnull;
mgr->GetFrameProperty(f, nsLayoutAtoms::maxElementWidthProperty,
0, (void**) &maxElementWidth);
if (maxElementWidth) {
useBackupValue = PR_FALSE;
if (*maxElementWidth > maxWidth) {
maxWidth = *maxElementWidth;
}
}
}
if (useBackupValue) {
usedBackupValue = PR_TRUE;
}
}
// Get the width of the impacted area and update the maxWidth
if (usedBackupValue) {
trap->GetRect(r);
if (r.width > maxWidth) maxWidth = r.width;
}
} else {
PRBool useBackupValue = PR_TRUE;
if (mgr) {
nscoord* maxElementWidth = nsnull;
mgr->GetFrameProperty(trap->mFrame,
nsLayoutAtoms::maxElementWidthProperty,
0, (void**) &maxElementWidth);
if (maxElementWidth) {
useBackupValue = PR_FALSE;
if (*maxElementWidth > maxWidth) {
maxWidth = *maxElementWidth;
}
}
}
if (useBackupValue) {
trap->GetRect(r);
if (r.width > maxWidth) maxWidth = r.width;
}
}
}
}
*aResult = maxWidth;
}
#ifdef DEBUG
void nsBlockBandData::List()
{

View File

@ -86,24 +86,6 @@ public:
return mRightFloaters;
}
// Return the impact on the max-element-width for this band by
// computing the maximum width and maximum height of all the
// floaters.
void GetMaxElementWidth(nsIPresContext* aPresContext,
nscoord* aResult) const;
// Utility method to save away the max-element-width associated with
// a floating frame.
static void StoreMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord aMaxElementWidth);
// Utility method to recover a stored max-element-width value
// associated with a floating frame.
static void RecoverMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord* aResult);
#ifdef DEBUG
void List();
#endif

View File

@ -1323,7 +1323,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
computedWidth += borderPadding.right;
}
// See if we should compute our max element size
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
// Add in border and padding dimensions to already computed
// max-element-width values.
@ -3446,13 +3445,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
nscoord maxElementWidth = 0;
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
maxElementWidth = brc.GetMaxElementWidth();
if (aState.IsImpactedByFloater() &&
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
// Add in floater impacts to the lines max-element-width, but
// only if the block element isn't one of us (otherwise the
// floater impacts will be counted twice).
ComputeLineMaxElementWidth(aState, aLine, &maxElementWidth);
}
}
// If we asked the block to update its maximum width, then record the
// updated value in the line, and update the current maximum width
@ -4355,24 +4347,6 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
aState.mY = newY;
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
#ifdef DEBUG
if (gNoisyMaxElementWidth) {
IndentBy(stdout, gNoiseIndent);
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
printf("PASS1 ");
}
ListTag(stdout);
printf(": band.floaterCount=%d\n",
//aLine->mFloaters.NotEmpty() ? "yes" : "no",
aState.mBand.GetFloaterCount());
}
#endif
if (0 != aState.mBand.GetFloaterCount()) {
// Add in floater impacts to the lines max-element-width
ComputeLineMaxElementWidth(aState, aLine, &maxElementWidth);
}
}
// If we're reflowing the line just to incrementally update the
// maximum width, then don't post-place the line. It's doing work we
@ -4458,40 +4432,6 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
return PR_FALSE;
}
// Compute the line's max-element-width by adding into the raw value
// computed by reflowing the contents of the line (aMaxElementWidth)
// the impact of floaters on this line or the preceeding lines.
void
nsBlockFrame::ComputeLineMaxElementWidth(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord* aMaxElementWidth)
{
nscoord maxWidth;
aState.mBand.GetMaxElementWidth(aState.mPresContext, &maxWidth);
#ifdef DEBUG
if (gNoisyMaxElementWidth) {
IndentBy(stdout, gNoiseIndent);
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
printf("PASS1 ");
}
ListTag(stdout);
printf(": maxFloaterWidth=%d\n", maxWidth);
}
#endif
// To ensure that we always place some content next to a floater,
// _add_ the max floater width to our line's max element size.
*aMaxElementWidth += maxWidth;
#ifdef DEBUG
if (gNoisyMaxElementWidth) {
IndentBy(stdout, gNoiseIndent);
printf ("nsBlockFrame::ComputeLineMaxElementWidth: %p returning MEW %d\n",
this, *aMaxElementWidth);
}
#endif
}
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
nsLineBox* aLine,
@ -5276,9 +5216,7 @@ nsBlockFrame::DeleteNextInFlowChild(nsIPresContext* aPresContext,
nsresult
nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nsFloaterCache* aFloaterCache,
nsReflowStatus& aReflowStatus)
{
// Delete the placeholder's next in flows, if any
@ -5379,7 +5317,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsCollapsingMargin margin;
nsresult rv = brc.ReflowBlock(availSpace, PR_TRUE, margin, isAdjacentWithTop,
aComputedOffsetsResult, floaterRS, aReflowStatus);
aFloaterCache->mOffsets, floaterRS,
aReflowStatus);
// An incomplete reflow status means we should split the floater
// if the height is constrained (bug 145305).
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) && (NS_UNCONSTRAINEDSIZE == availHeight))
@ -5399,7 +5338,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsSize(availSpace.width, availSpace.height),
aState.mReflowState.reason, PR_FALSE);
rv = brc.ReflowBlock(availSpace, PR_TRUE, marginMEW, isAdjacentWithTop,
aComputedOffsetsResult, redoFloaterRS, aReflowStatus);
aFloaterCache->mOffsets, redoFloaterRS,
aReflowStatus);
}
}
@ -5417,14 +5357,14 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
// Capture the margin information for the caller
const nsMargin& m = brc.GetMargin();
aMarginResult.top = brc.GetTopMargin();
aMarginResult.right = m.right;
aFloaterCache->mMargins.top = brc.GetTopMargin();
aFloaterCache->mMargins.right = m.right;
brc.GetCarriedOutBottomMargin().Include(m.bottom);
aMarginResult.bottom = brc.GetCarriedOutBottomMargin().get();
aMarginResult.left = m.left;
aFloaterCache->mMargins.bottom = brc.GetCarriedOutBottomMargin().get();
aFloaterCache->mMargins.left = m.left;
const nsHTMLReflowMetrics& metrics = brc.GetMetrics();
aCombinedRectResult = metrics.mOverflowArea;
aFloaterCache->mCombinedArea = metrics.mOverflowArea;
// Set the rect, make sure the view is properly sized and positioned,
// and tell the frame we're done reflowing it
@ -5444,11 +5384,17 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
floater->DidReflow(aState.mPresContext, &floaterRS, NS_FRAME_REFLOW_FINISHED);
// If we computed it, then stash away the max-element-width for later
if (computeMaxElementWidth) {
nscoord mew = brc.GetMaxElementWidth();
mew += aMarginResult.left + aMarginResult.right;
aState.StoreMaxElementWidth(floater, mew);
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
nscoord mew = brc.GetMaxElementWidth() +
aFloaterCache->mMargins.left + aFloaterCache->mMargins.right;
// This is all we need to do to include the floater
// max-element-width since we don't require that we end up with
// content next to floaters.
aState.UpdateMaxElementWidth(mew); // fix for bug 13553
// Allow the floater width to be restored in state recovery.
aFloaterCache->mMaxElementWidth = mew;
}
#ifdef NOISY_FLOATER
printf("end ReflowFloater %p, sized to %d,%d\n", floater, metrics.width, metrics.height);

View File

@ -368,10 +368,6 @@ protected:
nsLineBox* aLine,
nscoord aMaxElementWidth);
void ComputeLineMaxElementWidth(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord* aMaxElementWidth);
// XXX where to go
PRBool ShouldJustifyLine(nsBlockReflowState& aState,
line_iterator aLine);
@ -428,9 +424,7 @@ protected:
// but only if the available height is constrained.
nsresult ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nsFloaterCache* aFloaterCache,
nsReflowStatus& aReflowStatus);
//----------------------------------------

View File

@ -591,6 +591,14 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
}
#endif
UpdateMaxElementWidth(aLine->mMaxElementWidth);
// Recover the floater MEWs for floaters in this line (but not in
// blocks within it, since their MEWs are already part of the block's
// MEW).
if (aLine->HasFloaters()) {
for (nsFloaterCache* fc = aLine->GetFirstFloater(); fc; fc = fc->Next())
UpdateMaxElementWidth(fc->mMaxElementWidth);
}
}
// If computing the maximum width, then update mMaximumWidth
@ -669,6 +677,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
nsFloaterCache* fc = mFloaterCacheFreeList.Alloc();
fc->mPlaceholder = aPlaceholder;
fc->mIsCurrentLineFloater = aLineLayout.CanPlaceFloaterNow();
fc->mMaxElementWidth = 0;
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
@ -884,8 +893,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
// Reflow the floater
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
mBlock->ReflowFloater(*this, placeholder, aFloaterCache, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
@ -968,8 +976,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
mY += mAvailSpaceRect.height;
GetAvailableSpace();
// reflow the floater again now since we have more space
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
mBlock->ReflowFloater(*this, placeholder, aFloaterCache, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
// Adjust the floater size by its margin. That's the area that will

View File

@ -129,10 +129,6 @@ public:
void FreeLineBox(nsLineBox* aLine);
void StoreMaxElementWidth(nsIFrame* aFloater, nscoord aWidth) {
mBand.StoreMaxElementWidth(mPresContext, aFloater, aWidth);
}
//----------------------------------------
// This state is the "global" state computed once for the reflow of

View File

@ -83,6 +83,9 @@ public:
// the containing block frame.
nsRect mCombinedArea;
// The floater's max-element-width.
nscoord mMaxElementWidth;
protected:
nsFloaterCache* mNext;

View File

@ -351,137 +351,6 @@ nsBlockBandData::ClearFloaters(nscoord aY, PRUint8 aBreakType)
return aY;
}
//----------------------------------------------------------------------
static void
MaxElementWidthPropertyDtor(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
nscoord* size = (nscoord*) aPropertyValue;
delete size;
}
void
nsBlockBandData::StoreMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord aMaxElementWidth)
{
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> mgr;
shell->GetFrameManager(getter_AddRefs(mgr));
if (mgr) {
nscoord* size = new nscoord(aMaxElementWidth);
if (size) {
mgr->SetFrameProperty(aFrame, nsLayoutAtoms::maxElementWidthProperty,
size, MaxElementWidthPropertyDtor);
}
}
}
}
void
nsBlockBandData::RecoverMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord* aResult)
{
if (!aResult) return;
nscoord answer = 0;
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
nsCOMPtr<nsIFrameManager> mgr;
shell->GetFrameManager(getter_AddRefs(mgr));
if (mgr) {
nscoord* width = nsnull;
mgr->GetFrameProperty(aFrame, nsLayoutAtoms::maxElementWidthProperty,
0, (void**) &width);
if (width) {
answer = *width;
}
}
}
*aResult = answer;
}
void
nsBlockBandData::GetMaxElementWidth(nsIPresContext* aPresContext,
nscoord* aResult) const
{
nsCOMPtr<nsIFrameManager> mgr;
nsCOMPtr<nsIPresShell> shell;
aPresContext->GetShell(getter_AddRefs(shell));
if (shell) {
shell->GetFrameManager(getter_AddRefs(mgr));
}
nsRect r;
nscoord maxWidth = 0;
for (PRInt32 i = 0; i < mCount; i++) {
const nsBandTrapezoid* trap = &mTrapezoids[i];
if (trap->mState != nsBandTrapezoid::Available) {
// Note: get the total height of the frame to compute the maxHeight,
// not just the height that is part of this band.
if (nsBandTrapezoid::OccupiedMultiple == trap->mState) {
PRBool usedBackupValue = PR_FALSE;
PRInt32 j, numFrames = trap->mFrames->Count();
NS_ASSERTION(numFrames > 0, "bad trapezoid frame list");
for (j = 0; j < numFrames; j++) {
PRBool useBackupValue = PR_TRUE;
nsIFrame* f = (nsIFrame*) trap->mFrames->ElementAt(j);
if (mgr) {
nscoord* maxElementWidth = nsnull;
mgr->GetFrameProperty(f, nsLayoutAtoms::maxElementWidthProperty,
0, (void**) &maxElementWidth);
if (maxElementWidth) {
useBackupValue = PR_FALSE;
if (*maxElementWidth > maxWidth) {
maxWidth = *maxElementWidth;
}
}
}
if (useBackupValue) {
usedBackupValue = PR_TRUE;
}
}
// Get the width of the impacted area and update the maxWidth
if (usedBackupValue) {
trap->GetRect(r);
if (r.width > maxWidth) maxWidth = r.width;
}
} else {
PRBool useBackupValue = PR_TRUE;
if (mgr) {
nscoord* maxElementWidth = nsnull;
mgr->GetFrameProperty(trap->mFrame,
nsLayoutAtoms::maxElementWidthProperty,
0, (void**) &maxElementWidth);
if (maxElementWidth) {
useBackupValue = PR_FALSE;
if (*maxElementWidth > maxWidth) {
maxWidth = *maxElementWidth;
}
}
}
if (useBackupValue) {
trap->GetRect(r);
if (r.width > maxWidth) maxWidth = r.width;
}
}
}
}
*aResult = maxWidth;
}
#ifdef DEBUG
void nsBlockBandData::List()
{

View File

@ -86,24 +86,6 @@ public:
return mRightFloaters;
}
// Return the impact on the max-element-width for this band by
// computing the maximum width and maximum height of all the
// floaters.
void GetMaxElementWidth(nsIPresContext* aPresContext,
nscoord* aResult) const;
// Utility method to save away the max-element-width associated with
// a floating frame.
static void StoreMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord aMaxElementWidth);
// Utility method to recover a stored max-element-width value
// associated with a floating frame.
static void RecoverMaxElementWidth(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nscoord* aResult);
#ifdef DEBUG
void List();
#endif

View File

@ -1323,7 +1323,6 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
computedWidth += borderPadding.right;
}
// See if we should compute our max element size
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
// Add in border and padding dimensions to already computed
// max-element-width values.
@ -3446,13 +3445,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
nscoord maxElementWidth = 0;
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
maxElementWidth = brc.GetMaxElementWidth();
if (aState.IsImpactedByFloater() &&
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
// Add in floater impacts to the lines max-element-width, but
// only if the block element isn't one of us (otherwise the
// floater impacts will be counted twice).
ComputeLineMaxElementWidth(aState, aLine, &maxElementWidth);
}
}
// If we asked the block to update its maximum width, then record the
// updated value in the line, and update the current maximum width
@ -4355,24 +4347,6 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
}
aState.mY = newY;
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
#ifdef DEBUG
if (gNoisyMaxElementWidth) {
IndentBy(stdout, gNoiseIndent);
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
printf("PASS1 ");
}
ListTag(stdout);
printf(": band.floaterCount=%d\n",
//aLine->mFloaters.NotEmpty() ? "yes" : "no",
aState.mBand.GetFloaterCount());
}
#endif
if (0 != aState.mBand.GetFloaterCount()) {
// Add in floater impacts to the lines max-element-width
ComputeLineMaxElementWidth(aState, aLine, &maxElementWidth);
}
}
// If we're reflowing the line just to incrementally update the
// maximum width, then don't post-place the line. It's doing work we
@ -4458,40 +4432,6 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
return PR_FALSE;
}
// Compute the line's max-element-width by adding into the raw value
// computed by reflowing the contents of the line (aMaxElementWidth)
// the impact of floaters on this line or the preceeding lines.
void
nsBlockFrame::ComputeLineMaxElementWidth(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord* aMaxElementWidth)
{
nscoord maxWidth;
aState.mBand.GetMaxElementWidth(aState.mPresContext, &maxWidth);
#ifdef DEBUG
if (gNoisyMaxElementWidth) {
IndentBy(stdout, gNoiseIndent);
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
printf("PASS1 ");
}
ListTag(stdout);
printf(": maxFloaterWidth=%d\n", maxWidth);
}
#endif
// To ensure that we always place some content next to a floater,
// _add_ the max floater width to our line's max element size.
*aMaxElementWidth += maxWidth;
#ifdef DEBUG
if (gNoisyMaxElementWidth) {
IndentBy(stdout, gNoiseIndent);
printf ("nsBlockFrame::ComputeLineMaxElementWidth: %p returning MEW %d\n",
this, *aMaxElementWidth);
}
#endif
}
void
nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
nsLineBox* aLine,
@ -5276,9 +5216,7 @@ nsBlockFrame::DeleteNextInFlowChild(nsIPresContext* aPresContext,
nsresult
nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nsFloaterCache* aFloaterCache,
nsReflowStatus& aReflowStatus)
{
// Delete the placeholder's next in flows, if any
@ -5379,7 +5317,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsCollapsingMargin margin;
nsresult rv = brc.ReflowBlock(availSpace, PR_TRUE, margin, isAdjacentWithTop,
aComputedOffsetsResult, floaterRS, aReflowStatus);
aFloaterCache->mOffsets, floaterRS,
aReflowStatus);
// An incomplete reflow status means we should split the floater
// if the height is constrained (bug 145305).
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) && (NS_UNCONSTRAINEDSIZE == availHeight))
@ -5399,7 +5338,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
nsSize(availSpace.width, availSpace.height),
aState.mReflowState.reason, PR_FALSE);
rv = brc.ReflowBlock(availSpace, PR_TRUE, marginMEW, isAdjacentWithTop,
aComputedOffsetsResult, redoFloaterRS, aReflowStatus);
aFloaterCache->mOffsets, redoFloaterRS,
aReflowStatus);
}
}
@ -5417,14 +5357,14 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
// Capture the margin information for the caller
const nsMargin& m = brc.GetMargin();
aMarginResult.top = brc.GetTopMargin();
aMarginResult.right = m.right;
aFloaterCache->mMargins.top = brc.GetTopMargin();
aFloaterCache->mMargins.right = m.right;
brc.GetCarriedOutBottomMargin().Include(m.bottom);
aMarginResult.bottom = brc.GetCarriedOutBottomMargin().get();
aMarginResult.left = m.left;
aFloaterCache->mMargins.bottom = brc.GetCarriedOutBottomMargin().get();
aFloaterCache->mMargins.left = m.left;
const nsHTMLReflowMetrics& metrics = brc.GetMetrics();
aCombinedRectResult = metrics.mOverflowArea;
aFloaterCache->mCombinedArea = metrics.mOverflowArea;
// Set the rect, make sure the view is properly sized and positioned,
// and tell the frame we're done reflowing it
@ -5444,11 +5384,17 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
floater->DidReflow(aState.mPresContext, &floaterRS, NS_FRAME_REFLOW_FINISHED);
// If we computed it, then stash away the max-element-width for later
if (computeMaxElementWidth) {
nscoord mew = brc.GetMaxElementWidth();
mew += aMarginResult.left + aMarginResult.right;
aState.StoreMaxElementWidth(floater, mew);
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
nscoord mew = brc.GetMaxElementWidth() +
aFloaterCache->mMargins.left + aFloaterCache->mMargins.right;
// This is all we need to do to include the floater
// max-element-width since we don't require that we end up with
// content next to floaters.
aState.UpdateMaxElementWidth(mew); // fix for bug 13553
// Allow the floater width to be restored in state recovery.
aFloaterCache->mMaxElementWidth = mew;
}
#ifdef NOISY_FLOATER
printf("end ReflowFloater %p, sized to %d,%d\n", floater, metrics.width, metrics.height);

View File

@ -368,10 +368,6 @@ protected:
nsLineBox* aLine,
nscoord aMaxElementWidth);
void ComputeLineMaxElementWidth(nsBlockReflowState& aState,
nsLineBox* aLine,
nscoord* aMaxElementWidth);
// XXX where to go
PRBool ShouldJustifyLine(nsBlockReflowState& aState,
line_iterator aLine);
@ -428,9 +424,7 @@ protected:
// but only if the available height is constrained.
nsresult ReflowFloater(nsBlockReflowState& aState,
nsPlaceholderFrame* aPlaceholder,
nsRect& aCombinedRectResult,
nsMargin& aMarginResult,
nsMargin& aComputedOffsetsResult,
nsFloaterCache* aFloaterCache,
nsReflowStatus& aReflowStatus);
//----------------------------------------

View File

@ -591,6 +591,14 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
}
#endif
UpdateMaxElementWidth(aLine->mMaxElementWidth);
// Recover the floater MEWs for floaters in this line (but not in
// blocks within it, since their MEWs are already part of the block's
// MEW).
if (aLine->HasFloaters()) {
for (nsFloaterCache* fc = aLine->GetFirstFloater(); fc; fc = fc->Next())
UpdateMaxElementWidth(fc->mMaxElementWidth);
}
}
// If computing the maximum width, then update mMaximumWidth
@ -669,6 +677,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
nsFloaterCache* fc = mFloaterCacheFreeList.Alloc();
fc->mPlaceholder = aPlaceholder;
fc->mIsCurrentLineFloater = aLineLayout.CanPlaceFloaterNow();
fc->mMaxElementWidth = 0;
// Now place the floater immediately if possible. Otherwise stash it
// away in mPendingFloaters and place it later.
@ -884,8 +893,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
// Reflow the floater
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
mBlock->ReflowFloater(*this, placeholder, aFloaterCache, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
@ -968,8 +976,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
mY += mAvailSpaceRect.height;
GetAvailableSpace();
// reflow the floater again now since we have more space
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
mBlock->ReflowFloater(*this, placeholder, aFloaterCache, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
// Adjust the floater size by its margin. That's the area that will

View File

@ -129,10 +129,6 @@ public:
void FreeLineBox(nsLineBox* aLine);
void StoreMaxElementWidth(nsIFrame* aFloater, nscoord aWidth) {
mBand.StoreMaxElementWidth(mPresContext, aFloater, aWidth);
}
//----------------------------------------
// This state is the "global" state computed once for the reflow of

View File

@ -83,6 +83,9 @@ public:
// the containing block frame.
nsRect mCombinedArea;
// The floater's max-element-width.
nscoord mMaxElementWidth;
protected:
nsFloaterCache* mNext;