Work in progress on block incremental reflow

This commit is contained in:
troy 1998-05-09 03:52:29 +00:00
parent e09e86128b
commit e0a3f308d8
13 changed files with 1309 additions and 310 deletions

View File

@ -142,6 +142,45 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
return rv; return rv;
} }
// Recover the block reflow state to what it should be if aLine is about
// to be reflowed. aLine should not be nsnull
nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
{
NS_PRECONDITION(nsnull != aLine, "null parameter");
nsLineData* prevLine = aLine->mPrevLine;
if (nsnull != prevLine) {
// Compute the running y-offset, and the available height
mY = prevLine->mBounds.YMost();
if (!mUnconstrainedHeight) {
mAvailSize.height -= mY;
}
// Compute the kid x-most
for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
nscoord xmost = l->mBounds.XMost();
if (xmost > mKidXMost) {
mKidXMost = xmost;
}
}
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
}
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -780,6 +819,52 @@ done:
return rv; return rv;
} }
// XXX This is a short-term hack. It assumes that the caller has already recovered
// the state, and that some space has been retrieved from the space manager...
nsresult
nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
{
nsresult rv = NS_OK;
nsLineLayout lineLayout(aState);
aState.mCurrentLine = &lineLayout;
while (nsnull != aLine) {
// Initialize the line layout for this line
rv = lineLayout.Initialize(aState, aLine);
if (NS_OK != rv) {
goto done;
}
lineLayout.mPrevKidFrame = aState.mPrevKidFrame;
// Reflow the line
nsresult lineReflowStatus = lineLayout.ReflowLine();
if (lineReflowStatus < 0) {
// Some kind of hard error
rv = lineReflowStatus;
goto done;
}
mChildCount += lineLayout.mNewFrames;
// Now place it. It's possible it won't fit.
rv = PlaceLine(aState, lineLayout, aLine);
if (NS_LINE_LAYOUT_COMPLETE != rv) {
goto done;
}
mLastContentOffset = aLine->mLastContentOffset;
mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
aLine = aLine->mNextLine;
aState.mPrevKidFrame = lineLayout.mPrevKidFrame;
}
done:
aState.mCurrentLine = nsnull;
#ifdef NS_DEBUG
VerifyLines(PR_TRUE);
#endif
return rv;
}
nsresult nsresult
nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState) nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
{ {
@ -1194,6 +1279,51 @@ nsBlockFrame::ResizeReflow(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
{
// Find the line that contains the aFrame
nsLineData* line = mLines;
while (nsnull != line) {
nsIFrame* child = line->mFirstChild;
for (PRInt32 count = line->mChildCount; count > 0; count--) {
if (child == aFrame) {
return line;
}
child->GetNextSibling(child);
}
// Move to the next line
line = line->mNextLine;
}
return nsnull;
}
nsLineData* nsBlockFrame::LastLine()
{
nsLineData* lastLine = mLines;
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
return lastLine;
}
nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds)
{
// Now just reflow all the lines that follow...
// XXX Obviously this needs to be more efficient
return ReflowMappedFrom(aState, aLine->mNextLine);
}
NS_METHOD NS_METHOD
nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext, nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager, nsISpaceManager* aSpaceManager,
@ -1219,39 +1349,11 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Is the reflow command target at us? // Is the reflow command target at us?
if (this == aReflowCommand.GetTarget()) { if (this == aReflowCommand.GetTarget()) {
if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) { if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) {
nsLineData* lastLine = mLines; nsLineData* lastLine = LastLine();
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
// Restore the state // Restore the state
if ((nsnull != lastLine) && (nsnull != lastLine->mPrevLine)) { if (nsnull != lastLine) {
nsLineData* prevLine = lastLine->mPrevLine; state.RecoverState(lastLine);
state.mY = prevLine->mBounds.YMost();
if (!state.mUnconstrainedHeight) {
state.mAvailSize.height -= state.mY;
}
// XXX This isn't really right...
state.mKidXMost = mRect.width - state.mBorderPadding.right;
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
state.mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
state.mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
} }
// Reflow unmapped children // Reflow unmapped children
@ -1267,38 +1369,65 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
rv = ReflowUnmapped(state); rv = ReflowUnmapped(state);
} }
// Set return status } else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
aStatus = frComplete; // Restore our state as if the child that changed is the next frame to reflow
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) { nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
rv = NS_OK; state.RecoverState(line);
aStatus = frNotComplete;
} // Get some available space to start reflowing with
GetAvailableSpace(state, state.mY);
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
} else { } else {
NS_NOTYETIMPLEMENTED("unexpected reflow command"); NS_NOTYETIMPLEMENTED("unexpected reflow command");
} }
} else { } else {
#if 0
// The command is passing through us. Get the next frame in the reflow chain // The command is passing through us. Get the next frame in the reflow chain
nsIFrame* nextFrame = aReflowCommand.GetNext(); nsIFrame* nextFrame = aReflowCommand.GetNext();
// Restore our state as if nextFrame is the next frame to reflow // Restore our state as if nextFrame is the next frame to reflow
RecoverState(aPresContext, state, nextFrame); nsLineData* line = FindLine(nextFrame);
state.RecoverState(line);
// Get the current bounds. We'll need this to adjust the frames that follow // Get some available space to start reflowing with
nsRect oldBounds; GetAvailableSpace(state, state.mY);
nextFrame->GetRect(oldBounds);
// Pass along the reflow command // Reflow the affected line
nsRect desiredRect; nsLineLayout lineLayout(state);
aStatus = aReflowCommand.Next(aSpaceManager, desiredRect, aMaxSize, nextFrame);
#endif state.mCurrentLine = &lineLayout;
NS_NOTYETIMPLEMENTED("unexpected reflow command"); lineLayout.Initialize(state, line);
// Have the line handle the incremental reflow
nsRect oldBounds = line->mBounds;
rv = lineLayout.IncrementalReflowFromChild(aReflowCommand, nextFrame);
// Now place the line. It's possible it won't fit
rv = PlaceLine(state, lineLayout, line);
// XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
if (NS_LINE_LAYOUT_COMPLETE == rv) {
mLastContentOffset = line->mLastContentOffset;
mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
state.mPrevKidFrame = lineLayout.mPrevKidFrame;
// Now figure out what to do with the frames that follow
rv = IncrementalReflowAfter(state, line, rv, oldBounds);
}
} }
// Return our desired rect // Return our desired rect
ComputeDesiredRect(state, aMaxSize, aDesiredRect); ComputeDesiredRect(state, aMaxSize, aDesiredRect);
// Set return status
aStatus = frComplete;
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
rv = NS_OK;
aStatus = frNotComplete;
}
// Now that reflow has finished, remove the cached pointer // Now that reflow has finished, remove the cached pointer
shell->RemoveCachedData(this); shell->RemoveCachedData(this);
NS_RELEASE(shell); NS_RELEASE(shell);

View File

