From f756eb40765a58f095fa06c5127a59ed44368f9a Mon Sep 17 00:00:00 2001 From: "dbaron%fas.harvard.edu" Date: Thu, 29 Jun 2000 22:03:42 +0000 Subject: [PATCH] Fix bug 43882 (dogfood+) by removing special handling of empty P elements. (Most of the diffs are whitespace changes.) This also fixes bugs 43369, 43991, and 18050. However, it exposes a few other issues as well (the most important of which, nuking top margins on first *normal flow* children of BODY and TD, was previously fixed only in some cases, but shouldn't be hard to fix in general). r=waterson git-svn-id: svn://10.0.0.236/trunk@73541 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsBlockFrame.cpp | 493 ++++++++---------- mozilla/layout/generic/nsBlockFrame.h | 3 +- .../layout/generic/nsBlockReflowContext.cpp | 165 ++---- mozilla/layout/generic/nsBlockReflowContext.h | 8 - mozilla/layout/generic/nsBlockReflowState.cpp | 493 ++++++++---------- mozilla/layout/generic/nsBlockReflowState.h | 493 ++++++++---------- mozilla/layout/html/base/src/nsBlockFrame.cpp | 493 ++++++++---------- mozilla/layout/html/base/src/nsBlockFrame.h | 3 +- .../html/base/src/nsBlockReflowContext.cpp | 165 ++---- .../html/base/src/nsBlockReflowContext.h | 8 - .../html/base/src/nsBlockReflowState.cpp | 493 ++++++++---------- .../layout/html/base/src/nsBlockReflowState.h | 493 ++++++++---------- 12 files changed, 1378 insertions(+), 1932 deletions(-) diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 5d777fc69d9..3956f2e2a74 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -57,9 +57,6 @@ #include "prenv.h" #include "plstr.h" -// XXX HTML:P's that are empty yet have style indicating they should -// clear floaters - we need to ignore the clear behavior. - #ifdef DEBUG static PRBool gLamePaintMetrics; @@ -1045,22 +1042,16 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine, aLine->GetCombinedArea(&lineCombinedArea); if (aLine->IsBlock()) { if ((0 == aLine->mBounds.height) && (0 == lineCombinedArea.height)) { - if (nsBlockReflowContext::IsHTMLParagraph(aLine->mFirstChild)) { - // Empty HTML paragraphs disappear entirely - their margins go - // to zero. Therefore we leave mPrevBottomMargin alone. - } - else { - // The line's top and bottom margin values need to be collapsed - // with the mPrevBottomMargin to determine a new - // mPrevBottomMargin value. - nscoord topMargin, bottomMargin; - RecoverVerticalMargins(aLine, aApplyTopMargin, - &topMargin, &bottomMargin); - nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, - mPrevBottomMargin); - m = nsBlockReflowContext::MaxMargin(m, topMargin); - mPrevBottomMargin = m; - } + // The line's top and bottom margin values need to be collapsed + // with the mPrevBottomMargin to determine a new + // mPrevBottomMargin value. + nscoord topMargin, bottomMargin; + RecoverVerticalMargins(aLine, aApplyTopMargin, + &topMargin, &bottomMargin); + nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, + mPrevBottomMargin); + m = nsBlockReflowContext::MaxMargin(m, topMargin); + mPrevBottomMargin = m; } else { // Recover the top and bottom margins for this line @@ -2097,294 +2088,255 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, borderPadding.top, borderPadding.bottom); #endif - // Special check for zero sized content: If our content is zero - // sized then we collapse into nothingness. - // - // Consensus after discussion with a few CSS folks is that html's - // notion of collapsing

's should take precedence over non - // auto-sided block elements. Therefore we don't honor the width, - // height, border or padding attributes (the parent has to not apply - // a margin for us also). - // - // Note that this is only done for html paragraphs. Its not - // appropriate to apply it to other containers, especially XML - // content! - PRBool isHTMLParagraph = 0 != (mState & NS_BLOCK_IS_HTML_PARAGRAPH); - if (isHTMLParagraph && - (aReflowState.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_BLOCK) && - (((0 == aState.mKidXMost) || - (0 == aState.mKidXMost - borderPadding.left)) && - (0 == aState.mY - borderPadding.top))) { - // Zero out most everything - aMetrics.width = 0; - aMetrics.height = 0; - aMetrics.ascent = 0; - aMetrics.descent = 0; - aMetrics.mCarriedOutBottomMargin = 0; - - // Note: Don't zero out the max-element-sizes: they will be zero - // if this is truly empty, otherwise they won't because of a - // floater. - if (nsnull != aMetrics.maxElementSize) { - aMetrics.maxElementSize->width = aState.mMaxElementSize.width; - aMetrics.maxElementSize->height = aState.mMaxElementSize.height; -#ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p initially setting MES %d\n", - this, aState.mMaxElementSize.width); + // Compute final width + nscoord maxWidth = 0, maxHeight = 0; +#ifdef NOISY_KIDXMOST + printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif + nscoord minWidth = aState.mKidXMost + borderPadding.right; + if (!HaveAutoWidth(aReflowState)) { + // Use style defined width + aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + + borderPadding.right; + // XXX quote css1 section here + if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { + aMetrics.width = minWidth; } + + // When style defines the width use it for the max-element-size + // because we can't shrink any smaller. + maxWidth = aMetrics.width; } else { - // Compute final width - nscoord maxWidth = 0, maxHeight = 0; -#ifdef NOISY_KIDXMOST - printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); -#endif - nscoord minWidth = aState.mKidXMost + borderPadding.right; - if (!HaveAutoWidth(aReflowState)) { - // Use style defined width - aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + - borderPadding.right; - // XXX quote css1 section here - if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { - aMetrics.width = minWidth; - } - - // When style defines the width use it for the max-element-size - // because we can't shrink any smaller. - maxWidth = aMetrics.width; - } - else { - nscoord computedWidth = minWidth; - PRBool compact = PR_FALSE; + nscoord computedWidth = minWidth; + PRBool compact = PR_FALSE; #if 0 - if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { - // If we are display: compact AND we have no lines or we have - // exactly one line and that line is not a block line AND that - // line doesn't end in a BR of any sort THEN we remain a compact - // frame. - if ((nsnull == mLines) || - ((nsnull == mLines->mNext) && !mLines->IsBlock() && - (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) - /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ - )) { - compact = PR_TRUE; - } + if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { + // If we are display: compact AND we have no lines or we have + // exactly one line and that line is not a block line AND that + // line doesn't end in a BR of any sort THEN we remain a compact + // frame. + if ((nsnull == mLines) || + ((nsnull == mLines->mNext) && !mLines->IsBlock() && + (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) + /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ + )) { + compact = PR_TRUE; } + } #endif - // There are two options here. We either shrink wrap around our - // contents or we fluff out to the maximum block width. Note: - // We always shrink wrap when given an unconstrained width. - if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && - !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && - !compact) { - // Set our width to the max width if we aren't already that - // wide. Note that the max-width has nothing to do with our - // contents (CSS2 section XXX) - computedWidth = borderPadding.left + aState.mContentArea.width + - borderPadding.right; - } + // There are two options here. We either shrink wrap around our + // contents or we fluff out to the maximum block width. Note: + // We always shrink wrap when given an unconstrained width. + if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && + !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && + !compact) { + // Set our width to the max width if we aren't already that + // wide. Note that the max-width has nothing to do with our + // contents (CSS2 section XXX) + computedWidth = borderPadding.left + aState.mContentArea.width + + borderPadding.right; + } - // See if we should compute our max element size - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Adjust the computedWidth - if (aState.GetFlag(BRS_NOWRAP)) { - // When no-wrap is true the max-element-size.width is the - // width of the widest line plus the right border. Note that - // aState.mKidXMost already has the left border factored in - //maxWidth = aState.mKidXMost + borderPadding.right; - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - else { - // Add in border and padding dimensions to already computed - // max-element-size values. - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - if (computedWidth < maxWidth) { - computedWidth = maxWidth; - } - } - - // Apply min/max values - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { - nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + // See if we should compute our max element size + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Adjust the computedWidth + if (aState.GetFlag(BRS_NOWRAP)) { + // When no-wrap is true the max-element-size.width is the + // width of the widest line plus the right border. Note that + // aState.mKidXMost already has the left border factored in + //maxWidth = aState.mKidXMost + borderPadding.right; + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth > computedMaxWidth) { - computedWidth = computedMaxWidth; - } } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { - nscoord computedMinWidth = aReflowState.mComputedMinWidth + + else { + // Add in border and padding dimensions to already computed + // max-element-size values. + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth < computedMinWidth) { - computedWidth = computedMinWidth; - } } - aMetrics.width = computedWidth; - - // If we're shrink wrapping, then now that we know our final width we - // need to do horizontal alignment of the inline lines and make sure - // blocks are correctly sized and positioned. Any lines that need - // final adjustment will have been marked as dirty - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { - // If the parent reflow state is also shrink wrap width, then - // we don't need to do this, because it will reflow us after it - // calculates the final width - PRBool parentIsShrinkWrapWidth = PR_FALSE; - if (aReflowState.parentReflowState) { - if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { - parentIsShrinkWrapWidth = PR_TRUE; - } - } - - if (!parentIsShrinkWrapWidth) { - nsHTMLReflowState reflowState(aReflowState); - - reflowState.mComputedWidth = aMetrics.width - borderPadding.left - - borderPadding.right; - reflowState.reason = eReflowReason_Resize; - reflowState.mSpaceManager->ClearRegions(); - - nscoord oldDesiredWidth = aMetrics.width; - nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, - NS_BLOCK_MARGIN_ROOT & mState); - ReflowDirtyLines(state); - aState.mY = state.mY; - NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); - } + if (computedWidth < maxWidth) { + computedWidth = maxWidth; } } - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + // Apply min/max values + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { + nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + borderPadding.left + borderPadding.right; + if (computedWidth > computedMaxWidth) { + computedWidth = computedMaxWidth; + } + } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { + nscoord computedMinWidth = aReflowState.mComputedMinWidth + + borderPadding.left + borderPadding.right; + if (computedWidth < computedMinWidth) { + computedWidth = computedMinWidth; + } + } + aMetrics.width = computedWidth; + + // If we're shrink wrapping, then now that we know our final width we + // need to do horizontal alignment of the inline lines and make sure + // blocks are correctly sized and positioned. Any lines that need + // final adjustment will have been marked as dirty + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { + // If the parent reflow state is also shrink wrap width, then + // we don't need to do this, because it will reflow us after it + // calculates the final width PRBool parentIsShrinkWrapWidth = PR_FALSE; if (aReflowState.parentReflowState) { if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { parentIsShrinkWrapWidth = PR_TRUE; } } - } - // Compute final height - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - // Use style defined height - aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + - borderPadding.bottom; + if (!parentIsShrinkWrapWidth) { + nsHTMLReflowState reflowState(aReflowState); - // When style defines the height use it for the max-element-size - // because we can't shrink any smaller. - maxHeight = aMetrics.height; + reflowState.mComputedWidth = aMetrics.width - borderPadding.left - + borderPadding.right; + reflowState.reason = eReflowReason_Resize; + reflowState.mSpaceManager->ClearRegions(); - // Don't carry out a bottom margin when our height is fixed - // unless the bottom of the last line adjoins the bottom of our - // content area. - if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { - aState.mPrevBottomMargin = 0; - } + nscoord oldDesiredWidth = aMetrics.width; + nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, + NS_BLOCK_MARGIN_ROOT & mState); + ReflowDirtyLines(state); + aState.mY = state.mY; + NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); } } - else { - nscoord autoHeight = aState.mY; + } - // Shrink wrap our height around our contents. - if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. - // XXX check for a fit - autoHeight += aState.mPrevBottomMargin; + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + PRBool parentIsShrinkWrapWidth = PR_FALSE; + if (aReflowState.parentReflowState) { + if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { + parentIsShrinkWrapWidth = PR_TRUE; } - autoHeight += borderPadding.bottom; + } + } - // Apply min/max values + // Compute final height + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { + // Use style defined height + aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + + borderPadding.bottom; + + // When style defines the height use it for the max-element-size + // because we can't shrink any smaller. + maxHeight = aMetrics.height; + + // Don't carry out a bottom margin when our height is fixed + // unless the bottom of the last line adjoins the bottom of our + // content area. + if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { + aState.mPrevBottomMargin = 0; + } + } + } + else { + nscoord autoHeight = aState.mY; + + // Shrink wrap our height around our contents. + if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + // When we are a bottom-margin root make sure that our last + // childs bottom margin is fully applied. + // XXX check for a fit + autoHeight += aState.mPrevBottomMargin; + } + autoHeight += borderPadding.bottom; + + // Apply min/max values #ifdef MOZ_MATHML - // XXX Here in ComputeFinalSize() - // XXX What to do when min/max values are applied to the height? - // How do all this impact on the first line of the block? + // XXX Here in ComputeFinalSize() + // XXX What to do when min/max values are applied to the height? + // How do all this impact on the first line of the block? #endif - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { - nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight > computedMaxHeight) { - autoHeight = computedMaxHeight; - } - } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { - nscoord computedMinHeight = aReflowState.mComputedMinHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight < computedMinHeight) { - autoHeight = computedMinHeight; - } - } - aMetrics.height = autoHeight; - - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - maxHeight = aState.mMaxElementSize.height + - borderPadding.top + borderPadding.bottom; + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { + nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight > computedMaxHeight) { + autoHeight = computedMaxHeight; } } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { + nscoord computedMinHeight = aReflowState.mComputedMinHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight < computedMinHeight) { + autoHeight = computedMinHeight; + } + } + aMetrics.height = autoHeight; + + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + maxHeight = aState.mMaxElementSize.height + + borderPadding.top + borderPadding.bottom; + } + } #ifndef MOZ_MATHML - aMetrics.ascent = aMetrics.height; - aMetrics.descent = 0; + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; #else - if (mLines && mLines->mFirstChild && mLines->IsBlock()) { - // mAscent is not yet set because we didn't call VerticalAlignFrames() - // on mLines. So we need to fetch the ascent of the first child of mLines - nsBlockFrame* bf; - nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); - if (NS_SUCCEEDED(res) && bf) { - mAscent = bf->GetAscent(); - } + if (mLines && mLines->mFirstChild && mLines->IsBlock()) { + // mAscent is not yet set because we didn't call VerticalAlignFrames() + // on mLines. So we need to fetch the ascent of the first child of mLines + nsBlockFrame* bf; + nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); + if (NS_SUCCEEDED(res) && bf) { + mAscent = bf->GetAscent(); } - aMetrics.ascent = mAscent; - aMetrics.descent = aMetrics.height - aMetrics.ascent; + } + aMetrics.ascent = mAscent; + aMetrics.descent = aMetrics.height - aMetrics.ascent; #endif - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Store away the final value - aMetrics.maxElementSize->width = maxWidth; - aMetrics.maxElementSize->height = maxHeight; + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Store away the final value + aMetrics.maxElementSize->width = maxWidth; + aMetrics.maxElementSize->height = maxHeight; #ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p returning MES %d\n", - this, aMetrics.maxElementSize->width); -#endif - } - - // Return bottom margin information - aMetrics.mCarriedOutBottomMargin = - aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; - -#ifdef DEBUG_blocks - if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { - ListTag(stdout); - printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); - } - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && - ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { - ListTag(stdout); - printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } -#endif -#ifdef NOISY_MAX_ELEMENT_SIZE - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - IndentBy(stdout, GetDepth()); - if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { - printf("PASS1 "); - } - ListTag(stdout); - printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } + printf ("nsBlockFrame::CFS: %p returning MES %d\n", + this, aMetrics.maxElementSize->width); #endif } + // Return bottom margin information + aMetrics.mCarriedOutBottomMargin = + aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; + +#ifdef DEBUG_blocks + if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { + ListTag(stdout); + printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); + } + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && + ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { + ListTag(stdout); + printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif +#ifdef NOISY_MAX_ELEMENT_SIZE + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + IndentBy(stdout, GetDepth()); + if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { + printf("PASS1 "); + } + ListTag(stdout); + printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif + // If we're requested to update our maximum width, then compute it if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) { // We need to add in for the right border/padding @@ -4038,15 +3990,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n", aState.mPrevBottomMargin, collapsedBottomMargin); #endif - if (collapsedBottomMargin >= 0) { - aState.mPrevBottomMargin = collapsedBottomMargin; - } - else { - // Leave margin alone: it was a collapsed paragraph that - // must not interfere with the running margin calculations - // (in other words it should act like an empty line of - // whitespace). - } + aState.mPrevBottomMargin = collapsedBottomMargin; } #ifdef NOISY_VERTICAL_MARGINS ListTag(stdout); @@ -6889,9 +6833,6 @@ nsBlockFrame::Init(nsIPresContext* aPresContext, nsresult rv = nsBlockFrameSuper::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - if (nsBlockReflowContext::IsHTMLParagraph(this)) { - mState |= NS_BLOCK_IS_HTML_PARAGRAPH; - } return rv; } diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h index a8496f69f8c..82107ed212a 100644 --- a/mozilla/layout/generic/nsBlockFrame.h +++ b/mozilla/layout/generic/nsBlockFrame.h @@ -45,8 +45,7 @@ class nsFirstLineFrame; * Additional frame-state bits. There are more of these bits * defined in nsHTMLParts.h (XXX: note: this should be cleaned up) */ -#define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x80000000 -#define NS_BLOCK_IS_HTML_PARAGRAPH 0x40000000 +#define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x40000000 #define NS_BLOCK_HAS_FIRST_LETTER_STYLE 0x20000000 #define nsBlockFrameSuper nsHTMLContainerFrame diff --git a/mozilla/layout/generic/nsBlockReflowContext.cpp b/mozilla/layout/generic/nsBlockReflowContext.cpp index 26343e1b0d2..5fd8d66c6b6 100644 --- a/mozilla/layout/generic/nsBlockReflowContext.cpp +++ b/mozilla/layout/generic/nsBlockReflowContext.cpp @@ -30,7 +30,6 @@ #include "nsIReflowCommand.h" #include "nsHTMLContainerFrame.h" #include "nsBlockFrame.h" -#include "nsIDOMHTMLParagraphElement.h" #include "nsIDOMHTMLTableCellElement.h" #include "nsIDOMHTMLBodyElement.h" #include "nsLayoutAtoms.h" @@ -63,58 +62,6 @@ nsBlockReflowContext::nsBlockReflowContext(nsIPresContext* aPresContext, mMetrics.mFlags |= NS_REFLOW_CALC_MAX_WIDTH; } -PRBool -nsBlockReflowContext::IsHTMLParagraph(nsIFrame* aFrame) -{ - PRBool result = PR_FALSE; - nsCOMPtr content; - nsresult rv = aFrame->GetContent(getter_AddRefs(content)); - if (NS_SUCCEEDED(rv) && content) { - nsCOMPtr p(do_QueryInterface(content)); - if (p) { - result = PR_TRUE; - } - } - return result; -} - - -PRBool -nsBlockReflowContext::IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const -{ - NS_ASSERTION(aParentFrame && aChildFrame, "bad args"); - if (!aParentFrame || !aChildFrame) return PR_FALSE; - nsIFrame *child; - aParentFrame->FirstChild((nsIPresContext *)(&mPresContext), nsnull, &child); - while (child) - { - if (aChildFrame == child) { - return PR_TRUE; // we found aChildFrame, and we haven't yet encountered a geometrically significant frame - } - nsSize size; - child->GetSize(size); - if (size.width || size.height) { - return PR_FALSE; // we found a geometrically significant frame and it wasn't aChildFrame - } - child->GetNextSibling(&child); - } - return PR_FALSE; //aChildFrame is not in the default child list of aParentFrame -} - -PRBool IsCollapsingBlockParentFrame(const nsIFrame* aFrame) -{ - if (!aFrame) return PR_FALSE; - nsCOMPtr frameType; - aFrame->GetFrameType(getter_AddRefs(frameType)); - if (frameType.get()==nsLayoutAtoms::blockFrame || - frameType.get()==nsLayoutAtoms::areaFrame || - frameType.get()==nsLayoutAtoms::tableCellFrame || - frameType.get()==nsLayoutAtoms::tableCaptionFrame) { - return PR_TRUE; - } - return PR_FALSE; -} - nscoord nsBlockReflowContext::ComputeCollapsedTopMargin(nsIPresContext* aPresContext, nsHTMLReflowState& aRS) @@ -125,26 +72,35 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(nsIPresContext* aPresContext, // Calculate aFrame's generational top-margin from its child // blocks. Note that if aFrame has a non-zero top-border or // top-padding then this step is skipped because it will be a margin - // root. + // root. It is also skipped if the frame is a margin root for other + // reasons. nscoord generationalTopMargin = 0; if (0 == aRS.mComputedBorderPadding.top) { - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf))) { - // Ask the block frame for the top block child that we should - // try to collapse the top margin with. - nsIFrame* childFrame = bf->GetTopBlockChild(); - if (nsnull != childFrame) { + nsFrameState state; + aRS.frame->GetFrameState(&state); + if (!(state & NS_BLOCK_MARGIN_ROOT)) { + nsBlockFrame* bf; + if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf))) { + // Ask the block frame for the top block child that we should + // try to collapse the top margin with. - // Here is where we recurse. Now that we have determined that a - // generational collapse is required we need to compute the - // child blocks margin and so in so that we can look into - // it. For its margins to be computed we need to have a reflow - // state for it. - nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight); - nsHTMLReflowState reflowState(aPresContext, aRS, childFrame, - availSpace); - generationalTopMargin = - ComputeCollapsedTopMargin(aPresContext, reflowState); + // XXX If the block is empty, we need to check its bottom margin + // and its sibling's top margin (etc.) too! + + nsIFrame* childFrame = bf->GetTopBlockChild(); + if (nsnull != childFrame) { + + // Here is where we recurse. Now that we have determined that a + // generational collapse is required we need to compute the + // child blocks margin and so in so that we can look into + // it. For its margins to be computed we need to have a reflow + // state for it. + nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight); + nsHTMLReflowState reflowState(aPresContext, aRS, childFrame, + availSpace); + generationalTopMargin = + ComputeCollapsedTopMargin(aPresContext, reflowState); + } } } } @@ -736,53 +692,22 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool fits = PR_TRUE; nscoord x = mX; nscoord y = mY; - // When deciding whether it's an empty paragraph we also need to take into + // When deciding whether it's empty we also need to take into // account the overflow area if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height)) { - PRBool handled = PR_FALSE; - if (IsHTMLParagraph(mFrame)) { - // Special "feature" for HTML compatability - empty paragraphs - // collapse into nothingness, including their margins. Signal - // the special nature here by returning -1. - // In general, we turn off this behavior due to re-interpretation of the vague HTML 4 spec. - // See bug 35772. However, we do need this behavior for

inside of table cells, - // floaters, and positioned elements - nsIFrame *parent; - mFrame->GetParent(&parent); - if (parent) - { - if (IsCollapsingBlockParentFrame(mFrame) && - IsFirstSignificantChild(parent, mFrame)) - { - handled = PR_TRUE; - *aBottomMarginResult = -1; + // Collapse the bottom margin with the top margin that was already + // applied. + nscoord newBottomMargin = MaxMargin(collapsedBottomMargin, mTopMargin); + *aBottomMarginResult = newBottomMargin; #ifdef NOISY_VERTICAL_MARGINS - printf(" "); - nsFrame::ListTag(stdout, mOuterReflowState.frame); - printf(": "); - nsFrame::ListTag(stdout, mFrame); - printf(" -- zapping top & bottom margin; y=%d spaceY=%d\n", - y, mSpace.y); + printf(" "); + nsFrame::ListTag(stdout, mOuterReflowState.frame); + printf(": "); + nsFrame::ListTag(stdout, mFrame); + printf(" -- collapsing top & bottom margin together; y=%d spaceY=%d\n", + y, mSpace.y); #endif - } - } - } - if (!handled) - { - // Collapse the bottom margin with the top margin that was already - // applied. - nscoord newBottomMargin = MaxMargin(collapsedBottomMargin, mTopMargin); - *aBottomMarginResult = newBottomMargin; -#ifdef NOISY_VERTICAL_MARGINS - printf(" "); - nsFrame::ListTag(stdout, mOuterReflowState.frame); - printf(": "); - nsFrame::ListTag(stdout, mFrame); - printf(" -- collapsing top & bottom margin together; y=%d spaceY=%d\n", - y, mSpace.y); -#endif - } y = mSpace.y; @@ -805,22 +730,6 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // fits. if (aForceFit || (y + mMetrics.height <= mSpace.YMost())) { - // if it's a

and it's parent is special, then collapse the

's top margin - if (IsHTMLParagraph(mFrame)) { - // Special "feature" for HTML compatability - a paragraph's - // top margin collapses into nothingness, inside of certain containers. - nsIFrame *parent; - mFrame->GetParent(&parent); - if (parent) - { - if (IsCollapsingBlockParentFrame(mFrame) && - IsFirstSignificantChild(parent, mFrame)) - { - y=0; - } - } - } - // Calculate the actual x-offset and left and right margin nsBlockHorizontalAlign align; diff --git a/mozilla/layout/generic/nsBlockReflowContext.h b/mozilla/layout/generic/nsBlockReflowContext.h index 42975993919..308abd13c38 100644 --- a/mozilla/layout/generic/nsBlockReflowContext.h +++ b/mozilla/layout/generic/nsBlockReflowContext.h @@ -112,14 +112,6 @@ public: return b; } - static PRBool IsHTMLParagraph(nsIFrame* aFrame); - - /** return PR_TRUE if aChildFrame is the first geometrically significant child of aParentFrame - * to be considered significant, a frame must have both width and height != 0 - * if aChildFrame is not in the default child list of aParentFrame, we return PR_FALSE - */ - PRBool IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const; - static nscoord ComputeCollapsedTopMargin(nsIPresContext* aPresContext, nsHTMLReflowState& aRS); diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp index 5d777fc69d9..3956f2e2a74 100644 --- a/mozilla/layout/generic/nsBlockReflowState.cpp +++ b/mozilla/layout/generic/nsBlockReflowState.cpp @@ -57,9 +57,6 @@ #include "prenv.h" #include "plstr.h" -// XXX HTML:P's that are empty yet have style indicating they should -// clear floaters - we need to ignore the clear behavior. - #ifdef DEBUG static PRBool gLamePaintMetrics; @@ -1045,22 +1042,16 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine, aLine->GetCombinedArea(&lineCombinedArea); if (aLine->IsBlock()) { if ((0 == aLine->mBounds.height) && (0 == lineCombinedArea.height)) { - if (nsBlockReflowContext::IsHTMLParagraph(aLine->mFirstChild)) { - // Empty HTML paragraphs disappear entirely - their margins go - // to zero. Therefore we leave mPrevBottomMargin alone. - } - else { - // The line's top and bottom margin values need to be collapsed - // with the mPrevBottomMargin to determine a new - // mPrevBottomMargin value. - nscoord topMargin, bottomMargin; - RecoverVerticalMargins(aLine, aApplyTopMargin, - &topMargin, &bottomMargin); - nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, - mPrevBottomMargin); - m = nsBlockReflowContext::MaxMargin(m, topMargin); - mPrevBottomMargin = m; - } + // The line's top and bottom margin values need to be collapsed + // with the mPrevBottomMargin to determine a new + // mPrevBottomMargin value. + nscoord topMargin, bottomMargin; + RecoverVerticalMargins(aLine, aApplyTopMargin, + &topMargin, &bottomMargin); + nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, + mPrevBottomMargin); + m = nsBlockReflowContext::MaxMargin(m, topMargin); + mPrevBottomMargin = m; } else { // Recover the top and bottom margins for this line @@ -2097,294 +2088,255 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, borderPadding.top, borderPadding.bottom); #endif - // Special check for zero sized content: If our content is zero - // sized then we collapse into nothingness. - // - // Consensus after discussion with a few CSS folks is that html's - // notion of collapsing

's should take precedence over non - // auto-sided block elements. Therefore we don't honor the width, - // height, border or padding attributes (the parent has to not apply - // a margin for us also). - // - // Note that this is only done for html paragraphs. Its not - // appropriate to apply it to other containers, especially XML - // content! - PRBool isHTMLParagraph = 0 != (mState & NS_BLOCK_IS_HTML_PARAGRAPH); - if (isHTMLParagraph && - (aReflowState.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_BLOCK) && - (((0 == aState.mKidXMost) || - (0 == aState.mKidXMost - borderPadding.left)) && - (0 == aState.mY - borderPadding.top))) { - // Zero out most everything - aMetrics.width = 0; - aMetrics.height = 0; - aMetrics.ascent = 0; - aMetrics.descent = 0; - aMetrics.mCarriedOutBottomMargin = 0; - - // Note: Don't zero out the max-element-sizes: they will be zero - // if this is truly empty, otherwise they won't because of a - // floater. - if (nsnull != aMetrics.maxElementSize) { - aMetrics.maxElementSize->width = aState.mMaxElementSize.width; - aMetrics.maxElementSize->height = aState.mMaxElementSize.height; -#ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p initially setting MES %d\n", - this, aState.mMaxElementSize.width); + // Compute final width + nscoord maxWidth = 0, maxHeight = 0; +#ifdef NOISY_KIDXMOST + printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif + nscoord minWidth = aState.mKidXMost + borderPadding.right; + if (!HaveAutoWidth(aReflowState)) { + // Use style defined width + aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + + borderPadding.right; + // XXX quote css1 section here + if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { + aMetrics.width = minWidth; } + + // When style defines the width use it for the max-element-size + // because we can't shrink any smaller. + maxWidth = aMetrics.width; } else { - // Compute final width - nscoord maxWidth = 0, maxHeight = 0; -#ifdef NOISY_KIDXMOST - printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); -#endif - nscoord minWidth = aState.mKidXMost + borderPadding.right; - if (!HaveAutoWidth(aReflowState)) { - // Use style defined width - aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + - borderPadding.right; - // XXX quote css1 section here - if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { - aMetrics.width = minWidth; - } - - // When style defines the width use it for the max-element-size - // because we can't shrink any smaller. - maxWidth = aMetrics.width; - } - else { - nscoord computedWidth = minWidth; - PRBool compact = PR_FALSE; + nscoord computedWidth = minWidth; + PRBool compact = PR_FALSE; #if 0 - if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { - // If we are display: compact AND we have no lines or we have - // exactly one line and that line is not a block line AND that - // line doesn't end in a BR of any sort THEN we remain a compact - // frame. - if ((nsnull == mLines) || - ((nsnull == mLines->mNext) && !mLines->IsBlock() && - (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) - /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ - )) { - compact = PR_TRUE; - } + if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { + // If we are display: compact AND we have no lines or we have + // exactly one line and that line is not a block line AND that + // line doesn't end in a BR of any sort THEN we remain a compact + // frame. + if ((nsnull == mLines) || + ((nsnull == mLines->mNext) && !mLines->IsBlock() && + (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) + /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ + )) { + compact = PR_TRUE; } + } #endif - // There are two options here. We either shrink wrap around our - // contents or we fluff out to the maximum block width. Note: - // We always shrink wrap when given an unconstrained width. - if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && - !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && - !compact) { - // Set our width to the max width if we aren't already that - // wide. Note that the max-width has nothing to do with our - // contents (CSS2 section XXX) - computedWidth = borderPadding.left + aState.mContentArea.width + - borderPadding.right; - } + // There are two options here. We either shrink wrap around our + // contents or we fluff out to the maximum block width. Note: + // We always shrink wrap when given an unconstrained width. + if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && + !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && + !compact) { + // Set our width to the max width if we aren't already that + // wide. Note that the max-width has nothing to do with our + // contents (CSS2 section XXX) + computedWidth = borderPadding.left + aState.mContentArea.width + + borderPadding.right; + } - // See if we should compute our max element size - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Adjust the computedWidth - if (aState.GetFlag(BRS_NOWRAP)) { - // When no-wrap is true the max-element-size.width is the - // width of the widest line plus the right border. Note that - // aState.mKidXMost already has the left border factored in - //maxWidth = aState.mKidXMost + borderPadding.right; - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - else { - // Add in border and padding dimensions to already computed - // max-element-size values. - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - if (computedWidth < maxWidth) { - computedWidth = maxWidth; - } - } - - // Apply min/max values - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { - nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + // See if we should compute our max element size + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Adjust the computedWidth + if (aState.GetFlag(BRS_NOWRAP)) { + // When no-wrap is true the max-element-size.width is the + // width of the widest line plus the right border. Note that + // aState.mKidXMost already has the left border factored in + //maxWidth = aState.mKidXMost + borderPadding.right; + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth > computedMaxWidth) { - computedWidth = computedMaxWidth; - } } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { - nscoord computedMinWidth = aReflowState.mComputedMinWidth + + else { + // Add in border and padding dimensions to already computed + // max-element-size values. + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth < computedMinWidth) { - computedWidth = computedMinWidth; - } } - aMetrics.width = computedWidth; - - // If we're shrink wrapping, then now that we know our final width we - // need to do horizontal alignment of the inline lines and make sure - // blocks are correctly sized and positioned. Any lines that need - // final adjustment will have been marked as dirty - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { - // If the parent reflow state is also shrink wrap width, then - // we don't need to do this, because it will reflow us after it - // calculates the final width - PRBool parentIsShrinkWrapWidth = PR_FALSE; - if (aReflowState.parentReflowState) { - if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { - parentIsShrinkWrapWidth = PR_TRUE; - } - } - - if (!parentIsShrinkWrapWidth) { - nsHTMLReflowState reflowState(aReflowState); - - reflowState.mComputedWidth = aMetrics.width - borderPadding.left - - borderPadding.right; - reflowState.reason = eReflowReason_Resize; - reflowState.mSpaceManager->ClearRegions(); - - nscoord oldDesiredWidth = aMetrics.width; - nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, - NS_BLOCK_MARGIN_ROOT & mState); - ReflowDirtyLines(state); - aState.mY = state.mY; - NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); - } + if (computedWidth < maxWidth) { + computedWidth = maxWidth; } } - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + // Apply min/max values + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { + nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + borderPadding.left + borderPadding.right; + if (computedWidth > computedMaxWidth) { + computedWidth = computedMaxWidth; + } + } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { + nscoord computedMinWidth = aReflowState.mComputedMinWidth + + borderPadding.left + borderPadding.right; + if (computedWidth < computedMinWidth) { + computedWidth = computedMinWidth; + } + } + aMetrics.width = computedWidth; + + // If we're shrink wrapping, then now that we know our final width we + // need to do horizontal alignment of the inline lines and make sure + // blocks are correctly sized and positioned. Any lines that need + // final adjustment will have been marked as dirty + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { + // If the parent reflow state is also shrink wrap width, then + // we don't need to do this, because it will reflow us after it + // calculates the final width PRBool parentIsShrinkWrapWidth = PR_FALSE; if (aReflowState.parentReflowState) { if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { parentIsShrinkWrapWidth = PR_TRUE; } } - } - // Compute final height - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - // Use style defined height - aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + - borderPadding.bottom; + if (!parentIsShrinkWrapWidth) { + nsHTMLReflowState reflowState(aReflowState); - // When style defines the height use it for the max-element-size - // because we can't shrink any smaller. - maxHeight = aMetrics.height; + reflowState.mComputedWidth = aMetrics.width - borderPadding.left - + borderPadding.right; + reflowState.reason = eReflowReason_Resize; + reflowState.mSpaceManager->ClearRegions(); - // Don't carry out a bottom margin when our height is fixed - // unless the bottom of the last line adjoins the bottom of our - // content area. - if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { - aState.mPrevBottomMargin = 0; - } + nscoord oldDesiredWidth = aMetrics.width; + nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, + NS_BLOCK_MARGIN_ROOT & mState); + ReflowDirtyLines(state); + aState.mY = state.mY; + NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); } } - else { - nscoord autoHeight = aState.mY; + } - // Shrink wrap our height around our contents. - if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. - // XXX check for a fit - autoHeight += aState.mPrevBottomMargin; + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + PRBool parentIsShrinkWrapWidth = PR_FALSE; + if (aReflowState.parentReflowState) { + if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { + parentIsShrinkWrapWidth = PR_TRUE; } - autoHeight += borderPadding.bottom; + } + } - // Apply min/max values + // Compute final height + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { + // Use style defined height + aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + + borderPadding.bottom; + + // When style defines the height use it for the max-element-size + // because we can't shrink any smaller. + maxHeight = aMetrics.height; + + // Don't carry out a bottom margin when our height is fixed + // unless the bottom of the last line adjoins the bottom of our + // content area. + if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { + aState.mPrevBottomMargin = 0; + } + } + } + else { + nscoord autoHeight = aState.mY; + + // Shrink wrap our height around our contents. + if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + // When we are a bottom-margin root make sure that our last + // childs bottom margin is fully applied. + // XXX check for a fit + autoHeight += aState.mPrevBottomMargin; + } + autoHeight += borderPadding.bottom; + + // Apply min/max values #ifdef MOZ_MATHML - // XXX Here in ComputeFinalSize() - // XXX What to do when min/max values are applied to the height? - // How do all this impact on the first line of the block? + // XXX Here in ComputeFinalSize() + // XXX What to do when min/max values are applied to the height? + // How do all this impact on the first line of the block? #endif - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { - nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight > computedMaxHeight) { - autoHeight = computedMaxHeight; - } - } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { - nscoord computedMinHeight = aReflowState.mComputedMinHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight < computedMinHeight) { - autoHeight = computedMinHeight; - } - } - aMetrics.height = autoHeight; - - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - maxHeight = aState.mMaxElementSize.height + - borderPadding.top + borderPadding.bottom; + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { + nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight > computedMaxHeight) { + autoHeight = computedMaxHeight; } } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { + nscoord computedMinHeight = aReflowState.mComputedMinHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight < computedMinHeight) { + autoHeight = computedMinHeight; + } + } + aMetrics.height = autoHeight; + + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + maxHeight = aState.mMaxElementSize.height + + borderPadding.top + borderPadding.bottom; + } + } #ifndef MOZ_MATHML - aMetrics.ascent = aMetrics.height; - aMetrics.descent = 0; + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; #else - if (mLines && mLines->mFirstChild && mLines->IsBlock()) { - // mAscent is not yet set because we didn't call VerticalAlignFrames() - // on mLines. So we need to fetch the ascent of the first child of mLines - nsBlockFrame* bf; - nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); - if (NS_SUCCEEDED(res) && bf) { - mAscent = bf->GetAscent(); - } + if (mLines && mLines->mFirstChild && mLines->IsBlock()) { + // mAscent is not yet set because we didn't call VerticalAlignFrames() + // on mLines. So we need to fetch the ascent of the first child of mLines + nsBlockFrame* bf; + nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); + if (NS_SUCCEEDED(res) && bf) { + mAscent = bf->GetAscent(); } - aMetrics.ascent = mAscent; - aMetrics.descent = aMetrics.height - aMetrics.ascent; + } + aMetrics.ascent = mAscent; + aMetrics.descent = aMetrics.height - aMetrics.ascent; #endif - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Store away the final value - aMetrics.maxElementSize->width = maxWidth; - aMetrics.maxElementSize->height = maxHeight; + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Store away the final value + aMetrics.maxElementSize->width = maxWidth; + aMetrics.maxElementSize->height = maxHeight; #ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p returning MES %d\n", - this, aMetrics.maxElementSize->width); -#endif - } - - // Return bottom margin information - aMetrics.mCarriedOutBottomMargin = - aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; - -#ifdef DEBUG_blocks - if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { - ListTag(stdout); - printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); - } - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && - ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { - ListTag(stdout); - printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } -#endif -#ifdef NOISY_MAX_ELEMENT_SIZE - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - IndentBy(stdout, GetDepth()); - if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { - printf("PASS1 "); - } - ListTag(stdout); - printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } + printf ("nsBlockFrame::CFS: %p returning MES %d\n", + this, aMetrics.maxElementSize->width); #endif } + // Return bottom margin information + aMetrics.mCarriedOutBottomMargin = + aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; + +#ifdef DEBUG_blocks + if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { + ListTag(stdout); + printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); + } + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && + ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { + ListTag(stdout); + printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif +#ifdef NOISY_MAX_ELEMENT_SIZE + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + IndentBy(stdout, GetDepth()); + if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { + printf("PASS1 "); + } + ListTag(stdout); + printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif + // If we're requested to update our maximum width, then compute it if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) { // We need to add in for the right border/padding @@ -4038,15 +3990,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n", aState.mPrevBottomMargin, collapsedBottomMargin); #endif - if (collapsedBottomMargin >= 0) { - aState.mPrevBottomMargin = collapsedBottomMargin; - } - else { - // Leave margin alone: it was a collapsed paragraph that - // must not interfere with the running margin calculations - // (in other words it should act like an empty line of - // whitespace). - } + aState.mPrevBottomMargin = collapsedBottomMargin; } #ifdef NOISY_VERTICAL_MARGINS ListTag(stdout); @@ -6889,9 +6833,6 @@ nsBlockFrame::Init(nsIPresContext* aPresContext, nsresult rv = nsBlockFrameSuper::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - if (nsBlockReflowContext::IsHTMLParagraph(this)) { - mState |= NS_BLOCK_IS_HTML_PARAGRAPH; - } return rv; } diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h index 5d777fc69d9..3956f2e2a74 100644 --- a/mozilla/layout/generic/nsBlockReflowState.h +++ b/mozilla/layout/generic/nsBlockReflowState.h @@ -57,9 +57,6 @@ #include "prenv.h" #include "plstr.h" -// XXX HTML:P's that are empty yet have style indicating they should -// clear floaters - we need to ignore the clear behavior. - #ifdef DEBUG static PRBool gLamePaintMetrics; @@ -1045,22 +1042,16 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine, aLine->GetCombinedArea(&lineCombinedArea); if (aLine->IsBlock()) { if ((0 == aLine->mBounds.height) && (0 == lineCombinedArea.height)) { - if (nsBlockReflowContext::IsHTMLParagraph(aLine->mFirstChild)) { - // Empty HTML paragraphs disappear entirely - their margins go - // to zero. Therefore we leave mPrevBottomMargin alone. - } - else { - // The line's top and bottom margin values need to be collapsed - // with the mPrevBottomMargin to determine a new - // mPrevBottomMargin value. - nscoord topMargin, bottomMargin; - RecoverVerticalMargins(aLine, aApplyTopMargin, - &topMargin, &bottomMargin); - nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, - mPrevBottomMargin); - m = nsBlockReflowContext::MaxMargin(m, topMargin); - mPrevBottomMargin = m; - } + // The line's top and bottom margin values need to be collapsed + // with the mPrevBottomMargin to determine a new + // mPrevBottomMargin value. + nscoord topMargin, bottomMargin; + RecoverVerticalMargins(aLine, aApplyTopMargin, + &topMargin, &bottomMargin); + nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, + mPrevBottomMargin); + m = nsBlockReflowContext::MaxMargin(m, topMargin); + mPrevBottomMargin = m; } else { // Recover the top and bottom margins for this line @@ -2097,294 +2088,255 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, borderPadding.top, borderPadding.bottom); #endif - // Special check for zero sized content: If our content is zero - // sized then we collapse into nothingness. - // - // Consensus after discussion with a few CSS folks is that html's - // notion of collapsing

's should take precedence over non - // auto-sided block elements. Therefore we don't honor the width, - // height, border or padding attributes (the parent has to not apply - // a margin for us also). - // - // Note that this is only done for html paragraphs. Its not - // appropriate to apply it to other containers, especially XML - // content! - PRBool isHTMLParagraph = 0 != (mState & NS_BLOCK_IS_HTML_PARAGRAPH); - if (isHTMLParagraph && - (aReflowState.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_BLOCK) && - (((0 == aState.mKidXMost) || - (0 == aState.mKidXMost - borderPadding.left)) && - (0 == aState.mY - borderPadding.top))) { - // Zero out most everything - aMetrics.width = 0; - aMetrics.height = 0; - aMetrics.ascent = 0; - aMetrics.descent = 0; - aMetrics.mCarriedOutBottomMargin = 0; - - // Note: Don't zero out the max-element-sizes: they will be zero - // if this is truly empty, otherwise they won't because of a - // floater. - if (nsnull != aMetrics.maxElementSize) { - aMetrics.maxElementSize->width = aState.mMaxElementSize.width; - aMetrics.maxElementSize->height = aState.mMaxElementSize.height; -#ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p initially setting MES %d\n", - this, aState.mMaxElementSize.width); + // Compute final width + nscoord maxWidth = 0, maxHeight = 0; +#ifdef NOISY_KIDXMOST + printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif + nscoord minWidth = aState.mKidXMost + borderPadding.right; + if (!HaveAutoWidth(aReflowState)) { + // Use style defined width + aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + + borderPadding.right; + // XXX quote css1 section here + if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { + aMetrics.width = minWidth; } + + // When style defines the width use it for the max-element-size + // because we can't shrink any smaller. + maxWidth = aMetrics.width; } else { - // Compute final width - nscoord maxWidth = 0, maxHeight = 0; -#ifdef NOISY_KIDXMOST - printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); -#endif - nscoord minWidth = aState.mKidXMost + borderPadding.right; - if (!HaveAutoWidth(aReflowState)) { - // Use style defined width - aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + - borderPadding.right; - // XXX quote css1 section here - if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { - aMetrics.width = minWidth; - } - - // When style defines the width use it for the max-element-size - // because we can't shrink any smaller. - maxWidth = aMetrics.width; - } - else { - nscoord computedWidth = minWidth; - PRBool compact = PR_FALSE; + nscoord computedWidth = minWidth; + PRBool compact = PR_FALSE; #if 0 - if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { - // If we are display: compact AND we have no lines or we have - // exactly one line and that line is not a block line AND that - // line doesn't end in a BR of any sort THEN we remain a compact - // frame. - if ((nsnull == mLines) || - ((nsnull == mLines->mNext) && !mLines->IsBlock() && - (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) - /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ - )) { - compact = PR_TRUE; - } + if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { + // If we are display: compact AND we have no lines or we have + // exactly one line and that line is not a block line AND that + // line doesn't end in a BR of any sort THEN we remain a compact + // frame. + if ((nsnull == mLines) || + ((nsnull == mLines->mNext) && !mLines->IsBlock() && + (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) + /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ + )) { + compact = PR_TRUE; } + } #endif - // There are two options here. We either shrink wrap around our - // contents or we fluff out to the maximum block width. Note: - // We always shrink wrap when given an unconstrained width. - if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && - !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && - !compact) { - // Set our width to the max width if we aren't already that - // wide. Note that the max-width has nothing to do with our - // contents (CSS2 section XXX) - computedWidth = borderPadding.left + aState.mContentArea.width + - borderPadding.right; - } + // There are two options here. We either shrink wrap around our + // contents or we fluff out to the maximum block width. Note: + // We always shrink wrap when given an unconstrained width. + if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && + !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && + !compact) { + // Set our width to the max width if we aren't already that + // wide. Note that the max-width has nothing to do with our + // contents (CSS2 section XXX) + computedWidth = borderPadding.left + aState.mContentArea.width + + borderPadding.right; + } - // See if we should compute our max element size - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Adjust the computedWidth - if (aState.GetFlag(BRS_NOWRAP)) { - // When no-wrap is true the max-element-size.width is the - // width of the widest line plus the right border. Note that - // aState.mKidXMost already has the left border factored in - //maxWidth = aState.mKidXMost + borderPadding.right; - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - else { - // Add in border and padding dimensions to already computed - // max-element-size values. - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - if (computedWidth < maxWidth) { - computedWidth = maxWidth; - } - } - - // Apply min/max values - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { - nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + // See if we should compute our max element size + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Adjust the computedWidth + if (aState.GetFlag(BRS_NOWRAP)) { + // When no-wrap is true the max-element-size.width is the + // width of the widest line plus the right border. Note that + // aState.mKidXMost already has the left border factored in + //maxWidth = aState.mKidXMost + borderPadding.right; + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth > computedMaxWidth) { - computedWidth = computedMaxWidth; - } } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { - nscoord computedMinWidth = aReflowState.mComputedMinWidth + + else { + // Add in border and padding dimensions to already computed + // max-element-size values. + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth < computedMinWidth) { - computedWidth = computedMinWidth; - } } - aMetrics.width = computedWidth; - - // If we're shrink wrapping, then now that we know our final width we - // need to do horizontal alignment of the inline lines and make sure - // blocks are correctly sized and positioned. Any lines that need - // final adjustment will have been marked as dirty - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { - // If the parent reflow state is also shrink wrap width, then - // we don't need to do this, because it will reflow us after it - // calculates the final width - PRBool parentIsShrinkWrapWidth = PR_FALSE; - if (aReflowState.parentReflowState) { - if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { - parentIsShrinkWrapWidth = PR_TRUE; - } - } - - if (!parentIsShrinkWrapWidth) { - nsHTMLReflowState reflowState(aReflowState); - - reflowState.mComputedWidth = aMetrics.width - borderPadding.left - - borderPadding.right; - reflowState.reason = eReflowReason_Resize; - reflowState.mSpaceManager->ClearRegions(); - - nscoord oldDesiredWidth = aMetrics.width; - nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, - NS_BLOCK_MARGIN_ROOT & mState); - ReflowDirtyLines(state); - aState.mY = state.mY; - NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); - } + if (computedWidth < maxWidth) { + computedWidth = maxWidth; } } - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + // Apply min/max values + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { + nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + borderPadding.left + borderPadding.right; + if (computedWidth > computedMaxWidth) { + computedWidth = computedMaxWidth; + } + } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { + nscoord computedMinWidth = aReflowState.mComputedMinWidth + + borderPadding.left + borderPadding.right; + if (computedWidth < computedMinWidth) { + computedWidth = computedMinWidth; + } + } + aMetrics.width = computedWidth; + + // If we're shrink wrapping, then now that we know our final width we + // need to do horizontal alignment of the inline lines and make sure + // blocks are correctly sized and positioned. Any lines that need + // final adjustment will have been marked as dirty + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { + // If the parent reflow state is also shrink wrap width, then + // we don't need to do this, because it will reflow us after it + // calculates the final width PRBool parentIsShrinkWrapWidth = PR_FALSE; if (aReflowState.parentReflowState) { if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { parentIsShrinkWrapWidth = PR_TRUE; } } - } - // Compute final height - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - // Use style defined height - aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + - borderPadding.bottom; + if (!parentIsShrinkWrapWidth) { + nsHTMLReflowState reflowState(aReflowState); - // When style defines the height use it for the max-element-size - // because we can't shrink any smaller. - maxHeight = aMetrics.height; + reflowState.mComputedWidth = aMetrics.width - borderPadding.left - + borderPadding.right; + reflowState.reason = eReflowReason_Resize; + reflowState.mSpaceManager->ClearRegions(); - // Don't carry out a bottom margin when our height is fixed - // unless the bottom of the last line adjoins the bottom of our - // content area. - if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { - aState.mPrevBottomMargin = 0; - } + nscoord oldDesiredWidth = aMetrics.width; + nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, + NS_BLOCK_MARGIN_ROOT & mState); + ReflowDirtyLines(state); + aState.mY = state.mY; + NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); } } - else { - nscoord autoHeight = aState.mY; + } - // Shrink wrap our height around our contents. - if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. - // XXX check for a fit - autoHeight += aState.mPrevBottomMargin; + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + PRBool parentIsShrinkWrapWidth = PR_FALSE; + if (aReflowState.parentReflowState) { + if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { + parentIsShrinkWrapWidth = PR_TRUE; } - autoHeight += borderPadding.bottom; + } + } - // Apply min/max values + // Compute final height + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { + // Use style defined height + aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + + borderPadding.bottom; + + // When style defines the height use it for the max-element-size + // because we can't shrink any smaller. + maxHeight = aMetrics.height; + + // Don't carry out a bottom margin when our height is fixed + // unless the bottom of the last line adjoins the bottom of our + // content area. + if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { + aState.mPrevBottomMargin = 0; + } + } + } + else { + nscoord autoHeight = aState.mY; + + // Shrink wrap our height around our contents. + if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + // When we are a bottom-margin root make sure that our last + // childs bottom margin is fully applied. + // XXX check for a fit + autoHeight += aState.mPrevBottomMargin; + } + autoHeight += borderPadding.bottom; + + // Apply min/max values #ifdef MOZ_MATHML - // XXX Here in ComputeFinalSize() - // XXX What to do when min/max values are applied to the height? - // How do all this impact on the first line of the block? + // XXX Here in ComputeFinalSize() + // XXX What to do when min/max values are applied to the height? + // How do all this impact on the first line of the block? #endif - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { - nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight > computedMaxHeight) { - autoHeight = computedMaxHeight; - } - } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { - nscoord computedMinHeight = aReflowState.mComputedMinHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight < computedMinHeight) { - autoHeight = computedMinHeight; - } - } - aMetrics.height = autoHeight; - - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - maxHeight = aState.mMaxElementSize.height + - borderPadding.top + borderPadding.bottom; + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { + nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight > computedMaxHeight) { + autoHeight = computedMaxHeight; } } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { + nscoord computedMinHeight = aReflowState.mComputedMinHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight < computedMinHeight) { + autoHeight = computedMinHeight; + } + } + aMetrics.height = autoHeight; + + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + maxHeight = aState.mMaxElementSize.height + + borderPadding.top + borderPadding.bottom; + } + } #ifndef MOZ_MATHML - aMetrics.ascent = aMetrics.height; - aMetrics.descent = 0; + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; #else - if (mLines && mLines->mFirstChild && mLines->IsBlock()) { - // mAscent is not yet set because we didn't call VerticalAlignFrames() - // on mLines. So we need to fetch the ascent of the first child of mLines - nsBlockFrame* bf; - nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); - if (NS_SUCCEEDED(res) && bf) { - mAscent = bf->GetAscent(); - } + if (mLines && mLines->mFirstChild && mLines->IsBlock()) { + // mAscent is not yet set because we didn't call VerticalAlignFrames() + // on mLines. So we need to fetch the ascent of the first child of mLines + nsBlockFrame* bf; + nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); + if (NS_SUCCEEDED(res) && bf) { + mAscent = bf->GetAscent(); } - aMetrics.ascent = mAscent; - aMetrics.descent = aMetrics.height - aMetrics.ascent; + } + aMetrics.ascent = mAscent; + aMetrics.descent = aMetrics.height - aMetrics.ascent; #endif - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Store away the final value - aMetrics.maxElementSize->width = maxWidth; - aMetrics.maxElementSize->height = maxHeight; + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Store away the final value + aMetrics.maxElementSize->width = maxWidth; + aMetrics.maxElementSize->height = maxHeight; #ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p returning MES %d\n", - this, aMetrics.maxElementSize->width); -#endif - } - - // Return bottom margin information - aMetrics.mCarriedOutBottomMargin = - aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; - -#ifdef DEBUG_blocks - if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { - ListTag(stdout); - printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); - } - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && - ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { - ListTag(stdout); - printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } -#endif -#ifdef NOISY_MAX_ELEMENT_SIZE - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - IndentBy(stdout, GetDepth()); - if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { - printf("PASS1 "); - } - ListTag(stdout); - printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } + printf ("nsBlockFrame::CFS: %p returning MES %d\n", + this, aMetrics.maxElementSize->width); #endif } + // Return bottom margin information + aMetrics.mCarriedOutBottomMargin = + aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; + +#ifdef DEBUG_blocks + if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { + ListTag(stdout); + printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); + } + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && + ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { + ListTag(stdout); + printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif +#ifdef NOISY_MAX_ELEMENT_SIZE + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + IndentBy(stdout, GetDepth()); + if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { + printf("PASS1 "); + } + ListTag(stdout); + printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif + // If we're requested to update our maximum width, then compute it if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) { // We need to add in for the right border/padding @@ -4038,15 +3990,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n", aState.mPrevBottomMargin, collapsedBottomMargin); #endif - if (collapsedBottomMargin >= 0) { - aState.mPrevBottomMargin = collapsedBottomMargin; - } - else { - // Leave margin alone: it was a collapsed paragraph that - // must not interfere with the running margin calculations - // (in other words it should act like an empty line of - // whitespace). - } + aState.mPrevBottomMargin = collapsedBottomMargin; } #ifdef NOISY_VERTICAL_MARGINS ListTag(stdout); @@ -6889,9 +6833,6 @@ nsBlockFrame::Init(nsIPresContext* aPresContext, nsresult rv = nsBlockFrameSuper::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - if (nsBlockReflowContext::IsHTMLParagraph(this)) { - mState |= NS_BLOCK_IS_HTML_PARAGRAPH; - } return rv; } diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index 5d777fc69d9..3956f2e2a74 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -57,9 +57,6 @@ #include "prenv.h" #include "plstr.h" -// XXX HTML:P's that are empty yet have style indicating they should -// clear floaters - we need to ignore the clear behavior. - #ifdef DEBUG static PRBool gLamePaintMetrics; @@ -1045,22 +1042,16 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine, aLine->GetCombinedArea(&lineCombinedArea); if (aLine->IsBlock()) { if ((0 == aLine->mBounds.height) && (0 == lineCombinedArea.height)) { - if (nsBlockReflowContext::IsHTMLParagraph(aLine->mFirstChild)) { - // Empty HTML paragraphs disappear entirely - their margins go - // to zero. Therefore we leave mPrevBottomMargin alone. - } - else { - // The line's top and bottom margin values need to be collapsed - // with the mPrevBottomMargin to determine a new - // mPrevBottomMargin value. - nscoord topMargin, bottomMargin; - RecoverVerticalMargins(aLine, aApplyTopMargin, - &topMargin, &bottomMargin); - nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, - mPrevBottomMargin); - m = nsBlockReflowContext::MaxMargin(m, topMargin); - mPrevBottomMargin = m; - } + // The line's top and bottom margin values need to be collapsed + // with the mPrevBottomMargin to determine a new + // mPrevBottomMargin value. + nscoord topMargin, bottomMargin; + RecoverVerticalMargins(aLine, aApplyTopMargin, + &topMargin, &bottomMargin); + nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, + mPrevBottomMargin); + m = nsBlockReflowContext::MaxMargin(m, topMargin); + mPrevBottomMargin = m; } else { // Recover the top and bottom margins for this line @@ -2097,294 +2088,255 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, borderPadding.top, borderPadding.bottom); #endif - // Special check for zero sized content: If our content is zero - // sized then we collapse into nothingness. - // - // Consensus after discussion with a few CSS folks is that html's - // notion of collapsing

's should take precedence over non - // auto-sided block elements. Therefore we don't honor the width, - // height, border or padding attributes (the parent has to not apply - // a margin for us also). - // - // Note that this is only done for html paragraphs. Its not - // appropriate to apply it to other containers, especially XML - // content! - PRBool isHTMLParagraph = 0 != (mState & NS_BLOCK_IS_HTML_PARAGRAPH); - if (isHTMLParagraph && - (aReflowState.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_BLOCK) && - (((0 == aState.mKidXMost) || - (0 == aState.mKidXMost - borderPadding.left)) && - (0 == aState.mY - borderPadding.top))) { - // Zero out most everything - aMetrics.width = 0; - aMetrics.height = 0; - aMetrics.ascent = 0; - aMetrics.descent = 0; - aMetrics.mCarriedOutBottomMargin = 0; - - // Note: Don't zero out the max-element-sizes: they will be zero - // if this is truly empty, otherwise they won't because of a - // floater. - if (nsnull != aMetrics.maxElementSize) { - aMetrics.maxElementSize->width = aState.mMaxElementSize.width; - aMetrics.maxElementSize->height = aState.mMaxElementSize.height; -#ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p initially setting MES %d\n", - this, aState.mMaxElementSize.width); + // Compute final width + nscoord maxWidth = 0, maxHeight = 0; +#ifdef NOISY_KIDXMOST + printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif + nscoord minWidth = aState.mKidXMost + borderPadding.right; + if (!HaveAutoWidth(aReflowState)) { + // Use style defined width + aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + + borderPadding.right; + // XXX quote css1 section here + if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { + aMetrics.width = minWidth; } + + // When style defines the width use it for the max-element-size + // because we can't shrink any smaller. + maxWidth = aMetrics.width; } else { - // Compute final width - nscoord maxWidth = 0, maxHeight = 0; -#ifdef NOISY_KIDXMOST - printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); -#endif - nscoord minWidth = aState.mKidXMost + borderPadding.right; - if (!HaveAutoWidth(aReflowState)) { - // Use style defined width - aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + - borderPadding.right; - // XXX quote css1 section here - if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { - aMetrics.width = minWidth; - } - - // When style defines the width use it for the max-element-size - // because we can't shrink any smaller. - maxWidth = aMetrics.width; - } - else { - nscoord computedWidth = minWidth; - PRBool compact = PR_FALSE; + nscoord computedWidth = minWidth; + PRBool compact = PR_FALSE; #if 0 - if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { - // If we are display: compact AND we have no lines or we have - // exactly one line and that line is not a block line AND that - // line doesn't end in a BR of any sort THEN we remain a compact - // frame. - if ((nsnull == mLines) || - ((nsnull == mLines->mNext) && !mLines->IsBlock() && - (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) - /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ - )) { - compact = PR_TRUE; - } + if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { + // If we are display: compact AND we have no lines or we have + // exactly one line and that line is not a block line AND that + // line doesn't end in a BR of any sort THEN we remain a compact + // frame. + if ((nsnull == mLines) || + ((nsnull == mLines->mNext) && !mLines->IsBlock() && + (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) + /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ + )) { + compact = PR_TRUE; } + } #endif - // There are two options here. We either shrink wrap around our - // contents or we fluff out to the maximum block width. Note: - // We always shrink wrap when given an unconstrained width. - if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && - !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && - !compact) { - // Set our width to the max width if we aren't already that - // wide. Note that the max-width has nothing to do with our - // contents (CSS2 section XXX) - computedWidth = borderPadding.left + aState.mContentArea.width + - borderPadding.right; - } + // There are two options here. We either shrink wrap around our + // contents or we fluff out to the maximum block width. Note: + // We always shrink wrap when given an unconstrained width. + if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && + !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && + !compact) { + // Set our width to the max width if we aren't already that + // wide. Note that the max-width has nothing to do with our + // contents (CSS2 section XXX) + computedWidth = borderPadding.left + aState.mContentArea.width + + borderPadding.right; + } - // See if we should compute our max element size - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Adjust the computedWidth - if (aState.GetFlag(BRS_NOWRAP)) { - // When no-wrap is true the max-element-size.width is the - // width of the widest line plus the right border. Note that - // aState.mKidXMost already has the left border factored in - //maxWidth = aState.mKidXMost + borderPadding.right; - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - else { - // Add in border and padding dimensions to already computed - // max-element-size values. - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - if (computedWidth < maxWidth) { - computedWidth = maxWidth; - } - } - - // Apply min/max values - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { - nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + // See if we should compute our max element size + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Adjust the computedWidth + if (aState.GetFlag(BRS_NOWRAP)) { + // When no-wrap is true the max-element-size.width is the + // width of the widest line plus the right border. Note that + // aState.mKidXMost already has the left border factored in + //maxWidth = aState.mKidXMost + borderPadding.right; + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth > computedMaxWidth) { - computedWidth = computedMaxWidth; - } } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { - nscoord computedMinWidth = aReflowState.mComputedMinWidth + + else { + // Add in border and padding dimensions to already computed + // max-element-size values. + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth < computedMinWidth) { - computedWidth = computedMinWidth; - } } - aMetrics.width = computedWidth; - - // If we're shrink wrapping, then now that we know our final width we - // need to do horizontal alignment of the inline lines and make sure - // blocks are correctly sized and positioned. Any lines that need - // final adjustment will have been marked as dirty - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { - // If the parent reflow state is also shrink wrap width, then - // we don't need to do this, because it will reflow us after it - // calculates the final width - PRBool parentIsShrinkWrapWidth = PR_FALSE; - if (aReflowState.parentReflowState) { - if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { - parentIsShrinkWrapWidth = PR_TRUE; - } - } - - if (!parentIsShrinkWrapWidth) { - nsHTMLReflowState reflowState(aReflowState); - - reflowState.mComputedWidth = aMetrics.width - borderPadding.left - - borderPadding.right; - reflowState.reason = eReflowReason_Resize; - reflowState.mSpaceManager->ClearRegions(); - - nscoord oldDesiredWidth = aMetrics.width; - nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, - NS_BLOCK_MARGIN_ROOT & mState); - ReflowDirtyLines(state); - aState.mY = state.mY; - NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); - } + if (computedWidth < maxWidth) { + computedWidth = maxWidth; } } - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + // Apply min/max values + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { + nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + borderPadding.left + borderPadding.right; + if (computedWidth > computedMaxWidth) { + computedWidth = computedMaxWidth; + } + } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { + nscoord computedMinWidth = aReflowState.mComputedMinWidth + + borderPadding.left + borderPadding.right; + if (computedWidth < computedMinWidth) { + computedWidth = computedMinWidth; + } + } + aMetrics.width = computedWidth; + + // If we're shrink wrapping, then now that we know our final width we + // need to do horizontal alignment of the inline lines and make sure + // blocks are correctly sized and positioned. Any lines that need + // final adjustment will have been marked as dirty + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { + // If the parent reflow state is also shrink wrap width, then + // we don't need to do this, because it will reflow us after it + // calculates the final width PRBool parentIsShrinkWrapWidth = PR_FALSE; if (aReflowState.parentReflowState) { if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { parentIsShrinkWrapWidth = PR_TRUE; } } - } - // Compute final height - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - // Use style defined height - aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + - borderPadding.bottom; + if (!parentIsShrinkWrapWidth) { + nsHTMLReflowState reflowState(aReflowState); - // When style defines the height use it for the max-element-size - // because we can't shrink any smaller. - maxHeight = aMetrics.height; + reflowState.mComputedWidth = aMetrics.width - borderPadding.left - + borderPadding.right; + reflowState.reason = eReflowReason_Resize; + reflowState.mSpaceManager->ClearRegions(); - // Don't carry out a bottom margin when our height is fixed - // unless the bottom of the last line adjoins the bottom of our - // content area. - if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { - aState.mPrevBottomMargin = 0; - } + nscoord oldDesiredWidth = aMetrics.width; + nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, + NS_BLOCK_MARGIN_ROOT & mState); + ReflowDirtyLines(state); + aState.mY = state.mY; + NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); } } - else { - nscoord autoHeight = aState.mY; + } - // Shrink wrap our height around our contents. - if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. - // XXX check for a fit - autoHeight += aState.mPrevBottomMargin; + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + PRBool parentIsShrinkWrapWidth = PR_FALSE; + if (aReflowState.parentReflowState) { + if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { + parentIsShrinkWrapWidth = PR_TRUE; } - autoHeight += borderPadding.bottom; + } + } - // Apply min/max values + // Compute final height + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { + // Use style defined height + aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + + borderPadding.bottom; + + // When style defines the height use it for the max-element-size + // because we can't shrink any smaller. + maxHeight = aMetrics.height; + + // Don't carry out a bottom margin when our height is fixed + // unless the bottom of the last line adjoins the bottom of our + // content area. + if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { + aState.mPrevBottomMargin = 0; + } + } + } + else { + nscoord autoHeight = aState.mY; + + // Shrink wrap our height around our contents. + if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + // When we are a bottom-margin root make sure that our last + // childs bottom margin is fully applied. + // XXX check for a fit + autoHeight += aState.mPrevBottomMargin; + } + autoHeight += borderPadding.bottom; + + // Apply min/max values #ifdef MOZ_MATHML - // XXX Here in ComputeFinalSize() - // XXX What to do when min/max values are applied to the height? - // How do all this impact on the first line of the block? + // XXX Here in ComputeFinalSize() + // XXX What to do when min/max values are applied to the height? + // How do all this impact on the first line of the block? #endif - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { - nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight > computedMaxHeight) { - autoHeight = computedMaxHeight; - } - } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { - nscoord computedMinHeight = aReflowState.mComputedMinHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight < computedMinHeight) { - autoHeight = computedMinHeight; - } - } - aMetrics.height = autoHeight; - - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - maxHeight = aState.mMaxElementSize.height + - borderPadding.top + borderPadding.bottom; + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { + nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight > computedMaxHeight) { + autoHeight = computedMaxHeight; } } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { + nscoord computedMinHeight = aReflowState.mComputedMinHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight < computedMinHeight) { + autoHeight = computedMinHeight; + } + } + aMetrics.height = autoHeight; + + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + maxHeight = aState.mMaxElementSize.height + + borderPadding.top + borderPadding.bottom; + } + } #ifndef MOZ_MATHML - aMetrics.ascent = aMetrics.height; - aMetrics.descent = 0; + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; #else - if (mLines && mLines->mFirstChild && mLines->IsBlock()) { - // mAscent is not yet set because we didn't call VerticalAlignFrames() - // on mLines. So we need to fetch the ascent of the first child of mLines - nsBlockFrame* bf; - nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); - if (NS_SUCCEEDED(res) && bf) { - mAscent = bf->GetAscent(); - } + if (mLines && mLines->mFirstChild && mLines->IsBlock()) { + // mAscent is not yet set because we didn't call VerticalAlignFrames() + // on mLines. So we need to fetch the ascent of the first child of mLines + nsBlockFrame* bf; + nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); + if (NS_SUCCEEDED(res) && bf) { + mAscent = bf->GetAscent(); } - aMetrics.ascent = mAscent; - aMetrics.descent = aMetrics.height - aMetrics.ascent; + } + aMetrics.ascent = mAscent; + aMetrics.descent = aMetrics.height - aMetrics.ascent; #endif - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Store away the final value - aMetrics.maxElementSize->width = maxWidth; - aMetrics.maxElementSize->height = maxHeight; + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Store away the final value + aMetrics.maxElementSize->width = maxWidth; + aMetrics.maxElementSize->height = maxHeight; #ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p returning MES %d\n", - this, aMetrics.maxElementSize->width); -#endif - } - - // Return bottom margin information - aMetrics.mCarriedOutBottomMargin = - aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; - -#ifdef DEBUG_blocks - if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { - ListTag(stdout); - printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); - } - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && - ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { - ListTag(stdout); - printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } -#endif -#ifdef NOISY_MAX_ELEMENT_SIZE - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - IndentBy(stdout, GetDepth()); - if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { - printf("PASS1 "); - } - ListTag(stdout); - printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } + printf ("nsBlockFrame::CFS: %p returning MES %d\n", + this, aMetrics.maxElementSize->width); #endif } + // Return bottom margin information + aMetrics.mCarriedOutBottomMargin = + aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; + +#ifdef DEBUG_blocks + if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { + ListTag(stdout); + printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); + } + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && + ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { + ListTag(stdout); + printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif +#ifdef NOISY_MAX_ELEMENT_SIZE + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + IndentBy(stdout, GetDepth()); + if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { + printf("PASS1 "); + } + ListTag(stdout); + printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif + // If we're requested to update our maximum width, then compute it if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) { // We need to add in for the right border/padding @@ -4038,15 +3990,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n", aState.mPrevBottomMargin, collapsedBottomMargin); #endif - if (collapsedBottomMargin >= 0) { - aState.mPrevBottomMargin = collapsedBottomMargin; - } - else { - // Leave margin alone: it was a collapsed paragraph that - // must not interfere with the running margin calculations - // (in other words it should act like an empty line of - // whitespace). - } + aState.mPrevBottomMargin = collapsedBottomMargin; } #ifdef NOISY_VERTICAL_MARGINS ListTag(stdout); @@ -6889,9 +6833,6 @@ nsBlockFrame::Init(nsIPresContext* aPresContext, nsresult rv = nsBlockFrameSuper::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - if (nsBlockReflowContext::IsHTMLParagraph(this)) { - mState |= NS_BLOCK_IS_HTML_PARAGRAPH; - } return rv; } diff --git a/mozilla/layout/html/base/src/nsBlockFrame.h b/mozilla/layout/html/base/src/nsBlockFrame.h index a8496f69f8c..82107ed212a 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.h +++ b/mozilla/layout/html/base/src/nsBlockFrame.h @@ -45,8 +45,7 @@ class nsFirstLineFrame; * Additional frame-state bits. There are more of these bits * defined in nsHTMLParts.h (XXX: note: this should be cleaned up) */ -#define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x80000000 -#define NS_BLOCK_IS_HTML_PARAGRAPH 0x40000000 +#define NS_BLOCK_FRAME_HAS_OUTSIDE_BULLET 0x40000000 #define NS_BLOCK_HAS_FIRST_LETTER_STYLE 0x20000000 #define nsBlockFrameSuper nsHTMLContainerFrame diff --git a/mozilla/layout/html/base/src/nsBlockReflowContext.cpp b/mozilla/layout/html/base/src/nsBlockReflowContext.cpp index 26343e1b0d2..5fd8d66c6b6 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowContext.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowContext.cpp @@ -30,7 +30,6 @@ #include "nsIReflowCommand.h" #include "nsHTMLContainerFrame.h" #include "nsBlockFrame.h" -#include "nsIDOMHTMLParagraphElement.h" #include "nsIDOMHTMLTableCellElement.h" #include "nsIDOMHTMLBodyElement.h" #include "nsLayoutAtoms.h" @@ -63,58 +62,6 @@ nsBlockReflowContext::nsBlockReflowContext(nsIPresContext* aPresContext, mMetrics.mFlags |= NS_REFLOW_CALC_MAX_WIDTH; } -PRBool -nsBlockReflowContext::IsHTMLParagraph(nsIFrame* aFrame) -{ - PRBool result = PR_FALSE; - nsCOMPtr content; - nsresult rv = aFrame->GetContent(getter_AddRefs(content)); - if (NS_SUCCEEDED(rv) && content) { - nsCOMPtr p(do_QueryInterface(content)); - if (p) { - result = PR_TRUE; - } - } - return result; -} - - -PRBool -nsBlockReflowContext::IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const -{ - NS_ASSERTION(aParentFrame && aChildFrame, "bad args"); - if (!aParentFrame || !aChildFrame) return PR_FALSE; - nsIFrame *child; - aParentFrame->FirstChild((nsIPresContext *)(&mPresContext), nsnull, &child); - while (child) - { - if (aChildFrame == child) { - return PR_TRUE; // we found aChildFrame, and we haven't yet encountered a geometrically significant frame - } - nsSize size; - child->GetSize(size); - if (size.width || size.height) { - return PR_FALSE; // we found a geometrically significant frame and it wasn't aChildFrame - } - child->GetNextSibling(&child); - } - return PR_FALSE; //aChildFrame is not in the default child list of aParentFrame -} - -PRBool IsCollapsingBlockParentFrame(const nsIFrame* aFrame) -{ - if (!aFrame) return PR_FALSE; - nsCOMPtr frameType; - aFrame->GetFrameType(getter_AddRefs(frameType)); - if (frameType.get()==nsLayoutAtoms::blockFrame || - frameType.get()==nsLayoutAtoms::areaFrame || - frameType.get()==nsLayoutAtoms::tableCellFrame || - frameType.get()==nsLayoutAtoms::tableCaptionFrame) { - return PR_TRUE; - } - return PR_FALSE; -} - nscoord nsBlockReflowContext::ComputeCollapsedTopMargin(nsIPresContext* aPresContext, nsHTMLReflowState& aRS) @@ -125,26 +72,35 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(nsIPresContext* aPresContext, // Calculate aFrame's generational top-margin from its child // blocks. Note that if aFrame has a non-zero top-border or // top-padding then this step is skipped because it will be a margin - // root. + // root. It is also skipped if the frame is a margin root for other + // reasons. nscoord generationalTopMargin = 0; if (0 == aRS.mComputedBorderPadding.top) { - nsBlockFrame* bf; - if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf))) { - // Ask the block frame for the top block child that we should - // try to collapse the top margin with. - nsIFrame* childFrame = bf->GetTopBlockChild(); - if (nsnull != childFrame) { + nsFrameState state; + aRS.frame->GetFrameState(&state); + if (!(state & NS_BLOCK_MARGIN_ROOT)) { + nsBlockFrame* bf; + if (NS_SUCCEEDED(aRS.frame->QueryInterface(kBlockFrameCID, (void**)&bf))) { + // Ask the block frame for the top block child that we should + // try to collapse the top margin with. - // Here is where we recurse. Now that we have determined that a - // generational collapse is required we need to compute the - // child blocks margin and so in so that we can look into - // it. For its margins to be computed we need to have a reflow - // state for it. - nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight); - nsHTMLReflowState reflowState(aPresContext, aRS, childFrame, - availSpace); - generationalTopMargin = - ComputeCollapsedTopMargin(aPresContext, reflowState); + // XXX If the block is empty, we need to check its bottom margin + // and its sibling's top margin (etc.) too! + + nsIFrame* childFrame = bf->GetTopBlockChild(); + if (nsnull != childFrame) { + + // Here is where we recurse. Now that we have determined that a + // generational collapse is required we need to compute the + // child blocks margin and so in so that we can look into + // it. For its margins to be computed we need to have a reflow + // state for it. + nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight); + nsHTMLReflowState reflowState(aPresContext, aRS, childFrame, + availSpace); + generationalTopMargin = + ComputeCollapsedTopMargin(aPresContext, reflowState); + } } } } @@ -736,53 +692,22 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, PRBool fits = PR_TRUE; nscoord x = mX; nscoord y = mY; - // When deciding whether it's an empty paragraph we also need to take into + // When deciding whether it's empty we also need to take into // account the overflow area if ((0 == mMetrics.height) && (0 == mMetrics.mOverflowArea.height)) { - PRBool handled = PR_FALSE; - if (IsHTMLParagraph(mFrame)) { - // Special "feature" for HTML compatability - empty paragraphs - // collapse into nothingness, including their margins. Signal - // the special nature here by returning -1. - // In general, we turn off this behavior due to re-interpretation of the vague HTML 4 spec. - // See bug 35772. However, we do need this behavior for

inside of table cells, - // floaters, and positioned elements - nsIFrame *parent; - mFrame->GetParent(&parent); - if (parent) - { - if (IsCollapsingBlockParentFrame(mFrame) && - IsFirstSignificantChild(parent, mFrame)) - { - handled = PR_TRUE; - *aBottomMarginResult = -1; + // Collapse the bottom margin with the top margin that was already + // applied. + nscoord newBottomMargin = MaxMargin(collapsedBottomMargin, mTopMargin); + *aBottomMarginResult = newBottomMargin; #ifdef NOISY_VERTICAL_MARGINS - printf(" "); - nsFrame::ListTag(stdout, mOuterReflowState.frame); - printf(": "); - nsFrame::ListTag(stdout, mFrame); - printf(" -- zapping top & bottom margin; y=%d spaceY=%d\n", - y, mSpace.y); + printf(" "); + nsFrame::ListTag(stdout, mOuterReflowState.frame); + printf(": "); + nsFrame::ListTag(stdout, mFrame); + printf(" -- collapsing top & bottom margin together; y=%d spaceY=%d\n", + y, mSpace.y); #endif - } - } - } - if (!handled) - { - // Collapse the bottom margin with the top margin that was already - // applied. - nscoord newBottomMargin = MaxMargin(collapsedBottomMargin, mTopMargin); - *aBottomMarginResult = newBottomMargin; -#ifdef NOISY_VERTICAL_MARGINS - printf(" "); - nsFrame::ListTag(stdout, mOuterReflowState.frame); - printf(": "); - nsFrame::ListTag(stdout, mFrame); - printf(" -- collapsing top & bottom margin together; y=%d spaceY=%d\n", - y, mSpace.y); -#endif - } y = mSpace.y; @@ -805,22 +730,6 @@ nsBlockReflowContext::PlaceBlock(PRBool aForceFit, // fits. if (aForceFit || (y + mMetrics.height <= mSpace.YMost())) { - // if it's a

and it's parent is special, then collapse the

's top margin - if (IsHTMLParagraph(mFrame)) { - // Special "feature" for HTML compatability - a paragraph's - // top margin collapses into nothingness, inside of certain containers. - nsIFrame *parent; - mFrame->GetParent(&parent); - if (parent) - { - if (IsCollapsingBlockParentFrame(mFrame) && - IsFirstSignificantChild(parent, mFrame)) - { - y=0; - } - } - } - // Calculate the actual x-offset and left and right margin nsBlockHorizontalAlign align; diff --git a/mozilla/layout/html/base/src/nsBlockReflowContext.h b/mozilla/layout/html/base/src/nsBlockReflowContext.h index 42975993919..308abd13c38 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowContext.h +++ b/mozilla/layout/html/base/src/nsBlockReflowContext.h @@ -112,14 +112,6 @@ public: return b; } - static PRBool IsHTMLParagraph(nsIFrame* aFrame); - - /** return PR_TRUE if aChildFrame is the first geometrically significant child of aParentFrame - * to be considered significant, a frame must have both width and height != 0 - * if aChildFrame is not in the default child list of aParentFrame, we return PR_FALSE - */ - PRBool IsFirstSignificantChild(const nsIFrame* aParentFrame, const nsIFrame* aChildFrame) const; - static nscoord ComputeCollapsedTopMargin(nsIPresContext* aPresContext, nsHTMLReflowState& aRS); diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp index 5d777fc69d9..3956f2e2a74 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp @@ -57,9 +57,6 @@ #include "prenv.h" #include "plstr.h" -// XXX HTML:P's that are empty yet have style indicating they should -// clear floaters - we need to ignore the clear behavior. - #ifdef DEBUG static PRBool gLamePaintMetrics; @@ -1045,22 +1042,16 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine, aLine->GetCombinedArea(&lineCombinedArea); if (aLine->IsBlock()) { if ((0 == aLine->mBounds.height) && (0 == lineCombinedArea.height)) { - if (nsBlockReflowContext::IsHTMLParagraph(aLine->mFirstChild)) { - // Empty HTML paragraphs disappear entirely - their margins go - // to zero. Therefore we leave mPrevBottomMargin alone. - } - else { - // The line's top and bottom margin values need to be collapsed - // with the mPrevBottomMargin to determine a new - // mPrevBottomMargin value. - nscoord topMargin, bottomMargin; - RecoverVerticalMargins(aLine, aApplyTopMargin, - &topMargin, &bottomMargin); - nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, - mPrevBottomMargin); - m = nsBlockReflowContext::MaxMargin(m, topMargin); - mPrevBottomMargin = m; - } + // The line's top and bottom margin values need to be collapsed + // with the mPrevBottomMargin to determine a new + // mPrevBottomMargin value. + nscoord topMargin, bottomMargin; + RecoverVerticalMargins(aLine, aApplyTopMargin, + &topMargin, &bottomMargin); + nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, + mPrevBottomMargin); + m = nsBlockReflowContext::MaxMargin(m, topMargin); + mPrevBottomMargin = m; } else { // Recover the top and bottom margins for this line @@ -2097,294 +2088,255 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, borderPadding.top, borderPadding.bottom); #endif - // Special check for zero sized content: If our content is zero - // sized then we collapse into nothingness. - // - // Consensus after discussion with a few CSS folks is that html's - // notion of collapsing

's should take precedence over non - // auto-sided block elements. Therefore we don't honor the width, - // height, border or padding attributes (the parent has to not apply - // a margin for us also). - // - // Note that this is only done for html paragraphs. Its not - // appropriate to apply it to other containers, especially XML - // content! - PRBool isHTMLParagraph = 0 != (mState & NS_BLOCK_IS_HTML_PARAGRAPH); - if (isHTMLParagraph && - (aReflowState.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_BLOCK) && - (((0 == aState.mKidXMost) || - (0 == aState.mKidXMost - borderPadding.left)) && - (0 == aState.mY - borderPadding.top))) { - // Zero out most everything - aMetrics.width = 0; - aMetrics.height = 0; - aMetrics.ascent = 0; - aMetrics.descent = 0; - aMetrics.mCarriedOutBottomMargin = 0; - - // Note: Don't zero out the max-element-sizes: they will be zero - // if this is truly empty, otherwise they won't because of a - // floater. - if (nsnull != aMetrics.maxElementSize) { - aMetrics.maxElementSize->width = aState.mMaxElementSize.width; - aMetrics.maxElementSize->height = aState.mMaxElementSize.height; -#ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p initially setting MES %d\n", - this, aState.mMaxElementSize.width); + // Compute final width + nscoord maxWidth = 0, maxHeight = 0; +#ifdef NOISY_KIDXMOST + printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif + nscoord minWidth = aState.mKidXMost + borderPadding.right; + if (!HaveAutoWidth(aReflowState)) { + // Use style defined width + aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + + borderPadding.right; + // XXX quote css1 section here + if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { + aMetrics.width = minWidth; } + + // When style defines the width use it for the max-element-size + // because we can't shrink any smaller. + maxWidth = aMetrics.width; } else { - // Compute final width - nscoord maxWidth = 0, maxHeight = 0; -#ifdef NOISY_KIDXMOST - printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); -#endif - nscoord minWidth = aState.mKidXMost + borderPadding.right; - if (!HaveAutoWidth(aReflowState)) { - // Use style defined width - aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + - borderPadding.right; - // XXX quote css1 section here - if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { - aMetrics.width = minWidth; - } - - // When style defines the width use it for the max-element-size - // because we can't shrink any smaller. - maxWidth = aMetrics.width; - } - else { - nscoord computedWidth = minWidth; - PRBool compact = PR_FALSE; + nscoord computedWidth = minWidth; + PRBool compact = PR_FALSE; #if 0 - if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { - // If we are display: compact AND we have no lines or we have - // exactly one line and that line is not a block line AND that - // line doesn't end in a BR of any sort THEN we remain a compact - // frame. - if ((nsnull == mLines) || - ((nsnull == mLines->mNext) && !mLines->IsBlock() && - (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) - /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ - )) { - compact = PR_TRUE; - } + if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { + // If we are display: compact AND we have no lines or we have + // exactly one line and that line is not a block line AND that + // line doesn't end in a BR of any sort THEN we remain a compact + // frame. + if ((nsnull == mLines) || + ((nsnull == mLines->mNext) && !mLines->IsBlock() && + (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) + /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ + )) { + compact = PR_TRUE; } + } #endif - // There are two options here. We either shrink wrap around our - // contents or we fluff out to the maximum block width. Note: - // We always shrink wrap when given an unconstrained width. - if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && - !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && - !compact) { - // Set our width to the max width if we aren't already that - // wide. Note that the max-width has nothing to do with our - // contents (CSS2 section XXX) - computedWidth = borderPadding.left + aState.mContentArea.width + - borderPadding.right; - } + // There are two options here. We either shrink wrap around our + // contents or we fluff out to the maximum block width. Note: + // We always shrink wrap when given an unconstrained width. + if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && + !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && + !compact) { + // Set our width to the max width if we aren't already that + // wide. Note that the max-width has nothing to do with our + // contents (CSS2 section XXX) + computedWidth = borderPadding.left + aState.mContentArea.width + + borderPadding.right; + } - // See if we should compute our max element size - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Adjust the computedWidth - if (aState.GetFlag(BRS_NOWRAP)) { - // When no-wrap is true the max-element-size.width is the - // width of the widest line plus the right border. Note that - // aState.mKidXMost already has the left border factored in - //maxWidth = aState.mKidXMost + borderPadding.right; - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - else { - // Add in border and padding dimensions to already computed - // max-element-size values. - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - if (computedWidth < maxWidth) { - computedWidth = maxWidth; - } - } - - // Apply min/max values - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { - nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + // See if we should compute our max element size + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Adjust the computedWidth + if (aState.GetFlag(BRS_NOWRAP)) { + // When no-wrap is true the max-element-size.width is the + // width of the widest line plus the right border. Note that + // aState.mKidXMost already has the left border factored in + //maxWidth = aState.mKidXMost + borderPadding.right; + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth > computedMaxWidth) { - computedWidth = computedMaxWidth; - } } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { - nscoord computedMinWidth = aReflowState.mComputedMinWidth + + else { + // Add in border and padding dimensions to already computed + // max-element-size values. + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth < computedMinWidth) { - computedWidth = computedMinWidth; - } } - aMetrics.width = computedWidth; - - // If we're shrink wrapping, then now that we know our final width we - // need to do horizontal alignment of the inline lines and make sure - // blocks are correctly sized and positioned. Any lines that need - // final adjustment will have been marked as dirty - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { - // If the parent reflow state is also shrink wrap width, then - // we don't need to do this, because it will reflow us after it - // calculates the final width - PRBool parentIsShrinkWrapWidth = PR_FALSE; - if (aReflowState.parentReflowState) { - if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { - parentIsShrinkWrapWidth = PR_TRUE; - } - } - - if (!parentIsShrinkWrapWidth) { - nsHTMLReflowState reflowState(aReflowState); - - reflowState.mComputedWidth = aMetrics.width - borderPadding.left - - borderPadding.right; - reflowState.reason = eReflowReason_Resize; - reflowState.mSpaceManager->ClearRegions(); - - nscoord oldDesiredWidth = aMetrics.width; - nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, - NS_BLOCK_MARGIN_ROOT & mState); - ReflowDirtyLines(state); - aState.mY = state.mY; - NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); - } + if (computedWidth < maxWidth) { + computedWidth = maxWidth; } } - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + // Apply min/max values + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { + nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + borderPadding.left + borderPadding.right; + if (computedWidth > computedMaxWidth) { + computedWidth = computedMaxWidth; + } + } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { + nscoord computedMinWidth = aReflowState.mComputedMinWidth + + borderPadding.left + borderPadding.right; + if (computedWidth < computedMinWidth) { + computedWidth = computedMinWidth; + } + } + aMetrics.width = computedWidth; + + // If we're shrink wrapping, then now that we know our final width we + // need to do horizontal alignment of the inline lines and make sure + // blocks are correctly sized and positioned. Any lines that need + // final adjustment will have been marked as dirty + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { + // If the parent reflow state is also shrink wrap width, then + // we don't need to do this, because it will reflow us after it + // calculates the final width PRBool parentIsShrinkWrapWidth = PR_FALSE; if (aReflowState.parentReflowState) { if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { parentIsShrinkWrapWidth = PR_TRUE; } } - } - // Compute final height - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - // Use style defined height - aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + - borderPadding.bottom; + if (!parentIsShrinkWrapWidth) { + nsHTMLReflowState reflowState(aReflowState); - // When style defines the height use it for the max-element-size - // because we can't shrink any smaller. - maxHeight = aMetrics.height; + reflowState.mComputedWidth = aMetrics.width - borderPadding.left - + borderPadding.right; + reflowState.reason = eReflowReason_Resize; + reflowState.mSpaceManager->ClearRegions(); - // Don't carry out a bottom margin when our height is fixed - // unless the bottom of the last line adjoins the bottom of our - // content area. - if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { - aState.mPrevBottomMargin = 0; - } + nscoord oldDesiredWidth = aMetrics.width; + nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, + NS_BLOCK_MARGIN_ROOT & mState); + ReflowDirtyLines(state); + aState.mY = state.mY; + NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); } } - else { - nscoord autoHeight = aState.mY; + } - // Shrink wrap our height around our contents. - if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. - // XXX check for a fit - autoHeight += aState.mPrevBottomMargin; + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + PRBool parentIsShrinkWrapWidth = PR_FALSE; + if (aReflowState.parentReflowState) { + if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { + parentIsShrinkWrapWidth = PR_TRUE; } - autoHeight += borderPadding.bottom; + } + } - // Apply min/max values + // Compute final height + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { + // Use style defined height + aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + + borderPadding.bottom; + + // When style defines the height use it for the max-element-size + // because we can't shrink any smaller. + maxHeight = aMetrics.height; + + // Don't carry out a bottom margin when our height is fixed + // unless the bottom of the last line adjoins the bottom of our + // content area. + if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { + aState.mPrevBottomMargin = 0; + } + } + } + else { + nscoord autoHeight = aState.mY; + + // Shrink wrap our height around our contents. + if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + // When we are a bottom-margin root make sure that our last + // childs bottom margin is fully applied. + // XXX check for a fit + autoHeight += aState.mPrevBottomMargin; + } + autoHeight += borderPadding.bottom; + + // Apply min/max values #ifdef MOZ_MATHML - // XXX Here in ComputeFinalSize() - // XXX What to do when min/max values are applied to the height? - // How do all this impact on the first line of the block? + // XXX Here in ComputeFinalSize() + // XXX What to do when min/max values are applied to the height? + // How do all this impact on the first line of the block? #endif - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { - nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight > computedMaxHeight) { - autoHeight = computedMaxHeight; - } - } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { - nscoord computedMinHeight = aReflowState.mComputedMinHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight < computedMinHeight) { - autoHeight = computedMinHeight; - } - } - aMetrics.height = autoHeight; - - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - maxHeight = aState.mMaxElementSize.height + - borderPadding.top + borderPadding.bottom; + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { + nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight > computedMaxHeight) { + autoHeight = computedMaxHeight; } } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { + nscoord computedMinHeight = aReflowState.mComputedMinHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight < computedMinHeight) { + autoHeight = computedMinHeight; + } + } + aMetrics.height = autoHeight; + + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + maxHeight = aState.mMaxElementSize.height + + borderPadding.top + borderPadding.bottom; + } + } #ifndef MOZ_MATHML - aMetrics.ascent = aMetrics.height; - aMetrics.descent = 0; + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; #else - if (mLines && mLines->mFirstChild && mLines->IsBlock()) { - // mAscent is not yet set because we didn't call VerticalAlignFrames() - // on mLines. So we need to fetch the ascent of the first child of mLines - nsBlockFrame* bf; - nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); - if (NS_SUCCEEDED(res) && bf) { - mAscent = bf->GetAscent(); - } + if (mLines && mLines->mFirstChild && mLines->IsBlock()) { + // mAscent is not yet set because we didn't call VerticalAlignFrames() + // on mLines. So we need to fetch the ascent of the first child of mLines + nsBlockFrame* bf; + nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); + if (NS_SUCCEEDED(res) && bf) { + mAscent = bf->GetAscent(); } - aMetrics.ascent = mAscent; - aMetrics.descent = aMetrics.height - aMetrics.ascent; + } + aMetrics.ascent = mAscent; + aMetrics.descent = aMetrics.height - aMetrics.ascent; #endif - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Store away the final value - aMetrics.maxElementSize->width = maxWidth; - aMetrics.maxElementSize->height = maxHeight; + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Store away the final value + aMetrics.maxElementSize->width = maxWidth; + aMetrics.maxElementSize->height = maxHeight; #ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p returning MES %d\n", - this, aMetrics.maxElementSize->width); -#endif - } - - // Return bottom margin information - aMetrics.mCarriedOutBottomMargin = - aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; - -#ifdef DEBUG_blocks - if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { - ListTag(stdout); - printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); - } - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && - ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { - ListTag(stdout); - printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } -#endif -#ifdef NOISY_MAX_ELEMENT_SIZE - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - IndentBy(stdout, GetDepth()); - if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { - printf("PASS1 "); - } - ListTag(stdout); - printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } + printf ("nsBlockFrame::CFS: %p returning MES %d\n", + this, aMetrics.maxElementSize->width); #endif } + // Return bottom margin information + aMetrics.mCarriedOutBottomMargin = + aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; + +#ifdef DEBUG_blocks + if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { + ListTag(stdout); + printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); + } + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && + ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { + ListTag(stdout); + printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif +#ifdef NOISY_MAX_ELEMENT_SIZE + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + IndentBy(stdout, GetDepth()); + if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { + printf("PASS1 "); + } + ListTag(stdout); + printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif + // If we're requested to update our maximum width, then compute it if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) { // We need to add in for the right border/padding @@ -4038,15 +3990,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n", aState.mPrevBottomMargin, collapsedBottomMargin); #endif - if (collapsedBottomMargin >= 0) { - aState.mPrevBottomMargin = collapsedBottomMargin; - } - else { - // Leave margin alone: it was a collapsed paragraph that - // must not interfere with the running margin calculations - // (in other words it should act like an empty line of - // whitespace). - } + aState.mPrevBottomMargin = collapsedBottomMargin; } #ifdef NOISY_VERTICAL_MARGINS ListTag(stdout); @@ -6889,9 +6833,6 @@ nsBlockFrame::Init(nsIPresContext* aPresContext, nsresult rv = nsBlockFrameSuper::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - if (nsBlockReflowContext::IsHTMLParagraph(this)) { - mState |= NS_BLOCK_IS_HTML_PARAGRAPH; - } return rv; } diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h index 5d777fc69d9..3956f2e2a74 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.h +++ b/mozilla/layout/html/base/src/nsBlockReflowState.h @@ -57,9 +57,6 @@ #include "prenv.h" #include "plstr.h" -// XXX HTML:P's that are empty yet have style indicating they should -// clear floaters - we need to ignore the clear behavior. - #ifdef DEBUG static PRBool gLamePaintMetrics; @@ -1045,22 +1042,16 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine, aLine->GetCombinedArea(&lineCombinedArea); if (aLine->IsBlock()) { if ((0 == aLine->mBounds.height) && (0 == lineCombinedArea.height)) { - if (nsBlockReflowContext::IsHTMLParagraph(aLine->mFirstChild)) { - // Empty HTML paragraphs disappear entirely - their margins go - // to zero. Therefore we leave mPrevBottomMargin alone. - } - else { - // The line's top and bottom margin values need to be collapsed - // with the mPrevBottomMargin to determine a new - // mPrevBottomMargin value. - nscoord topMargin, bottomMargin; - RecoverVerticalMargins(aLine, aApplyTopMargin, - &topMargin, &bottomMargin); - nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, - mPrevBottomMargin); - m = nsBlockReflowContext::MaxMargin(m, topMargin); - mPrevBottomMargin = m; - } + // The line's top and bottom margin values need to be collapsed + // with the mPrevBottomMargin to determine a new + // mPrevBottomMargin value. + nscoord topMargin, bottomMargin; + RecoverVerticalMargins(aLine, aApplyTopMargin, + &topMargin, &bottomMargin); + nscoord m = nsBlockReflowContext::MaxMargin(bottomMargin, + mPrevBottomMargin); + m = nsBlockReflowContext::MaxMargin(m, topMargin); + mPrevBottomMargin = m; } else { // Recover the top and bottom margins for this line @@ -2097,294 +2088,255 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState, borderPadding.top, borderPadding.bottom); #endif - // Special check for zero sized content: If our content is zero - // sized then we collapse into nothingness. - // - // Consensus after discussion with a few CSS folks is that html's - // notion of collapsing

's should take precedence over non - // auto-sided block elements. Therefore we don't honor the width, - // height, border or padding attributes (the parent has to not apply - // a margin for us also). - // - // Note that this is only done for html paragraphs. Its not - // appropriate to apply it to other containers, especially XML - // content! - PRBool isHTMLParagraph = 0 != (mState & NS_BLOCK_IS_HTML_PARAGRAPH); - if (isHTMLParagraph && - (aReflowState.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_BLOCK) && - (((0 == aState.mKidXMost) || - (0 == aState.mKidXMost - borderPadding.left)) && - (0 == aState.mY - borderPadding.top))) { - // Zero out most everything - aMetrics.width = 0; - aMetrics.height = 0; - aMetrics.ascent = 0; - aMetrics.descent = 0; - aMetrics.mCarriedOutBottomMargin = 0; - - // Note: Don't zero out the max-element-sizes: they will be zero - // if this is truly empty, otherwise they won't because of a - // floater. - if (nsnull != aMetrics.maxElementSize) { - aMetrics.maxElementSize->width = aState.mMaxElementSize.width; - aMetrics.maxElementSize->height = aState.mMaxElementSize.height; -#ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p initially setting MES %d\n", - this, aState.mMaxElementSize.width); + // Compute final width + nscoord maxWidth = 0, maxHeight = 0; +#ifdef NOISY_KIDXMOST + printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif + nscoord minWidth = aState.mKidXMost + borderPadding.right; + if (!HaveAutoWidth(aReflowState)) { + // Use style defined width + aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + + borderPadding.right; + // XXX quote css1 section here + if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { + aMetrics.width = minWidth; } + + // When style defines the width use it for the max-element-size + // because we can't shrink any smaller. + maxWidth = aMetrics.width; } else { - // Compute final width - nscoord maxWidth = 0, maxHeight = 0; -#ifdef NOISY_KIDXMOST - printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); -#endif - nscoord minWidth = aState.mKidXMost + borderPadding.right; - if (!HaveAutoWidth(aReflowState)) { - // Use style defined width - aMetrics.width = borderPadding.left + aReflowState.mComputedWidth + - borderPadding.right; - // XXX quote css1 section here - if ((0 == aReflowState.mComputedWidth) && (aMetrics.width < minWidth)) { - aMetrics.width = minWidth; - } - - // When style defines the width use it for the max-element-size - // because we can't shrink any smaller. - maxWidth = aMetrics.width; - } - else { - nscoord computedWidth = minWidth; - PRBool compact = PR_FALSE; + nscoord computedWidth = minWidth; + PRBool compact = PR_FALSE; #if 0 - if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { - // If we are display: compact AND we have no lines or we have - // exactly one line and that line is not a block line AND that - // line doesn't end in a BR of any sort THEN we remain a compact - // frame. - if ((nsnull == mLines) || - ((nsnull == mLines->mNext) && !mLines->IsBlock() && - (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) - /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ - )) { - compact = PR_TRUE; - } + if (NS_STYLE_DISPLAY_COMPACT == aReflowState.mStyleDisplay->mDisplay) { + // If we are display: compact AND we have no lines or we have + // exactly one line and that line is not a block line AND that + // line doesn't end in a BR of any sort THEN we remain a compact + // frame. + if ((nsnull == mLines) || + ((nsnull == mLines->mNext) && !mLines->IsBlock() && + (NS_STYLE_CLEAR_NONE == mLines->GetBreakType()) + /*XXX && (computedWidth <= aState.mCompactMarginWidth) */ + )) { + compact = PR_TRUE; } + } #endif - // There are two options here. We either shrink wrap around our - // contents or we fluff out to the maximum block width. Note: - // We always shrink wrap when given an unconstrained width. - if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && - !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && - !compact) { - // Set our width to the max width if we aren't already that - // wide. Note that the max-width has nothing to do with our - // contents (CSS2 section XXX) - computedWidth = borderPadding.left + aState.mContentArea.width + - borderPadding.right; - } + // There are two options here. We either shrink wrap around our + // contents or we fluff out to the maximum block width. Note: + // We always shrink wrap when given an unconstrained width. + if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) && + !aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) && + !compact) { + // Set our width to the max width if we aren't already that + // wide. Note that the max-width has nothing to do with our + // contents (CSS2 section XXX) + computedWidth = borderPadding.left + aState.mContentArea.width + + borderPadding.right; + } - // See if we should compute our max element size - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Adjust the computedWidth - if (aState.GetFlag(BRS_NOWRAP)) { - // When no-wrap is true the max-element-size.width is the - // width of the widest line plus the right border. Note that - // aState.mKidXMost already has the left border factored in - //maxWidth = aState.mKidXMost + borderPadding.right; - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - else { - // Add in border and padding dimensions to already computed - // max-element-size values. - maxWidth = aState.mMaxElementSize.width + - borderPadding.left + borderPadding.right; - } - if (computedWidth < maxWidth) { - computedWidth = maxWidth; - } - } - - // Apply min/max values - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { - nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + // See if we should compute our max element size + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Adjust the computedWidth + if (aState.GetFlag(BRS_NOWRAP)) { + // When no-wrap is true the max-element-size.width is the + // width of the widest line plus the right border. Note that + // aState.mKidXMost already has the left border factored in + //maxWidth = aState.mKidXMost + borderPadding.right; + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth > computedMaxWidth) { - computedWidth = computedMaxWidth; - } } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { - nscoord computedMinWidth = aReflowState.mComputedMinWidth + + else { + // Add in border and padding dimensions to already computed + // max-element-size values. + maxWidth = aState.mMaxElementSize.width + borderPadding.left + borderPadding.right; - if (computedWidth < computedMinWidth) { - computedWidth = computedMinWidth; - } } - aMetrics.width = computedWidth; - - // If we're shrink wrapping, then now that we know our final width we - // need to do horizontal alignment of the inline lines and make sure - // blocks are correctly sized and positioned. Any lines that need - // final adjustment will have been marked as dirty - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { - // If the parent reflow state is also shrink wrap width, then - // we don't need to do this, because it will reflow us after it - // calculates the final width - PRBool parentIsShrinkWrapWidth = PR_FALSE; - if (aReflowState.parentReflowState) { - if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { - parentIsShrinkWrapWidth = PR_TRUE; - } - } - - if (!parentIsShrinkWrapWidth) { - nsHTMLReflowState reflowState(aReflowState); - - reflowState.mComputedWidth = aMetrics.width - borderPadding.left - - borderPadding.right; - reflowState.reason = eReflowReason_Resize; - reflowState.mSpaceManager->ClearRegions(); - - nscoord oldDesiredWidth = aMetrics.width; - nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, - NS_BLOCK_MARGIN_ROOT & mState); - ReflowDirtyLines(state); - aState.mY = state.mY; - NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); - } + if (computedWidth < maxWidth) { + computedWidth = maxWidth; } } - if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + // Apply min/max values + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) { + nscoord computedMaxWidth = aReflowState.mComputedMaxWidth + + borderPadding.left + borderPadding.right; + if (computedWidth > computedMaxWidth) { + computedWidth = computedMaxWidth; + } + } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinWidth) { + nscoord computedMinWidth = aReflowState.mComputedMinWidth + + borderPadding.left + borderPadding.right; + if (computedWidth < computedMinWidth) { + computedWidth = computedMinWidth; + } + } + aMetrics.width = computedWidth; + + // If we're shrink wrapping, then now that we know our final width we + // need to do horizontal alignment of the inline lines and make sure + // blocks are correctly sized and positioned. Any lines that need + // final adjustment will have been marked as dirty + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) { + // If the parent reflow state is also shrink wrap width, then + // we don't need to do this, because it will reflow us after it + // calculates the final width PRBool parentIsShrinkWrapWidth = PR_FALSE; if (aReflowState.parentReflowState) { if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { parentIsShrinkWrapWidth = PR_TRUE; } } - } - // Compute final height - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { - // Use style defined height - aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + - borderPadding.bottom; + if (!parentIsShrinkWrapWidth) { + nsHTMLReflowState reflowState(aReflowState); - // When style defines the height use it for the max-element-size - // because we can't shrink any smaller. - maxHeight = aMetrics.height; + reflowState.mComputedWidth = aMetrics.width - borderPadding.left - + borderPadding.right; + reflowState.reason = eReflowReason_Resize; + reflowState.mSpaceManager->ClearRegions(); - // Don't carry out a bottom margin when our height is fixed - // unless the bottom of the last line adjoins the bottom of our - // content area. - if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { - aState.mPrevBottomMargin = 0; - } + nscoord oldDesiredWidth = aMetrics.width; + nsBlockReflowState state(reflowState, aState.mPresContext, this, aMetrics, + NS_BLOCK_MARGIN_ROOT & mState); + ReflowDirtyLines(state); + aState.mY = state.mY; + NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width"); } } - else { - nscoord autoHeight = aState.mY; + } - // Shrink wrap our height around our contents. - if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { - // When we are a bottom-margin root make sure that our last - // childs bottom margin is fully applied. - // XXX check for a fit - autoHeight += aState.mPrevBottomMargin; + if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) { + PRBool parentIsShrinkWrapWidth = PR_FALSE; + if (aReflowState.parentReflowState) { + if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) { + parentIsShrinkWrapWidth = PR_TRUE; } - autoHeight += borderPadding.bottom; + } + } - // Apply min/max values + // Compute final height + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { + // Use style defined height + aMetrics.height = borderPadding.top + aReflowState.mComputedHeight + + borderPadding.bottom; + + // When style defines the height use it for the max-element-size + // because we can't shrink any smaller. + maxHeight = aMetrics.height; + + // Don't carry out a bottom margin when our height is fixed + // unless the bottom of the last line adjoins the bottom of our + // content area. + if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) { + aState.mPrevBottomMargin = 0; + } + } + } + else { + nscoord autoHeight = aState.mY; + + // Shrink wrap our height around our contents. + if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) { + // When we are a bottom-margin root make sure that our last + // childs bottom margin is fully applied. + // XXX check for a fit + autoHeight += aState.mPrevBottomMargin; + } + autoHeight += borderPadding.bottom; + + // Apply min/max values #ifdef MOZ_MATHML - // XXX Here in ComputeFinalSize() - // XXX What to do when min/max values are applied to the height? - // How do all this impact on the first line of the block? + // XXX Here in ComputeFinalSize() + // XXX What to do when min/max values are applied to the height? + // How do all this impact on the first line of the block? #endif - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { - nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight > computedMaxHeight) { - autoHeight = computedMaxHeight; - } - } - if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { - nscoord computedMinHeight = aReflowState.mComputedMinHeight + - borderPadding.top + borderPadding.bottom; - if (autoHeight < computedMinHeight) { - autoHeight = computedMinHeight; - } - } - aMetrics.height = autoHeight; - - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - maxHeight = aState.mMaxElementSize.height + - borderPadding.top + borderPadding.bottom; + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxHeight) { + nscoord computedMaxHeight = aReflowState.mComputedMaxHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight > computedMaxHeight) { + autoHeight = computedMaxHeight; } } + if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMinHeight) { + nscoord computedMinHeight = aReflowState.mComputedMinHeight + + borderPadding.top + borderPadding.bottom; + if (autoHeight < computedMinHeight) { + autoHeight = computedMinHeight; + } + } + aMetrics.height = autoHeight; + + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + maxHeight = aState.mMaxElementSize.height + + borderPadding.top + borderPadding.bottom; + } + } #ifndef MOZ_MATHML - aMetrics.ascent = aMetrics.height; - aMetrics.descent = 0; + aMetrics.ascent = aMetrics.height; + aMetrics.descent = 0; #else - if (mLines && mLines->mFirstChild && mLines->IsBlock()) { - // mAscent is not yet set because we didn't call VerticalAlignFrames() - // on mLines. So we need to fetch the ascent of the first child of mLines - nsBlockFrame* bf; - nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); - if (NS_SUCCEEDED(res) && bf) { - mAscent = bf->GetAscent(); - } + if (mLines && mLines->mFirstChild && mLines->IsBlock()) { + // mAscent is not yet set because we didn't call VerticalAlignFrames() + // on mLines. So we need to fetch the ascent of the first child of mLines + nsBlockFrame* bf; + nsresult res = mLines->mFirstChild->QueryInterface(kBlockFrameCID, (void**)&bf); + if (NS_SUCCEEDED(res) && bf) { + mAscent = bf->GetAscent(); } - aMetrics.ascent = mAscent; - aMetrics.descent = aMetrics.height - aMetrics.ascent; + } + aMetrics.ascent = mAscent; + aMetrics.descent = aMetrics.height - aMetrics.ascent; #endif - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - // Store away the final value - aMetrics.maxElementSize->width = maxWidth; - aMetrics.maxElementSize->height = maxHeight; + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + // Store away the final value + aMetrics.maxElementSize->width = maxWidth; + aMetrics.maxElementSize->height = maxHeight; #ifdef NOISY_MAX_ELEMENT_SIZE - printf ("nsBlockFrame::CFS: %p returning MES %d\n", - this, aMetrics.maxElementSize->width); -#endif - } - - // Return bottom margin information - aMetrics.mCarriedOutBottomMargin = - aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; - -#ifdef DEBUG_blocks - if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { - ListTag(stdout); - printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); - } - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && - ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { - ListTag(stdout); - printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } -#endif -#ifdef NOISY_MAX_ELEMENT_SIZE - if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { - IndentBy(stdout, GetDepth()); - if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { - printf("PASS1 "); - } - ListTag(stdout); - printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", - maxWidth, maxHeight, aMetrics.width, aMetrics.height, - aState.mReflowState.availableWidth, - aState.mReflowState.availableHeight); - } + printf ("nsBlockFrame::CFS: %p returning MES %d\n", + this, aMetrics.maxElementSize->width); #endif } + // Return bottom margin information + aMetrics.mCarriedOutBottomMargin = + aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin; + +#ifdef DEBUG_blocks + if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) { + ListTag(stdout); + printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height); + } + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) && + ((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) { + ListTag(stdout); + printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif +#ifdef NOISY_MAX_ELEMENT_SIZE + if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) { + IndentBy(stdout, GetDepth()); + if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) { + printf("PASS1 "); + } + ListTag(stdout); + printf(": max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n", + maxWidth, maxHeight, aMetrics.width, aMetrics.height, + aState.mReflowState.availableWidth, + aState.mReflowState.availableHeight); + } +#endif + // If we're requested to update our maximum width, then compute it if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) { // We need to add in for the right border/padding @@ -4038,15 +3990,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n", aState.mPrevBottomMargin, collapsedBottomMargin); #endif - if (collapsedBottomMargin >= 0) { - aState.mPrevBottomMargin = collapsedBottomMargin; - } - else { - // Leave margin alone: it was a collapsed paragraph that - // must not interfere with the running margin calculations - // (in other words it should act like an empty line of - // whitespace). - } + aState.mPrevBottomMargin = collapsedBottomMargin; } #ifdef NOISY_VERTICAL_MARGINS ListTag(stdout); @@ -6889,9 +6833,6 @@ nsBlockFrame::Init(nsIPresContext* aPresContext, nsresult rv = nsBlockFrameSuper::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); - if (nsBlockReflowContext::IsHTMLParagraph(this)) { - mState |= NS_BLOCK_IS_HTML_PARAGRAPH; - } return rv; }