bug 109043 - made percent tables without a computed height initiate a special 3rd pass reflow only when a table related frame up the chain has a fixed or percent height. Made row groups not allocate additional vertical space to percent rows in excess of the table height. sr=attinasi,r=alexsavulov

This commit is contained in:
karnaze%netscape.com 2001-11-14 13:44:38 +00:00
parent 436e1ac49e
commit 5550862ce8
6 changed files with 108 additions and 46 deletions

View File

@ -984,6 +984,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
SetDesiredSize(aDesiredSize);
if (aReflowState.mFlags.mSpecialTableReflow) {
aDesiredSize.height = mRect.height;
SetNeedSpecialReflow(PR_FALSE);
}

View File

@ -1840,6 +1840,30 @@ nsTableFrame::NotifyAncestorsOfSpecialReflow(const nsHTMLReflowState& aReflowSta
}
}
static PRBool
IsSpecialNested(const nsHTMLReflowState& aReflowState)
{
// Walk up the reflow state tree until we find anything with a style height.
// stop when we reach a table
const nsHTMLReflowState* rs = aReflowState.parentReflowState;
while (rs && rs->frame) {
const nsStylePosition* position;
rs->frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)position);
if (eStyleUnit_Coord == position->mHeight.GetUnit()) {
nscoord coordValue = position->mHeight.GetCoordValue();
if (coordValue > 0) return PR_TRUE;
}
else if (eStyleUnit_Percent == position->mHeight.GetUnit()) {
float percent = position->mHeight.GetPercentValue();
if (percent > 0.0f) return PR_TRUE;
}
nsCOMPtr<nsIAtom> frameType;
rs->frame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableFrame == frameType.get()) break;
rs = rs->parentReflowState;
}
return PR_FALSE;
}
/* overview:
if mFirstPassValid is false, this is our first time through since content was last changed
do pass 1
@ -1943,9 +1967,11 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
// during an unconstrained reflow because another reflow will be processed later.
if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) {
if (!mPrevInFlow) {
// see if an extra reflow will be necessary when there is a pct height but no height on the parent
// see if an extra reflow will be necessary when the table is nested, there is a pct height,
// no computed height, but a height on the containing table
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
(0 == aReflowState.mComputedHeight)) && IsPctHeight(mStyleContext)) {
(0 == aReflowState.mComputedHeight)) &&
IsPctHeight(mStyleContext) && IsSpecialNested(aReflowState)) {
NotifyAncestorsOfSpecialReflow(aReflowState);
SetNeedSpecialReflow(PR_TRUE);
}
@ -1970,7 +1996,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialTableReflow = PR_TRUE;
ReflowTable(aPresContext, aDesiredSize, aReflowState, aReflowState.availableHeight,
nextReason, doCollapse, balanced, aStatus);
haveDesiredHeight = PR_TRUE;;
haveDesiredHeight = PR_TRUE;
}
}
else if (aReflowState.mFlags.mSpecialTableReflow) {
@ -1988,7 +2014,6 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
if (!haveDesiredHeight) {
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState);
}
if (IsRowInserted()) {
ProcessRowInserted(aPresContext, *this, PR_TRUE, aDesiredSize.height);
}

View File

@ -503,8 +503,11 @@ nsTableRowGroupFrame::GetFirstRow()
struct RowInfo {
unsigned height:30;
RowInfo() { height = pctHeight = hasStyleHeight = hasPctHeight = isSpecial = 0; }
unsigned height; // content height or fixed height, excluding pct height
unsigned pctHeight:29; // pct height
unsigned hasStyleHeight:1;
unsigned hasPctHeight:1;
unsigned isSpecial:1; // there is no cell originating in the row with rowspan=1 and there are at
// least 2 cells spanning the row and there is no style height on the row
};
@ -577,20 +580,6 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
float p2t;
aPresContext->GetPixelsToTwips(&p2t);
// make sure that pct height rows do not exceed 100%
nscoord pctTotal = 0;
nsTableRowFrame* rowFrame;
for (rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
if (rowFrame->HasPctHeight()) {
nscoord pctHeight = NSToCoordRound(rowFrame->GetPctHeight() * 100.0f);
if ((pctHeight + pctTotal) > 100) {
pctHeight = PR_MAX(0, NSToCoordRound(100.0f - (float)pctTotal));
rowFrame->SetPctHeight((float)pctHeight / 100.0f, PR_TRUE);
}
pctTotal += pctHeight;
}
}
// find the nearest row at or before aStartRowFrameIn that isn't spanned into.
// If we have a computed height, then we can't compute the heights
// incrementally from aStartRowFrameIn, and we must start at the first row.
@ -637,9 +626,14 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// the style height of the row.
nscoord pctHeightBasis = GetHeightBasis(aReflowState);
PRInt32 rowIndex; // the index in rowInfo, not among the rows in the row group
nsTableRowFrame* rowFrame;
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
UpdateHeights(rowInfo[rowIndex], nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t),
heightOfRows, heightOfUnStyledRows);
if (rowFrame->HasPctHeight()) {
rowInfo[rowIndex].hasPctHeight = PR_TRUE;
rowInfo[rowIndex].pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t);
}
nscoord nonPctHeight = PR_MAX(rowFrame->GetContentHeight(), rowFrame->GetFixedHeight());
UpdateHeights(rowInfo[rowIndex], nonPctHeight, heightOfRows, heightOfUnStyledRows);
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
if (!rowInfo[rowIndex].hasStyleHeight) {
@ -773,12 +767,23 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
} // while (rowFrame)
}
// pct height rows have already got their content heights. Give them their pct heights up to pctHeightBasis
nscoord extra = pctHeightBasis - heightOfRows;
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame && (extra > 0); rowFrame = rowFrame->GetNextRow(), rowIndex++) {
RowInfo& rInfo = rowInfo[rowIndex];
if (rInfo.hasPctHeight) {
nscoord rowExtra = PR_MAX(0, rInfo.pctHeight - rInfo.height);
rowExtra = PR_MIN(rowExtra, extra);
UpdateHeights(rInfo, rowExtra, heightOfRows, heightOfUnStyledRows);
extra -= rowExtra;
}
}
nscoord rowGroupHeight = startRowGroupHeight + heightOfRows + ((numRows - 1) * cellSpacingY);
nscoord extraComputedHeight = 0;
// if we have a style height, allocate the extra height to unconstrained rows
if ((aReflowState.mComputedHeight > rowGroupHeight) &&
(NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight)) {
extraComputedHeight = aReflowState.mComputedHeight - rowGroupHeight;
nscoord extraComputedHeight = aReflowState.mComputedHeight - rowGroupHeight;
nscoord extraUsed = 0;
PRBool haveUnStyledRows = (heightOfUnStyledRows > 0);
nscoord divisor = (haveUnStyledRows)

View File

@ -984,6 +984,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
SetDesiredSize(aDesiredSize);
if (aReflowState.mFlags.mSpecialTableReflow) {
aDesiredSize.height = mRect.height;
SetNeedSpecialReflow(PR_FALSE);
}

View File

@ -1840,6 +1840,30 @@ nsTableFrame::NotifyAncestorsOfSpecialReflow(const nsHTMLReflowState& aReflowSta
}
}
static PRBool
IsSpecialNested(const nsHTMLReflowState& aReflowState)
{
// Walk up the reflow state tree until we find anything with a style height.
// stop when we reach a table
const nsHTMLReflowState* rs = aReflowState.parentReflowState;
while (rs && rs->frame) {
const nsStylePosition* position;
rs->frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)position);
if (eStyleUnit_Coord == position->mHeight.GetUnit()) {
nscoord coordValue = position->mHeight.GetCoordValue();
if (coordValue > 0) return PR_TRUE;
}
else if (eStyleUnit_Percent == position->mHeight.GetUnit()) {
float percent = position->mHeight.GetPercentValue();
if (percent > 0.0f) return PR_TRUE;
}
nsCOMPtr<nsIAtom> frameType;
rs->frame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableFrame == frameType.get()) break;
rs = rs->parentReflowState;
}
return PR_FALSE;
}
/* overview:
if mFirstPassValid is false, this is our first time through since content was last changed
do pass 1
@ -1943,9 +1967,11 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
// during an unconstrained reflow because another reflow will be processed later.
if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) {
if (!mPrevInFlow) {
// see if an extra reflow will be necessary when there is a pct height but no height on the parent
// see if an extra reflow will be necessary when the table is nested, there is a pct height,
// no computed height, but a height on the containing table
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
(0 == aReflowState.mComputedHeight)) && IsPctHeight(mStyleContext)) {
(0 == aReflowState.mComputedHeight)) &&
IsPctHeight(mStyleContext) && IsSpecialNested(aReflowState)) {
NotifyAncestorsOfSpecialReflow(aReflowState);
SetNeedSpecialReflow(PR_TRUE);
}
@ -1970,7 +1996,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialTableReflow = PR_TRUE;
ReflowTable(aPresContext, aDesiredSize, aReflowState, aReflowState.availableHeight,
nextReason, doCollapse, balanced, aStatus);
haveDesiredHeight = PR_TRUE;;
haveDesiredHeight = PR_TRUE;
}
}
else if (aReflowState.mFlags.mSpecialTableReflow) {
@ -1988,7 +2014,6 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
if (!haveDesiredHeight) {
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState);
}
if (IsRowInserted()) {
ProcessRowInserted(aPresContext, *this, PR_TRUE, aDesiredSize.height);
}

View File

@ -503,8 +503,11 @@ nsTableRowGroupFrame::GetFirstRow()
struct RowInfo {
unsigned height:30;
RowInfo() { height = pctHeight = hasStyleHeight = hasPctHeight = isSpecial = 0; }
unsigned height; // content height or fixed height, excluding pct height
unsigned pctHeight:29; // pct height
unsigned hasStyleHeight:1;
unsigned hasPctHeight:1;
unsigned isSpecial:1; // there is no cell originating in the row with rowspan=1 and there are at
// least 2 cells spanning the row and there is no style height on the row
};
@ -577,20 +580,6 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
float p2t;
aPresContext->GetPixelsToTwips(&p2t);
// make sure that pct height rows do not exceed 100%
nscoord pctTotal = 0;
nsTableRowFrame* rowFrame;
for (rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
if (rowFrame->HasPctHeight()) {
nscoord pctHeight = NSToCoordRound(rowFrame->GetPctHeight() * 100.0f);
if ((pctHeight + pctTotal) > 100) {
pctHeight = PR_MAX(0, NSToCoordRound(100.0f - (float)pctTotal));
rowFrame->SetPctHeight((float)pctHeight / 100.0f, PR_TRUE);
}
pctTotal += pctHeight;
}
}
// find the nearest row at or before aStartRowFrameIn that isn't spanned into.
// If we have a computed height, then we can't compute the heights
// incrementally from aStartRowFrameIn, and we must start at the first row.
@ -637,9 +626,14 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// the style height of the row.
nscoord pctHeightBasis = GetHeightBasis(aReflowState);
PRInt32 rowIndex; // the index in rowInfo, not among the rows in the row group
nsTableRowFrame* rowFrame;
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
UpdateHeights(rowInfo[rowIndex], nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t),
heightOfRows, heightOfUnStyledRows);
if (rowFrame->HasPctHeight()) {
rowInfo[rowIndex].hasPctHeight = PR_TRUE;
rowInfo[rowIndex].pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t);
}
nscoord nonPctHeight = PR_MAX(rowFrame->GetContentHeight(), rowFrame->GetFixedHeight());
UpdateHeights(rowInfo[rowIndex], nonPctHeight, heightOfRows, heightOfUnStyledRows);
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
if (!rowInfo[rowIndex].hasStyleHeight) {
@ -773,12 +767,23 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
} // while (rowFrame)
}
// pct height rows have already got their content heights. Give them their pct heights up to pctHeightBasis
nscoord extra = pctHeightBasis - heightOfRows;
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame && (extra > 0); rowFrame = rowFrame->GetNextRow(), rowIndex++) {
RowInfo& rInfo = rowInfo[rowIndex];
if (rInfo.hasPctHeight) {
nscoord rowExtra = PR_MAX(0, rInfo.pctHeight - rInfo.height);
rowExtra = PR_MIN(rowExtra, extra);
UpdateHeights(rInfo, rowExtra, heightOfRows, heightOfUnStyledRows);
extra -= rowExtra;
}
}
nscoord rowGroupHeight = startRowGroupHeight + heightOfRows + ((numRows - 1) * cellSpacingY);
nscoord extraComputedHeight = 0;
// if we have a style height, allocate the extra height to unconstrained rows
if ((aReflowState.mComputedHeight > rowGroupHeight) &&
(NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight)) {
extraComputedHeight = aReflowState.mComputedHeight - rowGroupHeight;
nscoord extraComputedHeight = aReflowState.mComputedHeight - rowGroupHeight;
nscoord extraUsed = 0;
PRBool haveUnStyledRows = (heightOfUnStyledRows > 0);
nscoord divisor = (haveUnStyledRows)