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

This commit is contained in:
dbaron%fas.harvard.edu 2000-06-29 22:03:42 +00:00
parent 5fa639ccb3
commit d05d4bef76
12 changed files with 1378 additions and 1932 deletions

View File

@ -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 <P>'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 <b>only</b> 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;
}

View File

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

View File

@ -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<nsIContent> content;
nsresult rv = aFrame->GetContent(getter_AddRefs(content));
if (NS_SUCCEEDED(rv) && content) {
nsCOMPtr<nsIDOMHTMLParagraphElement> 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<nsIAtom> 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 <P> 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 <P> and it's parent is special, then collapse the <P>'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;

View File

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

View File

@ -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 <P>'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 <b>only</b> 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;
}

View File

@ -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 <P>'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 <b>only</b> 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;
}

View File

@ -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 <P>'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 <b>only</b> 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;
}

View File

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

View File

@ -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<nsIContent> content;
nsresult rv = aFrame->GetContent(getter_AddRefs(content));
if (NS_SUCCEEDED(rv) && content) {
nsCOMPtr<nsIDOMHTMLParagraphElement> 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<nsIAtom> 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 <P> 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 <P> and it's parent is special, then collapse the <P>'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;

View File

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

View File

@ -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 <P>'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 <b>only</b> 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;
}

View File

@ -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 <P>'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 <b>only</b> 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;
}