Moved margin code into line layout
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user