Bug 253977 backout because of possible Tp regression on btek.

This commit is contained in:
roc+%cs.cmu.edu 2004-08-22 03:50:59 +00:00
Родитель 451af652a5
Коммит c930dd179f
6 изменённых файлов: 76 добавлений и 206 удалений

Просмотреть файл

@ -721,17 +721,13 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
nsresult rv = NS_OK; 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(aPresContext);
switch (aReflowState.reason) { switch (aReflowState.reason) {
case eReflowReason_Initial: case eReflowReason_Initial:
#ifdef NOISY_REFLOW_REASON #ifdef NOISY_REFLOW_REASON
ListTag(stdout); ListTag(stdout);
printf(": reflow=initial\n"); printf(": reflow=initial\n");
#endif #endif
DrainOverflowLines(aPresContext);
rv = PrepareInitialReflow(state); rv = PrepareInitialReflow(state);
mState &= ~NS_FRAME_FIRST_REFLOW; mState &= ~NS_FRAME_FIRST_REFLOW;
break; break;
@ -800,6 +796,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
} }
case eReflowReason_StyleChange: case eReflowReason_StyleChange:
DrainOverflowLines(aPresContext);
rv = PrepareStyleChangedReflow(state); rv = PrepareStyleChangedReflow(state);
break; break;
@ -809,6 +806,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
ListTag(stdout); ListTag(stdout);
printf(": reflow=resize (%d)\n", aReflowState.reason); printf(": reflow=resize (%d)\n", aReflowState.reason);
#endif #endif
DrainOverflowLines(aPresContext);
rv = PrepareResizeReflow(state); rv = PrepareResizeReflow(state);
break; break;
} }
@ -821,14 +819,6 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed"); NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
nsIFrame* nextInFlow;
GetNextInFlow(&nextInFlow);
if (nextInFlow && NS_FRAME_IS_NOT_COMPLETE(state.mReflowStatus)) {
if (GetOverflowLines() || GetOverflowPlaceholders()) {
state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
}
}
// If the block is complete, put continuted floats in the closest ancestor // 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 // 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 // allows subsequent lines on the page to be impacted by floats. If the
@ -904,7 +894,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
nsLineList::iterator nextToLastLine = ----end_lines(); nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine); PushLines(state, nextToLastLine);
} }
state.mReflowStatus |= NS_FRAME_NOT_COMPLETE; state.mReflowStatus = NS_FRAME_NOT_COMPLETE;
} }
delete overflowPlace; delete overflowPlace;
} }
@ -1714,7 +1704,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// is impacted by a float (bug 19579) // is impacted by a float (bug 19579)
aState.GetAvailableSpace(); aState.GetAvailableSpace();
// See if this is a constrained resize reflow that is not impacted by floats // See if this is this a constrained resize reflow that is not impacted by floats
if ((! aState.IsImpactedByFloat()) && if ((! aState.IsImpactedByFloat()) &&
(aState.mReflowState.reason == eReflowReason_Resize) && (aState.mReflowState.reason == eReflowReason_Resize) &&
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) { (NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
@ -2164,24 +2154,19 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (repositionViews) if (repositionViews)
::PlaceFrameView(aState.mPresContext, this); ::PlaceFrameView(aState.mPresContext, this);
PRBool touchedNextInFlow = PR_FALSE;
// Pull data from a next-in-flow if there's still room for more // Pull data from a next-in-flow if there's still room for more
// content here. // content here.
while (keepGoing && (nsnull != aState.mNextInFlow)) { while (keepGoing && (nsnull != aState.mNextInFlow)) {
touchedNextInFlow = PR_TRUE;
// Grab first line from our next-in-flow // Grab first line from our next-in-flow
nsBlockFrame* nextInFlow = aState.mNextInFlow; nsBlockFrame* nextInFlow = aState.mNextInFlow;
line_iterator nifLine = nextInFlow->begin_lines(); line_iterator nifLine = nextInFlow->begin_lines();
if (nifLine == nextInFlow->end_lines()) { if (nifLine == nextInFlow->end_lines()) {
NS_WARNING("Drained the life from next-in-flow!\n");
aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow; aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
continue; continue;
} }
// XXX See if the line is not dirty; if it's not maybe we can // XXX See if the line is not dirty; if it's not maybe we can
// avoid the pullup if it can't fit? This is important if we want // avoid the pullup if it can't fit?
// to avoid reflowing our next-in-flow!
nsLineBox *toMove = nifLine; nsLineBox *toMove = nifLine;
nextInFlow->mLines.erase(nifLine); nextInFlow->mLines.erase(nifLine);
if (0 == toMove->GetChildCount()) { if (0 == toMove->GetChildCount()) {
@ -2265,10 +2250,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.mY += metrics.height; aState.mY += metrics.height;
} }
if (touchedNextInFlow && NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
}
#ifdef DEBUG #ifdef DEBUG
if (gNoisyReflow) { if (gNoisyReflow) {
gNoiseIndent--; gNoiseIndent--;
@ -3096,7 +3077,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
UndoSplitPlaceholders(aState, lastPlaceholder); UndoSplitPlaceholders(aState, lastPlaceholder);
PushLines(aState, aLine.prev()); PushLines(aState, aLine.prev());
*aKeepReflowGoing = PR_FALSE; *aKeepReflowGoing = PR_FALSE;
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_FRAME_REFLOW_NEXTINFLOW; aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
} }
else { else {
// Note: line-break-after a block is a nop // Note: line-break-after a block is a nop
@ -3155,11 +3136,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// only the following lines will be pushed. // only the following lines will be pushed.
PushLines(aState, aLine); PushLines(aState, aLine);
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE; aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
// If we need to reflow the continuation of the block child,
// then we'd better reflow our continuation
if (frameReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
}
*aKeepReflowGoing = PR_FALSE; *aKeepReflowGoing = PR_FALSE;
// The bottom margin for a block is only applied on the last // The bottom margin for a block is only applied on the last
@ -4744,32 +4720,6 @@ nsBlockFrame::DoRemoveOutOfFlowFrame(nsPresContext* aPresContext,
aFrame->Destroy(aPresContext); aFrame->Destroy(aPresContext);
} }
// This helps us iterate over the list of all normal + overflow lines
void
nsBlockFrame::NextOverAllLines(nsLineList::iterator* aIterator,
nsLineList::iterator* aEndIterator,
PRBool* aInOverflowLines) {
(*aIterator)++;
if (*aIterator == *aEndIterator) {
if (!*aInOverflowLines) {
*aInOverflowLines = PR_TRUE;
// Try the overflow lines
nsLineList* overflowLines = GetOverflowLines();
if (overflowLines) {
*aIterator = overflowLines->begin();
*aEndIterator = overflowLines->end();
}
}
}
}
// This function removes aDeletedFrame and all its continuations. It
// is optimized for deleting a whole series of frames. The easy
// implementation would invoke itself recursively on
// aDeletedFrame->GetNextInFlow, then locate the line containing
// aDeletedFrame and remove aDeletedFrame from that line. But here we
// start by locating aDeletedFrame and then scanning from that point
// on looking for continuations.
nsresult nsresult
nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext, nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
nsIFrame* aDeletedFrame) nsIFrame* aDeletedFrame)
@ -4786,11 +4736,12 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// Find the line and the previous sibling that contains // Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line. // deletedFrame; we also find the pointer to the line.
nsLineList::iterator line = mLines.begin(), nsBlockFrame* flow = this;
line_end = mLines.end(); nsLineList* lines = &flow->mLines;
PRBool searchingOverflowList = PR_FALSE; nsLineList::iterator line = lines->begin(),
line_end = lines->end();
nsIFrame* prevSibling = nsnull; nsIFrame* prevSibling = nsnull;
for (; line != line_end; NextOverAllLines(&line, &line_end, &searchingOverflowList)) { for ( ; line != line_end; ++line) {
nsIFrame* frame = line->mFirstChild; nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->GetChildCount(); PRInt32 n = line->GetChildCount();
while (--n >= 0) { while (--n >= 0) {
@ -4806,16 +4757,12 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
NS_ERROR("can't find deleted frame in lines"); NS_ERROR("can't find deleted frame in lines");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (prevSibling && !prevSibling->GetNextSibling()) {
// We must have found the first frame in the overflow line list. So
// there is no prevSibling
prevSibling = nsnull;
}
NS_ASSERTION(!prevSibling || prevSibling->GetNextSibling() == aDeletedFrame, "bad prevSibling"); NS_ASSERTION(!prevSibling || prevSibling->GetNextSibling() == aDeletedFrame, "bad prevSibling");
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((line != line_end) && (nsnull != aDeletedFrame)) { while ((line != line_end) && (nsnull != aDeletedFrame)) {
NS_ASSERTION(this == aDeletedFrame->GetParent(), "messed up delete code"); NS_ASSERTION(flow == aDeletedFrame->GetParent(), "messed up delete code");
NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line");
// See if the frame being deleted is the last one on the line // See if the frame being deleted is the last one on the line
@ -4833,8 +4780,6 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
line->mFirstChild = nextFrame; line->mFirstChild = nextFrame;
} }
// Hmm, this won't do anything if we're removing a frame in the first
// overflow line... Hopefully doesn't matter
--line; --line;
if (line != line_end && !line->IsBlock()) { if (line != line_end && !line->IsBlock()) {
// Since we just removed a frame that follows some inline // Since we just removed a frame that follows some inline
@ -4845,7 +4790,7 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// Take aDeletedFrame out of the sibling list. Note that // Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very // prevSibling will only be nsnull when we are deleting the very
// first frame in the main or overflow list. // first frame.
if (prevSibling) { if (prevSibling) {
prevSibling->SetNextSibling(nextFrame); prevSibling->SetNextSibling(nextFrame);
} }
@ -4867,12 +4812,10 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
aDeletedFrame->Destroy(aPresContext); aDeletedFrame->Destroy(aPresContext);
aDeletedFrame = nextInFlow; aDeletedFrame = nextInFlow;
// If line is empty, remove it now. // If line is empty, remove it now
// Don't bother removing empty lines in the overflow list, they'll get if (0 == lineChildCount) {
// annihilated later
if (!searchingOverflowList && 0 == lineChildCount) {
nsLineBox *cur = line; nsLineBox *cur = line;
line = mLines.erase(line); line = lines->erase(line);
// Invalidate the space taken up by the line. // Invalidate the space taken up by the line.
// XXX We need to do this if we're removing a frame as a result of // XXX We need to do this if we're removing a frame as a result of
// a call to RemoveFrame(), but we may not need to do this in all // a call to RemoveFrame(), but we may not need to do this in all
@ -4899,12 +4842,7 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// If we just removed the last frame on the line then we need // If we just removed the last frame on the line then we need
// to advance to the next line. // to advance to the next line.
if (isLastFrameOnLine) { if (isLastFrameOnLine) {
NextOverAllLines(&line, &line_end, &searchingOverflowList); ++line;
// Detect the case when we've run off the end of the normal line
// list and we're starting the overflow line list
if (prevSibling && !prevSibling->GetNextSibling()) {
prevSibling = nsnull;
}
} }
} }
@ -4915,24 +4853,31 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// the current flow's frame list. Therefore we know that the // the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of // continuation is in a different parent. So break out of
// the loop so that we advance to the next parent. // the loop so that we advance to the next parent.
NS_ASSERTION(aDeletedFrame->GetParent() != this, "strange continuation"); NS_ASSERTION(aDeletedFrame->GetParent() != flow, "strange continuation");
break; break;
} }
} }
} }
// Advance to next flow block if the frame has more continuations
if (flow && aDeletedFrame) {
flow = (nsBlockFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
// add defensive pointer check for bug 56894
if (flow) {
lines = &flow->mLines;
line = lines->begin();
line_end = lines->end();
prevSibling = nsnull;
} else {
aDeletedFrame = nsnull;
}
}
}
#ifdef DEBUG #ifdef DEBUG
VerifyLines(PR_TRUE); VerifyLines(PR_TRUE);
#endif #endif
// Advance to next flow block if the frame has more continuations
if (aDeletedFrame) {
nsBlockFrame* nextBlock = NS_STATIC_CAST(nsBlockFrame*, aDeletedFrame->GetParent());
NS_ASSERTION(nextBlock->GetType() == nsLayoutAtoms::blockFrame,
"Our child's continuation's parent is not a block?");
return nextBlock->DoRemoveFrame(aPresContext, aDeletedFrame);
}
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -279,10 +279,6 @@ protected:
const nsPoint &aPoint, const nsPoint &aPoint,
PRInt32 &aClosestLine); PRInt32 &aClosestLine);
void NextOverAllLines(nsLineList::iterator* aIterator,
nsLineList::iterator* aEndIterator,
PRBool* aInOverflowLines);
void SetFlags(PRUint32 aFlags) { void SetFlags(PRUint32 aFlags) {
mState &= ~NS_BLOCK_FLAGS_MASK; mState &= ~NS_BLOCK_FLAGS_MASK;
mState |= aFlags; mState |= aFlags;

Просмотреть файл

@ -1317,12 +1317,6 @@ nsContainerFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
fprintf(out, " [state=%08x]", mState); fprintf(out, " [state=%08x]", mState);
} }
fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent)); fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent));
nsContainerFrame* f = NS_CONST_CAST(nsContainerFrame*, this);
nsRect* overflowArea = f->GetOverflowAreaProperty(PR_FALSE);
if (overflowArea) {
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea->x, overflowArea->y,
overflowArea->width, overflowArea->height);
}
fprintf(out, " [sc=%p]", NS_STATIC_CAST(void*, mStyleContext)); fprintf(out, " [sc=%p]", NS_STATIC_CAST(void*, mStyleContext));
// Output the children // Output the children