@ -33,7 +33,7 @@ class nsBlockFrame;
struct nsBandData; struct nsBandData;
struct nsBlockBandData : public nsBandData { struct nsBlockBandData : public nsBandData {
// Trapezoid's used during band processing // Trapezoids used during band processing
nsBandTrapezoid data[12]; nsBandTrapezoid data[12];
// Bounding rect of available space between any left and right floaters // Bounding rect of available space between any left and right floaters
@ -63,6 +63,8 @@ struct nsBlockReflowState {
nsSize* aMaxElementSize, nsSize* aMaxElementSize,
nsBlockFrame* aBlock); nsBlockFrame* aBlock);
nsresult RecoverState(nsLineData* aLine);
nsIPresContext* mPresContext; nsIPresContext* mPresContext;
nsBlockFrame* mBlock; nsBlockFrame* mBlock;
@ -249,6 +251,14 @@ protected:
const nsSize& aMaxSize, const nsSize& aMaxSize,
nsRect& aDesiredRect); nsRect& aDesiredRect);
nsLineData* LastLine();
nsLineData* FindLine(nsIFrame* aFrame);
nsresult IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds);
void DestroyLines(); void DestroyLines();
void DrainOverflowList(); void DrainOverflowList();
@ -278,6 +288,7 @@ protected:
nsLineData* aLine); nsLineData* aLine);
nsresult ReflowMapped(nsBlockReflowState& aState); nsresult ReflowMapped(nsBlockReflowState& aState);
nsresult ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine);
nsresult ReflowUnmapped(nsBlockReflowState& aState); nsresult ReflowUnmapped(nsBlockReflowState& aState);

View File

@ -142,6 +142,45 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
return rv; return rv;
} }
// Recover the block reflow state to what it should be if aLine is about
// to be reflowed. aLine should not be nsnull
nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
{
NS_PRECONDITION(nsnull != aLine, "null parameter");
nsLineData* prevLine = aLine->mPrevLine;
if (nsnull != prevLine) {
// Compute the running y-offset, and the available height
mY = prevLine->mBounds.YMost();
if (!mUnconstrainedHeight) {
mAvailSize.height -= mY;
}
// Compute the kid x-most
for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
nscoord xmost = l->mBounds.XMost();
if (xmost > mKidXMost) {
mKidXMost = xmost;
}
}
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
}
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -780,6 +819,52 @@ done:
return rv; return rv;
} }
// XXX This is a short-term hack. It assumes that the caller has already recovered
// the state, and that some space has been retrieved from the space manager...
nsresult
nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
{
nsresult rv = NS_OK;
nsLineLayout lineLayout(aState);
aState.mCurrentLine = &lineLayout;
while (nsnull != aLine) {
// Initialize the line layout for this line
rv = lineLayout.Initialize(aState, aLine);
if (NS_OK != rv) {
goto done;
}
lineLayout.mPrevKidFrame = aState.mPrevKidFrame;
// Reflow the line
nsresult lineReflowStatus = lineLayout.ReflowLine();
if (lineReflowStatus < 0) {
// Some kind of hard error
rv = lineReflowStatus;
goto done;
}
mChildCount += lineLayout.mNewFrames;
// Now place it. It's possible it won't fit.
rv = PlaceLine(aState, lineLayout, aLine);
if (NS_LINE_LAYOUT_COMPLETE != rv) {
goto done;
}
mLastContentOffset = aLine->mLastContentOffset;
mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
aLine = aLine->mNextLine;
aState.mPrevKidFrame = lineLayout.mPrevKidFrame;
}
done:
aState.mCurrentLine = nsnull;
#ifdef NS_DEBUG
VerifyLines(PR_TRUE);
#endif
return rv;
}
nsresult nsresult
nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState) nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
{ {
@ -1194,6 +1279,51 @@ nsBlockFrame::ResizeReflow(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
{
// Find the line that contains the aFrame
nsLineData* line = mLines;
while (nsnull != line) {
nsIFrame* child = line->mFirstChild;
for (PRInt32 count = line->mChildCount; count > 0; count--) {
if (child == aFrame) {
return line;
}
child->GetNextSibling(child);
}
// Move to the next line
line = line->mNextLine;
}
return nsnull;
}
nsLineData* nsBlockFrame::LastLine()
{
nsLineData* lastLine = mLines;
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
return lastLine;
}
nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds)
{
// Now just reflow all the lines that follow...
// XXX Obviously this needs to be more efficient
return ReflowMappedFrom(aState, aLine->mNextLine);
}
NS_METHOD NS_METHOD
nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext, nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager, nsISpaceManager* aSpaceManager,
@ -1219,39 +1349,11 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Is the reflow command target at us? // Is the reflow command target at us?
if (this == aReflowCommand.GetTarget()) { if (this == aReflowCommand.GetTarget()) {
if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) { if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) {
nsLineData* lastLine = mLines; nsLineData* lastLine = LastLine();
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
// Restore the state // Restore the state
if ((nsnull != lastLine) && (nsnull != lastLine->mPrevLine)) { if (nsnull != lastLine) {
nsLineData* prevLine = lastLine->mPrevLine; state.RecoverState(lastLine);
state.mY = prevLine->mBounds.YMost();
if (!state.mUnconstrainedHeight) {
state.mAvailSize.height -= state.mY;
}
// XXX This isn't really right...
state.mKidXMost = mRect.width - state.mBorderPadding.right;
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
state.mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
state.mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
} }
// Reflow unmapped children // Reflow unmapped children
@ -1267,38 +1369,65 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
rv = ReflowUnmapped(state); rv = ReflowUnmapped(state);
} }
// Set return status } else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
aStatus = frComplete; // Restore our state as if the child that changed is the next frame to reflow
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) { nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
rv = NS_OK; state.RecoverState(line);
aStatus = frNotComplete;
} // Get some available space to start reflowing with
GetAvailableSpace(state, state.mY);
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
} else { } else {
NS_NOTYETIMPLEMENTED("unexpected reflow command"); NS_NOTYETIMPLEMENTED("unexpected reflow command");
} }
} else { } else {
#if 0
// The command is passing through us. Get the next frame in the reflow chain // The command is passing through us. Get the next frame in the reflow chain
nsIFrame* nextFrame = aReflowCommand.GetNext(); nsIFrame* nextFrame = aReflowCommand.GetNext();
// Restore our state as if nextFrame is the next frame to reflow // Restore our state as if nextFrame is the next frame to reflow
RecoverState(aPresContext, state, nextFrame); nsLineData* line = FindLine(nextFrame);
state.RecoverState(line);
// Get the current bounds. We'll need this to adjust the frames that follow // Get some available space to start reflowing with
nsRect oldBounds; GetAvailableSpace(state, state.mY);
nextFrame->GetRect(oldBounds);
// Pass along the reflow command // Reflow the affected line
nsRect desiredRect; nsLineLayout lineLayout(state);
aStatus = aReflowCommand.Next(aSpaceManager, desiredRect, aMaxSize, nextFrame);
#endif state.mCurrentLine = &lineLayout;
NS_NOTYETIMPLEMENTED("unexpected reflow command"); lineLayout.Initialize(state, line);
// Have the line handle the incremental reflow
nsRect oldBounds = line->mBounds;
rv = lineLayout.IncrementalReflowFromChild(aReflowCommand, nextFrame);
// Now place the line. It's possible it won't fit
rv = PlaceLine(state, lineLayout, line);
// XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
if (NS_LINE_LAYOUT_COMPLETE == rv) {
mLastContentOffset = line->mLastContentOffset;
mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
state.mPrevKidFrame = lineLayout.mPrevKidFrame;
// Now figure out what to do with the frames that follow
rv = IncrementalReflowAfter(state, line, rv, oldBounds);
}
} }
// Return our desired rect // Return our desired rect
ComputeDesiredRect(state, aMaxSize, aDesiredRect); ComputeDesiredRect(state, aMaxSize, aDesiredRect);
// Set return status
aStatus = frComplete;
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
rv = NS_OK;
aStatus = frNotComplete;
}
// Now that reflow has finished, remove the cached pointer // Now that reflow has finished, remove the cached pointer
shell->RemoveCachedData(this); shell->RemoveCachedData(this);
NS_RELEASE(shell); NS_RELEASE(shell);

