if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {   nscoord computedHeightLeftOver = aReflowState.mComputedHeight; if (mPrevInFlow) {  for (nsIFrame* prev = mPrevInFlow; prev; prev = prev->GetPrevInFlow()) { nscoord contentHeight = prev->GetRect().height; if (prev == mPrevInFlow) {   contentHeight -= aReflowState.mComputedBorderPadding.top;
aMetrics.ascent = aMetrics.height; aMetrics.descent = 0;   if (aState.mComputeMaxElementSize) { *aMetrics.maxElementSize = aState.mMaxElementSize;    aMetrics.maxElementSize->width += aState.mBorderPadding.left + aState.mBorderPadding.right; aMetrics.maxElementSize->height += aState.mBorderPadding.top + aState.mBorderPadding.bottom;   LineData* line = mLines; PRInt32 maxLeft = 0, maxRight = 0; while (nsnull != line) { if (nsnull != line->mFloaters) { nsRect r; nsMargin floaterMargin; PRInt32 leftSum = 0, rightSum = 0; PRInt32 n = line->mFloaters->Count(); for (PRInt32 i = 0; i < n; i++) { nsPlaceholderFrame* placeholder = (nsPlaceholderFrame*) line->mFloaters->ElementAt(i); nsIFrame* floater = placeholder->GetAnchoredItem(); floater->GetRect(r); const nsStyleDisplay* floaterDisplay; const nsStyleSpacing* floaterSpacing; floater->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)floaterDisplay); floater->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)floaterSpacing); floaterSpacing->CalcMarginFor(floater, floaterMargin); nscoord width = r.width + floaterMargin.left + floaterMargin.right; NS_ASSERTION((NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) || (NS_STYLE_FLOAT_RIGHT == floaterDisplay->mFloats), "invalid float type"); if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) { leftSum += width;
nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,                               nsBlockReflowState&      aState,                               nsHTMLReflowMetrics&     aMetrics){  const nsMargin& borderPadding = aState.BorderPadding();#ifdef NOISY_FINAL_SIZE  ListTag(stdout);  printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",         aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",         aState.mPrevBottomMargin,         borderPadding.top, borderPadding.bottom);#endif  // XXXldb Handling min-width/max-width stuff after reflowing children  // seems wrong.  But IIRC this function only does more than a little  // bit in rare cases (or something like that, I'm not really sure).  // What are those cases, and do we get the wrong behavior?  // Compute final width  nscoord maxElementWidth = 0;#ifdef NOISY_KIDXMOST  printf("%p aState.mKidXMost=%d\n", this, aState.mKidXMost); #endif  if (!HaveAutoWidth(aReflowState)) {    // Use style defined width    aMetrics.width = borderPadding.left + aReflowState.mComputedWidth +      borderPadding.right;    if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {      if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Percent) {        // for percentage widths, |HaveAutoWidth| is sometimes true and        // sometimes false (XXXldb check that this is really true), and        // we want the max-element-width to be the same either way        // (i.e., whether it's an uncontsrained reflow or a fixed-width        // reflow).  Thus, do the same thing we do below.        maxElementWidth = aState.mMaxElementWidth +          borderPadding.left + borderPadding.right;      } else {        // When style defines the width use it for the max-element-width        // because we can't shrink any smaller.        maxElementWidth = aMetrics.width;      }    }  }  else {    nscoord computedWidth;    // XXX Misleading comment:    // 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)) {      // XXX Misleading comment:      // 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)      // XXXldb In what cases do we reach this code?      computedWidth = borderPadding.left + aState.mContentArea.width +        borderPadding.right;    } else {      computedWidth = aState.mKidXMost;      if (NS_BLOCK_SPACE_MGR & mState) {        // Include the space manager's state to properly account for the        // extent of floated elements.        nscoord xmost;        if (aReflowState.mSpaceManager->XMost(xmost) &&            computedWidth < xmost)          computedWidth = xmost;      }      computedWidth += borderPadding.right;    }    if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {      // Add in border and padding dimensions to already computed      // max-element-width values.      maxElementWidth = aState.mMaxElementWidth +        borderPadding.left + borderPadding.right;    }    // Apply min/max values    computedWidth -= borderPadding.left + borderPadding.right;    aReflowState.ApplyMinMaxConstraints(&computedWidth, nsnull);    computedWidth += borderPadding.left + borderPadding.right;    if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {      nscoord computedMinWidth = aReflowState.mComputedMinWidth +        borderPadding.left + borderPadding.right;      if (maxElementWidth < computedMinWidth &&          GetStylePosition()->mMinWidth.GetUnit() != eStyleUnit_Percent) {        maxElementWidth = 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      const nsHTMLReflowState *prs = aReflowState.parentReflowState;      if (!prs || NS_SHRINKWRAPWIDTH != prs->mComputedWidth) {        // XXX Is this only used on things that are already NS_BLOCK_SPACE_MGR        // and NS_BLOCK_MARGIN_ROOT?        nsHTMLReflowState reflowState(aReflowState);        reflowState.mComputedWidth = aMetrics.width - borderPadding.left -                                     borderPadding.right;        reflowState.reason = eReflowReason_Resize;        reflowState.mSpaceManager->ClearRegions();#ifdef DEBUG        nscoord oldDesiredWidth = aMetrics.width;#endif        nsBlockReflowState state(reflowState, aState.mPresContext, this,                                 aMetrics,                                 aReflowState.mFlags.mHasClearance || (NS_BLOCK_MARGIN_ROOT & mState),                                 (NS_BLOCK_MARGIN_ROOT & mState));        // Don't try to pull up any new content from our next in flow. Shrinkwrapping        // shouldn't make us shorter anyway.        ReflowDirtyLines(state, PR_FALSE);        aState.mY = state.mY;        NS_ASSERTION(oldDesiredWidth == aMetrics.width, "bad desired width");      }    }  }  // Return bottom margin information  // rbs says he hit this assertion occasionally (see bug 86947), so  // just set the margin to zero and we'll figure out why later  //NS_ASSERTION(aMetrics.mCarriedOutBottomMargin.IsZero(),  //             "someone else set the margin");  nscoord nonCarriedOutVerticalMargin = 0;  if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {    // Apply rule from CSS 2.1 section 8.3.1. If we have some empty    // line with clearance and a non-zero top margin and all    // subsequent lines are empty, then we do not allow our childrens'    // carried out bottom margin to be carried out of us and collapse    // with our own bottom margin.    if (CheckForCollapsedBottomMarginFromClearanceLine()) {      // Convert the children's carried out margin to something that      // we will include in our height      nonCarriedOutVerticalMargin = aState.mPrevBottomMargin.get();      aState.mPrevBottomMargin.Zero();    }    aMetrics.mCarriedOutBottomMargin = aState.mPrevBottomMargin;  } else {    aMetrics.mCarriedOutBottomMargin.Zero();  }  // Compute final height  if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) {    if (NS_FRAME_IS_COMPLETE(aState.mReflowStatus)) {      // Figure out how much of the computed height should be      // applied to this frame.      nscoord computedHeightLeftOver = aReflowState.mComputedHeight;      if (mPrevInFlow) {        // Reduce the height by the computed height of prev-in-flows.        for (nsIFrame* prev = mPrevInFlow; prev; prev = prev->GetPrevInFlow()) {          nscoord contentHeight = prev->GetRect().height;          if (prev == mPrevInFlow) {            // subtract off the style top borderpadding to get the            // content height            contentHeight -= aReflowState.mComputedBorderPadding.top;          }          computedHeightLeftOver -= contentHeight;        }        // We may have stretched the frame beyond its computed height. Oh well.        computedHeightLeftOver = PR_MAX(0, computedHeightLeftOver);      }      aMetrics.height = borderPadding.top + computedHeightLeftOver + borderPadding.bottom;      if (computedHeightLeftOver > 0 &&          aMetrics.height > aReflowState.availableHeight) {        // We don't fit and we consumed some of the computed height,        // so we should consume all the available height and then        // break.  If our bottom border/padding straddles the break        // point, then this will increase our height and push the        // border/padding to the next page/column.        aMetrics.height = aReflowState.availableHeight;        aState.mReflowStatus |= NS_FRAME_NOT_COMPLETE;      }    }    else {      // Use the current height; continuations will take up the rest.      // Do extend the height to at least consume the available      // height, otherwise our left/right borders (for example) won't      // extend all the way to the break.      aMetrics.height = PR_MAX(aReflowState.availableHeight,                               aState.mY + nonCarriedOutVerticalMargin);    }    // Don't carry out a bottom margin when our height is fixed.    aMetrics.mCarriedOutBottomMargin.Zero();  }  else {    nscoord autoHeight = aState.mY + nonCarriedOutVerticalMargin;    // 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.      // Apply the margin only if there's space for it.      if (autoHeight < aState.mReflowState.availableHeight)      {        // Truncate bottom margin if it doesn't fit to our available height.        autoHeight = PR_MIN(autoHeight + aState.mPrevBottomMargin.get(), aState.mReflowState.availableHeight);      }    }    if (NS_BLOCK_SPACE_MGR & mState) {      // Include the space manager's state to properly account for the      // bottom margin of any floated elements; e.g., inside a table cell.      nscoord ymost;      if (aReflowState.mSpaceManager->YMost(ymost) &&          autoHeight < ymost)        autoHeight = ymost;    }    // Apply min/max values    autoHeight -= borderPadding.top;    nscoord oldAutoHeight = autoHeight;    aReflowState.ApplyMinMaxConstraints(nsnull, &autoHeight);    if (autoHeight != oldAutoHeight) {      // Our min-height or max-height made our height change.  Don't carry out      // our kids' bottom margins.      aMetrics.mCarriedOutBottomMargin.Zero();    }    autoHeight += borderPadding.top + borderPadding.bottom;    aMetrics.height = autoHeight;  }  aMetrics.ascent = mAscent;  aMetrics.descent = aMetrics.height - aMetrics.ascent;  if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {    // Store away the final value    aMetrics.mMaxElementWidth = maxElementWidth;#ifdef DEBUG    if (gNoisyMaxElementWidth) {      IndentBy(stdout, gNoiseIndent);      printf ("nsBlockFrame::CFS: %p returning MEW %d\n",               NS_STATIC_CAST(void*, this), aMetrics.mMaxElementWidth);    }#endif  }#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_COMPUTEMAXELEMENTWIDTH) &&      (maxElementWidth > aMetrics.width))) {    ListTag(stdout);    printf(": WARNING: max-element-width:%d desired:%d,%d maxSize:%d,%d\n",           maxElementWidth, aMetrics.width, aMetrics.height,           aState.mReflowState.availableWidth,           aState.mReflowState.availableHeight);  }#endif#ifdef DEBUG  if (gNoisyMaxElementWidth) {    if (aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {      IndentBy(stdout, gNoiseIndent);      if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {        printf("PASS1 ");      }      ListTag(stdout);      printf(": max-element-width:%d desired:%d,%d maxSize:%d,%d\n",             maxElementWidth, 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)) {    if (!HaveAutoWidth(aReflowState) &&        aReflowState.mStylePosition->mWidth.GetUnit() != eStyleUnit_Percent) {      aMetrics.mMaximumWidth = aMetrics.width;    } else {      // We need to add in for the right border/padding      // The maximum width in the reflow state includes the left      // border/padding but not the right.      aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;    }#ifdef NOISY_MAXIMUM_WIDTH    printf("nsBlockFrame::ComputeFinalSize block %p setting aMetrics.mMaximumWidth to %d\n", this, aMetrics.mMaximumWidth);#endif  }  ComputeCombinedArea(aReflowState, aMetrics);}