better handle reflow avoidance; factored align children slightly different so that more code is shared between ResizeReflow and IncrementalReflow; fixed more cases where reflow is required

This commit is contained in:
kipp 1998-05-21 16:12:10 +00:00
Родитель d0c79cf1df
Коммит 460f3aac59
2 изменённых файлов: 132 добавлений и 110 удалений

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

@ -215,6 +215,7 @@ nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
mMarginApplied = PR_FALSE; mMarginApplied = PR_FALSE;
SetReflowSpace(aState.mCurrentBand.availSpace); SetReflowSpace(aState.mCurrentBand.availSpace);
mMustReflowMappedChildren = PR_FALSE;
mY = aState.mY; mY = aState.mY;
mMaxHeight = aState.mAvailSize.height; mMaxHeight = aState.mAvailSize.height;
mReflowDataChanged = PR_FALSE; mReflowDataChanged = PR_FALSE;
@ -244,6 +245,7 @@ nsLineLayout::SetReflowSpace(nsRect& aAvailableSpaceRect)
mMaxWidth = mReflowData.mAvailWidth; mMaxWidth = mReflowData.mAvailWidth;
mNewRightEdge = mX0 + mMaxWidth; mNewRightEdge = mX0 + mMaxWidth;
mReflowDataChanged = PR_TRUE; mReflowDataChanged = PR_TRUE;
mMustReflowMappedChildren = PR_TRUE;
} }
nsresult nsresult
@ -340,17 +342,13 @@ nsLineLayout::WordBreakReflow()
* since the last time it was reflowed. * since the last time it was reflowed.
*/ */
nsresult nsresult
nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand) nsLineLayout::ReflowMappedChild()
{ {
if (1 == 1) { if (mMustReflowMappedChildren) {
return ReflowChild(aReflowCommand); NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
} ("nsLineLayout::ReflowMappedChild: must reflow frame=%p[%d]",
mKidFrame, mKidIndex));
// XXX look at reflow command and look at the next frame to get the return ReflowChild(nsnull);
// command and if it's mKidFrame then pass through to ReflowChild
// otherwise don't
if (nsnull != aReflowCommand) {
return ReflowChild(aReflowCommand);
} }
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
@ -366,7 +364,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (nsnull != f) { if (nsnull != f) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: has children")); ("nsLineLayout::ReflowMappedChild: has children"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
@ -374,13 +372,26 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
// have to reflow to get it. // have to reflow to get it.
nsIFrame::SplittableType splits; nsIFrame::SplittableType splits;
mKidFrame->IsSplittable(splits); mKidFrame->IsSplittable(splits);
#if 0
if (nsnull != mMaxElementSizePointer) { if (nsnull != mMaxElementSizePointer) {
if (nsIFrame::NotSplittable != splits) { if (nsIFrame::NotSplittable != splits) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: need max-element-size")); ("nsLineLayout::ReflowMappedChild: need max-element-size"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
#else
// XXX For now, if the child is splittable we reflow it. The reason
// is that the text whitespace compression needs to be consulted
// here to properly handle reflow avoidance. To do that properly we
// really need a first-rate protocol here (WillPlace?
// CanAvoidReflow?) that gets the frame involved.
if (nsIFrame::NotSplittable != splits) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: splittable hack"));
return ReflowChild(nsnull);
}
#endif
nsFrameState state; nsFrameState state;
mKidFrame->GetFrameState(state); mKidFrame->GetFrameState(state);
@ -395,7 +406,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (0 != (state & NS_FRAME_IN_REFLOW)) { if (0 != (state & NS_FRAME_IN_REFLOW)) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: frame is dirty")); ("nsLineLayout::ReflowMappedChild: frame is dirty"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
if (nsIFrame::NotSplittable != splits) { if (nsIFrame::NotSplittable != splits) {
@ -413,7 +424,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (0 != (prevState & NS_FRAME_IN_REFLOW)) { if (0 != (prevState & NS_FRAME_IN_REFLOW)) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: prev-in-flow frame is dirty")); ("nsLineLayout::ReflowMappedChild: prev-in-flow frame is dirty"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
@ -424,7 +435,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (nsnull != nextInFlow) { if (nsnull != nextInFlow) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: frame has next-in-flow")); ("nsLineLayout::ReflowMappedChild: frame has next-in-flow"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
@ -436,10 +447,15 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (NS_OK != rv) { if (NS_OK != rv) {
return rv; return rv;
} }
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(eStyleStruct_Spacing);
nsStyleDisplay* kidDisplay = (nsStyleDisplay*) nsStyleDisplay* kidDisplay = (nsStyleDisplay*)
kidSC->GetData(eStyleStruct_Display); kidSC->GetData(eStyleStruct_Display);
if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
// XXX If it floats it needs to go through the normal path so that
// PlaceFloater is invoked.
return ReflowChild(nsnull);
}
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(eStyleStruct_Spacing);
PRBool isBlock = PR_FALSE; PRBool isBlock = PR_FALSE;
switch (kidDisplay->mDisplay) { switch (kidDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK: case NS_STYLE_DISPLAY_BLOCK:
@ -470,7 +486,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: failed edge test")); ("nsLineLayout::ReflowMappedChild: failed edge test"));
// XXX if !splittable then return NS_LINE_LAYOUT_BREAK_BEFORE // XXX if !splittable then return NS_LINE_LAYOUT_BREAK_BEFORE
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
// Make sure the child will fit. The child always fits if it's the // Make sure the child will fit. The child always fits if it's the
@ -513,7 +529,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (nsIFrame::NotSplittable != splits) { if (nsIFrame::NotSplittable != splits) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: can't directly fit")); ("nsLineLayout::ReflowMappedChild: can't directly fit"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
return NS_LINE_LAYOUT_BREAK_BEFORE; return NS_LINE_LAYOUT_BREAK_BEFORE;
} }
@ -798,14 +814,6 @@ nsresult
nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand, nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
nsIFrame* aChildFrame) nsIFrame* aChildFrame)
{ {
#if 0
// Get the current bounds. We'll need this to adjust the frames that follow
nsRect oldBounds;
aChildFrame->GetRect(oldBounds);
#endif
// For the time being reflow all the children, and when we get to aChildFrame
// handle it specially
nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE; nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
mLine->mBounds.x = mReflowData.mX; mLine->mBounds.x = mReflowData.mX;
@ -813,13 +821,11 @@ nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
mKidFrame = mLine->mFirstChild; mKidFrame = mLine->mFirstChild;
PRInt32 kidNum = 0; PRInt32 kidNum = 0;
while (kidNum < mLine->mChildCount) { while (kidNum < mLine->mChildCount) {
// XXX Code to avoid reflowing a child goes here
nsresult childReflowStatus; nsresult childReflowStatus;
if (mKidFrame == aChildFrame) { if (mKidFrame == aChildFrame) {
childReflowStatus = ReflowChild(&aReflowCommand); childReflowStatus = ReflowChild(&aReflowCommand);
} else { } else {
childReflowStatus = ReflowChild(nsnull); childReflowStatus = ReflowMappedChild();
} }
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
@ -862,12 +868,7 @@ nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
done: done:
// Perform alignment operations // Perform alignment operations
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
}
else {
AlignChildren(); AlignChildren();
}
// Set final bounds of the line // Set final bounds of the line
mLine->mBounds.height = mLineHeight; mLine->mBounds.height = mLineHeight;
@ -994,7 +995,7 @@ nsLineLayout::ReflowMapped()
mKidFrame = mLine->mFirstChild; mKidFrame = mLine->mFirstChild;
PRInt32 kidNum = 0; PRInt32 kidNum = 0;
while (kidNum < mLine->mChildCount) { while (kidNum < mLine->mChildCount) {
nsresult childReflowStatus = ReflowMappedChild(nsnull); nsresult childReflowStatus = ReflowMappedChild();
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -1134,7 +1135,7 @@ nsLineLayout::PullUpChildren()
} }
// Try to reflow it like any other mapped child // Try to reflow it like any other mapped child
nsresult childReflowStatus = ReflowMappedChild(nsnull); nsresult childReflowStatus = ReflowMappedChild();
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -1216,7 +1217,7 @@ nsLineLayout::CreateFrameFor(nsIContent* aKid)
if (NS_OK == rv) { if (NS_OK == rv) {
kidFrame->SetStyleContext(mPresContext, kidSC); kidFrame->SetStyleContext(mPresContext, kidSC);
} }
} else if (kidDisplay->mFloats != NS_STYLE_FLOAT_NONE) { } else if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
rv = PlaceholderFrame::NewFrame(&kidFrame, aKid, mBlock); rv = PlaceholderFrame::NewFrame(&kidFrame, aKid, mBlock);
if (NS_OK == rv) { if (NS_OK == rv) {
kidFrame->SetStyleContext(mPresContext, kidSC); kidFrame->SetStyleContext(mPresContext, kidSC);
@ -1360,13 +1361,16 @@ nsresult
nsLineLayout::ReflowLine() nsLineLayout::ReflowLine()
{ {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("enter nsLineLayout::ReflowLine: childCount=%d", ("enter nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
mLine->mChildCount)); mLine->mChildCount,
mLine->mBounds.x, mLine->mBounds.y,
mLine->mBounds.width, mLine->mBounds.height));
nsresult rv = NS_LINE_LAYOUT_COMPLETE; nsresult rv = NS_LINE_LAYOUT_COMPLETE;
mLine->mBounds.x = mReflowData.mX; mLine->mBounds.x = mReflowData.mX;
mLine->mBounds.y = mY; mLine->mBounds.y = mY;
mOldChildCount = mLine->mChildCount;
// Reflow the mapped frames // Reflow the mapped frames
if (0 != mLine->mChildCount) { if (0 != mLine->mChildCount) {
@ -1391,14 +1395,7 @@ nsLineLayout::ReflowLine()
} }
// Perform alignment operations // Perform alignment operations
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
}
else {
if (0 != mFramesReflowed) {
AlignChildren(); AlignChildren();
}
}
// Set final bounds of the line // Set final bounds of the line
mLine->mBounds.height = mLineHeight; mLine->mBounds.height = mLineHeight;
@ -1410,17 +1407,33 @@ nsLineLayout::ReflowLine()
} }
#endif #endif
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("exit nsLineLayout::ReflowLine: childCount=%d", ("exit nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
mLine->mChildCount)); mLine->mChildCount,
mLine->mBounds.x, mLine->mBounds.y,
mLine->mBounds.width, mLine->mBounds.height));
return rv; return rv;
} }
nsresult void
nsLineLayout::AlignChildren() nsLineLayout::AlignChildren()
{ {
NS_PRECONDITION(mLine->mChildCount == mAscentNum, "bad line reflow"); NS_PRECONDITION(mLine->mChildCount == mAscentNum, "bad line reflow");
nsresult rv = NS_OK; // Block lines don't require (or allow!) alignment
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
return;
}
// Avoid alignment when we didn't actually reflow any frames and we
// also didn't change the number of frames we had (which means the
// pullup code didn't pull anything up). When this happens it means
// that nothing changed which means that we can avoid the alignment
// work.
if ((0 == mFramesReflowed) && (mOldChildCount == mLine->mChildCount)) {
mLineHeight = mLine->mBounds.height;
return;
}
nsIStyleContextPtr blockSC; nsIStyleContextPtr blockSC;
mBlock->GetStyleContext(mPresContext, blockSC.AssignRef()); mBlock->GetStyleContext(mPresContext, blockSC.AssignRef());
@ -1449,6 +1462,4 @@ nsLineLayout::AlignChildren()
nsCSSLayout::RelativePositionChildren(mPresContext, mBlock, nsCSSLayout::RelativePositionChildren(mPresContext, mBlock,
mLine->mFirstChild, mLine->mFirstChild,
mLine->mChildCount); mLine->mChildCount);
return rv;
} }

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

@ -215,6 +215,7 @@ nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
mMarginApplied = PR_FALSE; mMarginApplied = PR_FALSE;
SetReflowSpace(aState.mCurrentBand.availSpace); SetReflowSpace(aState.mCurrentBand.availSpace);
mMustReflowMappedChildren = PR_FALSE;
mY = aState.mY; mY = aState.mY;
mMaxHeight = aState.mAvailSize.height; mMaxHeight = aState.mAvailSize.height;
mReflowDataChanged = PR_FALSE; mReflowDataChanged = PR_FALSE;
@ -244,6 +245,7 @@ nsLineLayout::SetReflowSpace(nsRect& aAvailableSpaceRect)
mMaxWidth = mReflowData.mAvailWidth; mMaxWidth = mReflowData.mAvailWidth;
mNewRightEdge = mX0 + mMaxWidth; mNewRightEdge = mX0 + mMaxWidth;
mReflowDataChanged = PR_TRUE; mReflowDataChanged = PR_TRUE;
mMustReflowMappedChildren = PR_TRUE;
} }
nsresult nsresult
@ -340,17 +342,13 @@ nsLineLayout::WordBreakReflow()
* since the last time it was reflowed. * since the last time it was reflowed.
*/ */
nsresult nsresult
nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand) nsLineLayout::ReflowMappedChild()
{ {
if (1 == 1) { if (mMustReflowMappedChildren) {
return ReflowChild(aReflowCommand); NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
} ("nsLineLayout::ReflowMappedChild: must reflow frame=%p[%d]",
mKidFrame, mKidIndex));
// XXX look at reflow command and look at the next frame to get the return ReflowChild(nsnull);
// command and if it's mKidFrame then pass through to ReflowChild
// otherwise don't
if (nsnull != aReflowCommand) {
return ReflowChild(aReflowCommand);
} }
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
@ -366,7 +364,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (nsnull != f) { if (nsnull != f) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: has children")); ("nsLineLayout::ReflowMappedChild: has children"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
@ -374,13 +372,26 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
// have to reflow to get it. // have to reflow to get it.
nsIFrame::SplittableType splits; nsIFrame::SplittableType splits;
mKidFrame->IsSplittable(splits); mKidFrame->IsSplittable(splits);
#if 0
if (nsnull != mMaxElementSizePointer) { if (nsnull != mMaxElementSizePointer) {
if (nsIFrame::NotSplittable != splits) { if (nsIFrame::NotSplittable != splits) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: need max-element-size")); ("nsLineLayout::ReflowMappedChild: need max-element-size"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
#else
// XXX For now, if the child is splittable we reflow it. The reason
// is that the text whitespace compression needs to be consulted
// here to properly handle reflow avoidance. To do that properly we
// really need a first-rate protocol here (WillPlace?
// CanAvoidReflow?) that gets the frame involved.
if (nsIFrame::NotSplittable != splits) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: splittable hack"));
return ReflowChild(nsnull);
}
#endif
nsFrameState state; nsFrameState state;
mKidFrame->GetFrameState(state); mKidFrame->GetFrameState(state);
@ -395,7 +406,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (0 != (state & NS_FRAME_IN_REFLOW)) { if (0 != (state & NS_FRAME_IN_REFLOW)) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: frame is dirty")); ("nsLineLayout::ReflowMappedChild: frame is dirty"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
if (nsIFrame::NotSplittable != splits) { if (nsIFrame::NotSplittable != splits) {
@ -413,7 +424,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (0 != (prevState & NS_FRAME_IN_REFLOW)) { if (0 != (prevState & NS_FRAME_IN_REFLOW)) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: prev-in-flow frame is dirty")); ("nsLineLayout::ReflowMappedChild: prev-in-flow frame is dirty"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
@ -424,7 +435,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (nsnull != nextInFlow) { if (nsnull != nextInFlow) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: frame has next-in-flow")); ("nsLineLayout::ReflowMappedChild: frame has next-in-flow"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
} }
@ -436,10 +447,15 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (NS_OK != rv) { if (NS_OK != rv) {
return rv; return rv;
} }
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(eStyleStruct_Spacing);
nsStyleDisplay* kidDisplay = (nsStyleDisplay*) nsStyleDisplay* kidDisplay = (nsStyleDisplay*)
kidSC->GetData(eStyleStruct_Display); kidSC->GetData(eStyleStruct_Display);
if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
// XXX If it floats it needs to go through the normal path so that
// PlaceFloater is invoked.
return ReflowChild(nsnull);
}
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(eStyleStruct_Spacing);
PRBool isBlock = PR_FALSE; PRBool isBlock = PR_FALSE;
switch (kidDisplay->mDisplay) { switch (kidDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK: case NS_STYLE_DISPLAY_BLOCK:
@ -470,7 +486,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: failed edge test")); ("nsLineLayout::ReflowMappedChild: failed edge test"));
// XXX if !splittable then return NS_LINE_LAYOUT_BREAK_BEFORE // XXX if !splittable then return NS_LINE_LAYOUT_BREAK_BEFORE
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
// Make sure the child will fit. The child always fits if it's the // Make sure the child will fit. The child always fits if it's the
@ -513,7 +529,7 @@ nsLineLayout::ReflowMappedChild(nsReflowCommand* aReflowCommand)
if (nsIFrame::NotSplittable != splits) { if (nsIFrame::NotSplittable != splits) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsLineLayout::ReflowMappedChild: can't directly fit")); ("nsLineLayout::ReflowMappedChild: can't directly fit"));
return ReflowChild(aReflowCommand); return ReflowChild(nsnull);
} }
return NS_LINE_LAYOUT_BREAK_BEFORE; return NS_LINE_LAYOUT_BREAK_BEFORE;
} }
@ -798,14 +814,6 @@ nsresult
nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand, nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
nsIFrame* aChildFrame) nsIFrame* aChildFrame)
{ {
#if 0
// Get the current bounds. We'll need this to adjust the frames that follow
nsRect oldBounds;
aChildFrame->GetRect(oldBounds);
#endif
// For the time being reflow all the children, and when we get to aChildFrame
// handle it specially
nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE; nsresult reflowStatus = NS_LINE_LAYOUT_COMPLETE;
mLine->mBounds.x = mReflowData.mX; mLine->mBounds.x = mReflowData.mX;
@ -813,13 +821,11 @@ nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
mKidFrame = mLine->mFirstChild; mKidFrame = mLine->mFirstChild;
PRInt32 kidNum = 0; PRInt32 kidNum = 0;
while (kidNum < mLine->mChildCount) { while (kidNum < mLine->mChildCount) {
// XXX Code to avoid reflowing a child goes here
nsresult childReflowStatus; nsresult childReflowStatus;
if (mKidFrame == aChildFrame) { if (mKidFrame == aChildFrame) {
childReflowStatus = ReflowChild(&aReflowCommand); childReflowStatus = ReflowChild(&aReflowCommand);
} else { } else {
childReflowStatus = ReflowChild(nsnull); childReflowStatus = ReflowMappedChild();
} }
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
@ -862,12 +868,7 @@ nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
done: done:
// Perform alignment operations // Perform alignment operations
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
}
else {
AlignChildren(); AlignChildren();
}
// Set final bounds of the line // Set final bounds of the line
mLine->mBounds.height = mLineHeight; mLine->mBounds.height = mLineHeight;
@ -994,7 +995,7 @@ nsLineLayout::ReflowMapped()
mKidFrame = mLine->mFirstChild; mKidFrame = mLine->mFirstChild;
PRInt32 kidNum = 0; PRInt32 kidNum = 0;
while (kidNum < mLine->mChildCount) { while (kidNum < mLine->mChildCount) {
nsresult childReflowStatus = ReflowMappedChild(nsnull); nsresult childReflowStatus = ReflowMappedChild();
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -1134,7 +1135,7 @@ nsLineLayout::PullUpChildren()
} }
// Try to reflow it like any other mapped child // Try to reflow it like any other mapped child
nsresult childReflowStatus = ReflowMappedChild(nsnull); nsresult childReflowStatus = ReflowMappedChild();
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -1216,7 +1217,7 @@ nsLineLayout::CreateFrameFor(nsIContent* aKid)
if (NS_OK == rv) { if (NS_OK == rv) {
kidFrame->SetStyleContext(mPresContext, kidSC); kidFrame->SetStyleContext(mPresContext, kidSC);
} }
} else if (kidDisplay->mFloats != NS_STYLE_FLOAT_NONE) { } else if (NS_STYLE_FLOAT_NONE != kidDisplay->mFloats) {
rv = PlaceholderFrame::NewFrame(&kidFrame, aKid, mBlock); rv = PlaceholderFrame::NewFrame(&kidFrame, aKid, mBlock);
if (NS_OK == rv) { if (NS_OK == rv) {
kidFrame->SetStyleContext(mPresContext, kidSC); kidFrame->SetStyleContext(mPresContext, kidSC);
@ -1360,13 +1361,16 @@ nsresult
nsLineLayout::ReflowLine() nsLineLayout::ReflowLine()
{ {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("enter nsLineLayout::ReflowLine: childCount=%d", ("enter nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
mLine->mChildCount)); mLine->mChildCount,
mLine->mBounds.x, mLine->mBounds.y,
mLine->mBounds.width, mLine->mBounds.height));
nsresult rv = NS_LINE_LAYOUT_COMPLETE; nsresult rv = NS_LINE_LAYOUT_COMPLETE;
mLine->mBounds.x = mReflowData.mX; mLine->mBounds.x = mReflowData.mX;
mLine->mBounds.y = mY; mLine->mBounds.y = mY;
mOldChildCount = mLine->mChildCount;
// Reflow the mapped frames // Reflow the mapped frames
if (0 != mLine->mChildCount) { if (0 != mLine->mChildCount) {
@ -1391,14 +1395,7 @@ nsLineLayout::ReflowLine()
} }
// Perform alignment operations // Perform alignment operations
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
}
else {
if (0 != mFramesReflowed) {
AlignChildren(); AlignChildren();
}
}
// Set final bounds of the line // Set final bounds of the line
mLine->mBounds.height = mLineHeight; mLine->mBounds.height = mLineHeight;
@ -1410,17 +1407,33 @@ nsLineLayout::ReflowLine()
} }
#endif #endif
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("exit nsLineLayout::ReflowLine: childCount=%d", ("exit nsLineLayout::ReflowLine: childCount=%d {%d, %d, %d, %d}",
mLine->mChildCount)); mLine->mChildCount,
mLine->mBounds.x, mLine->mBounds.y,
mLine->mBounds.width, mLine->mBounds.height));
return rv; return rv;
} }
nsresult void
nsLineLayout::AlignChildren() nsLineLayout::AlignChildren()
{ {
NS_PRECONDITION(mLine->mChildCount == mAscentNum, "bad line reflow"); NS_PRECONDITION(mLine->mChildCount == mAscentNum, "bad line reflow");
nsresult rv = NS_OK; // Block lines don't require (or allow!) alignment
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
return;
}
// Avoid alignment when we didn't actually reflow any frames and we
// also didn't change the number of frames we had (which means the
// pullup code didn't pull anything up). When this happens it means
// that nothing changed which means that we can avoid the alignment
// work.
if ((0 == mFramesReflowed) && (mOldChildCount == mLine->mChildCount)) {
mLineHeight = mLine->mBounds.height;
return;
}
nsIStyleContextPtr blockSC; nsIStyleContextPtr blockSC;
mBlock->GetStyleContext(mPresContext, blockSC.AssignRef()); mBlock->GetStyleContext(mPresContext, blockSC.AssignRef());
@ -1449,6 +1462,4 @@ nsLineLayout::AlignChildren()
nsCSSLayout::RelativePositionChildren(mPresContext, mBlock, nsCSSLayout::RelativePositionChildren(mPresContext, mBlock,
mLine->mFirstChild, mLine->mFirstChild,
mLine->mChildCount); mLine->mChildCount);
return rv;
} }