View File

@ -142,6 +142,45 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
return rv; return rv;
} }
// Recover the block reflow state to what it should be if aLine is about
// to be reflowed. aLine should not be nsnull
nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
{
NS_PRECONDITION(nsnull != aLine, "null parameter");
nsLineData* prevLine = aLine->mPrevLine;
if (nsnull != prevLine) {
// Compute the running y-offset, and the available height
mY = prevLine->mBounds.YMost();
if (!mUnconstrainedHeight) {
mAvailSize.height -= mY;
}
// Compute the kid x-most
for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
nscoord xmost = l->mBounds.XMost();
if (xmost > mKidXMost) {
mKidXMost = xmost;
}
}
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
}
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -780,6 +819,52 @@ done:
return rv; return rv;
} }
// XXX This is a short-term hack. It assumes that the caller has already recovered
// the state, and that some space has been retrieved from the space manager...
nsresult
nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
{
nsresult rv = NS_OK;
nsLineLayout lineLayout(aState);
aState.mCurrentLine = &lineLayout;
while (nsnull != aLine) {
// Initialize the line layout for this line
rv = lineLayout.Initialize(aState, aLine);
if (NS_OK != rv) {
goto done;
}
lineLayout.mPrevKidFrame = aState.mPrevKidFrame;
// Reflow the line
nsresult lineReflowStatus = lineLayout.ReflowLine();
if (lineReflowStatus < 0) {
// Some kind of hard error
rv = lineReflowStatus;
goto done;
}
mChildCount += lineLayout.mNewFrames;
// Now place it. It's possible it won't fit.
rv = PlaceLine(aState, lineLayout, aLine);
if (NS_LINE_LAYOUT_COMPLETE != rv) {
goto done;
}
mLastContentOffset = aLine->mLastContentOffset;
mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
aLine = aLine->mNextLine;
aState.mPrevKidFrame = lineLayout.mPrevKidFrame;
}
done:
aState.mCurrentLine = nsnull;
#ifdef NS_DEBUG
VerifyLines(PR_TRUE);
#endif
return rv;
}
nsresult nsresult
nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState) nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
{ {
@ -1194,6 +1279,51 @@ nsBlockFrame::ResizeReflow(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
{
// Find the line that contains the aFrame
nsLineData* line = mLines;
while (nsnull != line) {
nsIFrame* child = line->mFirstChild;
for (PRInt32 count = line->mChildCount; count > 0; count--) {
if (child == aFrame) {
return line;
}
child->GetNextSibling(child);
}
// Move to the next line
line = line->mNextLine;
}
return nsnull;
}
nsLineData* nsBlockFrame::LastLine()
{
nsLineData* lastLine = mLines;
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
return lastLine;
}
nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds)
{
// Now just reflow all the lines that follow...
// XXX Obviously this needs to be more efficient
return ReflowMappedFrom(aState, aLine->mNextLine);
}
NS_METHOD NS_METHOD
nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext, nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager, nsISpaceManager* aSpaceManager,
@ -1219,39 +1349,11 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Is the reflow command target at us? // Is the reflow command target at us?
if (this == aReflowCommand.GetTarget()) { if (this == aReflowCommand.GetTarget()) {
if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) { if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) {
nsLineData* lastLine = mLines; nsLineData* lastLine = LastLine();
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
// Restore the state // Restore the state
if ((nsnull != lastLine) && (nsnull != lastLine->mPrevLine)) { if (nsnull != lastLine) {
nsLineData* prevLine = lastLine->mPrevLine; state.RecoverState(lastLine);
state.mY = prevLine->mBounds.YMost();
if (!state.mUnconstrainedHeight) {
state.mAvailSize.height -= state.mY;
}
// XXX This isn't really right...
state.mKidXMost = mRect.width - state.mBorderPadding.right;
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
state.mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
state.mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
} }
// Reflow unmapped children // Reflow unmapped children
@ -1267,38 +1369,65 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
rv = ReflowUnmapped(state); rv = ReflowUnmapped(state);
} }
// Set return status } else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
aStatus = frComplete; // Restore our state as if the child that changed is the next frame to reflow
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) { nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
rv = NS_OK; state.RecoverState(line);
aStatus = frNotComplete;
} // Get some available space to start reflowing with
GetAvailableSpace(state, state.mY);
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
} else { } else {
NS_NOTYETIMPLEMENTED("unexpected reflow command"); NS_NOTYETIMPLEMENTED("unexpected reflow command");
} }
} else { } else {
#if 0
// The command is passing through us. Get the next frame in the reflow chain // The command is passing through us. Get the next frame in the reflow chain
nsIFrame* nextFrame = aReflowCommand.GetNext(); nsIFrame* nextFrame = aReflowCommand.GetNext();
// Restore our state as if nextFrame is the next frame to reflow // Restore our state as if nextFrame is the next frame to reflow
RecoverState(aPresContext, state, nextFrame); nsLineData* line = FindLine(nextFrame);
state.RecoverState(line);
// Get the current bounds. We'll need this to adjust the frames that follow // Get some available space to start reflowing with
nsRect oldBounds; GetAvailableSpace(state, state.mY);
nextFrame->GetRect(oldBounds);
// Pass along the reflow command // Reflow the affected line
nsRect desiredRect; nsLineLayout lineLayout(state);
aStatus = aReflowCommand.Next(aSpaceManager, desiredRect, aMaxSize, nextFrame);
#endif state.mCurrentLine = &lineLayout;
NS_NOTYETIMPLEMENTED("unexpected reflow command"); lineLayout.Initialize(state, line);
// Have the line handle the incremental reflow
nsRect oldBounds = line->mBounds;
rv = lineLayout.IncrementalReflowFromChild(aReflowCommand, nextFrame);
// Now place the line. It's possible it won't fit
rv = PlaceLine(state, lineLayout, line);
// XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
if (NS_LINE_LAYOUT_COMPLETE == rv) {
mLastContentOffset = line->mLastContentOffset;
mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
state.mPrevKidFrame = lineLayout.mPrevKidFrame;
// Now figure out what to do with the frames that follow
rv = IncrementalReflowAfter(state, line, rv, oldBounds);
}
} }
// Return our desired rect // Return our desired rect
ComputeDesiredRect(state, aMaxSize, aDesiredRect); ComputeDesiredRect(state, aMaxSize, aDesiredRect);
// Set return status
aStatus = frComplete;
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
rv = NS_OK;
aStatus = frNotComplete;
}
// Now that reflow has finished, remove the cached pointer // Now that reflow has finished, remove the cached pointer
shell->RemoveCachedData(this); shell->RemoveCachedData(this);
NS_RELEASE(shell); NS_RELEASE(shell);

View File

@ -28,6 +28,7 @@
#include "nsPlaceholderFrame.h" #include "nsPlaceholderFrame.h"
#include "nsCSSLayout.h" #include "nsCSSLayout.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsReflowCommand.h"
#undef NOISY_REFLOW #undef NOISY_REFLOW
@ -356,7 +357,7 @@ nsLineLayout::WordBreakReflow()
// Return values: <0 for error // Return values: <0 for error
// 0 == NS_LINE_LAYOUT // 0 == NS_LINE_LAYOUT
nsresult nsresult
nsLineLayout::ReflowChild() nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand)
{ {
// Get kid frame's style context // Get kid frame's style context
nsIStyleContextPtr kidSC; nsIStyleContextPtr kidSC;
@ -413,7 +414,20 @@ nsLineLayout::ReflowChild()
} }
mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE; mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
nscoord dx = mReflowData.mX + kidSpacing->mMargin.left; nscoord dx = mReflowData.mX + kidSpacing->mMargin.left;
if (isBlock) { if (aReflowCommand) {
nsIFrame* nextFrame;
mSpaceManager->Translate(dx, mY);
kidReflowStatus = aReflowCommand->Next(mSpaceManager, kidRect, kidAvailSize, nextFrame);
mSpaceManager->Translate(-dx, -mY);
kidRect.x = dx;
kidRect.y = mY;
kidSize.width = kidRect.width;
kidSize.height = kidRect.height;
kidSize.ascent = kidRect.height;
kidSize.descent = 0;
} else if (isBlock) {
mSpaceManager->Translate(dx, mY); mSpaceManager->Translate(dx, mY);
rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext, rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext,
mSpaceManager, kidAvailSize, kidRect, mSpaceManager, kidAvailSize, kidRect,
@ -518,6 +532,94 @@ nsLineLayout::ReflowChild()
return rv; return rv;
} }
nsresult
nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
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;
mLine->mBounds.x = mReflowData.mX;
mLine->mBounds.y = mY;
mKidFrame = mLine->mFirstChild;
PRInt32 kidNum = 0;
while (kidNum < mLine->mChildCount) {
// XXX Code to avoid reflowing a child goes here
nsresult childReflowStatus;
if (mKidFrame == aChildFrame) {
childReflowStatus = ReflowChild(&aReflowCommand);
} else {
childReflowStatus = ReflowChild(nsnull);
}
if (childReflowStatus < 0) {
reflowStatus = childReflowStatus;
goto done;
}
switch (childReflowStatus) {
default:
case NS_LINE_LAYOUT_COMPLETE:
mPrevKidFrame = mKidFrame;
mKidFrame->GetNextSibling(mKidFrame);
mKidIndex++;
kidNum++;
break;
case NS_LINE_LAYOUT_NOT_COMPLETE:
reflowStatus = childReflowStatus;
mPrevKidFrame = mKidFrame;
mKidFrame->GetNextSibling(mKidFrame);
kidNum++;
goto split_line;
case NS_LINE_LAYOUT_BREAK_BEFORE:
reflowStatus = childReflowStatus;
goto split_line;
case NS_LINE_LAYOUT_BREAK_AFTER:
reflowStatus = childReflowStatus;
mPrevKidFrame = mKidFrame;
mKidFrame->GetNextSibling(mKidFrame);
mKidIndex++;
kidNum++;
split_line:
reflowStatus = SplitLine(childReflowStatus, mLine->mChildCount - kidNum);
goto done;
}
}
done:
// Perform alignment operations
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
}
else {
AlignChildren();
}
// Set final bounds of the line
mLine->mBounds.height = mLineHeight;
mLine->mBounds.width = mReflowData.mX - mLine->mBounds.x;
NS_ASSERTION(((reflowStatus < 0) ||
(reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
(reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
(reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
(reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
"bad return status from ReflowMapped");
return reflowStatus;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -630,7 +732,7 @@ nsLineLayout::ReflowMapped()
while (kidNum < mLine->mChildCount) { while (kidNum < mLine->mChildCount) {
// XXX Code to avoid reflowing a child goes here // XXX Code to avoid reflowing a child goes here
nsresult childReflowStatus = ReflowChild(); nsresult childReflowStatus = ReflowChild(nsnull);
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -769,7 +871,7 @@ nsLineLayout::PullUpChildren()
} }
// Try to reflow it like any other mapped child // Try to reflow it like any other mapped child
nsresult childReflowStatus = ReflowChild(); nsresult childReflowStatus = ReflowChild(nsnull);
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -942,7 +1044,7 @@ nsLineLayout::ReflowUnmapped()
} }
// Reflow new child frame // Reflow new child frame
childReflowStatus = ReflowChild(); childReflowStatus = ReflowChild(nsnull);
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;

View File

@ -100,16 +100,16 @@ struct nsLineLayout {
*/ */
nsresult ReflowLine(); nsresult ReflowLine();
nsresult IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
nsIFrame* aChildFrame);
// The presentation context // The presentation context
nsIPresContext* mPresContext; nsIPresContext* mPresContext;
// The block behind the line // The block behind the line
nsBlockFrame* mBlock; nsBlockFrame* mBlock;
nsISpaceManager* mSpaceManager; nsISpaceManager* mSpaceManager;
#if 0
// XXX I don't think we need this anymore...
PRBool mBlockIsPseudo;
#endif
nsIContent* mBlockContent; nsIContent* mBlockContent;
PRInt32 mKidIndex; PRInt32 mKidIndex;
@ -180,7 +180,7 @@ protected:
nsresult WordBreakReflow(); nsresult WordBreakReflow();
nsresult ReflowChild(); nsresult ReflowChild(nsReflowCommand* aReflowCommand);
nsresult ReflowMapped(); nsresult ReflowMapped();

View File

@ -142,6 +142,45 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
return rv; return rv;
} }
// Recover the block reflow state to what it should be if aLine is about
// to be reflowed. aLine should not be nsnull
nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
{
NS_PRECONDITION(nsnull != aLine, "null parameter");
nsLineData* prevLine = aLine->mPrevLine;
if (nsnull != prevLine) {
// Compute the running y-offset, and the available height
mY = prevLine->mBounds.YMost();
if (!mUnconstrainedHeight) {
mAvailSize.height -= mY;
}
// Compute the kid x-most
for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
nscoord xmost = l->mBounds.XMost();
if (xmost > mKidXMost) {
mKidXMost = xmost;
}
}
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
}
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -780,6 +819,52 @@ done:
return rv; return rv;
} }
// XXX This is a short-term hack. It assumes that the caller has already recovered
// the state, and that some space has been retrieved from the space manager...
nsresult
nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
{
nsresult rv = NS_OK;
nsLineLayout lineLayout(aState);
aState.mCurrentLine = &lineLayout;
while (nsnull != aLine) {
// Initialize the line layout for this line
rv = lineLayout.Initialize(aState, aLine);
if (NS_OK != rv) {
goto done;
}
lineLayout.mPrevKidFrame = aState.mPrevKidFrame;
// Reflow the line
nsresult lineReflowStatus = lineLayout.ReflowLine();
if (lineReflowStatus < 0) {
// Some kind of hard error
rv = lineReflowStatus;
goto done;
}
mChildCount += lineLayout.mNewFrames;
// Now place it. It's possible it won't fit.
rv = PlaceLine(aState, lineLayout, aLine);
if (NS_LINE_LAYOUT_COMPLETE != rv) {
goto done;
}
mLastContentOffset = aLine->mLastContentOffset;
mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
aLine = aLine->mNextLine;
aState.mPrevKidFrame = lineLayout.mPrevKidFrame;
}
done:
aState.mCurrentLine = nsnull;
#ifdef NS_DEBUG
VerifyLines(PR_TRUE);
#endif
return rv;
}
nsresult nsresult
nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState) nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
{ {
@ -1194,6 +1279,51 @@ nsBlockFrame::ResizeReflow(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
{
// Find the line that contains the aFrame
nsLineData* line = mLines;
while (nsnull != line) {
nsIFrame* child = line->mFirstChild;
for (PRInt32 count = line->mChildCount; count > 0; count--) {
if (child == aFrame) {
return line;
}
child->GetNextSibling(child);
}
// Move to the next line
line = line->mNextLine;
}
return nsnull;
}
nsLineData* nsBlockFrame::LastLine()
{
nsLineData* lastLine = mLines;
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
return lastLine;
}
nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds)
{
// Now just reflow all the lines that follow...
// XXX Obviously this needs to be more efficient
return ReflowMappedFrom(aState, aLine->mNextLine);
}
NS_METHOD NS_METHOD
nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext, nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager, nsISpaceManager* aSpaceManager,
@ -1219,39 +1349,11 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Is the reflow command target at us? // Is the reflow command target at us?
if (this == aReflowCommand.GetTarget()) { if (this == aReflowCommand.GetTarget()) {
if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) { if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) {
nsLineData* lastLine = mLines; nsLineData* lastLine = LastLine();
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
// Restore the state // Restore the state
if ((nsnull != lastLine) && (nsnull != lastLine->mPrevLine)) { if (nsnull != lastLine) {
nsLineData* prevLine = lastLine->mPrevLine; state.RecoverState(lastLine);
state.mY = prevLine->mBounds.YMost();
if (!state.mUnconstrainedHeight) {
state.mAvailSize.height -= state.mY;
}
// XXX This isn't really right...
state.mKidXMost = mRect.width - state.mBorderPadding.right;
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
state.mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
state.mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
} }
// Reflow unmapped children // Reflow unmapped children
@ -1267,38 +1369,65 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
rv = ReflowUnmapped(state); rv = ReflowUnmapped(state);
} }
// Set return status } else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
aStatus = frComplete; // Restore our state as if the child that changed is the next frame to reflow
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) { nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
rv = NS_OK; state.RecoverState(line);
aStatus = frNotComplete;
} // Get some available space to start reflowing with
GetAvailableSpace(state, state.mY);
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
} else { } else {
NS_NOTYETIMPLEMENTED("unexpected reflow command"); NS_NOTYETIMPLEMENTED("unexpected reflow command");
} }
} else { } else {
#if 0
// The command is passing through us. Get the next frame in the reflow chain // The command is passing through us. Get the next frame in the reflow chain
nsIFrame* nextFrame = aReflowCommand.GetNext(); nsIFrame* nextFrame = aReflowCommand.GetNext();
// Restore our state as if nextFrame is the next frame to reflow // Restore our state as if nextFrame is the next frame to reflow
RecoverState(aPresContext, state, nextFrame); nsLineData* line = FindLine(nextFrame);
state.RecoverState(line);
// Get the current bounds. We'll need this to adjust the frames that follow // Get some available space to start reflowing with
nsRect oldBounds; GetAvailableSpace(state, state.mY);
nextFrame->GetRect(oldBounds);
// Pass along the reflow command // Reflow the affected line
nsRect desiredRect; nsLineLayout lineLayout(state);
aStatus = aReflowCommand.Next(aSpaceManager, desiredRect, aMaxSize, nextFrame);
#endif state.mCurrentLine = &lineLayout;
NS_NOTYETIMPLEMENTED("unexpected reflow command"); lineLayout.Initialize(state, line);
// Have the line handle the incremental reflow
nsRect oldBounds = line->mBounds;
rv = lineLayout.IncrementalReflowFromChild(aReflowCommand, nextFrame);
// Now place the line. It's possible it won't fit
rv = PlaceLine(state, lineLayout, line);
// XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
if (NS_LINE_LAYOUT_COMPLETE == rv) {
mLastContentOffset = line->mLastContentOffset;
mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
state.mPrevKidFrame = lineLayout.mPrevKidFrame;
// Now figure out what to do with the frames that follow
rv = IncrementalReflowAfter(state, line, rv, oldBounds);
}
} }
// Return our desired rect // Return our desired rect
ComputeDesiredRect(state, aMaxSize, aDesiredRect); ComputeDesiredRect(state, aMaxSize, aDesiredRect);
// Set return status
aStatus = frComplete;
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
rv = NS_OK;
aStatus = frNotComplete;
}
// Now that reflow has finished, remove the cached pointer // Now that reflow has finished, remove the cached pointer
shell->RemoveCachedData(this); shell->RemoveCachedData(this);
NS_RELEASE(shell); NS_RELEASE(shell);

View File

@ -33,7 +33,7 @@ class nsBlockFrame;
struct nsBandData; struct nsBandData;
struct nsBlockBandData : public nsBandData { struct nsBlockBandData : public nsBandData {
// Trapezoid's used during band processing // Trapezoids used during band processing
nsBandTrapezoid data[12]; nsBandTrapezoid data[12];
// Bounding rect of available space between any left and right floaters // Bounding rect of available space between any left and right floaters
@ -63,6 +63,8 @@ struct nsBlockReflowState {
nsSize* aMaxElementSize, nsSize* aMaxElementSize,
nsBlockFrame* aBlock); nsBlockFrame* aBlock);
nsresult RecoverState(nsLineData* aLine);
nsIPresContext* mPresContext; nsIPresContext* mPresContext;
nsBlockFrame* mBlock; nsBlockFrame* mBlock;
@ -249,6 +251,14 @@ protected:
const nsSize& aMaxSize, const nsSize& aMaxSize,
nsRect& aDesiredRect); nsRect& aDesiredRect);
nsLineData* LastLine();
nsLineData* FindLine(nsIFrame* aFrame);
nsresult IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds);
void DestroyLines(); void DestroyLines();
void DrainOverflowList(); void DrainOverflowList();
@ -278,6 +288,7 @@ protected:
nsLineData* aLine); nsLineData* aLine);
nsresult ReflowMapped(nsBlockReflowState& aState); nsresult ReflowMapped(nsBlockReflowState& aState);
nsresult ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine);
nsresult ReflowUnmapped(nsBlockReflowState& aState); nsresult ReflowUnmapped(nsBlockReflowState& aState);

View File

@ -142,6 +142,45 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
return rv; return rv;
} }
// Recover the block reflow state to what it should be if aLine is about
// to be reflowed. aLine should not be nsnull
nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
{
NS_PRECONDITION(nsnull != aLine, "null parameter");
nsLineData* prevLine = aLine->mPrevLine;
if (nsnull != prevLine) {
// Compute the running y-offset, and the available height
mY = prevLine->mBounds.YMost();
if (!mUnconstrainedHeight) {
mAvailSize.height -= mY;
}
// Compute the kid x-most
for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
nscoord xmost = l->mBounds.XMost();
if (xmost > mKidXMost) {
mKidXMost = xmost;
}
}
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
}
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -780,6 +819,52 @@ done:
return rv; return rv;
} }
// XXX This is a short-term hack. It assumes that the caller has already recovered
// the state, and that some space has been retrieved from the space manager...
nsresult
nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
{
nsresult rv = NS_OK;
nsLineLayout lineLayout(aState);
aState.mCurrentLine = &lineLayout;
while (nsnull != aLine) {
// Initialize the line layout for this line
rv = lineLayout.Initialize(aState, aLine);
if (NS_OK != rv) {
goto done;
}
lineLayout.mPrevKidFrame = aState.mPrevKidFrame;
// Reflow the line
nsresult lineReflowStatus = lineLayout.ReflowLine();
if (lineReflowStatus < 0) {
// Some kind of hard error
rv = lineReflowStatus;
goto done;
}
mChildCount += lineLayout.mNewFrames;
// Now place it. It's possible it won't fit.
rv = PlaceLine(aState, lineLayout, aLine);
if (NS_LINE_LAYOUT_COMPLETE != rv) {
goto done;
}
mLastContentOffset = aLine->mLastContentOffset;
mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
aLine = aLine->mNextLine;
aState.mPrevKidFrame = lineLayout.mPrevKidFrame;
}
done:
aState.mCurrentLine = nsnull;
#ifdef NS_DEBUG
VerifyLines(PR_TRUE);
#endif
return rv;
}
nsresult nsresult
nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState) nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
{ {
@ -1194,6 +1279,51 @@ nsBlockFrame::ResizeReflow(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
{
// Find the line that contains the aFrame
nsLineData* line = mLines;
while (nsnull != line) {
nsIFrame* child = line->mFirstChild;
for (PRInt32 count = line->mChildCount; count > 0; count--) {
if (child == aFrame) {
return line;
}
child->GetNextSibling(child);
}
// Move to the next line
line = line->mNextLine;
}
return nsnull;
}
nsLineData* nsBlockFrame::LastLine()
{
nsLineData* lastLine = mLines;
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
return lastLine;
}
nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds)
{
// Now just reflow all the lines that follow...
// XXX Obviously this needs to be more efficient
return ReflowMappedFrom(aState, aLine->mNextLine);
}
NS_METHOD NS_METHOD
nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext, nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager, nsISpaceManager* aSpaceManager,
@ -1219,39 +1349,11 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Is the reflow command target at us? // Is the reflow command target at us?
if (this == aReflowCommand.GetTarget()) { if (this == aReflowCommand.GetTarget()) {
if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) { if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) {
nsLineData* lastLine = mLines; nsLineData* lastLine = LastLine();
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
// Restore the state // Restore the state
if ((nsnull != lastLine) && (nsnull != lastLine->mPrevLine)) { if (nsnull != lastLine) {
nsLineData* prevLine = lastLine->mPrevLine; state.RecoverState(lastLine);
state.mY = prevLine->mBounds.YMost();
if (!state.mUnconstrainedHeight) {
state.mAvailSize.height -= state.mY;
}
// XXX This isn't really right...
state.mKidXMost = mRect.width - state.mBorderPadding.right;
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
state.mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
state.mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
} }
// Reflow unmapped children // Reflow unmapped children
@ -1267,38 +1369,65 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
rv = ReflowUnmapped(state); rv = ReflowUnmapped(state);
} }
// Set return status } else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
aStatus = frComplete; // Restore our state as if the child that changed is the next frame to reflow
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) { nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
rv = NS_OK; state.RecoverState(line);
aStatus = frNotComplete;
} // Get some available space to start reflowing with
GetAvailableSpace(state, state.mY);
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
} else { } else {
NS_NOTYETIMPLEMENTED("unexpected reflow command"); NS_NOTYETIMPLEMENTED("unexpected reflow command");
} }
} else { } else {
#if 0
// The command is passing through us. Get the next frame in the reflow chain // The command is passing through us. Get the next frame in the reflow chain
nsIFrame* nextFrame = aReflowCommand.GetNext(); nsIFrame* nextFrame = aReflowCommand.GetNext();
// Restore our state as if nextFrame is the next frame to reflow // Restore our state as if nextFrame is the next frame to reflow
RecoverState(aPresContext, state, nextFrame); nsLineData* line = FindLine(nextFrame);
state.RecoverState(line);
// Get the current bounds. We'll need this to adjust the frames that follow // Get some available space to start reflowing with
nsRect oldBounds; GetAvailableSpace(state, state.mY);
nextFrame->GetRect(oldBounds);
// Pass along the reflow command // Reflow the affected line
nsRect desiredRect; nsLineLayout lineLayout(state);
aStatus = aReflowCommand.Next(aSpaceManager, desiredRect, aMaxSize, nextFrame);
#endif state.mCurrentLine = &lineLayout;
NS_NOTYETIMPLEMENTED("unexpected reflow command"); lineLayout.Initialize(state, line);
// Have the line handle the incremental reflow
nsRect oldBounds = line->mBounds;
rv = lineLayout.IncrementalReflowFromChild(aReflowCommand, nextFrame);
// Now place the line. It's possible it won't fit
rv = PlaceLine(state, lineLayout, line);
// XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
if (NS_LINE_LAYOUT_COMPLETE == rv) {
mLastContentOffset = line->mLastContentOffset;
mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
state.mPrevKidFrame = lineLayout.mPrevKidFrame;
// Now figure out what to do with the frames that follow
rv = IncrementalReflowAfter(state, line, rv, oldBounds);
}
} }
// Return our desired rect // Return our desired rect
ComputeDesiredRect(state, aMaxSize, aDesiredRect); ComputeDesiredRect(state, aMaxSize, aDesiredRect);
// Set return status
aStatus = frComplete;
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
rv = NS_OK;
aStatus = frNotComplete;
}
// Now that reflow has finished, remove the cached pointer // Now that reflow has finished, remove the cached pointer
shell->RemoveCachedData(this); shell->RemoveCachedData(this);
NS_RELEASE(shell); NS_RELEASE(shell);

View File

@ -142,6 +142,45 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
return rv; return rv;
} }
// Recover the block reflow state to what it should be if aLine is about
// to be reflowed. aLine should not be nsnull
nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
{
NS_PRECONDITION(nsnull != aLine, "null parameter");
nsLineData* prevLine = aLine->mPrevLine;
if (nsnull != prevLine) {
// Compute the running y-offset, and the available height
mY = prevLine->mBounds.YMost();
if (!mUnconstrainedHeight) {
mAvailSize.height -= mY;
}
// Compute the kid x-most
for (nsLineData* l = prevLine; nsnull != l; l = l->mPrevLine) {
nscoord xmost = l->mBounds.XMost();
if (xmost > mKidXMost) {
mKidXMost = xmost;
}
}
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
}
return NS_OK;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -780,6 +819,52 @@ done:
return rv; return rv;
} }
// XXX This is a short-term hack. It assumes that the caller has already recovered
// the state, and that some space has been retrieved from the space manager...
nsresult
nsBlockFrame::ReflowMappedFrom(nsBlockReflowState& aState, nsLineData* aLine)
{
nsresult rv = NS_OK;
nsLineLayout lineLayout(aState);
aState.mCurrentLine = &lineLayout;
while (nsnull != aLine) {
// Initialize the line layout for this line
rv = lineLayout.Initialize(aState, aLine);
if (NS_OK != rv) {
goto done;
}
lineLayout.mPrevKidFrame = aState.mPrevKidFrame;
// Reflow the line
nsresult lineReflowStatus = lineLayout.ReflowLine();
if (lineReflowStatus < 0) {
// Some kind of hard error
rv = lineReflowStatus;
goto done;
}
mChildCount += lineLayout.mNewFrames;
// Now place it. It's possible it won't fit.
rv = PlaceLine(aState, lineLayout, aLine);
if (NS_LINE_LAYOUT_COMPLETE != rv) {
goto done;
}
mLastContentOffset = aLine->mLastContentOffset;
mLastContentIsComplete = PRBool(aLine->mLastContentIsComplete);
aLine = aLine->mNextLine;
aState.mPrevKidFrame = lineLayout.mPrevKidFrame;
}
done:
aState.mCurrentLine = nsnull;
#ifdef NS_DEBUG
VerifyLines(PR_TRUE);
#endif
return rv;
}
nsresult nsresult
nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState) nsBlockFrame::ReflowUnmapped(nsBlockReflowState& aState)
{ {
@ -1194,6 +1279,51 @@ nsBlockFrame::ResizeReflow(nsIPresContext* aPresContext,
return rv; return rv;
} }
nsLineData* nsBlockFrame::FindLine(nsIFrame* aFrame)
{
// Find the line that contains the aFrame
nsLineData* line = mLines;
while (nsnull != line) {
nsIFrame* child = line->mFirstChild;
for (PRInt32 count = line->mChildCount; count > 0; count--) {
if (child == aFrame) {
return line;
}
child->GetNextSibling(child);
}
// Move to the next line
line = line->mNextLine;
}
return nsnull;
}
nsLineData* nsBlockFrame::LastLine()
{
nsLineData* lastLine = mLines;
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
return lastLine;
}
nsresult nsBlockFrame::IncrementalReflowAfter(nsBlockReflowState& aState,
nsLineData* aLine,
nsresult aReflowStatus,
const nsRect& aOldBounds)
{
// Now just reflow all the lines that follow...
// XXX Obviously this needs to be more efficient
return ReflowMappedFrom(aState, aLine->mNextLine);
}
NS_METHOD NS_METHOD
nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext, nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager, nsISpaceManager* aSpaceManager,
@ -1219,39 +1349,11 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Is the reflow command target at us? // Is the reflow command target at us?
if (this == aReflowCommand.GetTarget()) { if (this == aReflowCommand.GetTarget()) {
if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) { if (aReflowCommand.GetType() == nsReflowCommand::FrameAppended) {
nsLineData* lastLine = mLines; nsLineData* lastLine = LastLine();
// Get the last line
if (nsnull != lastLine) {
while (nsnull != lastLine->mNextLine) {
lastLine = lastLine->mNextLine;
}
}
// Restore the state // Restore the state
if ((nsnull != lastLine) && (nsnull != lastLine->mPrevLine)) { if (nsnull != lastLine) {
nsLineData* prevLine = lastLine->mPrevLine; state.RecoverState(lastLine);
state.mY = prevLine->mBounds.YMost();
if (!state.mUnconstrainedHeight) {
state.mAvailSize.height -= state.mY;
}
// XXX This isn't really right...
state.mKidXMost = mRect.width - state.mBorderPadding.right;
// If the previous line is a block, then factor in its bottom margin
if (prevLine->mIsBlock) {
nsStyleSpacing* spacing;
nsIFrame* kid = prevLine->mFirstChild;
kid->GetStyleData(kStyleSpacingSID, (nsStyleStruct*&)spacing);
if (spacing->mMargin.bottom < 0) {
state.mPrevMaxNegBottomMargin = -spacing->mMargin.bottom;
} else {
state.mPrevMaxPosBottomMargin = spacing->mMargin.bottom;
}
}
} }
// Reflow unmapped children // Reflow unmapped children
@ -1267,38 +1369,65 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
rv = ReflowUnmapped(state); rv = ReflowUnmapped(state);
} }
// Set return status } else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
aStatus = frComplete; // Restore our state as if the child that changed is the next frame to reflow
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) { nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
rv = NS_OK; state.RecoverState(line);
aStatus = frNotComplete;
} // Get some available space to start reflowing with
GetAvailableSpace(state, state.mY);
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
} else { } else {
NS_NOTYETIMPLEMENTED("unexpected reflow command"); NS_NOTYETIMPLEMENTED("unexpected reflow command");
} }
} else { } else {
#if 0
// The command is passing through us. Get the next frame in the reflow chain // The command is passing through us. Get the next frame in the reflow chain
nsIFrame* nextFrame = aReflowCommand.GetNext(); nsIFrame* nextFrame = aReflowCommand.GetNext();
// Restore our state as if nextFrame is the next frame to reflow // Restore our state as if nextFrame is the next frame to reflow
RecoverState(aPresContext, state, nextFrame); nsLineData* line = FindLine(nextFrame);
state.RecoverState(line);
// Get the current bounds. We'll need this to adjust the frames that follow // Get some available space to start reflowing with
nsRect oldBounds; GetAvailableSpace(state, state.mY);
nextFrame->GetRect(oldBounds);
// Pass along the reflow command // Reflow the affected line
nsRect desiredRect; nsLineLayout lineLayout(state);
aStatus = aReflowCommand.Next(aSpaceManager, desiredRect, aMaxSize, nextFrame);
#endif state.mCurrentLine = &lineLayout;
NS_NOTYETIMPLEMENTED("unexpected reflow command"); lineLayout.Initialize(state, line);
// Have the line handle the incremental reflow
nsRect oldBounds = line->mBounds;
rv = lineLayout.IncrementalReflowFromChild(aReflowCommand, nextFrame);
// Now place the line. It's possible it won't fit
rv = PlaceLine(state, lineLayout, line);
// XXX The way NS_LINE_LAYOUT_COMPLETE is being used is very confusing...
if (NS_LINE_LAYOUT_COMPLETE == rv) {
mLastContentOffset = line->mLastContentOffset;
mLastContentIsComplete = PRBool(line->mLastContentIsComplete);
state.mPrevKidFrame = lineLayout.mPrevKidFrame;
// Now figure out what to do with the frames that follow
rv = IncrementalReflowAfter(state, line, rv, oldBounds);
}
} }
// Return our desired rect // Return our desired rect
ComputeDesiredRect(state, aMaxSize, aDesiredRect); ComputeDesiredRect(state, aMaxSize, aDesiredRect);
// Set return status
aStatus = frComplete;
if (NS_LINE_LAYOUT_NOT_COMPLETE == rv) {
rv = NS_OK;
aStatus = frNotComplete;
}
// Now that reflow has finished, remove the cached pointer // Now that reflow has finished, remove the cached pointer
shell->RemoveCachedData(this); shell->RemoveCachedData(this);
NS_RELEASE(shell); NS_RELEASE(shell);

View File

@ -272,14 +272,13 @@ NS_METHOD nsBodyFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsSize columnMaxSize = GetColumnAvailSpace(aPresContext, mySpacing, nsSize columnMaxSize = GetColumnAvailSpace(aPresContext, mySpacing,
aMaxSize); aMaxSize);
// Pass the command along to our child frame // Pass the command along to our column pseudo frame
nsIRunaround* reflowRunaround; nsRect desiredRect;
nsRect desiredRect; nsIFrame* nextFrame;
NS_ASSERTION(nsnull != mFirstChild, "no first child"); NS_ASSERTION(nsnull != mFirstChild, "no first child");
mFirstChild->QueryInterface(kIRunaroundIID, (void**)&reflowRunaround); aStatus = aReflowCommand.Next(mSpaceManager, desiredRect, columnMaxSize,
reflowRunaround->IncrementalReflow(aPresContext, mSpaceManager, nextFrame);
columnMaxSize, desiredRect, aReflowCommand, aStatus);
// Place and size the frame // Place and size the frame
desiredRect.x += leftInset; desiredRect.x += leftInset;

View File

@ -28,6 +28,7 @@
#include "nsPlaceholderFrame.h" #include "nsPlaceholderFrame.h"
#include "nsCSSLayout.h" #include "nsCSSLayout.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsReflowCommand.h"
#undef NOISY_REFLOW #undef NOISY_REFLOW
@ -356,7 +357,7 @@ nsLineLayout::WordBreakReflow()
// Return values: <0 for error // Return values: <0 for error
// 0 == NS_LINE_LAYOUT // 0 == NS_LINE_LAYOUT
nsresult nsresult
nsLineLayout::ReflowChild() nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand)
{ {
// Get kid frame's style context // Get kid frame's style context
nsIStyleContextPtr kidSC; nsIStyleContextPtr kidSC;
@ -413,7 +414,20 @@ nsLineLayout::ReflowChild()
} }
mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE; mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
nscoord dx = mReflowData.mX + kidSpacing->mMargin.left; nscoord dx = mReflowData.mX + kidSpacing->mMargin.left;
if (isBlock) { if (aReflowCommand) {
nsIFrame* nextFrame;
mSpaceManager->Translate(dx, mY);
kidReflowStatus = aReflowCommand->Next(mSpaceManager, kidRect, kidAvailSize, nextFrame);
mSpaceManager->Translate(-dx, -mY);
kidRect.x = dx;
kidRect.y = mY;
kidSize.width = kidRect.width;
kidSize.height = kidRect.height;
kidSize.ascent = kidRect.height;
kidSize.descent = 0;
} else if (isBlock) {
mSpaceManager->Translate(dx, mY); mSpaceManager->Translate(dx, mY);
rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext, rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext,
mSpaceManager, kidAvailSize, kidRect, mSpaceManager, kidAvailSize, kidRect,
@ -518,6 +532,94 @@ nsLineLayout::ReflowChild()
return rv; return rv;
} }
nsresult
nsLineLayout::IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
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;
mLine->mBounds.x = mReflowData.mX;
mLine->mBounds.y = mY;
mKidFrame = mLine->mFirstChild;
PRInt32 kidNum = 0;
while (kidNum < mLine->mChildCount) {
// XXX Code to avoid reflowing a child goes here
nsresult childReflowStatus;
if (mKidFrame == aChildFrame) {
childReflowStatus = ReflowChild(&aReflowCommand);
} else {
childReflowStatus = ReflowChild(nsnull);
}
if (childReflowStatus < 0) {
reflowStatus = childReflowStatus;
goto done;
}
switch (childReflowStatus) {
default:
case NS_LINE_LAYOUT_COMPLETE:
mPrevKidFrame = mKidFrame;
mKidFrame->GetNextSibling(mKidFrame);
mKidIndex++;
kidNum++;
break;
case NS_LINE_LAYOUT_NOT_COMPLETE:
reflowStatus = childReflowStatus;
mPrevKidFrame = mKidFrame;
mKidFrame->GetNextSibling(mKidFrame);
kidNum++;
goto split_line;
case NS_LINE_LAYOUT_BREAK_BEFORE:
reflowStatus = childReflowStatus;
goto split_line;
case NS_LINE_LAYOUT_BREAK_AFTER:
reflowStatus = childReflowStatus;
mPrevKidFrame = mKidFrame;
mKidFrame->GetNextSibling(mKidFrame);
mKidIndex++;
kidNum++;
split_line:
reflowStatus = SplitLine(childReflowStatus, mLine->mChildCount - kidNum);
goto done;
}
}
done:
// Perform alignment operations
if (mLine->mIsBlock) {
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
}
else {
AlignChildren();
}
// Set final bounds of the line
mLine->mBounds.height = mLineHeight;
mLine->mBounds.width = mReflowData.mX - mLine->mBounds.x;
NS_ASSERTION(((reflowStatus < 0) ||
(reflowStatus == NS_LINE_LAYOUT_COMPLETE) ||
(reflowStatus == NS_LINE_LAYOUT_NOT_COMPLETE) ||
(reflowStatus == NS_LINE_LAYOUT_BREAK_BEFORE) ||
(reflowStatus == NS_LINE_LAYOUT_BREAK_AFTER)),
"bad return status from ReflowMapped");
return reflowStatus;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsresult nsresult
@ -630,7 +732,7 @@ nsLineLayout::ReflowMapped()
while (kidNum < mLine->mChildCount) { while (kidNum < mLine->mChildCount) {
// XXX Code to avoid reflowing a child goes here // XXX Code to avoid reflowing a child goes here
nsresult childReflowStatus = ReflowChild(); nsresult childReflowStatus = ReflowChild(nsnull);
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -769,7 +871,7 @@ nsLineLayout::PullUpChildren()
} }
// Try to reflow it like any other mapped child // Try to reflow it like any other mapped child
nsresult childReflowStatus = ReflowChild(); nsresult childReflowStatus = ReflowChild(nsnull);
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;
@ -942,7 +1044,7 @@ nsLineLayout::ReflowUnmapped()
} }
// Reflow new child frame // Reflow new child frame
childReflowStatus = ReflowChild(); childReflowStatus = ReflowChild(nsnull);
if (childReflowStatus < 0) { if (childReflowStatus < 0) {
reflowStatus = childReflowStatus; reflowStatus = childReflowStatus;
goto done; goto done;

View File

@ -100,16 +100,16 @@ struct nsLineLayout {
*/ */
nsresult ReflowLine(); nsresult ReflowLine();
nsresult IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
nsIFrame* aChildFrame);
// The presentation context // The presentation context
nsIPresContext* mPresContext; nsIPresContext* mPresContext;
// The block behind the line // The block behind the line
nsBlockFrame* mBlock; nsBlockFrame* mBlock;
nsISpaceManager* mSpaceManager; nsISpaceManager* mSpaceManager;
#if 0
// XXX I don't think we need this anymore...
PRBool mBlockIsPseudo;
#endif
nsIContent* mBlockContent; nsIContent* mBlockContent;
PRInt32 mKidIndex; PRInt32 mKidIndex;
@ -180,7 +180,7 @@ protected:
nsresult WordBreakReflow(); nsresult WordBreakReflow();
nsresult ReflowChild(); nsresult ReflowChild(nsReflowCommand* aReflowCommand);
nsresult ReflowMapped(); nsresult ReflowMapped();