if (command) {  reflow += " (";  reflow += kReflowCommandType[command->Type()];  reflow += ")"; } }  IndentBy(stdout, gNoiseIndent); ListTag(stdout); printf(": begin %s reflow availSize=%d,%d computedSize=%d,%d\n", reflow.get(), aReflowState.availableWidth, aReflowState.availableHeight, aReflowState.mComputedWidth, aReflowState.mComputedHeight);
if (nsnull != aMetrics.maxElementSize) { aMetrics.maxElementSize->width = aMetrics.width; aMetrics.maxElementSize->height = aMetrics.height;
nsBlockFrame::Reflow(nsPresContext*          aPresContext,                     nsHTMLReflowMetrics&     aMetrics,                     const nsHTMLReflowState& aReflowState,                     nsReflowStatus&          aStatus){  DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason);  DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);#ifdef DEBUG  if (gNoisyReflow) {    nsCAutoString reflow;    reflow.Append(nsHTMLReflowState::ReasonToString(aReflowState.reason));    if (aReflowState.reason == eReflowReason_Incremental) {      nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;      if (command) {        // We're the target.        reflow += " (";        reflow += kReflowCommandType[command->Type()];        reflow += ")";      }    }    IndentBy(stdout, gNoiseIndent);    ListTag(stdout);    printf(": begin %s reflow availSize=%d,%d computedSize=%d,%d\n",           reflow.get(),           aReflowState.availableWidth, aReflowState.availableHeight,           aReflowState.mComputedWidth, aReflowState.mComputedHeight);  }  AutoNoisyIndenter indent(gNoisy);  PRTime start = LL_ZERO; // Initialize these variablies to silence the compiler.  PRInt32 ctc = 0;        // We only use these if they are set (gLameReflowMetrics).  if (gLameReflowMetrics) {    start = PR_Now();    ctc = nsLineBox::GetCtorCount();  }#endif  nsSize oldSize = GetSize();  // Should we create a space manager?  nsAutoSpaceManager autoSpaceManager(NS_CONST_CAST(nsHTMLReflowState &, aReflowState));  // XXXldb If we start storing the space manager in the frame rather  // than keeping it around only during reflow then we should create it  // only when there are actually floats to manage.  Otherwise things  // like tables will gain significant bloat.  if (NS_BLOCK_SPACE_MGR & mState)    autoSpaceManager.CreateSpaceManagerFor(aPresContext, this);  // See if it's an incremental reflow command targeted only at  // absolute frames and we can skip ReflowDirtyLines().  PRBool needToReflowLines = aMetrics.mComputeMEW ||    // If we have lines with clearance, we need to check their positions    (GetStateBits() & NS_BLOCK_HAS_CLEAR_CHILDREN) ||    // The areas of any floats in this block or in blocks under us    // need to be put into the space manager --- unless we are our own    // space manager, in which case it doesn't matter.    !(GetStateBits() & NS_BLOCK_SPACE_MGR);  if (mAbsoluteContainer.HasAbsoluteFrames() &&      eReflowReason_Incremental == aReflowState.reason &&      !needToReflowLines &&      mAbsoluteContainer.ReflowingAbsolutesOnly(this, aReflowState)) {    nsSize containingBlockSize      = CalculateContainingBlockSizeForAbsolutes(aReflowState, GetSize());        mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState,                                         containingBlockSize.width,                                         containingBlockSize.height);    // Just return our current size as our desired size.    aMetrics.width = mRect.width;    aMetrics.height = mRect.height;    aMetrics.ascent = mAscent;    aMetrics.descent = aMetrics.height - aMetrics.ascent;        // Whether or not we're complete hasn't changed    aStatus = (nsnull != mNextInFlow) ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;        // Factor the absolutely positioned child bounds into the overflow area    ComputeCombinedArea(aReflowState, aMetrics);    nsRect childBounds;    mAbsoluteContainer.CalculateChildBounds(aPresContext, childBounds);    aMetrics.mOverflowArea.UnionRect(aMetrics.mOverflowArea, childBounds);        FinishAndStoreOverflow(&aMetrics);    return NS_OK;  }  // OK, some lines may be reflowed. Blow away any saved line cursor because  // we may invalidate the nondecreasing combinedArea.y/yMost invariant,  // and we may even delete the line with the line cursor.  ClearLineCursor();  if (IsFrameTreeTooDeep(aReflowState, aMetrics)) {#ifdef DEBUG_kipp    {      extern char* nsPresShell_ReflowStackPointerTop;      char marker;      char* newsp = (char*) &marker;      printf("XXX: frame tree is too deep; approx stack size = %d\n",             nsPresShell_ReflowStackPointerTop - newsp);    }#endif    aStatus = NS_FRAME_COMPLETE;    return NS_OK;  }  nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,                           aReflowState.mFlags.mHasClearance || (NS_BLOCK_MARGIN_ROOT & mState),                           (NS_BLOCK_MARGIN_ROOT & mState));  // The condition for doing Bidi resolutions includes a test for the  // dirtiness flags, because blocks sometimes send a resize reflow  // even though they have dirty children, An example where this can  // occur is when adding lines to a text control (bugs 95228 and 95400  // were caused by not doing Bidi resolution in these cases)  if (eReflowReason_Resize != aReflowState.reason ||      mState & NS_FRAME_IS_DIRTY || mState & NS_FRAME_HAS_DIRTY_CHILDREN) {#ifdef IBMBIDI    if (! mLines.empty()) {      if (aPresContext->BidiEnabled()) {        nsBidiPresUtils* bidiUtils = aPresContext->GetBidiUtils();        if (bidiUtils) {          PRBool forceReflow;          nsresult rc = bidiUtils->Resolve(aPresContext, this,                                           mLines.front()->mFirstChild,                                           forceReflow,                                           aReflowState.mFlags.mVisualBidiFormControl);          if (NS_SUCCEEDED(rc) && forceReflow) {            // Mark everything dirty            // XXXldb This should be done right.            for (line_iterator line = begin_lines(), line_end = end_lines();                 line != line_end;                 ++line)            {              line->MarkDirty();            }          }        }      }    }#endif // IBMBIDI    RenumberLists(aPresContext);  }  nsresult rv = NS_OK;  // ALWAYS drain overflow. We never want to leave the previnflow's  // overflow lines hanging around; block reflow depends on the  // overflow line lists being cleared out between reflow passes.  DrainOverflowLines(state);  switch (aReflowState.reason) {  case eReflowReason_Initial:#ifdef NOISY_REFLOW_REASON    ListTag(stdout);    printf(": reflow=initial\n");#endif    rv = PrepareInitialReflow(state);    mState &= ~NS_FRAME_FIRST_REFLOW;    break;    case eReflowReason_Dirty:    // Do nothing; the dirty lines will already have been marked.    break;  case eReflowReason_Incremental: {#ifdef NOISY_REFLOW_REASON    ListTag(stdout);    printf(": reflow=incremental ");#endif    nsReflowPath *path = aReflowState.path;    nsHTMLReflowCommand *command = path->mReflowCommand;    if (command) {#ifdef NOISY_REFLOW_REASON      printf("type=%s ", kReflowCommandType[command->Type()]);#endif      switch (command->Type()) {      case eReflowType_StyleChanged:        rv = PrepareStyleChangedReflow(state);        break;      case eReflowType_ReflowDirty:        // Do nothing; the dirty lines will already have been marked.        break;      case eReflowType_ContentChanged:        // Perform a full reflow.        rv = PrepareResizeReflow(state);        break;      default:        // We shouldn't get here. But, if we do, perform a full reflow.        NS_ERROR("unexpected reflow type");        rv = PrepareResizeReflow(state);        break;      }    }    if (path->FirstChild() != path->EndChildren()) {      // We're along the reflow path, but not necessarily the target      // of the reflow.#ifdef NOISY_REFLOW_REASON      ListTag(stdout);      printf(" next={ ");      for (nsReflowPath::iterator iter = path->FirstChild();           iter != path->EndChildren();           ++iter) {        nsFrame::ListTag(stdout, *iter);        printf(" ");      }      printf("}");#endif      rv = PrepareChildIncrementalReflow(state);    }#ifdef NOISY_REFLOW_REASON    printf("\n");#endif    break;  }  case eReflowReason_StyleChange:    rv = PrepareStyleChangedReflow(state);    break;  case eReflowReason_Resize:  default:#ifdef NOISY_REFLOW_REASON    ListTag(stdout);    printf(": reflow=resize (%d)\n", aReflowState.reason);#endif    rv = PrepareResizeReflow(state);    break;  }  NS_ASSERTION(NS_SUCCEEDED(rv), "setting up reflow failed");  if (NS_FAILED(rv)) return rv;  // Now reflow...  rv = ReflowDirtyLines(state, PR_TRUE);  NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");  if (NS_FAILED(rv)) return rv;  // If the block is complete, put continuted floats in the closest ancestor   // block that uses the same space manager and leave the block complete; this   // allows subsequent lines on the page to be impacted by floats. If the   // block is incomplete or there is no ancestor using the same space manager,   // put continued floats at the beginning of the first overflow line.  if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) &&       state.mOverflowPlaceholders.NotEmpty()) {    PRBool gaveToAncestor = PR_FALSE;    if (NS_FRAME_IS_COMPLETE(state.mReflowStatus)) {      // find the nearest block ancestor that uses the same space manager      for (const nsHTMLReflowState* ancestorRS = aReflowState.parentReflowState;            ancestorRS;            ancestorRS = ancestorRS->parentReflowState) {        nsIFrame* ancestor = ancestorRS->frame;        nsIAtom* fType = ancestor->GetType();        if ((nsLayoutAtoms::blockFrame == fType || nsLayoutAtoms::areaFrame == fType) &&            aReflowState.mSpaceManager == ancestorRS->mSpaceManager) {          // Put the continued floats in ancestor since it uses the same space manager          nsFrameList* ancestorPlace =            ((nsBlockFrame*)ancestor)->GetOverflowPlaceholders();          // The ancestor should have this list, since it's being reflowed. But maybe          // it isn't because of reflow roots or something.          if (ancestorPlace) {            for (nsIFrame* f = state.mOverflowPlaceholders.FirstChild();                 f; f = f->GetNextSibling()) {              NS_ASSERTION(IsContinuationPlaceholder(f),                           "Overflow placeholders must be continuation placeholders");              ReparentFrame(f, this, ancestorRS->frame);              nsIFrame* oof = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);              mFloats.RemoveFrame(oof);              ReparentFrame(oof, this, ancestorRS->frame);              // Clear the next-sibling in case the frame wasn't in mFloats              oof->SetNextSibling(nsnull);              NS_STATIC_CAST(nsBlockFrame*, ancestorRS->frame)                ->mFloats.AppendFrame(nsnull, oof);            }            ancestorPlace->AppendFrames(nsnull, state.mOverflowPlaceholders.FirstChild());            gaveToAncestor = PR_TRUE;            break;          }        }      }    }    if (!gaveToAncestor) {      state.mOverflowPlaceholders.SortByContentOrder();      PRInt32 numOverflowPlace = state.mOverflowPlaceholders.GetLength();      nsLineBox* newLine =        state.NewLineBox(state.mOverflowPlaceholders.FirstChild(),                         numOverflowPlace, PR_FALSE);      if (newLine) {        nsLineList* overflowLines = GetOverflowLines();        if (overflowLines) {          // Put the new placeholders *last* in the overflow lines          // because they might have previnflows in the overflow lines.          nsIFrame* lastChild = overflowLines->back()->LastChild();          lastChild->SetNextSibling(state.mOverflowPlaceholders.FirstChild());          // Create a new line as the last line and put the          // placeholders there          overflowLines->push_back(newLine);        }        else {          mLines.push_back(newLine);          nsLineList::iterator nextToLastLine = ----end_lines();          PushLines(state, nextToLastLine);        }      }      state.mReflowStatus |= NS_FRAME_NOT_COMPLETE | NS_FRAME_REFLOW_NEXTINFLOW;    }  }  if (NS_FRAME_IS_NOT_COMPLETE(state.mReflowStatus)) {    if (GetOverflowLines()) {      state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;    }    if (NS_STYLE_OVERFLOW_CLIP == aReflowState.mStyleDisplay->mOverflowX) {      state.mReflowStatus = NS_FRAME_COMPLETE;    }    else {#ifdef DEBUG_kipp      ListTag(stdout); printf(": block is not complete\n");#endif    }  }  // XXX_perf get rid of this!  This is one of the things that makes  // incremental reflow O(N^2).  BuildFloatList(state);  // Compute our final size  ComputeFinalSize(aReflowState, state, aMetrics);  nsRect currentOverflow = aMetrics.mOverflowArea;  FinishAndStoreOverflow(&aMetrics);  // see if verifyReflow is enabled, and if so store off the space manager pointer#ifdef DEBUG  PRInt32 verifyReflowFlags = nsIPresShell::GetVerifyReflowFlags();  if (VERIFY_REFLOW_INCLUDE_SPACE_MANAGER & verifyReflowFlags)  {    // this is a leak of the space manager, but it's only in debug if verify reflow is enabled, so not a big deal    nsIPresShell *shell = aPresContext->GetPresShell();    if (shell) {      nsHTMLReflowState&  reflowState = (nsHTMLReflowState&)aReflowState;      rv = SetProperty(nsLayoutAtoms::spaceManagerProperty,                       reflowState.mSpaceManager,                       nsnull /* should be nsSpaceManagerDestroyer*/);      autoSpaceManager.DebugOrphanSpaceManager();    }  }#endif  // Let the absolutely positioned container reflow any absolutely positioned  // child frames that need to be reflowed, e.g., elements with a percentage  // based width/height  // We want to do this under either of two conditions:  //  1. If we didn't do the incremental reflow above.  //  2. If our size changed.  // Even though it's the padding edge that's the containing block, we  // can use our rect (the border edge) since if the border style  // changed, the reflow would have been targeted at us so we'd satisfy  // condition 1.  if (mAbsoluteContainer.HasAbsoluteFrames()) {    nsRect childBounds;    nsSize containingBlockSize      = CalculateContainingBlockSizeForAbsolutes(aReflowState,                                                 nsSize(aMetrics.width, aMetrics.height));    PRBool forceAbsoluteReflow = PR_TRUE;    PRBool cbWidthChanged = PR_TRUE;    PRBool cbHeightChanged = PR_TRUE;    if (eReflowReason_Incremental == aReflowState.reason) {      // Do the incremental reflows ... would be nice to merge with      // the reflows below but that would be more work, and more risky      mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState,                                           containingBlockSize.width,                                           containingBlockSize.height);            // If a reflow was targeted at this block then we'd better      // reflow the absolutes. For example the borders and padding      // might have changed in a way that leaves the frame size the      // same but the padding edge has moved.      if (!aReflowState.path->mReflowCommand) {        // We don't have to force reflow of all the absolutes.        forceAbsoluteReflow = PR_FALSE;                // We need to reflow those absolutes that depend on their        // placeholder position, or the containing block size in a        // direction in which the containing block size might have        // changed.  So figure out whether our size changed.        cbWidthChanged = aMetrics.width != oldSize.width;        PRBool isRoot = !GetContent()->GetParent();        // If isRoot and we have auto height, then we are the initial        // containing block and the containing block height is the        // viewport height, which can't change during incremental        // reflow.        cbHeightChanged = isRoot && NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight          ? PR_FALSE : aMetrics.height != oldSize.height;      }    }    rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState,                                   containingBlockSize.width,                                   containingBlockSize.height,                                   &childBounds,                                   forceAbsoluteReflow,                                   cbWidthChanged,                                   cbHeightChanged);    // Factor the absolutely positioned child bounds into the overflow area    aMetrics.mOverflowArea.UnionRect(currentOverflow, childBounds);    FinishAndStoreOverflow(&aMetrics);  }  // Determine if we need to repaint our border, background or outline  CheckInvalidateSizeChange(aPresContext, aMetrics, aReflowState);  // Clear the space manager pointer in the block reflow state so we  // don't waste time translating the coordinate system back on a dead  // space manager.  if (NS_BLOCK_SPACE_MGR & mState)    state.mSpaceManager = nsnull;  aStatus = state.mReflowStatus;#ifdef DEBUG  if (gNoisyReflow) {    IndentBy(stdout, gNoiseIndent);    ListTag(stdout);    printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d",           aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ",           aMetrics.width, aMetrics.height,           aMetrics.mCarriedOutBottomMargin.get());    if (mState & NS_FRAME_OUTSIDE_CHILDREN) {      printf(" combinedArea={%d,%d,%d,%d}",             aMetrics.mOverflowArea.x,             aMetrics.mOverflowArea.y,             aMetrics.mOverflowArea.width,             aMetrics.mOverflowArea.height);    }    if (aMetrics.mComputeMEW) {      printf(" maxElementWidth=%d", aMetrics.mMaxElementWidth);    }    printf("\n");  }  if (gLameReflowMetrics) {    PRTime end = PR_Now();    PRInt32 ectc = nsLineBox::GetCtorCount();    PRInt32 numLines = mLines.size();    if (!numLines) numLines = 1;    PRTime delta, perLineDelta, lines;    LL_I2L(lines, numLines);    LL_SUB(delta, end, start);    LL_DIV(perLineDelta, delta, lines);    ListTag(stdout);    char buf[400];    PR_snprintf(buf, sizeof(buf),                ": %lld elapsed (%lld per line) (%d lines; %d new lines)",                delta, perLineDelta, numLines, ectc - ctc);    printf("%s\n", buf);  }  if (gNoisyMaxElementWidth) {    if (aMetrics.mComputeMEW) {      IndentBy(stdout, gNoiseIndent);      printf("block %p returning with maxElementWidth=%d\n",             NS_STATIC_CAST(void*, this),             aMetrics.mMaxElementWidth);    }  }#endif  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);  return rv;}