nsReflowStatus frameReflowStatus=NS_FRAME_COMPLETE; nsMargin computedOffsets; rv = brc.ReflowBlock(frame, availSpace, applyTopMargin, aState.mPrevBottomMargin, aState.IsAdjacentWithTop(), computedOffsets, frameReflowStatus); if (brc.BlockShouldInvalidateItself() && !mRect.IsEmpty()) { Invalidate(aState.mPresContext, mRect);
aState.mPrevChild = aFrame;     aState.GetAvailableSpace();  if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {   nsIFrame* nextInFlow; nsresult rv; rv = nsHTMLContainerFrame::CreateNextInFlow(aState.mPresContext, this, aFrame, nextInFlow); if (NS_OK != rv) { aReflowResult = rv; return PR_FALSE; } if (nsnull != nextInFlow) {   LineData* line = new LineData(nextInFlow, 1, (LINE_IS_BLOCK | LINE_LAST_CONTENT_IS_COMPLETE)); if (nsnull == line) { aReflowResult = NS_ERROR_OUT_OF_MEMORY; return PR_FALSE; } line->mNext = aLine->mNext; aLine->mNext = line; }     aState.mPrevLine = aLine; if (nsnull != aLine->mNext) { PushLines(aState); } aReflowResult = NS_INLINE_LINE_BREAK_AFTER(reflowStatus); return PR_FALSE;
nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,                               line_iterator aLine,                               PRBool* aKeepReflowGoing){  NS_PRECONDITION(*aKeepReflowGoing, "bad caller");  nsresult rv = NS_OK;  nsIFrame* frame = aLine->mFirstChild;  // Prepare the block reflow engine  const nsStyleDisplay* display;  frame->GetStyleData(eStyleStruct_Display,                      (const nsStyleStruct*&) display);  nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,                           aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),                           aState.GetFlag(BRS_COMPUTEMAXWIDTH));  brc.SetNextRCFrame(aState.mNextRCFrame);  // See if we should apply the top margin. If the block frame being  // reflowed is a continuation (non-null prev-in-flow) then we don't  // apply its top margin because its not significant. Otherwise, dig  // deeper.  PRBool applyTopMargin = PR_FALSE;  nsIFrame* framePrevInFlow;  frame->GetPrevInFlow(&framePrevInFlow);  if (nsnull == framePrevInFlow) {    applyTopMargin = ShouldApplyTopMargin(aState, aLine);  }  // Clear past floaters before the block if the clear style is not none  PRUint8 breakType = display->mBreakType;  aLine->SetBreakType(breakType);  if (NS_STYLE_CLEAR_NONE != breakType) {    PRBool alsoApplyTopMargin = aState.ClearPastFloaters(breakType);    if (alsoApplyTopMargin) {      applyTopMargin = PR_TRUE;    }#ifdef NOISY_VERTICAL_MARGINS    ListTag(stdout);    printf(": y=%d child ", aState.mY);    ListTag(stdout, frame);    printf(" has clear of %d => %s, mPrevBottomMargin=%d\n",           breakType,           applyTopMargin ? "applyTopMargin" : "nope",           aState.mPrevBottomMargin);#endif  }  nscoord topMargin = 0;  if (applyTopMargin) {    // Precompute the blocks top margin value so that we can get the    // correct available space (there might be a floater that's    // already been placed below the aState.mPrevBottomMargin    // Setup a reflowState to get the style computed margin-top value    // The availSpace here is irrelevant to our needs - all we want    // out if this setup is the margin-top value which doesn't depend    // on the childs available space.    nsSize availSpace(aState.mContentArea.width, NS_UNCONSTRAINEDSIZE);    nsHTMLReflowState reflowState(aState.mPresContext, aState.mReflowState,                                  frame, availSpace);    // Now compute the collapsed margin-top value into aState.mPrevBottomMargin    nsCollapsingMargin oldPrevBottomMargin = aState.mPrevBottomMargin;    nsBlockReflowContext::ComputeCollapsedTopMargin(aState.mPresContext,                                                    reflowState,                                                    aState.mPrevBottomMargin);    topMargin = aState.mPrevBottomMargin.get();    aState.mPrevBottomMargin = oldPrevBottomMargin; // perhaps not needed    // Temporarily advance the running Y value so that the    // GetAvailableSpace method will return the right available    // space. This undone as soon as the margin is computed.    aState.mY += topMargin;  }  // Compute the available space for the block  aState.GetAvailableSpace();#ifdef REALLY_NOISY_REFLOW  printf("setting line %p isImpacted to %s\n", aLine, aState.IsImpactedByFloater()?"true":"false");#endif  PRBool isImpacted = aState.IsImpactedByFloater() ? PR_TRUE : PR_FALSE;  aLine->SetLineIsImpactedByFloater(isImpacted);  nsSplittableType splitType = NS_FRAME_NOT_SPLITTABLE;  frame->IsSplittable(splitType);  nsRect availSpace;  aState.ComputeBlockAvailSpace(frame, splitType, display, availSpace);  // Now put the Y coordinate back and flow the block letting the  // block reflow context compute the same top margin value we just  // computed (sigh).  if (topMargin) {    aState.mY -= topMargin;    availSpace.y -= topMargin;    if (NS_UNCONSTRAINEDSIZE != availSpace.height) {      availSpace.height += topMargin;    }  }  // Reflow the block into the available space  nsReflowStatus frameReflowStatus=NS_FRAME_COMPLETE;  nsMargin computedOffsets;  rv = brc.ReflowBlock(frame, availSpace,                       applyTopMargin, aState.mPrevBottomMargin,                       aState.IsAdjacentWithTop(),                       computedOffsets, frameReflowStatus);  if (brc.BlockShouldInvalidateItself() && !mRect.IsEmpty()) {    Invalidate(aState.mPresContext, mRect);  }  if (frame == aState.mNextRCFrame) {    // NULL out mNextRCFrame so if we reflow it again we don't think it's still    // an incremental reflow    aState.mNextRCFrame = nsnull;  }  if (NS_FAILED(rv)) {    return rv;  }  aState.mPrevChild = frame;#if defined(REFLOW_STATUS_COVERAGE)  RecordReflowStatus(PR_TRUE, frameReflowStatus);#endif  if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {    // None of the child block fits.    PushLines(aState, aLine.prev());    *aKeepReflowGoing = PR_FALSE;    aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;  }  else {    // Note: line-break-after a block is a nop    // Try to place the child block    PRBool isAdjacentWithTop = aState.IsAdjacentWithTop();    nsCollapsingMargin collapsedBottomMargin;    nsRect combinedArea(0,0,0,0);    *aKeepReflowGoing = brc.PlaceBlock(aState.mReflowState, isAdjacentWithTop, computedOffsets,                                       collapsedBottomMargin, aLine->mBounds, combinedArea);    aLine->SetCarriedOutBottomMargin(collapsedBottomMargin);    if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {      // Mark the line as dirty so once we known the final shrink wrap width      // we can reflow the block to the correct size      // XXX We don't always need to do this...      aLine->MarkDirty();      aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);    }    if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {      // Add the right margin to the line's bounds.  That way it will be      // taken into account when we compute our shrink wrap size.      nscoord marginRight = brc.GetMargin().right;      if (marginRight != NS_UNCONSTRAINEDSIZE) {        aLine->mBounds.width += marginRight;      }    }    aLine->SetCombinedArea(combinedArea);    if (*aKeepReflowGoing) {      // Some of the child block fit      // Advance to new Y position      nscoord newY = aLine->mBounds.YMost();      aState.mY = newY;      // Continue the block frame now if it didn't completely fit in      // the available space.      if (NS_FRAME_IS_NOT_COMPLETE(frameReflowStatus)) {        PRBool madeContinuation;        rv = CreateContinuationFor(aState, aLine, frame, madeContinuation);        if (NS_FAILED(rv)) {          return rv;        }        // Push continuation to a new line, but only if we actually        // made one.        if (madeContinuation) {          frame->GetNextSibling(&frame);          nsLineBox* line = aState.NewLineBox(frame, 1, PR_TRUE);          if (nsnull == line) {            return NS_ERROR_OUT_OF_MEMORY;          }          mLines.after_insert(aLine, line);          // Do not count the continuation child on the line it used          // to be on          aLine->SetChildCount(aLine->GetChildCount() - 1);       }        // Advance to next line since some of the block fit. That way        // only the following lines will be pushed.        PushLines(aState, aLine);        aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;        *aKeepReflowGoing = PR_FALSE;        // The bottom margin for a block is only applied on the last        // flow block. Since we just continued the child block frame,        // we know that line->mFirstChild is not the last flow block        // therefore zero out the running margin value.#ifdef NOISY_VERTICAL_MARGINS        ListTag(stdout);        printf(": reflow incomplete, frame=");        nsFrame::ListTag(stdout, frame);        printf(" prevBottomMargin=%d, setting to zero\n",               aState.mPrevBottomMargin);#endif        aState.mPrevBottomMargin.Zero();      }      else {#ifdef NOISY_VERTICAL_MARGINS        ListTag(stdout);        printf(": reflow complete for ");        nsFrame::ListTag(stdout, frame);        printf(" prevBottomMargin=%d collapsedBottomMargin=%d\n",               aState.mPrevBottomMargin, collapsedBottomMargin.get());#endif        aState.mPrevBottomMargin = collapsedBottomMargin;      }#ifdef NOISY_VERTICAL_MARGINS      ListTag(stdout);      printf(": frame=");      nsFrame::ListTag(stdout, frame);      printf(" carriedOutBottomMargin=%d collapsedBottomMargin=%d => %d\n",             brc.GetCarriedOutBottomMargin(), collapsedBottomMargin.get(),             aState.mPrevBottomMargin);#endif      // Post-process the "line"      nsSize maxElementSize(0, 0);      if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {        maxElementSize = brc.GetMaxElementSize();        if (aState.IsImpactedByFloater() &&            (NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {          // Add in floater impacts to the lines max-element-size, but          // only if the block element isn't one of us (otherwise the          // floater impacts will be counted twice).          ComputeLineMaxElementSize(aState, aLine, &maxElementSize);        }      }      // If we asked the block to update its maximum width, then record the      // updated value in the line, and update the current maximum width      if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {        aLine->mMaximumWidth = brc.GetMaximumWidth();        // need to add in margin on block's reported max width (see bug 35964)        const nsMargin& margin = brc.GetMargin();        aLine->mMaximumWidth += margin.left + margin.right;#ifdef NOISY_MAXIMUM_WIDTH        printf("nsBlockFrame::ReflowBlockFrame parent block %p line %p aLine->mMaximumWidth set to brc.GetMaximumWidth %d, updating aState.mMaximumWidth\n",              this, aLine, aLine->mMaximumWidth);#endif        aState.UpdateMaximumWidth(aLine->mMaximumWidth);      }      PostPlaceLine(aState, aLine, maxElementSize);      // If the block frame that we just reflowed happens to be our      // first block, then its computed ascent is ours      if (frame == GetTopBlockChild()) {        const nsHTMLReflowMetrics& metrics = brc.GetMetrics();        mAscent = metrics.ascent;      }      // Place the "marker" (bullet) frame.      //      // According to the CSS2 spec, section 12.6.1, the "marker" box      // participates in the height calculation of the list-item box's      // first line box.      //      // There are exactly two places a bullet can be placed: near the      // first or second line. Its only placed on the second line in a      // rare case: an empty first line followed by a second line that      // contains a block (example: <LI>\n<P>... ). This is where      // the second case can happen.      if (mBullet && HaveOutsideBullet() &&          ((aLine == mLines.front()) ||           ((0 == mLines.front()->mBounds.height) &&            (aLine == begin_lines().next())))) {        // Reflow the bullet        nsHTMLReflowMetrics metrics(nsnull);        ReflowBullet(aState, metrics);        // Doing the alignment using |mAscent| will also cater for bullets        // that are placed next to a child block (bug 92896)        // (Note that mAscent should be set by now, otherwise why would        // we be placing the bullet yet?)        // Tall bullets won't look particularly nice here...        nsRect bbox;        mBullet->GetRect(bbox);        nscoord bulletTopMargin = applyTopMargin                                    ? collapsedBottomMargin.get()                                    : 0;        bbox.y = aState.BorderPadding().top + mAscent -          metrics.ascent + bulletTopMargin;        mBullet->SetRect(aState.mPresContext, bbox);      }    }    else {      // None of the block fits. Determine the correct reflow status.      if (aLine == mLines.front()) {        // If it's our very first line then we need to be pushed to        // our parents next-in-flow. Therefore, return break-before        // status for our reflow status.        aState.mReflowStatus = NS_INLINE_LINE_BREAK_BEFORE();      }      else {        // Push the line that didn't fit and any lines that follow it        // to our next-in-flow.        PushLines(aState, aLine.prev());        aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;      }    }  }#ifdef DEBUG  VerifyLines(PR_TRUE);#endif  return rv;}