Simplify PullFrame()/PullFrameFrom(). b=538525 r=roc

This commit is contained in:
Mats Palmgren 2010-01-11 15:08:23 +01:00
parent 4db40a3534
commit d637043263
2 changed files with 115 additions and 137 deletions

View File

@ -2454,79 +2454,46 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
return rv;
}
/**
* Pull frame from the next available location (one of our lines or
* one of our next-in-flows lines).
*/
nsresult
nsIFrame*
nsBlockFrame::PullFrame(nsBlockReflowState& aState,
line_iterator aLine,
nsIFrame*& aFrameResult)
line_iterator aLine)
{
aFrameResult = nsnull;
// First check our remaining lines
// First check our remaining lines.
if (end_lines() != aLine.next()) {
#ifdef DEBUG
PRBool retry =
#endif
PullFrameFrom(aState, aLine, this, PR_FALSE, aLine.next(), aFrameResult);
NS_ASSERTION(!retry, "Shouldn't have to retry in the current block");
return NS_OK;
return PullFrameFrom(aState, aLine, this, PR_FALSE, aLine.next());
}
NS_ASSERTION(!GetOverflowLines(),
"Our overflow lines should have been removed at the start of reflow");
// Try each next in flows
// Try each next-in-flow.
nsBlockFrame* nextInFlow = aState.mNextInFlow;
while (nextInFlow) {
// first normal lines, then overflow lines
if (!nextInFlow->mLines.empty()) {
if (PullFrameFrom(aState, aLine, nextInFlow, PR_FALSE,
nextInFlow->mLines.begin(), aFrameResult)) {
// try again with the same value of nextInFlow
continue;
}
break;
return PullFrameFrom(aState, aLine, nextInFlow, PR_FALSE,
nextInFlow->mLines.begin());
}
nsLineList* overflowLines = nextInFlow->GetOverflowLines();
if (overflowLines) {
if (PullFrameFrom(aState, aLine, nextInFlow, PR_TRUE,
overflowLines->begin(), aFrameResult)) {
// try again with the same value of nextInFlow
continue;
}
break;
return PullFrameFrom(aState, aLine, nextInFlow, PR_TRUE,
overflowLines->begin());
}
nextInFlow = (nsBlockFrame*) nextInFlow->GetNextInFlow();
nextInFlow = static_cast<nsBlockFrame*>(nextInFlow->GetNextInFlow());
aState.mNextInFlow = nextInFlow;
}
return NS_OK;
return nsnull;
}
/**
* Try to pull a frame out of a line pointed at by aFromLine.
*
* Note: pulling a frame from a line that is a place-holder frame
* doesn't automatically remove the corresponding float from the
* line's float array. This happens indirectly: either the line gets
* emptied (and destroyed) or the line gets reflowed (because we mark
* it dirty) and the code at the top of ReflowLine empties the
* array. So eventually, it will be removed, just not right away.
*
* @return PR_TRUE to force retrying of the pull.
*/
PRBool
nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nsBlockFrame* aFromContainer,
PRBool aFromOverflowLine,
nsLineList::iterator aFromLine,
nsIFrame*& aFrameResult)
nsIFrame*
nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nsBlockFrame* aFromContainer,
PRBool aFromOverflowLine,
nsLineList::iterator aFromLine)
{
nsLineBox* fromLine = aFromLine;
NS_ABORT_IF_FALSE(fromLine, "bad line to pull from");
@ -2540,88 +2507,85 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState,
// If our line is not empty and the child in aFromLine is a block
// then we cannot pull up the frame into this line. In this case
// we stop pulling.
aFrameResult = nsnull;
return nsnull;
}
// Take frame from fromLine
nsIFrame* frame = fromLine->mFirstChild;
nsIFrame* newFirstChild = frame->GetNextSibling();
if (aFromContainer != this) {
NS_ASSERTION(aState.mPrevChild == aLine->LastChild(),
"mPrevChild should be the LastChild of the line we are adding to");
// The frame is being pulled from a next-in-flow; therefore we
// need to add it to our sibling list.
if (NS_LIKELY(!aFromOverflowLine)) {
NS_ASSERTION(aFromLine == aFromContainer->mLines.begin(),
"should only pull from first line");
// Pulling from the next-in-flow's normal line list
aFromContainer->mFrames.RemoveFrame(frame);
} else {
// Pulling from the next-in-flow's overflow list
// XXXbz If we switch overflow lines to nsFrameList, we should
// change this SetNextSibling call.
frame->SetNextSibling(nsnull);
}
// When pushing and pulling frames we need to check for whether any
// views need to be reparented
NS_ASSERTION(frame->GetParent() == aFromContainer, "unexpected parent frame");
ReparentFrame(frame, aFromContainer, this);
mFrames.InsertFrame(nsnull, aState.mPrevChild, frame);
// The frame might have (or contain) floats that need to be
// brought over too.
ReparentFloats(frame, aFromContainer, aFromOverflowLine, PR_TRUE);
}
// when aFromContainer is 'this', then aLine->LastChild()'s next sibling
// is already set correctly.
aLine->SetChildCount(aLine->GetChildCount() + 1);
PRInt32 fromLineChildCount = fromLine->GetChildCount();
if (0 != --fromLineChildCount) {
// Mark line dirty now that we pulled a child
fromLine->SetChildCount(fromLineChildCount);
fromLine->MarkDirty();
fromLine->mFirstChild = newFirstChild;
}
else {
// Take frame from fromLine
nsIFrame* frame = fromLine->mFirstChild;
nsIFrame* newFirstChild = frame->GetNextSibling();
// Free up the fromLine now that it's empty
// Its bounds might need to be redrawn, though.
// XXX WHY do we invalidate the bounds AND the combined area? doesn't
// the combined area always enclose the bounds?
Invalidate(fromLine->mBounds);
nsLineList* fromLineList = aFromOverflowLine
? aFromContainer->RemoveOverflowLines()
: &aFromContainer->mLines;
if (aFromLine.next() != fromLineList->end())
aFromLine.next()->MarkPreviousMarginDirty();
if (aFromContainer != this) {
NS_ASSERTION(aState.mPrevChild == aLine->LastChild(),
"mPrevChild should be the LastChild of the line we are adding to");
// The frame is being pulled from a next-in-flow; therefore we
// need to add it to our sibling list.
if (NS_LIKELY(!aFromOverflowLine)) {
NS_ASSERTION(aFromLine == aFromContainer->mLines.begin(),
"should only pull from first line");
// Pulling from the next-in-flow's normal line list
aFromContainer->mFrames.RemoveFrame(frame);
Invalidate(fromLine->GetCombinedArea());
fromLineList->erase(aFromLine);
// aFromLine is now invalid
aState.FreeLineBox(fromLine);
// Put any remaining overflow lines back.
if (aFromOverflowLine) {
if (!fromLineList->empty()) {
aFromContainer->SetOverflowLines(fromLineList);
} else {
// Pulling from the next-in-flow's overflow list
// XXXbz If we switch overflow lines to nsFrameList, we should
// change this SetNextSibling call.
frame->SetNextSibling(nsnull);
}
// When pushing and pulling frames we need to check for whether any
// views need to be reparented
NS_ASSERTION(frame->GetParent() == aFromContainer, "unexpected parent frame");
ReparentFrame(frame, aFromContainer, this);
mFrames.InsertFrame(nsnull, aState.mPrevChild, frame);
// The frame might have (or contain) floats that need to be
// brought over too.
ReparentFloats(frame, aFromContainer, aFromOverflowLine, PR_TRUE);
}
// when aFromContainer is 'this', then aLine->LastChild()'s next sibling
// is already set correctly.
aLine->SetChildCount(aLine->GetChildCount() + 1);
PRInt32 fromLineChildCount = fromLine->GetChildCount();
if (0 != --fromLineChildCount) {
// Mark line dirty now that we pulled a child
fromLine->SetChildCount(fromLineChildCount);
fromLine->MarkDirty();
fromLine->mFirstChild = newFirstChild;
}
else {
// Free up the fromLine now that it's empty
// Its bounds might need to be redrawn, though.
// XXX WHY do we invalidate the bounds AND the combined area? doesn't
// the combined area always enclose the bounds?
Invalidate(fromLine->mBounds);
nsLineList* fromLineList = aFromOverflowLine
? aFromContainer->RemoveOverflowLines()
: &aFromContainer->mLines;
if (aFromLine.next() != fromLineList->end())
aFromLine.next()->MarkPreviousMarginDirty();
Invalidate(fromLine->GetCombinedArea());
fromLineList->erase(aFromLine);
// aFromLine is now invalid
aState.FreeLineBox(fromLine);
// Put any remaining overflow lines back.
if (aFromOverflowLine) {
if (!fromLineList->empty()) {
aFromContainer->SetOverflowLines(fromLineList);
} else {
delete fromLineList;
// Now any iterators into fromLineList are invalid (but
// aFromLine already was invalidated above)
}
delete fromLineList;
// Now any iterators into fromLineList are invalid (but
// aFromLine already was invalidated above)
}
}
// Stop pulling because we found a frame to pull
aFrameResult = frame;
#ifdef DEBUG
VerifyLines(PR_TRUE);
#endif
}
return PR_FALSE;
#ifdef DEBUG
VerifyLines(PR_TRUE);
#endif
return frame;
}
static void
@ -3571,9 +3535,8 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
if (aAllowPullUp) {
// Pull frames and reflow them until we can't
while (LINE_REFLOW_OK == lineReflowStatus) {
rv = PullFrame(aState, aLine, frame);
NS_ENSURE_SUCCESS(rv, rv);
if (nsnull == frame) {
frame = PullFrame(aState, aLine);
if (!frame) {
break;
}

View File

@ -621,16 +621,31 @@ protected:
nsIFrame* aFrame,
LineReflowStatus* aLineReflowStatus);
nsresult PullFrame(nsBlockReflowState& aState,
line_iterator aLine,
nsIFrame*& aFrameResult);
/**
* Pull a frame from the next available location (one of our lines or
* one of our next-in-flows lines).
* @return the pulled frame or nsnull
*/
nsIFrame* PullFrame(nsBlockReflowState& aState,
line_iterator aLine);
PRBool PullFrameFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nsBlockFrame* aFromContainer,
PRBool aFromOverflowLine,
nsLineList::iterator aFromLine,
nsIFrame*& aFrameResult);
/**
* Try to pull a frame out of a line pointed at by aFromLine.
*
* Note: pulling a frame from a line that is a place-holder frame
* doesn't automatically remove the corresponding float from the
* line's float array. This happens indirectly: either the line gets
* emptied (and destroyed) or the line gets reflowed (because we mark
* it dirty) and the code at the top of ReflowLine empties the
* array. So eventually, it will be removed, just not right away.
*
* @return the pulled frame or nsnull
*/
nsIFrame* PullFrameFrom(nsBlockReflowState& aState,
nsLineBox* aLine,
nsBlockFrame* aFromContainer,
PRBool aFromOverflowLine,
nsLineList::iterator aFromLine);
void PushLines(nsBlockReflowState& aState,
nsLineList::iterator aLineBefore);