Просмотреть файл

@ -721,17 +721,13 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
nsresult rv = NS_OK; 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(aPresContext);
switch (aReflowState.reason) { switch (aReflowState.reason) {
case eReflowReason_Initial: case eReflowReason_Initial:
#ifdef NOISY_REFLOW_REASON #ifdef NOISY_REFLOW_REASON
ListTag(stdout); ListTag(stdout);
printf(": reflow=initial\n"); printf(": reflow=initial\n");
#endif #endif
DrainOverflowLines(aPresContext);
rv = PrepareInitialReflow(state); rv = PrepareInitialReflow(state);
mState &= ~NS_FRAME_FIRST_REFLOW; mState &= ~NS_FRAME_FIRST_REFLOW;
break; break;
@ -800,6 +796,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
} }
case eReflowReason_StyleChange: case eReflowReason_StyleChange:
DrainOverflowLines(aPresContext);
rv = PrepareStyleChangedReflow(state); rv = PrepareStyleChangedReflow(state);
break; break;
@ -809,6 +806,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
ListTag(stdout); ListTag(stdout);
printf(": reflow=resize (%d)\n", aReflowState.reason); printf(": reflow=resize (%d)\n", aReflowState.reason);
#endif #endif
DrainOverflowLines(aPresContext);
rv = PrepareResizeReflow(state); rv = PrepareResizeReflow(state);
break; break;
} }
@ -821,14 +819,6 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed"); NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
nsIFrame* nextInFlow;
GetNextInFlow(&nextInFlow);
if (nextInFlow && NS_FRAME_IS_NOT_COMPLETE(state.mReflowStatus)) {
if (GetOverflowLines() || GetOverflowPlaceholders()) {
state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
}
}
// If the block is complete, put continuted floats in the closest ancestor // 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 // 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 // allows subsequent lines on the page to be impacted by floats. If the
@ -904,7 +894,7 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
nsLineList::iterator nextToLastLine = ----end_lines(); nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine); PushLines(state, nextToLastLine);
} }
state.mReflowStatus |= NS_FRAME_NOT_COMPLETE; state.mReflowStatus = NS_FRAME_NOT_COMPLETE;
} }
delete overflowPlace; delete overflowPlace;
} }
@ -1714,7 +1704,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// is impacted by a float (bug 19579) // is impacted by a float (bug 19579)
aState.GetAvailableSpace(); aState.GetAvailableSpace();
// See if this is a constrained resize reflow that is not impacted by floats // See if this is this a constrained resize reflow that is not impacted by floats
if ((! aState.IsImpactedByFloat()) && if ((! aState.IsImpactedByFloat()) &&
(aState.mReflowState.reason == eReflowReason_Resize) && (aState.mReflowState.reason == eReflowReason_Resize) &&
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) { (NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
@ -2164,24 +2154,19 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (repositionViews) if (repositionViews)
::PlaceFrameView(aState.mPresContext, this); ::PlaceFrameView(aState.mPresContext, this);
PRBool touchedNextInFlow = PR_FALSE;
// Pull data from a next-in-flow if there's still room for more // Pull data from a next-in-flow if there's still room for more
// content here. // content here.
while (keepGoing && (nsnull != aState.mNextInFlow)) { while (keepGoing && (nsnull != aState.mNextInFlow)) {
touchedNextInFlow = PR_TRUE;
// Grab first line from our next-in-flow // Grab first line from our next-in-flow
nsBlockFrame* nextInFlow = aState.mNextInFlow; nsBlockFrame* nextInFlow = aState.mNextInFlow;
line_iterator nifLine = nextInFlow->begin_lines(); line_iterator nifLine = nextInFlow->begin_lines();
if (nifLine == nextInFlow->end_lines()) { if (nifLine == nextInFlow->end_lines()) {
NS_WARNING("Drained the life from next-in-flow!\n");
aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow; aState.mNextInFlow = (nsBlockFrame*) aState.mNextInFlow->mNextInFlow;
continue; continue;
} }
// XXX See if the line is not dirty; if it's not maybe we can // XXX See if the line is not dirty; if it's not maybe we can
// avoid the pullup if it can't fit? This is important if we want // avoid the pullup if it can't fit?
// to avoid reflowing our next-in-flow!
nsLineBox *toMove = nifLine; nsLineBox *toMove = nifLine;
nextInFlow->mLines.erase(nifLine); nextInFlow->mLines.erase(nifLine);
if (0 == toMove->GetChildCount()) { if (0 == toMove->GetChildCount()) {
@ -2265,10 +2250,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
aState.mY += metrics.height; aState.mY += metrics.height;
} }
if (touchedNextInFlow && NS_FRAME_IS_NOT_COMPLETE(aState.mReflowStatus)) {
aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
}
#ifdef DEBUG #ifdef DEBUG
if (gNoisyReflow) { if (gNoisyReflow) {
gNoiseIndent--; gNoiseIndent--;
@ -3096,7 +3077,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
UndoSplitPlaceholders(aState, lastPlaceholder); UndoSplitPlaceholders(aState, lastPlaceholder);
PushLines(aState, aLine.prev()); PushLines(aState, aLine.prev());
*aKeepReflowGoing = PR_FALSE; *aKeepReflowGoing = PR_FALSE;
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE | NS_FRAME_REFLOW_NEXTINFLOW; aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
} }
else { else {
// Note: line-break-after a block is a nop // Note: line-break-after a block is a nop
@ -3155,11 +3136,6 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
// only the following lines will be pushed. // only the following lines will be pushed.
PushLines(aState, aLine); PushLines(aState, aLine);
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE; aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
// If we need to reflow the continuation of the block child,
// then we'd better reflow our continuation
if (frameReflowStatus & NS_FRAME_REFLOW_NEXTINFLOW) {
aState.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW;
}
*aKeepReflowGoing = PR_FALSE; *aKeepReflowGoing = PR_FALSE;
// The bottom margin for a block is only applied on the last // The bottom margin for a block is only applied on the last
@ -4744,32 +4720,6 @@ nsBlockFrame::DoRemoveOutOfFlowFrame(nsPresContext* aPresContext,
aFrame->Destroy(aPresContext); aFrame->Destroy(aPresContext);
} }
// This helps us iterate over the list of all normal + overflow lines
void
nsBlockFrame::NextOverAllLines(nsLineList::iterator* aIterator,
nsLineList::iterator* aEndIterator,
PRBool* aInOverflowLines) {
(*aIterator)++;
if (*aIterator == *aEndIterator) {
if (!*aInOverflowLines) {
*aInOverflowLines = PR_TRUE;
// Try the overflow lines
nsLineList* overflowLines = GetOverflowLines();
if (overflowLines) {
*aIterator = overflowLines->begin();
*aEndIterator = overflowLines->end();
}
}
}
}
// This function removes aDeletedFrame and all its continuations. It
// is optimized for deleting a whole series of frames. The easy
// implementation would invoke itself recursively on
// aDeletedFrame->GetNextInFlow, then locate the line containing
// aDeletedFrame and remove aDeletedFrame from that line. But here we
// start by locating aDeletedFrame and then scanning from that point
// on looking for continuations.
nsresult nsresult
nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext, nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
nsIFrame* aDeletedFrame) nsIFrame* aDeletedFrame)
@ -4786,11 +4736,12 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// Find the line and the previous sibling that contains // Find the line and the previous sibling that contains
// deletedFrame; we also find the pointer to the line. // deletedFrame; we also find the pointer to the line.
nsLineList::iterator line = mLines.begin(), nsBlockFrame* flow = this;
line_end = mLines.end(); nsLineList* lines = &flow->mLines;
PRBool searchingOverflowList = PR_FALSE; nsLineList::iterator line = lines->begin(),
line_end = lines->end();
nsIFrame* prevSibling = nsnull; nsIFrame* prevSibling = nsnull;
for (; line != line_end; NextOverAllLines(&line, &line_end, &searchingOverflowList)) { for ( ; line != line_end; ++line) {
nsIFrame* frame = line->mFirstChild; nsIFrame* frame = line->mFirstChild;
PRInt32 n = line->GetChildCount(); PRInt32 n = line->GetChildCount();
while (--n >= 0) { while (--n >= 0) {
@ -4806,16 +4757,12 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
NS_ERROR("can't find deleted frame in lines"); NS_ERROR("can't find deleted frame in lines");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (prevSibling && !prevSibling->GetNextSibling()) {
// We must have found the first frame in the overflow line list. So
// there is no prevSibling
prevSibling = nsnull;
}
NS_ASSERTION(!prevSibling || prevSibling->GetNextSibling() == aDeletedFrame, "bad prevSibling"); NS_ASSERTION(!prevSibling || prevSibling->GetNextSibling() == aDeletedFrame, "bad prevSibling");
// Remove frame and all of its continuations
while (nsnull != aDeletedFrame) {
while ((line != line_end) && (nsnull != aDeletedFrame)) { while ((line != line_end) && (nsnull != aDeletedFrame)) {
NS_ASSERTION(this == aDeletedFrame->GetParent(), "messed up delete code"); NS_ASSERTION(flow == aDeletedFrame->GetParent(), "messed up delete code");
NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line"); NS_ASSERTION(line->Contains(aDeletedFrame), "frame not in line");
// See if the frame being deleted is the last one on the line // See if the frame being deleted is the last one on the line
@ -4833,8 +4780,6 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
line->mFirstChild = nextFrame; line->mFirstChild = nextFrame;
} }
// Hmm, this won't do anything if we're removing a frame in the first
// overflow line... Hopefully doesn't matter
--line; --line;
if (line != line_end && !line->IsBlock()) { if (line != line_end && !line->IsBlock()) {
// Since we just removed a frame that follows some inline // Since we just removed a frame that follows some inline
@ -4845,7 +4790,7 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// Take aDeletedFrame out of the sibling list. Note that // Take aDeletedFrame out of the sibling list. Note that
// prevSibling will only be nsnull when we are deleting the very // prevSibling will only be nsnull when we are deleting the very
// first frame in the main or overflow list. // first frame.
if (prevSibling) { if (prevSibling) {
prevSibling->SetNextSibling(nextFrame); prevSibling->SetNextSibling(nextFrame);
} }
@ -4867,12 +4812,10 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
aDeletedFrame->Destroy(aPresContext); aDeletedFrame->Destroy(aPresContext);
aDeletedFrame = nextInFlow; aDeletedFrame = nextInFlow;
// If line is empty, remove it now. // If line is empty, remove it now
// Don't bother removing empty lines in the overflow list, they'll get if (0 == lineChildCount) {
// annihilated later
if (!searchingOverflowList && 0 == lineChildCount) {
nsLineBox *cur = line; nsLineBox *cur = line;
line = mLines.erase(line); line = lines->erase(line);
// Invalidate the space taken up by the line. // Invalidate the space taken up by the line.
// XXX We need to do this if we're removing a frame as a result of // XXX We need to do this if we're removing a frame as a result of
// a call to RemoveFrame(), but we may not need to do this in all // a call to RemoveFrame(), but we may not need to do this in all
@ -4899,12 +4842,7 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// If we just removed the last frame on the line then we need // If we just removed the last frame on the line then we need
// to advance to the next line. // to advance to the next line.
if (isLastFrameOnLine) { if (isLastFrameOnLine) {
NextOverAllLines(&line, &line_end, &searchingOverflowList); ++line;
// Detect the case when we've run off the end of the normal line
// list and we're starting the overflow line list
if (prevSibling && !prevSibling->GetNextSibling()) {
prevSibling = nsnull;
}
} }
} }
@ -4915,24 +4853,31 @@ nsBlockFrame::DoRemoveFrame(nsPresContext* aPresContext,
// the current flow's frame list. Therefore we know that the // the current flow's frame list. Therefore we know that the
// continuation is in a different parent. So break out of // continuation is in a different parent. So break out of
// the loop so that we advance to the next parent. // the loop so that we advance to the next parent.
NS_ASSERTION(aDeletedFrame->GetParent() != this, "strange continuation"); NS_ASSERTION(aDeletedFrame->GetParent() != flow, "strange continuation");
break; break;
} }
} }
} }
// Advance to next flow block if the frame has more continuations
if (flow && aDeletedFrame) {
flow = (nsBlockFrame*) flow->mNextInFlow;
NS_ASSERTION(nsnull != flow, "whoops, continuation without a parent");
// add defensive pointer check for bug 56894
if (flow) {
lines = &flow->mLines;
line = lines->begin();
line_end = lines->end();
prevSibling = nsnull;
} else {
aDeletedFrame = nsnull;
}
}
}
#ifdef DEBUG #ifdef DEBUG
VerifyLines(PR_TRUE); VerifyLines(PR_TRUE);
#endif #endif
// Advance to next flow block if the frame has more continuations
if (aDeletedFrame) {
nsBlockFrame* nextBlock = NS_STATIC_CAST(nsBlockFrame*, aDeletedFrame->GetParent());
NS_ASSERTION(nextBlock->GetType() == nsLayoutAtoms::blockFrame,
"Our child's continuation's parent is not a block?");
return nextBlock->DoRemoveFrame(aPresContext, aDeletedFrame);
}
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -279,10 +279,6 @@ protected:
const nsPoint &aPoint, const nsPoint &aPoint,
PRInt32 &aClosestLine); PRInt32 &aClosestLine);
void NextOverAllLines(nsLineList::iterator* aIterator,
nsLineList::iterator* aEndIterator,
PRBool* aInOverflowLines);
void SetFlags(PRUint32 aFlags) { void SetFlags(PRUint32 aFlags) {
mState &= ~NS_BLOCK_FLAGS_MASK; mState &= ~NS_BLOCK_FLAGS_MASK;
mState |= aFlags; mState |= aFlags;

Просмотреть файл

@ -1317,12 +1317,6 @@ nsContainerFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
fprintf(out, " [state=%08x]", mState); fprintf(out, " [state=%08x]", mState);
} }
fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent)); fprintf(out, " [content=%p]", NS_STATIC_CAST(void*, mContent));
nsContainerFrame* f = NS_CONST_CAST(nsContainerFrame*, this);
nsRect* overflowArea = f->GetOverflowAreaProperty(PR_FALSE);
if (overflowArea) {
fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea->x, overflowArea->y,
overflowArea->width, overflowArea->height);
}
fprintf(out, " [sc=%p]", NS_STATIC_CAST(void*, mStyleContext)); fprintf(out, " [sc=%p]", NS_STATIC_CAST(void*, mStyleContext));
// Output the children // Output the children