From da886dbfef80acbe40812ae69cc76d859b4161cf Mon Sep 17 00:00:00 2001 From: "karnaze%netscape.com" Date: Wed, 8 Aug 2001 01:13:35 +0000 Subject: [PATCH] bug 85738 - added 3rd pass reflow for tables in pagination mode which specified heights. sr=attinasi, r=savulov git-svn-id: svn://10.0.0.236/trunk@100549 18797224-902f-48f8-a5cc-f745e15eee43 --- .../html/table/src/nsTableCellFrame.cpp | 7 + .../layout/html/table/src/nsTableFrame.cpp | 185 +++++++++++------- mozilla/layout/html/table/src/nsTableFrame.h | 28 ++- .../html/table/src/nsTableRowGroupFrame.cpp | 1 + mozilla/layout/tables/nsTableCellFrame.cpp | 7 + mozilla/layout/tables/nsTableFrame.cpp | 185 +++++++++++------- mozilla/layout/tables/nsTableFrame.h | 28 ++- .../layout/tables/nsTableRowGroupFrame.cpp | 1 + 8 files changed, 294 insertions(+), 148 deletions(-) diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp index 5123c43c4ab..8204ae1f149 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp @@ -838,11 +838,18 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, // first, compute the height which can be set w/o being restricted by aMaxSize.height nscoord cellHeight = kidSize.height; + if (NS_UNCONSTRAINEDSIZE != cellHeight) { cellHeight += topInset + bottomInset; } cellHeight = nsTableFrame::RoundToPixel(cellHeight, p2t); // work around block rounding errors + // if the table allocated extra vertical space to row groups, rows, cells in pagination mode + // then use that height as the desired height unless the cell needs to split. + nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow(); + if ((NS_FRAME_COMPLETE == aStatus) && tableFrameFirstInFlow->IsThirdPassReflow()) { + cellHeight = PR_MAX(cellHeight, mRect.height); + } // next determine the cell's width nscoord cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index c031ba1b5a4..fd72b32113b 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -1828,7 +1828,8 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, nsReflowReason nextReason = aReflowState.reason; - // The 1st reflow processes the needs of the reflow command + // Processes an initial (except when there is mPrevInFlow), incremental, or style + // change reflow 1st. resize reflows are processed in the next phase. switch (aReflowState.reason) { case eReflowReason_Initial: case eReflowReason_StyleChange: { @@ -1882,54 +1883,39 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, } if (NS_FAILED(rv)) return rv; + + PRBool needPass3Reflow = PR_FALSE; PRBool balanced = PR_FALSE; - // The 2nd reflow is necessary during a constrained initial reflow and other reflows - // which require either a strategy init or balance. This isn't done during an - // unconstrained reflow because it is useless, and we will be reflowed again later. + // Reflow the entire table. This phase is necessary during a constrained initial reflow + // and other reflows which require either a strategy init or balance. This isn't done + // during an unconstrained reflow because another reflow will be processed later. if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) { - PRBool haveReflowedColGroups = PR_TRUE; - if (!mPrevInFlow) { - if (NeedStrategyInit()) { - mTableLayoutStrategy->Initialize(aPresContext, aReflowState); - BalanceColumnWidths(aPresContext, aReflowState); - balanced = PR_TRUE; + // see if an extra (3rd) reflow will be necessary in pagination mode when there is a specified table height + if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) { + nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); + if ((tableSpecifiedHeight > 0) && + (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) { + needPass3Reflow = PR_TRUE; } - if (NeedStrategyBalance()) { - BalanceColumnWidths(aPresContext, aReflowState); - balanced = PR_TRUE; - } - haveReflowedColGroups = HaveReflowedColGroups(); } - // Constrain our reflow width to the computed table width (of the 1st in flow). - // and our reflow height to our avail height minus border, padding, cellspacing - aDesiredSize.width = GetDesiredWidth(); - nsTableReflowState reflowState(aReflowState, *this, nextReason, - aDesiredSize.width, aReflowState.availableHeight); - ReflowChildren(aPresContext, reflowState, haveReflowedColGroups, PR_FALSE, aStatus); + // if we need to reflow the table an extra time, then don't constrain the height of the previous reflow + nscoord availHeight = (needPass3Reflow) ? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight; - // If we're here that means we had to reflow all the rows, e.g., the column widths - // changed. We need to make sure that any damaged areas are repainted - Invalidate(aPresContext, mRect); - if (IsRowInserted()) { - ProcessRowInserted(aPresContext, *this, PR_FALSE, 0); - } + ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason, doCollapse, balanced, aStatus); - if (eReflowReason_Resize == aReflowState.reason) { - if (isPaginated && (NS_FRAME_COMPLETE == aStatus) && (reflowState.availSize.height > 0)) { - // Try and pull-up some children from a next-in-flow - rv = PullUpChildren(aPresContext, aDesiredSize, reflowState, aStatus); - } - if (!DidResizeReflow()) { - // XXX we need to do this in other cases as well, but it needs to be made more incremental - doCollapse = PR_TRUE; - SetResizeReflow(PR_TRUE); - } + if (needPass3Reflow) { + aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); // distributes extra vertical space to rows + SetThirdPassReflow(PR_TRUE); // set it and leave it set for frames that may split + ReflowTable(aPresContext, aDesiredSize, aReflowState, aReflowState.availableHeight, + nextReason, doCollapse, balanced, aStatus); } } aDesiredSize.width = GetDesiredWidth(); - aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); + if (!needPass3Reflow) { + aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); + } if (IsRowInserted()) { ProcessRowInserted(aPresContext, *this, PR_TRUE, aDesiredSize.height); @@ -1986,7 +1972,61 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, return rv; } - +nsresult +nsTableFrame::ReflowTable(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aAvailHeight, + nsReflowReason aReason, + PRBool& aDoCollapse, + PRBool& aDidBalance, + nsReflowStatus& aStatus) +{ + nsresult rv = NS_OK; + aDoCollapse = PR_FALSE; + aDidBalance = PR_FALSE; + + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + + PRBool haveReflowedColGroups = PR_TRUE; + if (!mPrevInFlow) { + if (NeedStrategyInit()) { + mTableLayoutStrategy->Initialize(aPresContext, aReflowState); + BalanceColumnWidths(aPresContext, aReflowState); + aDidBalance = PR_TRUE; + } + if (NeedStrategyBalance()) { + BalanceColumnWidths(aPresContext, aReflowState); + aDidBalance = PR_TRUE; + } + haveReflowedColGroups = HaveReflowedColGroups(); + } + // Constrain our reflow width to the computed table width (of the 1st in flow). + // and our reflow height to our avail height minus border, padding, cellspacing + aDesiredSize.width = GetDesiredWidth(); + nsTableReflowState reflowState(aReflowState, *this, aReason, + aDesiredSize.width, aAvailHeight); + ReflowChildren(aPresContext, reflowState, haveReflowedColGroups, PR_FALSE, aStatus); + + // If we're here that means we had to reflow all the rows, e.g., the column widths + // changed. We need to make sure that any damaged areas are repainted + Invalidate(aPresContext, mRect); + + if (eReflowReason_Resize == aReflowState.reason) { + if (isPaginated && (NS_FRAME_COMPLETE == aStatus) && (reflowState.availSize.height > 0)) { + // Try and pull-up some children from a next-in-flow + rv = PullUpChildren(aPresContext, aDesiredSize, reflowState, aStatus); + } + if (!DidResizeReflow()) { + // XXX we need to do this in other cases as well, but it needs to be made more incremental + aDoCollapse = PR_TRUE; + SetResizeReflow(PR_TRUE); + } + } + return rv; +} + nsIFrame* nsTableFrame::GetFirstBodyRowGroupFrame() { @@ -3430,46 +3470,47 @@ nsTableFrame::CalcDesiredHeight(nsIPresContext* aPresContext, nscoord desiredHeight = naturalHeight; - // see if a specified table height requires diving additional space to rows - nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); - if ((tableSpecifiedHeight > 0) && - (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) && - (tableSpecifiedHeight > naturalHeight)) { - desiredHeight = tableSpecifiedHeight; + // see if a specified table height requires dividing additional space to rows + if (!mPrevInFlow) { + nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); + if ((tableSpecifiedHeight > 0) && + (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) && + (tableSpecifiedHeight > naturalHeight)) { + desiredHeight = tableSpecifiedHeight; - if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) { - // proportionately distribute the excess height to each row. Note that we - // don't need to do this if it's an unconstrained reflow - nscoord excess = tableSpecifiedHeight - naturalHeight; - nscoord sumOfRowHeights = 0; - nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY; + if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) { + // proportionately distribute the excess height to each row. Note that we + // don't need to do this if it's an unconstrained reflow + nscoord excess = tableSpecifiedHeight - naturalHeight; + nscoord sumOfRowHeights = 0; + nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY; - nsVoidArray rowGroups; - PRUint32 numRowGroups; - OrderRowGroups(rowGroups, numRowGroups, nsnull); + nsVoidArray rowGroups; + PRUint32 numRowGroups; + OrderRowGroups(rowGroups, numRowGroups, nsnull); - PRUint32 rgX; - for (rgX = 0; rgX < numRowGroups; rgX++) { - nsTableRowGroupFrame* rgFrame = - GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX)); - if (rgFrame) { - sumOfRowHeights += rgFrame->GetHeightOfRows(aPresContext); + PRUint32 rgX; + for (rgX = 0; rgX < numRowGroups; rgX++) { + nsTableRowGroupFrame* rgFrame = + GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX)); + if (rgFrame) { + sumOfRowHeights += rgFrame->GetHeightOfRows(aPresContext); + } } - } - - nscoord excessAllocated = 0; - for (rgX = 0; rgX < numRowGroups; rgX++) { - nsTableRowGroupFrame* rgFrame = + nscoord excessAllocated = 0; + for (rgX = 0; rgX < numRowGroups; rgX++) { + nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX)); - if (rgFrame) { - DistributeSpaceToRows(aPresContext, aReflowState, rgFrame, sumOfRowHeights, - excess, excessAllocated, rowGroupYPos); + if (rgFrame) { + DistributeSpaceToRows(aPresContext, aReflowState, rgFrame, sumOfRowHeights, + excess, excessAllocated, rowGroupYPos); - // Make sure child views are properly positioned - // XXX what happens if childFrame is a scroll frame and this gets skipped? - nsTableFrame::RePositionViews(aPresContext, rgFrame); + // Make sure child views are properly positioned + // XXX what happens if childFrame is a scroll frame and this gets skipped? + nsTableFrame::RePositionViews(aPresContext, rgFrame); + } + rowGroupYPos += cellSpacingY; } - rowGroupYPos += cellSpacingY; } } } diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index 8f07d2a4f29..9a96c40b8f2 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -305,6 +305,15 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + nsresult ReflowTable(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aAvailHeight, + nsReflowReason aReason, + PRBool& aDoCollapse, + PRBool& aDidBalance, + nsReflowStatus& aStatus); + NS_IMETHOD GetParentStyleContextProvider(nsIPresContext* aPresContext, nsIFrame** aProviderFrame, nsContextProviderRelationship& aRelationship); @@ -470,6 +479,8 @@ public: PRBool HasCellSpanningPctCol() const; void SetHasCellSpanningPctCol(PRBool aValue); + // is this the 3rd reflow due to a height on a table in pagination mode. + PRBool IsThirdPassReflow() const; protected: @@ -498,6 +509,8 @@ protected: void SetDescendantReflowedNotTimeout(PRBool aValue); PRBool RequestedTimeoutReflow() const; void SetRequestedTimeoutReflow(PRBool aValue); + void SetThirdPassReflow(PRBool aValue); + void InterruptNotification(nsIPresContext* aPresContext, PRBool aIsRequest); @@ -870,8 +883,9 @@ protected: // we know that a descendant will be getting a timeout reflow and we cancel the one // targeted at us, as an optimization. unsigned mRequestedTimeoutReflow:1; - unsigned mRowInserted; - int : 22; // unused + unsigned mRowInserted:1; + unsigned mThirdPassReflow:1; + int : 21; // unused } mBits; nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells @@ -980,6 +994,16 @@ inline void nsTableFrame::SetRequestedTimeoutReflow(PRBool aValue) mBits.mRequestedTimeoutReflow = (unsigned)aValue; } +inline PRBool nsTableFrame::IsThirdPassReflow() const +{ + return (PRBool)mBits.mThirdPassReflow; +} + +inline void nsTableFrame::SetThirdPassReflow(PRBool aValue) +{ + mBits.mThirdPassReflow = (unsigned)aValue; +} + inline PRBool nsTableFrame::IsRowInserted() const { return (PRBool)mBits.mRowInserted; diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp index c64bb3ee962..0b15877fd07 100644 --- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -543,6 +543,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext, } // get the height of the tallest cell in the row (excluding cells that span rows) rowHeights[rowIndex] = ((nsTableRowFrame*)rowFrame)->GetTallestCell(); + // See if a cell spans into the row. If so we'll have to do step 2 if (!hasRowSpanningCell) { if (tableFrame->RowIsSpannedInto(rowIndex + startRowIndex)) { diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index 5123c43c4ab..8204ae1f149 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -838,11 +838,18 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext, // first, compute the height which can be set w/o being restricted by aMaxSize.height nscoord cellHeight = kidSize.height; + if (NS_UNCONSTRAINEDSIZE != cellHeight) { cellHeight += topInset + bottomInset; } cellHeight = nsTableFrame::RoundToPixel(cellHeight, p2t); // work around block rounding errors + // if the table allocated extra vertical space to row groups, rows, cells in pagination mode + // then use that height as the desired height unless the cell needs to split. + nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow(); + if ((NS_FRAME_COMPLETE == aStatus) && tableFrameFirstInFlow->IsThirdPassReflow()) { + cellHeight = PR_MAX(cellHeight, mRect.height); + } // next determine the cell's width nscoord cellWidth = kidSize.width; // at this point, we've factored in the cell's style attributes diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index c031ba1b5a4..fd72b32113b 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -1828,7 +1828,8 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, nsReflowReason nextReason = aReflowState.reason; - // The 1st reflow processes the needs of the reflow command + // Processes an initial (except when there is mPrevInFlow), incremental, or style + // change reflow 1st. resize reflows are processed in the next phase. switch (aReflowState.reason) { case eReflowReason_Initial: case eReflowReason_StyleChange: { @@ -1882,54 +1883,39 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, } if (NS_FAILED(rv)) return rv; + + PRBool needPass3Reflow = PR_FALSE; PRBool balanced = PR_FALSE; - // The 2nd reflow is necessary during a constrained initial reflow and other reflows - // which require either a strategy init or balance. This isn't done during an - // unconstrained reflow because it is useless, and we will be reflowed again later. + // Reflow the entire table. This phase is necessary during a constrained initial reflow + // and other reflows which require either a strategy init or balance. This isn't done + // during an unconstrained reflow because another reflow will be processed later. if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) { - PRBool haveReflowedColGroups = PR_TRUE; - if (!mPrevInFlow) { - if (NeedStrategyInit()) { - mTableLayoutStrategy->Initialize(aPresContext, aReflowState); - BalanceColumnWidths(aPresContext, aReflowState); - balanced = PR_TRUE; + // see if an extra (3rd) reflow will be necessary in pagination mode when there is a specified table height + if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) { + nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); + if ((tableSpecifiedHeight > 0) && + (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) { + needPass3Reflow = PR_TRUE; } - if (NeedStrategyBalance()) { - BalanceColumnWidths(aPresContext, aReflowState); - balanced = PR_TRUE; - } - haveReflowedColGroups = HaveReflowedColGroups(); } - // Constrain our reflow width to the computed table width (of the 1st in flow). - // and our reflow height to our avail height minus border, padding, cellspacing - aDesiredSize.width = GetDesiredWidth(); - nsTableReflowState reflowState(aReflowState, *this, nextReason, - aDesiredSize.width, aReflowState.availableHeight); - ReflowChildren(aPresContext, reflowState, haveReflowedColGroups, PR_FALSE, aStatus); + // if we need to reflow the table an extra time, then don't constrain the height of the previous reflow + nscoord availHeight = (needPass3Reflow) ? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight; - // If we're here that means we had to reflow all the rows, e.g., the column widths - // changed. We need to make sure that any damaged areas are repainted - Invalidate(aPresContext, mRect); - if (IsRowInserted()) { - ProcessRowInserted(aPresContext, *this, PR_FALSE, 0); - } + ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason, doCollapse, balanced, aStatus); - if (eReflowReason_Resize == aReflowState.reason) { - if (isPaginated && (NS_FRAME_COMPLETE == aStatus) && (reflowState.availSize.height > 0)) { - // Try and pull-up some children from a next-in-flow - rv = PullUpChildren(aPresContext, aDesiredSize, reflowState, aStatus); - } - if (!DidResizeReflow()) { - // XXX we need to do this in other cases as well, but it needs to be made more incremental - doCollapse = PR_TRUE; - SetResizeReflow(PR_TRUE); - } + if (needPass3Reflow) { + aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); // distributes extra vertical space to rows + SetThirdPassReflow(PR_TRUE); // set it and leave it set for frames that may split + ReflowTable(aPresContext, aDesiredSize, aReflowState, aReflowState.availableHeight, + nextReason, doCollapse, balanced, aStatus); } } aDesiredSize.width = GetDesiredWidth(); - aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); + if (!needPass3Reflow) { + aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); + } if (IsRowInserted()) { ProcessRowInserted(aPresContext, *this, PR_TRUE, aDesiredSize.height); @@ -1986,7 +1972,61 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext, return rv; } - +nsresult +nsTableFrame::ReflowTable(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aAvailHeight, + nsReflowReason aReason, + PRBool& aDoCollapse, + PRBool& aDidBalance, + nsReflowStatus& aStatus) +{ + nsresult rv = NS_OK; + aDoCollapse = PR_FALSE; + aDidBalance = PR_FALSE; + + PRBool isPaginated; + aPresContext->IsPaginated(&isPaginated); + + PRBool haveReflowedColGroups = PR_TRUE; + if (!mPrevInFlow) { + if (NeedStrategyInit()) { + mTableLayoutStrategy->Initialize(aPresContext, aReflowState); + BalanceColumnWidths(aPresContext, aReflowState); + aDidBalance = PR_TRUE; + } + if (NeedStrategyBalance()) { + BalanceColumnWidths(aPresContext, aReflowState); + aDidBalance = PR_TRUE; + } + haveReflowedColGroups = HaveReflowedColGroups(); + } + // Constrain our reflow width to the computed table width (of the 1st in flow). + // and our reflow height to our avail height minus border, padding, cellspacing + aDesiredSize.width = GetDesiredWidth(); + nsTableReflowState reflowState(aReflowState, *this, aReason, + aDesiredSize.width, aAvailHeight); + ReflowChildren(aPresContext, reflowState, haveReflowedColGroups, PR_FALSE, aStatus); + + // If we're here that means we had to reflow all the rows, e.g., the column widths + // changed. We need to make sure that any damaged areas are repainted + Invalidate(aPresContext, mRect); + + if (eReflowReason_Resize == aReflowState.reason) { + if (isPaginated && (NS_FRAME_COMPLETE == aStatus) && (reflowState.availSize.height > 0)) { + // Try and pull-up some children from a next-in-flow + rv = PullUpChildren(aPresContext, aDesiredSize, reflowState, aStatus); + } + if (!DidResizeReflow()) { + // XXX we need to do this in other cases as well, but it needs to be made more incremental + aDoCollapse = PR_TRUE; + SetResizeReflow(PR_TRUE); + } + } + return rv; +} + nsIFrame* nsTableFrame::GetFirstBodyRowGroupFrame() { @@ -3430,46 +3470,47 @@ nsTableFrame::CalcDesiredHeight(nsIPresContext* aPresContext, nscoord desiredHeight = naturalHeight; - // see if a specified table height requires diving additional space to rows - nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); - if ((tableSpecifiedHeight > 0) && - (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) && - (tableSpecifiedHeight > naturalHeight)) { - desiredHeight = tableSpecifiedHeight; + // see if a specified table height requires dividing additional space to rows + if (!mPrevInFlow) { + nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState); + if ((tableSpecifiedHeight > 0) && + (tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) && + (tableSpecifiedHeight > naturalHeight)) { + desiredHeight = tableSpecifiedHeight; - if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) { - // proportionately distribute the excess height to each row. Note that we - // don't need to do this if it's an unconstrained reflow - nscoord excess = tableSpecifiedHeight - naturalHeight; - nscoord sumOfRowHeights = 0; - nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY; + if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) { + // proportionately distribute the excess height to each row. Note that we + // don't need to do this if it's an unconstrained reflow + nscoord excess = tableSpecifiedHeight - naturalHeight; + nscoord sumOfRowHeights = 0; + nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY; - nsVoidArray rowGroups; - PRUint32 numRowGroups; - OrderRowGroups(rowGroups, numRowGroups, nsnull); + nsVoidArray rowGroups; + PRUint32 numRowGroups; + OrderRowGroups(rowGroups, numRowGroups, nsnull); - PRUint32 rgX; - for (rgX = 0; rgX < numRowGroups; rgX++) { - nsTableRowGroupFrame* rgFrame = - GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX)); - if (rgFrame) { - sumOfRowHeights += rgFrame->GetHeightOfRows(aPresContext); + PRUint32 rgX; + for (rgX = 0; rgX < numRowGroups; rgX++) { + nsTableRowGroupFrame* rgFrame = + GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX)); + if (rgFrame) { + sumOfRowHeights += rgFrame->GetHeightOfRows(aPresContext); + } } - } - - nscoord excessAllocated = 0; - for (rgX = 0; rgX < numRowGroups; rgX++) { - nsTableRowGroupFrame* rgFrame = + nscoord excessAllocated = 0; + for (rgX = 0; rgX < numRowGroups; rgX++) { + nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX)); - if (rgFrame) { - DistributeSpaceToRows(aPresContext, aReflowState, rgFrame, sumOfRowHeights, - excess, excessAllocated, rowGroupYPos); + if (rgFrame) { + DistributeSpaceToRows(aPresContext, aReflowState, rgFrame, sumOfRowHeights, + excess, excessAllocated, rowGroupYPos); - // Make sure child views are properly positioned - // XXX what happens if childFrame is a scroll frame and this gets skipped? - nsTableFrame::RePositionViews(aPresContext, rgFrame); + // Make sure child views are properly positioned + // XXX what happens if childFrame is a scroll frame and this gets skipped? + nsTableFrame::RePositionViews(aPresContext, rgFrame); + } + rowGroupYPos += cellSpacingY; } - rowGroupYPos += cellSpacingY; } } } diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index 8f07d2a4f29..9a96c40b8f2 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -305,6 +305,15 @@ public: const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + nsresult ReflowTable(nsIPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aAvailHeight, + nsReflowReason aReason, + PRBool& aDoCollapse, + PRBool& aDidBalance, + nsReflowStatus& aStatus); + NS_IMETHOD GetParentStyleContextProvider(nsIPresContext* aPresContext, nsIFrame** aProviderFrame, nsContextProviderRelationship& aRelationship); @@ -470,6 +479,8 @@ public: PRBool HasCellSpanningPctCol() const; void SetHasCellSpanningPctCol(PRBool aValue); + // is this the 3rd reflow due to a height on a table in pagination mode. + PRBool IsThirdPassReflow() const; protected: @@ -498,6 +509,8 @@ protected: void SetDescendantReflowedNotTimeout(PRBool aValue); PRBool RequestedTimeoutReflow() const; void SetRequestedTimeoutReflow(PRBool aValue); + void SetThirdPassReflow(PRBool aValue); + void InterruptNotification(nsIPresContext* aPresContext, PRBool aIsRequest); @@ -870,8 +883,9 @@ protected: // we know that a descendant will be getting a timeout reflow and we cancel the one // targeted at us, as an optimization. unsigned mRequestedTimeoutReflow:1; - unsigned mRowInserted; - int : 22; // unused + unsigned mRowInserted:1; + unsigned mThirdPassReflow:1; + int : 21; // unused } mBits; nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells @@ -980,6 +994,16 @@ inline void nsTableFrame::SetRequestedTimeoutReflow(PRBool aValue) mBits.mRequestedTimeoutReflow = (unsigned)aValue; } +inline PRBool nsTableFrame::IsThirdPassReflow() const +{ + return (PRBool)mBits.mThirdPassReflow; +} + +inline void nsTableFrame::SetThirdPassReflow(PRBool aValue) +{ + mBits.mThirdPassReflow = (unsigned)aValue; +} + inline PRBool nsTableFrame::IsRowInserted() const { return (PRBool)mBits.mRowInserted; diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp index c64bb3ee962..0b15877fd07 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp @@ -543,6 +543,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext, } // get the height of the tallest cell in the row (excluding cells that span rows) rowHeights[rowIndex] = ((nsTableRowFrame*)rowFrame)->GetTallestCell(); + // See if a cell spans into the row. If so we'll have to do step 2 if (!hasRowSpanningCell) { if (tableFrame->RowIsSpannedInto(rowIndex + startRowIndex)) {