зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5fa639ccb3
Коммит
d05d4bef76
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче