Moved margin code into line layout

This commit is contained in:
kipp
1998-05-12 23:49:40 +00:00
parent 1d5d052d7a
commit 2bd46793e7
12 changed files with 210 additions and 640 deletions

View File

@@ -133,8 +133,8 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
}
mKidXMost = 0;
mPrevMaxPosBottomMargin = 0;
mPrevMaxNegBottomMargin = 0;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = 0;
mNextListOrdinal = -1;
mFirstChildIsInsideBullet = PR_FALSE;
@@ -173,9 +173,11 @@ nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
if (kidMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -kidMargin.bottom;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = -kidMargin.bottom;
} else {
mPrevMaxPosBottomMargin = kidMargin.bottom;
mPrevPosBottomMargin = kidMargin.bottom;
mPrevNegBottomMargin = 0;
}
}
}
@@ -526,97 +528,23 @@ nsBlockFrame::DrainOverflowList()
#endif
}
// XXX add in code here that notices if margin's were not provided by
// the style system and when that is the case to apply the old layout
// engines margin calculations.
nsresult
nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine)
{
nsresult rv = NS_LINE_LAYOUT_COMPLETE;
nscoord topMargin = 0;
nscoord bottomMargin = 0;
nscoord maxNegBottomMargin = 0;
nscoord maxPosBottomMargin = 0;
// See if block margins apply to this line or not
PRBool isBlockLine = PR_FALSE;
if (1 == aLine->mChildCount) {
nsIStyleContextPtr kidSC;
nsIFrame* kid = aLine->mFirstChild;
rv = kid->GetStyleContext(aState.mPresContext, kidSC.AssignRef());
if (NS_OK != rv) return rv;
nsStyleDisplay* display = (nsStyleDisplay*)
kidSC->GetData(kStyleDisplaySID);
switch (display->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
isBlockLine = PR_TRUE;
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(kStyleSpacingSID);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
// Calculate top margin by collapsing with previous bottom margin
// if any.
nscoord maxNegTopMargin = 0;
nscoord maxPosTopMargin = 0;
if (kidMargin.top < 0) {
maxNegTopMargin = -kidMargin.top;
} else {
maxPosTopMargin = kidMargin.top;
}
nscoord maxPos = PR_MAX(aState.mPrevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.mPrevMaxNegBottomMargin, maxNegTopMargin);
topMargin = maxPos - maxNeg;
// Save away bottom information for later promotion into aState
if (kidMargin.bottom < 0) {
maxNegBottomMargin = -kidMargin.bottom;
} else {
maxPosBottomMargin = kidMargin.bottom;
}
break;
}
}
// Before we move the line, make sure that it will fit in it's new
// Before we place the line, make sure that it will fit in it's new
// location. It always fits if the height isn't constrained or it's
// the first line.
nscoord totalHeight = topMargin + aLine->mBounds.height;
if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
if (aState.mY + totalHeight > aState.mAvailSize.height) {
if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
// The line will not fit
rv = PushLines(aState, aLine);
goto done;
}
}
if (isBlockLine) {
if (0 != topMargin) {
// We have to move the line now that we know the top margin
// for it.
aLine->MoveLineBy(0, topMargin);
aState.mY += topMargin;
}
}
else {
// Apply previous line's bottom margin before the inline-line.
nscoord bottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
if (0 != bottomMargin) {
aLine->MoveLineBy(0, bottomMargin);
aState.mY += bottomMargin;
return PushLines(aState, aLine);
}
}
// Consume space and advance running values
aState.mY += aLine->mBounds.height;
aState.mPrevMaxNegBottomMargin = maxNegBottomMargin;
aState.mPrevMaxPosBottomMargin = maxPosBottomMargin;
if (nsnull != aState.mMaxElementSizePointer) {
nsSize* maxSize = aState.mMaxElementSizePointer;
if (aLineLayout.mReflowData.mMaxElementSize.width > maxSize->width) {
@@ -626,11 +554,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
maxSize->height = aLineLayout.mReflowData.mMaxElementSize.height;
}
}
{
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
// Any below current line floaters to place?
@@ -648,8 +574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
GetAvailableSpace(aState, aState.mY);
}
done:
return rv;
return NS_LINE_LAYOUT_COMPLETE;
}
// aY has borderpadding.top already factored in
@@ -1465,8 +1390,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
}
}
aState.mY += aState.mBorderPadding.bottom;
nscoord lastBottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
aState.mPrevNegBottomMargin;
if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
// It's possible that we don't have room for the last bottom
// margin (the last bottom margin is the margin following a block
@@ -1481,8 +1406,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
lastBottomMargin = 0;
}
}
aState.mY += lastBottomMargin;
}
aState.mY += lastBottomMargin;
aDesiredRect.height = aState.mY;
if (!aState.mBlockIsPseudo) {

View File

@@ -87,9 +87,10 @@ struct nsBlockReflowState {
nsSize* mMaxElementSizePointer;
nscoord mKidXMost;
// Bottom margin information from the previous line
nscoord mPrevMaxNegBottomMargin;
nscoord mPrevMaxPosBottomMargin;
// Bottom margin information from the previous line (only when
// the previous line contains a block element)
nscoord mPrevNegBottomMargin;
nscoord mPrevPosBottomMargin;
// Block frame border+padding information
nsMargin mBorderPadding;

View File

@@ -133,8 +133,8 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
}
mKidXMost = 0;
mPrevMaxPosBottomMargin = 0;
mPrevMaxNegBottomMargin = 0;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = 0;
mNextListOrdinal = -1;
mFirstChildIsInsideBullet = PR_FALSE;
@@ -173,9 +173,11 @@ nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
if (kidMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -kidMargin.bottom;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = -kidMargin.bottom;
} else {
mPrevMaxPosBottomMargin = kidMargin.bottom;
mPrevPosBottomMargin = kidMargin.bottom;
mPrevNegBottomMargin = 0;
}
}
}
@@ -526,97 +528,23 @@ nsBlockFrame::DrainOverflowList()
#endif
}
// XXX add in code here that notices if margin's were not provided by
// the style system and when that is the case to apply the old layout
// engines margin calculations.
nsresult
nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine)
{
nsresult rv = NS_LINE_LAYOUT_COMPLETE;
nscoord topMargin = 0;
nscoord bottomMargin = 0;
nscoord maxNegBottomMargin = 0;
nscoord maxPosBottomMargin = 0;
// See if block margins apply to this line or not
PRBool isBlockLine = PR_FALSE;
if (1 == aLine->mChildCount) {
nsIStyleContextPtr kidSC;
nsIFrame* kid = aLine->mFirstChild;
rv = kid->GetStyleContext(aState.mPresContext, kidSC.AssignRef());
if (NS_OK != rv) return rv;
nsStyleDisplay* display = (nsStyleDisplay*)
kidSC->GetData(kStyleDisplaySID);
switch (display->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
isBlockLine = PR_TRUE;
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(kStyleSpacingSID);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
// Calculate top margin by collapsing with previous bottom margin
// if any.
nscoord maxNegTopMargin = 0;
nscoord maxPosTopMargin = 0;
if (kidMargin.top < 0) {
maxNegTopMargin = -kidMargin.top;
} else {
maxPosTopMargin = kidMargin.top;
}
nscoord maxPos = PR_MAX(aState.mPrevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.mPrevMaxNegBottomMargin, maxNegTopMargin);
topMargin = maxPos - maxNeg;
// Save away bottom information for later promotion into aState
if (kidMargin.bottom < 0) {
maxNegBottomMargin = -kidMargin.bottom;
} else {
maxPosBottomMargin = kidMargin.bottom;
}
break;
}
}
// Before we move the line, make sure that it will fit in it's new
// Before we place the line, make sure that it will fit in it's new
// location. It always fits if the height isn't constrained or it's
// the first line.
nscoord totalHeight = topMargin + aLine->mBounds.height;
if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
if (aState.mY + totalHeight > aState.mAvailSize.height) {
if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
// The line will not fit
rv = PushLines(aState, aLine);
goto done;
}
}
if (isBlockLine) {
if (0 != topMargin) {
// We have to move the line now that we know the top margin
// for it.
aLine->MoveLineBy(0, topMargin);
aState.mY += topMargin;
}
}
else {
// Apply previous line's bottom margin before the inline-line.
nscoord bottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
if (0 != bottomMargin) {
aLine->MoveLineBy(0, bottomMargin);
aState.mY += bottomMargin;
return PushLines(aState, aLine);
}
}
// Consume space and advance running values
aState.mY += aLine->mBounds.height;
aState.mPrevMaxNegBottomMargin = maxNegBottomMargin;
aState.mPrevMaxPosBottomMargin = maxPosBottomMargin;
if (nsnull != aState.mMaxElementSizePointer) {
nsSize* maxSize = aState.mMaxElementSizePointer;
if (aLineLayout.mReflowData.mMaxElementSize.width > maxSize->width) {
@@ -626,11 +554,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
maxSize->height = aLineLayout.mReflowData.mMaxElementSize.height;
}
}
{
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
// Any below current line floaters to place?
@@ -648,8 +574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
GetAvailableSpace(aState, aState.mY);
}
done:
return rv;
return NS_LINE_LAYOUT_COMPLETE;
}
// aY has borderpadding.top already factored in
@@ -1465,8 +1390,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
}
}
aState.mY += aState.mBorderPadding.bottom;
nscoord lastBottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
aState.mPrevNegBottomMargin;
if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
// It's possible that we don't have room for the last bottom
// margin (the last bottom margin is the margin following a block
@@ -1481,8 +1406,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
lastBottomMargin = 0;
}
}
aState.mY += lastBottomMargin;
}
aState.mY += lastBottomMargin;
aDesiredRect.height = aState.mY;
if (!aState.mBlockIsPseudo) {

View File

@@ -133,8 +133,8 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
}
mKidXMost = 0;
mPrevMaxPosBottomMargin = 0;
mPrevMaxNegBottomMargin = 0;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = 0;
mNextListOrdinal = -1;
mFirstChildIsInsideBullet = PR_FALSE;
@@ -173,9 +173,11 @@ nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
if (kidMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -kidMargin.bottom;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = -kidMargin.bottom;
} else {
mPrevMaxPosBottomMargin = kidMargin.bottom;
mPrevPosBottomMargin = kidMargin.bottom;
mPrevNegBottomMargin = 0;
}
}
}
@@ -526,97 +528,23 @@ nsBlockFrame::DrainOverflowList()
#endif
}
// XXX add in code here that notices if margin's were not provided by
// the style system and when that is the case to apply the old layout
// engines margin calculations.
nsresult
nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine)
{
nsresult rv = NS_LINE_LAYOUT_COMPLETE;
nscoord topMargin = 0;
nscoord bottomMargin = 0;
nscoord maxNegBottomMargin = 0;
nscoord maxPosBottomMargin = 0;
// See if block margins apply to this line or not
PRBool isBlockLine = PR_FALSE;
if (1 == aLine->mChildCount) {
nsIStyleContextPtr kidSC;
nsIFrame* kid = aLine->mFirstChild;
rv = kid->GetStyleContext(aState.mPresContext, kidSC.AssignRef());
if (NS_OK != rv) return rv;
nsStyleDisplay* display = (nsStyleDisplay*)
kidSC->GetData(kStyleDisplaySID);
switch (display->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
isBlockLine = PR_TRUE;
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(kStyleSpacingSID);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
// Calculate top margin by collapsing with previous bottom margin
// if any.
nscoord maxNegTopMargin = 0;
nscoord maxPosTopMargin = 0;
if (kidMargin.top < 0) {
maxNegTopMargin = -kidMargin.top;
} else {
maxPosTopMargin = kidMargin.top;
}
nscoord maxPos = PR_MAX(aState.mPrevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.mPrevMaxNegBottomMargin, maxNegTopMargin);
topMargin = maxPos - maxNeg;
// Save away bottom information for later promotion into aState
if (kidMargin.bottom < 0) {
maxNegBottomMargin = -kidMargin.bottom;
} else {
maxPosBottomMargin = kidMargin.bottom;
}
break;
}
}
// Before we move the line, make sure that it will fit in it's new
// Before we place the line, make sure that it will fit in it's new
// location. It always fits if the height isn't constrained or it's
// the first line.
nscoord totalHeight = topMargin + aLine->mBounds.height;
if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
if (aState.mY + totalHeight > aState.mAvailSize.height) {
if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
// The line will not fit
rv = PushLines(aState, aLine);
goto done;
}
}
if (isBlockLine) {
if (0 != topMargin) {
// We have to move the line now that we know the top margin
// for it.
aLine->MoveLineBy(0, topMargin);
aState.mY += topMargin;
}
}
else {
// Apply previous line's bottom margin before the inline-line.
nscoord bottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
if (0 != bottomMargin) {
aLine->MoveLineBy(0, bottomMargin);
aState.mY += bottomMargin;
return PushLines(aState, aLine);
}
}
// Consume space and advance running values
aState.mY += aLine->mBounds.height;
aState.mPrevMaxNegBottomMargin = maxNegBottomMargin;
aState.mPrevMaxPosBottomMargin = maxPosBottomMargin;
if (nsnull != aState.mMaxElementSizePointer) {
nsSize* maxSize = aState.mMaxElementSizePointer;
if (aLineLayout.mReflowData.mMaxElementSize.width > maxSize->width) {
@@ -626,11 +554,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
maxSize->height = aLineLayout.mReflowData.mMaxElementSize.height;
}
}
{
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
// Any below current line floaters to place?
@@ -648,8 +574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
GetAvailableSpace(aState, aState.mY);
}
done:
return rv;
return NS_LINE_LAYOUT_COMPLETE;
}
// aY has borderpadding.top already factored in
@@ -1465,8 +1390,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
}
}
aState.mY += aState.mBorderPadding.bottom;
nscoord lastBottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
aState.mPrevNegBottomMargin;
if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
// It's possible that we don't have room for the last bottom
// margin (the last bottom margin is the margin following a block
@@ -1481,8 +1406,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
lastBottomMargin = 0;
}
}
aState.mY += lastBottomMargin;
}
aState.mY += lastBottomMargin;
aDesiredRect.height = aState.mY;
if (!aState.mBlockIsPseudo) {

View File

@@ -68,21 +68,6 @@ nsLineData::UnlinkLine()
if (nsnull != prevLine) prevLine->mNextLine = nextLine;
}
void
nsLineData::MoveLineBy(nscoord dx, nscoord dy)
{
nsIFrame* kid = mFirstChild;
nsPoint pt;
for (PRInt32 i = mChildCount; --i >= 0; ) {
kid->GetOrigin(pt);
pt.x += dx;
pt.y += dy;
kid->MoveTo(pt.x, pt.y);
kid->GetNextSibling(kid);
}
mBounds.MoveBy(dx, dy);
}
nsresult
nsLineData::Verify(PRBool aFinalCheck) const
{
@@ -196,15 +181,12 @@ nsLineData::List(FILE* out, PRInt32 aIndent) const
//----------------------------------------------------------------------
nsLineLayout::nsLineLayout(nsBlockReflowState& aState)
: mBlockReflowState(aState)
{
mBlock = aState.mBlock;
mSpaceManager = aState.mSpaceManager;
mBlock->GetContent(mBlockContent);
mPresContext = aState.mPresContext;
#if 0
// XXX Do we still need this?
mBlockIsPseudo = aState.mBlockIsPseudo;
#endif
mUnconstrainedWidth = aState.mUnconstrainedWidth;
mUnconstrainedHeight = aState.mUnconstrainedHeight;
mMaxElementSizePointer = aState.mMaxElementSizePointer;
@@ -235,6 +217,7 @@ nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
mReflowData.mMaxElementSize.height = 0;
mReflowData.mMaxAscent = nsnull;
mReflowData.mMaxDescent = nsnull;
mMarginApplied = PR_FALSE;
SetReflowSpace(aState.mCurrentBand.availSpace);
mY = aState.mY;
@@ -430,8 +413,39 @@ nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand)
kidSize.height = kidRect.height;
kidSize.ascent = kidRect.height;
kidSize.descent = 0;
} else if (isBlock) {
// Calculate top margin by collapsing with previous bottom margin
nscoord negTopMargin;
nscoord posTopMargin;
nsMargin kidMargin;
kidSpacing->CalcMarginFor(mKidFrame, kidMargin);
if (kidMargin.top < 0) {
negTopMargin = -kidMargin.top;
posTopMargin = 0;
} else {
negTopMargin = 0;
posTopMargin = kidMargin.top;
}
nscoord maxPos =
PR_MAX(mBlockReflowState.mPrevPosBottomMargin, posTopMargin);
nscoord maxNeg =
PR_MAX(mBlockReflowState.mPrevNegBottomMargin, negTopMargin);
nscoord topMargin = maxPos - maxNeg;
// Save away bottom margin information for later
if (kidMargin.bottom < 0) {
mBlockReflowState.mPrevNegBottomMargin = -kidMargin.bottom;
mBlockReflowState.mPrevPosBottomMargin = 0;
} else {
mBlockReflowState.mPrevNegBottomMargin = 0;
mBlockReflowState.mPrevPosBottomMargin = kidMargin.bottom;
}
mY += topMargin;
mBlockReflowState.mY += topMargin;
// XXX tell block what topMargin ended up being so that it can
// undo it if it ends up pushing the line.
mSpaceManager->Translate(dx, mY);
rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext,
mSpaceManager, kidAvailSize, kidRect,
@@ -445,9 +459,26 @@ nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand)
kidSize.descent = 0;
}
else {
// Reflow the inline child
rv = mBlock->ReflowInlineChild(mKidFrame, mPresContext,
kidSize, kidAvailSize, kidMaxElementSize,
kidReflowStatus);
// After we reflow the inline child we will know whether or not it
// has any height/width. If it doesn't have any height/width then
// we do not yet apply any previous block bottom margin.
if ((0 != kidSize.height) && !mMarginApplied) {
// Before we place the first inline child on this line apply
// the previous block's bottom margin.
nscoord bottomMargin = mBlockReflowState.mPrevPosBottomMargin -
mBlockReflowState.mPrevNegBottomMargin;
mY += bottomMargin;
mBlockReflowState.mY += bottomMargin;
// XXX tell block what bottomMargin ended up being so that it can
// undo it if it ends up pushing the line.
mMarginApplied = PR_TRUE;
mBlockReflowState.mPrevPosBottomMargin = 0;
mBlockReflowState.mPrevNegBottomMargin = 0;
}
kidRect.x = dx;
kidRect.y = mY;
kidRect.width = kidSize.width;

View File

@@ -39,7 +39,6 @@ struct nsLineData {
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
void UnlinkLine();
PRIntn GetLineNumber() const;
void MoveLineBy(nscoord dx, nscoord dy);
nsLineData* mNextLine;
nsLineData* mPrevLine;
@@ -75,29 +74,6 @@ struct nsLineLayout {
void SetReflowSpace(nsRect& aAvailableSpaceRect);
/**
* <h2>Rules of order</h2>
*
* Lines are disassociated from the block frame's state
* (mLastContentIsComplete, mLastContentOffset, mChildCount). Upon
* completion of this routine the block frame is responsible for
* updating it's own state.<p>
*
* ReflowLine can return the following status:
*
* <dl>
* <dt>NS_LINE_LAYOUT_BREAK_BEFORE</dt>
*
* <dd>mKidFrame and mKidIndex indicate the child to break
* before. Note that we will always have a child frame created which
* means we must not lose it!</dd>
*
* <dt>NS_LINE_LAYOUT_OK</dt>
*
* <dd>This means that the line should be flushed out as is</dd>
*
* </dl>
*/
nsresult ReflowLine();
nsresult IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
@@ -109,6 +85,7 @@ struct nsLineLayout {
// The block behind the line
nsBlockFrame* mBlock;
nsBlockReflowState& mBlockReflowState;
nsISpaceManager* mSpaceManager;
nsIContent* mBlockContent;
PRInt32 mKidIndex;
@@ -130,6 +107,7 @@ struct nsLineLayout {
PRPackedBool mUnconstrainedWidth;
PRPackedBool mUnconstrainedHeight;
PRPackedBool mMarginApplied;
nscoord mY;
nscoord mLineHeight;
nscoord mMaxWidth;

View File

@@ -133,8 +133,8 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
}
mKidXMost = 0;
mPrevMaxPosBottomMargin = 0;
mPrevMaxNegBottomMargin = 0;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = 0;
mNextListOrdinal = -1;
mFirstChildIsInsideBullet = PR_FALSE;
@@ -173,9 +173,11 @@ nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
if (kidMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -kidMargin.bottom;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = -kidMargin.bottom;
} else {
mPrevMaxPosBottomMargin = kidMargin.bottom;
mPrevPosBottomMargin = kidMargin.bottom;
mPrevNegBottomMargin = 0;
}
}
}
@@ -526,97 +528,23 @@ nsBlockFrame::DrainOverflowList()
#endif
}
// XXX add in code here that notices if margin's were not provided by
// the style system and when that is the case to apply the old layout
// engines margin calculations.
nsresult
nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine)
{
nsresult rv = NS_LINE_LAYOUT_COMPLETE;
nscoord topMargin = 0;
nscoord bottomMargin = 0;
nscoord maxNegBottomMargin = 0;
nscoord maxPosBottomMargin = 0;
// See if block margins apply to this line or not
PRBool isBlockLine = PR_FALSE;
if (1 == aLine->mChildCount) {
nsIStyleContextPtr kidSC;
nsIFrame* kid = aLine->mFirstChild;
rv = kid->GetStyleContext(aState.mPresContext, kidSC.AssignRef());
if (NS_OK != rv) return rv;
nsStyleDisplay* display = (nsStyleDisplay*)
kidSC->GetData(kStyleDisplaySID);
switch (display->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
isBlockLine = PR_TRUE;
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(kStyleSpacingSID);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
// Calculate top margin by collapsing with previous bottom margin
// if any.
nscoord maxNegTopMargin = 0;
nscoord maxPosTopMargin = 0;
if (kidMargin.top < 0) {
maxNegTopMargin = -kidMargin.top;
} else {
maxPosTopMargin = kidMargin.top;
}
nscoord maxPos = PR_MAX(aState.mPrevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.mPrevMaxNegBottomMargin, maxNegTopMargin);
topMargin = maxPos - maxNeg;
// Save away bottom information for later promotion into aState
if (kidMargin.bottom < 0) {
maxNegBottomMargin = -kidMargin.bottom;
} else {
maxPosBottomMargin = kidMargin.bottom;
}
break;
}
}
// Before we move the line, make sure that it will fit in it's new
// Before we place the line, make sure that it will fit in it's new
// location. It always fits if the height isn't constrained or it's
// the first line.
nscoord totalHeight = topMargin + aLine->mBounds.height;
if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
if (aState.mY + totalHeight > aState.mAvailSize.height) {
if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
// The line will not fit
rv = PushLines(aState, aLine);
goto done;
}
}
if (isBlockLine) {
if (0 != topMargin) {
// We have to move the line now that we know the top margin
// for it.
aLine->MoveLineBy(0, topMargin);
aState.mY += topMargin;
}
}
else {
// Apply previous line's bottom margin before the inline-line.
nscoord bottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
if (0 != bottomMargin) {
aLine->MoveLineBy(0, bottomMargin);
aState.mY += bottomMargin;
return PushLines(aState, aLine);
}
}
// Consume space and advance running values
aState.mY += aLine->mBounds.height;
aState.mPrevMaxNegBottomMargin = maxNegBottomMargin;
aState.mPrevMaxPosBottomMargin = maxPosBottomMargin;
if (nsnull != aState.mMaxElementSizePointer) {
nsSize* maxSize = aState.mMaxElementSizePointer;
if (aLineLayout.mReflowData.mMaxElementSize.width > maxSize->width) {
@@ -626,11 +554,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
maxSize->height = aLineLayout.mReflowData.mMaxElementSize.height;
}
}
{
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
// Any below current line floaters to place?
@@ -648,8 +574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
GetAvailableSpace(aState, aState.mY);
}
done:
return rv;
return NS_LINE_LAYOUT_COMPLETE;
}
// aY has borderpadding.top already factored in
@@ -1465,8 +1390,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
}
}
aState.mY += aState.mBorderPadding.bottom;
nscoord lastBottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
aState.mPrevNegBottomMargin;
if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
// It's possible that we don't have room for the last bottom
// margin (the last bottom margin is the margin following a block
@@ -1481,8 +1406,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
lastBottomMargin = 0;
}
}
aState.mY += lastBottomMargin;
}
aState.mY += lastBottomMargin;
aDesiredRect.height = aState.mY;
if (!aState.mBlockIsPseudo) {

View File

@@ -87,9 +87,10 @@ struct nsBlockReflowState {
nsSize* mMaxElementSizePointer;
nscoord mKidXMost;
// Bottom margin information from the previous line
nscoord mPrevMaxNegBottomMargin;
nscoord mPrevMaxPosBottomMargin;
// Bottom margin information from the previous line (only when
// the previous line contains a block element)
nscoord mPrevNegBottomMargin;
nscoord mPrevPosBottomMargin;
// Block frame border+padding information
nsMargin mBorderPadding;

View File

@@ -133,8 +133,8 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
}
mKidXMost = 0;
mPrevMaxPosBottomMargin = 0;
mPrevMaxNegBottomMargin = 0;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = 0;
mNextListOrdinal = -1;
mFirstChildIsInsideBullet = PR_FALSE;
@@ -173,9 +173,11 @@ nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
if (kidMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -kidMargin.bottom;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = -kidMargin.bottom;
} else {
mPrevMaxPosBottomMargin = kidMargin.bottom;
mPrevPosBottomMargin = kidMargin.bottom;
mPrevNegBottomMargin = 0;
}
}
}
@@ -526,97 +528,23 @@ nsBlockFrame::DrainOverflowList()
#endif
}
// XXX add in code here that notices if margin's were not provided by
// the style system and when that is the case to apply the old layout
// engines margin calculations.
nsresult
nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine)
{
nsresult rv = NS_LINE_LAYOUT_COMPLETE;
nscoord topMargin = 0;
nscoord bottomMargin = 0;
nscoord maxNegBottomMargin = 0;
nscoord maxPosBottomMargin = 0;
// See if block margins apply to this line or not
PRBool isBlockLine = PR_FALSE;
if (1 == aLine->mChildCount) {
nsIStyleContextPtr kidSC;
nsIFrame* kid = aLine->mFirstChild;
rv = kid->GetStyleContext(aState.mPresContext, kidSC.AssignRef());
if (NS_OK != rv) return rv;
nsStyleDisplay* display = (nsStyleDisplay*)
kidSC->GetData(kStyleDisplaySID);
switch (display->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
isBlockLine = PR_TRUE;
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(kStyleSpacingSID);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
// Calculate top margin by collapsing with previous bottom margin
// if any.
nscoord maxNegTopMargin = 0;
nscoord maxPosTopMargin = 0;
if (kidMargin.top < 0) {
maxNegTopMargin = -kidMargin.top;
} else {
maxPosTopMargin = kidMargin.top;
}
nscoord maxPos = PR_MAX(aState.mPrevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.mPrevMaxNegBottomMargin, maxNegTopMargin);
topMargin = maxPos - maxNeg;
// Save away bottom information for later promotion into aState
if (kidMargin.bottom < 0) {
maxNegBottomMargin = -kidMargin.bottom;
} else {
maxPosBottomMargin = kidMargin.bottom;
}
break;
}
}
// Before we move the line, make sure that it will fit in it's new
// Before we place the line, make sure that it will fit in it's new
// location. It always fits if the height isn't constrained or it's
// the first line.
nscoord totalHeight = topMargin + aLine->mBounds.height;
if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
if (aState.mY + totalHeight > aState.mAvailSize.height) {
if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
// The line will not fit
rv = PushLines(aState, aLine);
goto done;
}
}
if (isBlockLine) {
if (0 != topMargin) {
// We have to move the line now that we know the top margin
// for it.
aLine->MoveLineBy(0, topMargin);
aState.mY += topMargin;
}
}
else {
// Apply previous line's bottom margin before the inline-line.
nscoord bottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
if (0 != bottomMargin) {
aLine->MoveLineBy(0, bottomMargin);
aState.mY += bottomMargin;
return PushLines(aState, aLine);
}
}
// Consume space and advance running values
aState.mY += aLine->mBounds.height;
aState.mPrevMaxNegBottomMargin = maxNegBottomMargin;
aState.mPrevMaxPosBottomMargin = maxPosBottomMargin;
if (nsnull != aState.mMaxElementSizePointer) {
nsSize* maxSize = aState.mMaxElementSizePointer;
if (aLineLayout.mReflowData.mMaxElementSize.width > maxSize->width) {
@@ -626,11 +554,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
maxSize->height = aLineLayout.mReflowData.mMaxElementSize.height;
}
}
{
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
// Any below current line floaters to place?
@@ -648,8 +574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
GetAvailableSpace(aState, aState.mY);
}
done:
return rv;
return NS_LINE_LAYOUT_COMPLETE;
}
// aY has borderpadding.top already factored in
@@ -1465,8 +1390,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
}
}
aState.mY += aState.mBorderPadding.bottom;
nscoord lastBottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
aState.mPrevNegBottomMargin;
if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
// It's possible that we don't have room for the last bottom
// margin (the last bottom margin is the margin following a block
@@ -1481,8 +1406,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
lastBottomMargin = 0;
}
}
aState.mY += lastBottomMargin;
}
aState.mY += lastBottomMargin;
aDesiredRect.height = aState.mY;
if (!aState.mBlockIsPseudo) {

View File

@@ -133,8 +133,8 @@ nsBlockReflowState::Initialize(nsIPresContext* aPresContext,
}
mKidXMost = 0;
mPrevMaxPosBottomMargin = 0;
mPrevMaxNegBottomMargin = 0;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = 0;
mNextListOrdinal = -1;
mFirstChildIsInsideBullet = PR_FALSE;
@@ -173,9 +173,11 @@ nsresult nsBlockReflowState::RecoverState(nsLineData* aLine)
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
if (kidMargin.bottom < 0) {
mPrevMaxNegBottomMargin = -kidMargin.bottom;
mPrevPosBottomMargin = 0;
mPrevNegBottomMargin = -kidMargin.bottom;
} else {
mPrevMaxPosBottomMargin = kidMargin.bottom;
mPrevPosBottomMargin = kidMargin.bottom;
mPrevNegBottomMargin = 0;
}
}
}
@@ -526,97 +528,23 @@ nsBlockFrame::DrainOverflowList()
#endif
}
// XXX add in code here that notices if margin's were not provided by
// the style system and when that is the case to apply the old layout
// engines margin calculations.
nsresult
nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine)
{
nsresult rv = NS_LINE_LAYOUT_COMPLETE;
nscoord topMargin = 0;
nscoord bottomMargin = 0;
nscoord maxNegBottomMargin = 0;
nscoord maxPosBottomMargin = 0;
// See if block margins apply to this line or not
PRBool isBlockLine = PR_FALSE;
if (1 == aLine->mChildCount) {
nsIStyleContextPtr kidSC;
nsIFrame* kid = aLine->mFirstChild;
rv = kid->GetStyleContext(aState.mPresContext, kidSC.AssignRef());
if (NS_OK != rv) return rv;
nsStyleDisplay* display = (nsStyleDisplay*)
kidSC->GetData(kStyleDisplaySID);
switch (display->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
isBlockLine = PR_TRUE;
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
kidSC->GetData(kStyleSpacingSID);
nsMargin kidMargin;
kidSpacing->CalcMarginFor(kid, kidMargin);
// Calculate top margin by collapsing with previous bottom margin
// if any.
nscoord maxNegTopMargin = 0;
nscoord maxPosTopMargin = 0;
if (kidMargin.top < 0) {
maxNegTopMargin = -kidMargin.top;
} else {
maxPosTopMargin = kidMargin.top;
}
nscoord maxPos = PR_MAX(aState.mPrevMaxPosBottomMargin, maxPosTopMargin);
nscoord maxNeg = PR_MAX(aState.mPrevMaxNegBottomMargin, maxNegTopMargin);
topMargin = maxPos - maxNeg;
// Save away bottom information for later promotion into aState
if (kidMargin.bottom < 0) {
maxNegBottomMargin = -kidMargin.bottom;
} else {
maxPosBottomMargin = kidMargin.bottom;
}
break;
}
}
// Before we move the line, make sure that it will fit in it's new
// Before we place the line, make sure that it will fit in it's new
// location. It always fits if the height isn't constrained or it's
// the first line.
nscoord totalHeight = topMargin + aLine->mBounds.height;
if (!aState.mUnconstrainedHeight && (aLine != mLines)) {
if (aState.mY + totalHeight > aState.mAvailSize.height) {
if (aState.mY + aLine->mBounds.height > aState.mAvailSize.height) {
// The line will not fit
rv = PushLines(aState, aLine);
goto done;
}
}
if (isBlockLine) {
if (0 != topMargin) {
// We have to move the line now that we know the top margin
// for it.
aLine->MoveLineBy(0, topMargin);
aState.mY += topMargin;
}
}
else {
// Apply previous line's bottom margin before the inline-line.
nscoord bottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
if (0 != bottomMargin) {
aLine->MoveLineBy(0, bottomMargin);
aState.mY += bottomMargin;
return PushLines(aState, aLine);
}
}
// Consume space and advance running values
aState.mY += aLine->mBounds.height;
aState.mPrevMaxNegBottomMargin = maxNegBottomMargin;
aState.mPrevMaxPosBottomMargin = maxPosBottomMargin;
if (nsnull != aState.mMaxElementSizePointer) {
nsSize* maxSize = aState.mMaxElementSizePointer;
if (aLineLayout.mReflowData.mMaxElementSize.width > maxSize->width) {
@@ -626,11 +554,9 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
maxSize->height = aLineLayout.mReflowData.mMaxElementSize.height;
}
}
{
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
nscoord xmost = aLine->mBounds.XMost();
if (xmost > aState.mKidXMost) {
aState.mKidXMost = xmost;
}
// Any below current line floaters to place?
@@ -648,8 +574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
GetAvailableSpace(aState, aState.mY);
}
done:
return rv;
return NS_LINE_LAYOUT_COMPLETE;
}
// aY has borderpadding.top already factored in
@@ -1465,8 +1390,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
}
}
aState.mY += aState.mBorderPadding.bottom;
nscoord lastBottomMargin = aState.mPrevMaxPosBottomMargin -
aState.mPrevMaxNegBottomMargin;
nscoord lastBottomMargin = aState.mPrevPosBottomMargin -
aState.mPrevNegBottomMargin;
if (!aState.mUnconstrainedHeight && (lastBottomMargin > 0)) {
// It's possible that we don't have room for the last bottom
// margin (the last bottom margin is the margin following a block
@@ -1481,8 +1406,8 @@ void nsBlockFrame::ComputeDesiredRect(nsBlockReflowState& aState,
lastBottomMargin = 0;
}
}
aState.mY += lastBottomMargin;
}
aState.mY += lastBottomMargin;
aDesiredRect.height = aState.mY;
if (!aState.mBlockIsPseudo) {

View File

@@ -68,21 +68,6 @@ nsLineData::UnlinkLine()
if (nsnull != prevLine) prevLine->mNextLine = nextLine;
}
void
nsLineData::MoveLineBy(nscoord dx, nscoord dy)
{
nsIFrame* kid = mFirstChild;
nsPoint pt;
for (PRInt32 i = mChildCount; --i >= 0; ) {
kid->GetOrigin(pt);
pt.x += dx;
pt.y += dy;
kid->MoveTo(pt.x, pt.y);
kid->GetNextSibling(kid);
}
mBounds.MoveBy(dx, dy);
}
nsresult
nsLineData::Verify(PRBool aFinalCheck) const
{
@@ -196,15 +181,12 @@ nsLineData::List(FILE* out, PRInt32 aIndent) const
//----------------------------------------------------------------------
nsLineLayout::nsLineLayout(nsBlockReflowState& aState)
: mBlockReflowState(aState)
{
mBlock = aState.mBlock;
mSpaceManager = aState.mSpaceManager;
mBlock->GetContent(mBlockContent);
mPresContext = aState.mPresContext;
#if 0
// XXX Do we still need this?
mBlockIsPseudo = aState.mBlockIsPseudo;
#endif
mUnconstrainedWidth = aState.mUnconstrainedWidth;
mUnconstrainedHeight = aState.mUnconstrainedHeight;
mMaxElementSizePointer = aState.mMaxElementSizePointer;
@@ -235,6 +217,7 @@ nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
mReflowData.mMaxElementSize.height = 0;
mReflowData.mMaxAscent = nsnull;
mReflowData.mMaxDescent = nsnull;
mMarginApplied = PR_FALSE;
SetReflowSpace(aState.mCurrentBand.availSpace);
mY = aState.mY;
@@ -430,8 +413,39 @@ nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand)
kidSize.height = kidRect.height;
kidSize.ascent = kidRect.height;
kidSize.descent = 0;
} else if (isBlock) {
// Calculate top margin by collapsing with previous bottom margin
nscoord negTopMargin;
nscoord posTopMargin;
nsMargin kidMargin;
kidSpacing->CalcMarginFor(mKidFrame, kidMargin);
if (kidMargin.top < 0) {
negTopMargin = -kidMargin.top;
posTopMargin = 0;
} else {
negTopMargin = 0;
posTopMargin = kidMargin.top;
}
nscoord maxPos =
PR_MAX(mBlockReflowState.mPrevPosBottomMargin, posTopMargin);
nscoord maxNeg =
PR_MAX(mBlockReflowState.mPrevNegBottomMargin, negTopMargin);
nscoord topMargin = maxPos - maxNeg;
// Save away bottom margin information for later
if (kidMargin.bottom < 0) {
mBlockReflowState.mPrevNegBottomMargin = -kidMargin.bottom;
mBlockReflowState.mPrevPosBottomMargin = 0;
} else {
mBlockReflowState.mPrevNegBottomMargin = 0;
mBlockReflowState.mPrevPosBottomMargin = kidMargin.bottom;
}
mY += topMargin;
mBlockReflowState.mY += topMargin;
// XXX tell block what topMargin ended up being so that it can
// undo it if it ends up pushing the line.
mSpaceManager->Translate(dx, mY);
rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext,
mSpaceManager, kidAvailSize, kidRect,
@@ -445,9 +459,26 @@ nsLineLayout::ReflowChild(nsReflowCommand* aReflowCommand)
kidSize.descent = 0;
}
else {
// Reflow the inline child
rv = mBlock->ReflowInlineChild(mKidFrame, mPresContext,
kidSize, kidAvailSize, kidMaxElementSize,
kidReflowStatus);
// After we reflow the inline child we will know whether or not it
// has any height/width. If it doesn't have any height/width then
// we do not yet apply any previous block bottom margin.
if ((0 != kidSize.height) && !mMarginApplied) {
// Before we place the first inline child on this line apply
// the previous block's bottom margin.
nscoord bottomMargin = mBlockReflowState.mPrevPosBottomMargin -
mBlockReflowState.mPrevNegBottomMargin;
mY += bottomMargin;
mBlockReflowState.mY += bottomMargin;
// XXX tell block what bottomMargin ended up being so that it can
// undo it if it ends up pushing the line.
mMarginApplied = PR_TRUE;
mBlockReflowState.mPrevPosBottomMargin = 0;
mBlockReflowState.mPrevNegBottomMargin = 0;
}
kidRect.x = dx;
kidRect.y = mY;
kidRect.width = kidSize.width;

View File

@@ -39,7 +39,6 @@ struct nsLineData {
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
void UnlinkLine();
PRIntn GetLineNumber() const;
void MoveLineBy(nscoord dx, nscoord dy);
nsLineData* mNextLine;
nsLineData* mPrevLine;
@@ -75,29 +74,6 @@ struct nsLineLayout {
void SetReflowSpace(nsRect& aAvailableSpaceRect);
/**
* <h2>Rules of order</h2>
*
* Lines are disassociated from the block frame's state
* (mLastContentIsComplete, mLastContentOffset, mChildCount). Upon
* completion of this routine the block frame is responsible for
* updating it's own state.<p>
*
* ReflowLine can return the following status:
*
* <dl>
* <dt>NS_LINE_LAYOUT_BREAK_BEFORE</dt>
*
* <dd>mKidFrame and mKidIndex indicate the child to break
* before. Note that we will always have a child frame created which
* means we must not lose it!</dd>
*
* <dt>NS_LINE_LAYOUT_OK</dt>
*
* <dd>This means that the line should be flushed out as is</dd>
*
* </dl>
*/
nsresult ReflowLine();
nsresult IncrementalReflowFromChild(nsReflowCommand& aReflowCommand,
@@ -109,6 +85,7 @@ struct nsLineLayout {
// The block behind the line
nsBlockFrame* mBlock;
nsBlockReflowState& mBlockReflowState;
nsISpaceManager* mSpaceManager;
nsIContent* mBlockContent;
PRInt32 mKidIndex;
@@ -130,6 +107,7 @@ struct nsLineLayout {
PRPackedBool mUnconstrainedWidth;
PRPackedBool mUnconstrainedHeight;
PRPackedBool mMarginApplied;
nscoord mY;
nscoord mLineHeight;
nscoord mMaxWidth;