bug 123983 - set mIsTopOfPage in the reflow state, fix desired height in rows and row groups, clean up nsTableRowGroupFrame::SplitRowGroups and handle more cases of splitting/moving rows. a=roc+moz, sr=attinasi, r=alexsavulov

git-svn-id: svn://10.0.0.236/trunk@117609 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
karnaze%netscape.com 2002-03-27 05:50:24 +00:00
parent 31ee5d4e7d
commit 3cc1086578
12 changed files with 396 additions and 198 deletions

View File

@ -1098,8 +1098,10 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
}
else if (HadSpecialReflow() && ((eReflowReason_Incremental == aReflowState.reason) ||
(eReflowReason_Resize == aReflowState.reason))) {
// if the block height value hasn't changed, use the last height of the cell, otherwise ignore it
if (GetLastBlockHeight() == priorBlockHeight) {
// with an unconstrained height, if the block height value hasn't changed,
// use the last height of the cell.
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) &&
(GetLastBlockHeight() == priorBlockHeight)) {
aDesiredSize.height = mRect.height;
}
else {

View File

@ -2112,6 +2112,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
#if defined DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
#endif
return rv;
}
@ -3297,6 +3298,10 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
// XXX fix up bad mComputedWidth for scroll frame
kidReflowState.mComputedWidth = PR_MAX(kidReflowState.mComputedWidth, 0);
// If this isn't the first row group, then we can't be at the top of the page
if (childX > 0) {
kidReflowState.mFlags.mIsTopOfPage = PR_FALSE;
}
aReflowState.y += cellSpacingY;
// record the next in flow in case it gets destroyed and the row group array

View File

@ -1011,6 +1011,15 @@ nsTableOuterFrame::OuterReflowChild(nsIPresContext* aPresContext,
}
}
// see if we need to reset top of page due to a caption
if (mCaptionFrame) {
PRUint8 captionSide = GetCaptionSide();
if (((NS_SIDE_BOTTOM == captionSide) && (mCaptionFrame == aChildFrame)) ||
((NS_SIDE_TOP == captionSide) && (mInnerTableFrame == aChildFrame))) {
childRS.mFlags.mIsTopOfPage = PR_FALSE;
}
}
// use the current position as a best guess for placement
nsRect childRect;
aChildFrame->GetRect(childRect);

View File

@ -863,6 +863,24 @@ GetComputedWidth(const nsHTMLReflowState& aReflowState,
return computedWidth;
}
// subtract the heights of aRow's prev in flows from the unpaginated height
static
nscoord CalcHeightFromUnpaginatedHeight(nsIPresContext* aPresContext,
nsTableRowFrame& aRow)
{
nscoord height = 0;
nsTableRowFrame* firstInFlow = (nsTableRowFrame*)aRow.GetFirstInFlow(); if (!firstInFlow) ABORT1(0);
if (firstInFlow->HasUnpaginatedHeight()) {
height = firstInFlow->GetUnpaginatedHeight(aPresContext);
for (nsIFrame* prevInFlow = aRow.GetPrevInFlow(); prevInFlow; prevInFlow->GetPrevInFlow(&prevInFlow)) {
nsRect rect;
prevInFlow->GetRect(rect);
height -= rect.height;
}
}
return PR_MAX(height, 0);
}
// Called for a dirty or resize reflow. Reflows all the existing table cell
// frames unless aDirtyOnly is PR_TRUE in which case only reflow the dirty frames
@ -1063,22 +1081,23 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
nsTableFrame::RePositionViews(aPresContext, kidFrame);
}
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !mPrevInFlow) {
// Calculate the cell's actual size given its pass2 size. This function
// takes into account the specified height (in the style), and any special
// logic needed for backwards compatibility
CalculateCellActualSize(kidFrame, desiredSize.width,
desiredSize.height, availCellWidth);
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) {
if (!mPrevInFlow) {
// Calculate the cell's actual size given its pass2 size. This function
// takes into account the specified height (in the style), and any special
// logic needed for backwards compatibility
CalculateCellActualSize(kidFrame, desiredSize.width,
desiredSize.height, availCellWidth);
}
// height may have changed, adjust descent to absorb any excess difference
nscoord ascent = cellFrame->GetDesiredAscent();
nscoord descent = desiredSize.height - ascent;
UpdateHeight(desiredSize.height, ascent, descent, &aTableFrame, cellFrame);
}
else {
paginatedHeight = PR_MAX(paginatedHeight, desiredSize.height);
PRInt32 rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
if ((1 == rowSpan) && (desiredSize.height > paginatedHeight)) {
paginatedHeight = desiredSize.height;
if (1 == rowSpan) {
SetContentHeight(paginatedHeight);
}
}
@ -1117,8 +1136,32 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// just set our width to what was available. The table will calculate the width and not use our value.
aDesiredSize.width = aReflowState.availableWidth;
aDesiredSize.height = (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight)
? CalcHeight(aReflowState) : paginatedHeight;
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) {
aDesiredSize.height = CalcHeight(aReflowState);
if (mPrevInFlow) {
nscoord height = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
aDesiredSize.height = PR_MAX(aDesiredSize.height, height);
}
else {
if (isPaginated && HasStyleHeight()) {
// set the unpaginated height so next in flows can try to honor it
SetHasUnpaginatedHeight(PR_TRUE);
SetUnpaginatedHeight(aPresContext, aDesiredSize.height);
}
if (isPaginated && HasUnpaginatedHeight()) {
aDesiredSize.height = PR_MAX(aDesiredSize.height, GetUnpaginatedHeight(aPresContext));
}
}
}
else { // constrained height, paginated
aDesiredSize.height = paginatedHeight;
if (aDesiredSize.height <= aReflowState.availableHeight) {
nscoord height = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
aDesiredSize.height = PR_MAX(aDesiredSize.height, height);
aDesiredSize.height = PR_MIN(aDesiredSize.height, aReflowState.availableHeight);
}
}
return rv;
}
@ -1585,6 +1628,7 @@ void
nsTableRowFrame::SetUnpaginatedHeight(nsIPresContext* aPresContext,
nscoord aValue)
{
NS_ASSERTION(!mPrevInFlow, "program error");
// Get the property
nscoord* value = (nscoord*)nsTableFrame::GetProperty(aPresContext, this, nsLayoutAtoms::rowUnpaginatedHeightProperty, PR_TRUE);
if (value) {
@ -1596,7 +1640,7 @@ nscoord
nsTableRowFrame::GetUnpaginatedHeight(nsIPresContext* aPresContext)
{
// See if the property is set
nscoord* value = (nscoord*)nsTableFrame::GetProperty(aPresContext, this, nsLayoutAtoms::rowUnpaginatedHeightProperty);
nscoord* value = (nscoord*)nsTableFrame::GetProperty(aPresContext, GetFirstInFlow(), nsLayoutAtoms::rowUnpaginatedHeightProperty);
if (value)
return *value;
else

View File

@ -437,8 +437,7 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
kidAvailSize, reason);
InitChildReflowState(*aPresContext, borderCollapse, p2t, kidReflowState);
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
// If this isn't the first row, then we can't be at the top of the page
if (kidFrame != GetFirstFrame()) {
kidReflowState.mFlags.mIsTopOfPage = PR_FALSE;
}
@ -571,6 +570,20 @@ HasMoreThanOneCell(nsTableCellMap* aCellMap,
return PR_FALSE;
}
static void
CacheRowHeightsForPrinting(nsIPresContext* aPresContext,
nsTableRowFrame* aFirstRow)
{
for (nsTableRowFrame* row = aFirstRow; row; row = row->GetNextRow()) {
if (!row->GetPrevInFlow()) {
nsRect rect;
row->GetRect(rect);
row->SetHasUnpaginatedHeight(PR_TRUE);
row->SetUnpaginatedHeight(aPresContext, rect.height);
}
}
}
// This calculates the height of rows starting at aStartRowFrameIn and takes into account
// style height on the row group, style heights on rows and cells, style heights on rowspans.
// Actual row heights will be adjusted later if the table has a style height.
@ -586,6 +599,9 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
nsTableFrame::GetTableFrame(this, tableFrame);
if (!aPresContext || !tableFrame) return;
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
// all table cells have the same top and bottom margins, namely cellSpacingY
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
float p2t;
@ -639,16 +655,24 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
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++) {
if (rowFrame->HasPctHeight()) {
rowInfo[rowIndex].hasPctHeight = PR_TRUE;
rowInfo[rowIndex].pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t);
nscoord nonPctHeight = rowFrame->GetContentHeight();
if (isPaginated) {
nsRect rowRect;
rowFrame->GetRect(rowRect);
nonPctHeight = PR_MAX(nonPctHeight, rowRect.height);
}
if (!rowFrame->GetPrevInFlow()) {
if (rowFrame->HasPctHeight()) {
rowInfo[rowIndex].hasPctHeight = PR_TRUE;
rowInfo[rowIndex].pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t);
}
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
nonPctHeight = PR_MAX(nonPctHeight, rowFrame->GetFixedHeight());
}
nscoord nonPctHeight = PR_MAX(rowFrame->GetContentHeight(), rowFrame->GetFixedHeight());
UpdateHeights(rowInfo[rowIndex], nonPctHeight, heightOfRows, heightOfUnStyledRows);
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
if (!rowInfo[rowIndex].hasStyleHeight) {
if (HasMoreThanOneCell(tableFrame->GetCellMap(), rowIndex)) {
if (isPaginated || HasMoreThanOneCell(tableFrame->GetCellMap(), rowIndex + startRowIndex)) {
rowInfo[rowIndex].isSpecial = PR_TRUE;
// iteratate the row's cell frames to see if any do not have rowspan > 1
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
@ -674,7 +698,10 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// Get the height of cells with rowspans and allocate any extra space to the rows they span
// iteratate the child frames and process the row frames among them
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
if (tableFrame->RowHasSpanningCells(startRowIndex + rowIndex)) {
// See if the row has an originating cell with rowspan > 1. We cannot determine this for a row in a
// continued row group by calling RowHasSpanningCells, because the row's fif may not have any originating
// cells yet the row may have a continued cell which originates in it.
if (mPrevInFlow || tableFrame->RowHasSpanningCells(startRowIndex + rowIndex)) {
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
// iteratate the row's cell frames
while (cellFrame) {
@ -790,6 +817,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
}
}
PRBool styleHeightAllocation = PR_FALSE;
nscoord rowGroupHeight = startRowGroupHeight + heightOfRows + ((numRows - 1) * cellSpacingY);
// if we have a style height, allocate the extra height to unconstrained rows
if ((aReflowState.mComputedHeight > rowGroupHeight) &&
@ -800,6 +828,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
nscoord divisor = (haveUnStyledRows)
? heightOfUnStyledRows : heightOfRows;
if (divisor > 0) {
styleHeightAllocation = PR_TRUE;
for (rowIndex = 0; rowIndex < numRows; rowIndex++) {
if (!haveUnStyledRows || !rowInfo[rowIndex].hasStyleHeight) {
// The amount of additional space each row gets is based on the
@ -844,6 +873,11 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
yOrigin += rowHeight + cellSpacingY;
}
if (isPaginated && styleHeightAllocation) {
// since the row group has a style height, cache the row heights, so next in flows can honor them
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
DidResizeRows(*aPresContext, aReflowState, startRowFrame);
aDesiredSize.height = rowGroupHeight; // Adjust our desired size
@ -902,6 +936,7 @@ nsTableRowGroupFrame::CreateContinuingRowFrame(nsIPresContext& aPresContext,
nsIFrame& aRowFrame,
nsIFrame** aContRowFrame)
{
// XXX what is the row index?
if (!aContRowFrame) {NS_ASSERTION(PR_FALSE, "bad call"); return;}
// create the continuing frame which will create continuing cell frames
aStyleSet.CreateContinuingFrame(&aPresContext, &aRowFrame, this, aContRowFrame);
@ -917,7 +952,7 @@ nsTableRowGroupFrame::CreateContinuingRowFrame(nsIPresContext& aPresContext,
PushChildren(&aPresContext, *aContRowFrame, &aRowFrame);
}
nscoord
void
nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsIStyleSet& aStyleSet,
@ -929,9 +964,8 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
PRInt32 rowIndex = aRowFrame.GetRowIndex();
PRInt32 colCount = aTableFrame.GetColCount();
nsTableCellFrame* prevCellFrame = nsnull;
nsTableRowFrame* rowToMoveToNextPage = nsnull;
nscoord tallestCell = 0;
for (PRInt32 colX = 0; colX < colCount; colX++) {
nsTableCellFrame* cellFrame = aTableFrame.GetCellInfoAt(rowIndex, colX);
if (!cellFrame) continue;
@ -939,20 +973,19 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
cellFrame = (nsTableCellFrame*)cellFrame->GetLastInFlow();
// See if the cell frame is really in this row, or whether it's a cell spanning from a previous row
PRInt32 realRowIndex;
cellFrame->GetRowIndex(realRowIndex);
if (realRowIndex == rowIndex) {
PRInt32 cellRowIndex;
cellFrame->GetRowIndex(cellRowIndex);
if (cellRowIndex == rowIndex) { // cell originates in this row
prevCellFrame = cellFrame;
}
else {
else { // cell originates in a prior row
nsTableRowFrame* parentFrame;
nsPoint cellOrigin;
nsReflowStatus status;
// Ask the cell frame's parent to reflow it to the height of all the
// rows it spans between its origin and aRowEndY
cellFrame->GetParent((nsIFrame**)&parentFrame);
if (!parentFrame) {NS_ASSERTION(PR_FALSE, "bad parent"); return 0;}
cellFrame->GetParent((nsIFrame**)&parentFrame); if (!parentFrame) ABORT0();
parentFrame->GetOrigin(cellOrigin);
nscoord cellAvailHeight = aRowEndY - cellOrigin.y;
nscoord cellHeight = parentFrame->ReflowCellFrame(&aPresContext, aReflowState, cellFrame,
@ -965,7 +998,7 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
if (contCellFrame) {
if (aContRowFrame) {
aContRowFrame->InsertCellFrame(contCellFrame, colX);
}
}
else {
aRowFrame.InsertCellFrame(contCellFrame, prevCellFrame);
}
@ -978,10 +1011,8 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
aContRowFrame->InsertCellFrame(cellFrame, colX);
prevCellFrame = cellFrame;
}
tallestCell = PR_MAX(tallestCell, cellHeight);
}
}
return tallestCell;
}
nsresult
@ -1008,32 +1039,40 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
nscoord availWidth = nsTableFrame::RoundToPixel(aReflowState.availableWidth, p2t);
nscoord availHeight = nsTableFrame::RoundToPixel(aReflowState.availableHeight, p2t);
nscoord lastDesiredHeight = 0;
// get the page height
nsRect actualRect;
nsRect adjRect;
aPresContext->GetPageDim(&actualRect, &adjRect);
nscoord pageHeight = actualRect.height;
PRBool isTopOfPage = aReflowState.mFlags.mIsTopOfPage;
nscoord cellSpacingY = aTableFrame->GetCellSpacingY();
// Walk each of the row frames looking for the first row frame that
// doesn't fit in the available space
for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
PRBool rowIsOnCurrentPage = PR_TRUE;
PRBool degenerateRow = PR_FALSE;
nsRect bounds;
rowFrame->GetRect(bounds);
if (bounds.YMost() > availHeight) {
nsRect actualRect;
nsRect adjRect;
aPresContext->GetPageDim(&actualRect, &adjRect);
nsIFrame* contRowFrame = nsnull;
nscoord pageHeight = actualRect.height;
// reflow the row in the availabe space and have it split if it is the 1st
// row or there is at least 5% of the current page available
if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) {
// Reflow the row in the available space and have it split
nsSize availSize(availWidth, PR_MAX(availHeight - bounds.y, 0));
// don't let the available height exceed what CalculateRowHeights set for it
availSize.height = PR_MIN(availSize.height, bounds.height);
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, borderCollapse, p2t, rowReflowState);
rowReflowState.mFlags.mIsTopOfPage = isTopOfPage; // set top of page
nsHTMLReflowMetrics desiredSize(nsnull);
// A row that has all originating cells with rowspan>1 will return a desired height
// of the largest cell (in contrast to an unconstrained height reflow which returns 0).
rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
rowFrame->SizeTo(aPresContext, desiredSize.width, desiredSize.height);
@ -1042,27 +1081,26 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// the row frame is incomplete and all of the cells' block frames have split
CreateContinuingRowFrame(*aPresContext, *styleSet.get(), *rowFrame, &contRowFrame);
aDesiredSize.height += desiredSize.height;
if (prevRowFrame) {
aDesiredSize.height += aTableFrame->GetCellSpacingY();
}
}
else if (0 == desiredSize.height) {
// the row frame is complete because it had no cells originating in it.
CreateContinuingRowFrame(*aPresContext, *styleSet.get(), *rowFrame, &contRowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
aDesiredSize.height = availHeight;
degenerateRow = PR_TRUE;
}
else {
// the row frame is complete because it's minimum height was greater than the
// the available height we gave it
if (aDesiredSize.height > 0) {
// put the row on the next page since it needs more height than it was given
rowIsOnCurrentPage = PR_FALSE;
if ((desiredSize.height <= rowReflowState.availableHeight) || isTopOfPage) {
// the row stays on this page because either it split ok or we're on the top of page
// if top of page and the height exceeded the avail height,then there will be data loss
NS_WARN_IF_FALSE(desiredSize.height <= rowReflowState.availableHeight,
"data loss - incomplete row needed more height than available, on top of page");
CreateContinuingRowFrame(*aPresContext, *styleSet.get(), *rowFrame, &contRowFrame);
aDesiredSize.height += desiredSize.height;
if (prevRowFrame)
aDesiredSize.height += cellSpacingY;
}
else {
// put the row on the next page to give it more height
rowIsOnCurrentPage = PR_FALSE;
}
}
else {
// The row frame is complete because it's minimum height was greater than the
// the available height we gave it.
if (isTopOfPage) {
// We're on top of the page, so keep the row on this page. There will be data loss.
nsIFrame* nextRowFrame;
// Push the row frame that follows
@ -1070,32 +1108,45 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
if (nextRowFrame) {
PushChildren(aPresContext, nextRowFrame, rowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
}
aStatus = nextRowFrame ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
aDesiredSize.height = bounds.YMost();
aDesiredSize.height += desiredSize.height;
if (prevRowFrame)
aDesiredSize.height += cellSpacingY;
NS_WARN_IF_FALSE(PR_FALSE, "data loss - complete row needed more height than available, on top of page");
}
else {
// We're not on top of the page, so put the row on the next page to give it more height
rowIsOnCurrentPage = PR_FALSE;
}
}
}
else rowIsOnCurrentPage = PR_FALSE;
if (!rowIsOnCurrentPage) {
// Push this row frame and those that follow to the next-in-flow
PushChildren(aPresContext, rowFrame, prevRowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
else {
// put the row on the next page to give it more height
rowIsOnCurrentPage = PR_FALSE;
}
if (prevRowFrame) {
nscoord tallestCell =
SplitSpanningCells(*aPresContext, aReflowState, *styleSet, *aTableFrame,
*rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
if (degenerateRow) {
aDesiredSize.height = lastDesiredHeight + aTableFrame->GetCellSpacingY() + tallestCell;
PRBool willGetAnotherReflow = PR_FALSE;
if (!rowIsOnCurrentPage) {
if (prevRowFrame) {
PushChildren(aPresContext, rowFrame, prevRowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
}
else {
// We can't push children, so let our parent reflow us again with more space
aDesiredSize.height = bounds.YMost();
willGetAnotherReflow = PR_TRUE;
}
}
if (prevRowFrame && !willGetAnotherReflow) {
SplitSpanningCells(*aPresContext, aReflowState, *styleSet, *aTableFrame,
*rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
}
break;
}
else {
aDesiredSize.height = bounds.YMost();
lastDesiredHeight = aDesiredSize.height;
prevRowFrame = rowFrame;
// see if there is a page break after the row
nsTableRowFrame* nextRow = rowFrame->GetNextRow();
@ -1105,22 +1156,11 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
break;
}
}
isTopOfPage = PR_FALSE; // after the 1st row, we can't be on top of the page any more.
}
return NS_OK;
}
static void
CacheRowHeightsForPrinting(nsIPresContext* aPresContext,
nsTableRowFrame* aFirstRow)
{
for (nsTableRowFrame* row = aFirstRow; row; row = row->GetNextRow()) {
nsRect rect;
row->GetRect(rect);
row->SetHasUnpaginatedHeight(PR_TRUE);
row->SetUnpaginatedHeight(aPresContext, rect.height);
}
}
/** Layout the entire row group.
* This method stacks rows vertically according to HTML 4.0 rules.
* Rows are responsible for layout of their children.
@ -1157,10 +1197,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
// Check for an overflow list
MoveOverflowToChildList(aPresContext);
if (isPaginated && aReflowState.mFlags.mSpecialHeightReflow) {
// cache row height info for printing, now that row heights are known.
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
// Reflow the existing frames.
PRBool splitDueToPageBreak = PR_FALSE;
rv = ReflowChildren(aPresContext, aDesiredSize, state, aStatus,
@ -1181,6 +1217,9 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
// are row spans unless we do this step
if (aReflowState.mFlags.mSpecialHeightReflow) {
DidResizeRows(*aPresContext, aReflowState);
if (isPaginated) {
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
}
else if ((eReflowReason_Initial != aReflowState.reason) ||
isTableUnconstrainedReflow ||

View File

@ -334,13 +334,13 @@ protected:
nsTableFrame* aTableFrame,
nsReflowStatus& aStatus);
nscoord SplitSpanningCells(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsIStyleSet& aStyleSet,
nsTableFrame& aTableFrame,
nsTableRowFrame& aRowFrame,
nscoord aRowEndY,
nsTableRowFrame* aContRowFrame);
void SplitSpanningCells(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsIStyleSet& aStyleSet,
nsTableFrame& aTableFrame,
nsTableRowFrame& aRowFrame,
nscoord aRowEndY,
nsTableRowFrame* aContRowFrame);
void CreateContinuingRowFrame(nsIPresContext& aPresContext,
nsIStyleSet& aStyleSet,

View File

@ -1098,8 +1098,10 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
}
else if (HadSpecialReflow() && ((eReflowReason_Incremental == aReflowState.reason) ||
(eReflowReason_Resize == aReflowState.reason))) {
// if the block height value hasn't changed, use the last height of the cell, otherwise ignore it
if (GetLastBlockHeight() == priorBlockHeight) {
// with an unconstrained height, if the block height value hasn't changed,
// use the last height of the cell.
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) &&
(GetLastBlockHeight() == priorBlockHeight)) {
aDesiredSize.height = mRect.height;
}
else {

View File

@ -2112,6 +2112,7 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
#if defined DEBUG_TABLE_REFLOW_TIMING
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
#endif
return rv;
}
@ -3297,6 +3298,10 @@ nsTableFrame::ReflowChildren(nsIPresContext* aPresContext,
// XXX fix up bad mComputedWidth for scroll frame
kidReflowState.mComputedWidth = PR_MAX(kidReflowState.mComputedWidth, 0);
// If this isn't the first row group, then we can't be at the top of the page
if (childX > 0) {
kidReflowState.mFlags.mIsTopOfPage = PR_FALSE;
}
aReflowState.y += cellSpacingY;
// record the next in flow in case it gets destroyed and the row group array

View File

@ -1011,6 +1011,15 @@ nsTableOuterFrame::OuterReflowChild(nsIPresContext* aPresContext,
}
}
// see if we need to reset top of page due to a caption
if (mCaptionFrame) {
PRUint8 captionSide = GetCaptionSide();
if (((NS_SIDE_BOTTOM == captionSide) && (mCaptionFrame == aChildFrame)) ||
((NS_SIDE_TOP == captionSide) && (mInnerTableFrame == aChildFrame))) {
childRS.mFlags.mIsTopOfPage = PR_FALSE;
}
}
// use the current position as a best guess for placement
nsRect childRect;
aChildFrame->GetRect(childRect);

View File

@ -863,6 +863,24 @@ GetComputedWidth(const nsHTMLReflowState& aReflowState,
return computedWidth;
}
// subtract the heights of aRow's prev in flows from the unpaginated height
static
nscoord CalcHeightFromUnpaginatedHeight(nsIPresContext* aPresContext,
nsTableRowFrame& aRow)
{
nscoord height = 0;
nsTableRowFrame* firstInFlow = (nsTableRowFrame*)aRow.GetFirstInFlow(); if (!firstInFlow) ABORT1(0);
if (firstInFlow->HasUnpaginatedHeight()) {
height = firstInFlow->GetUnpaginatedHeight(aPresContext);
for (nsIFrame* prevInFlow = aRow.GetPrevInFlow(); prevInFlow; prevInFlow->GetPrevInFlow(&prevInFlow)) {
nsRect rect;
prevInFlow->GetRect(rect);
height -= rect.height;
}
}
return PR_MAX(height, 0);
}
// Called for a dirty or resize reflow. Reflows all the existing table cell
// frames unless aDirtyOnly is PR_TRUE in which case only reflow the dirty frames
@ -1063,22 +1081,23 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
nsTableFrame::RePositionViews(aPresContext, kidFrame);
}
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !mPrevInFlow) {
// Calculate the cell's actual size given its pass2 size. This function
// takes into account the specified height (in the style), and any special
// logic needed for backwards compatibility
CalculateCellActualSize(kidFrame, desiredSize.width,
desiredSize.height, availCellWidth);
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) {
if (!mPrevInFlow) {
// Calculate the cell's actual size given its pass2 size. This function
// takes into account the specified height (in the style), and any special
// logic needed for backwards compatibility
CalculateCellActualSize(kidFrame, desiredSize.width,
desiredSize.height, availCellWidth);
}
// height may have changed, adjust descent to absorb any excess difference
nscoord ascent = cellFrame->GetDesiredAscent();
nscoord descent = desiredSize.height - ascent;
UpdateHeight(desiredSize.height, ascent, descent, &aTableFrame, cellFrame);
}
else {
paginatedHeight = PR_MAX(paginatedHeight, desiredSize.height);
PRInt32 rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
if ((1 == rowSpan) && (desiredSize.height > paginatedHeight)) {
paginatedHeight = desiredSize.height;
if (1 == rowSpan) {
SetContentHeight(paginatedHeight);
}
}
@ -1117,8 +1136,32 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// just set our width to what was available. The table will calculate the width and not use our value.
aDesiredSize.width = aReflowState.availableWidth;
aDesiredSize.height = (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight)
? CalcHeight(aReflowState) : paginatedHeight;
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) {
aDesiredSize.height = CalcHeight(aReflowState);
if (mPrevInFlow) {
nscoord height = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
aDesiredSize.height = PR_MAX(aDesiredSize.height, height);
}
else {
if (isPaginated && HasStyleHeight()) {
// set the unpaginated height so next in flows can try to honor it
SetHasUnpaginatedHeight(PR_TRUE);
SetUnpaginatedHeight(aPresContext, aDesiredSize.height);
}
if (isPaginated && HasUnpaginatedHeight()) {
aDesiredSize.height = PR_MAX(aDesiredSize.height, GetUnpaginatedHeight(aPresContext));
}
}
}
else { // constrained height, paginated
aDesiredSize.height = paginatedHeight;
if (aDesiredSize.height <= aReflowState.availableHeight) {
nscoord height = CalcHeightFromUnpaginatedHeight(aPresContext, *this);
aDesiredSize.height = PR_MAX(aDesiredSize.height, height);
aDesiredSize.height = PR_MIN(aDesiredSize.height, aReflowState.availableHeight);
}
}
return rv;
}
@ -1585,6 +1628,7 @@ void
nsTableRowFrame::SetUnpaginatedHeight(nsIPresContext* aPresContext,
nscoord aValue)
{
NS_ASSERTION(!mPrevInFlow, "program error");
// Get the property
nscoord* value = (nscoord*)nsTableFrame::GetProperty(aPresContext, this, nsLayoutAtoms::rowUnpaginatedHeightProperty, PR_TRUE);
if (value) {
@ -1596,7 +1640,7 @@ nscoord
nsTableRowFrame::GetUnpaginatedHeight(nsIPresContext* aPresContext)
{
// See if the property is set
nscoord* value = (nscoord*)nsTableFrame::GetProperty(aPresContext, this, nsLayoutAtoms::rowUnpaginatedHeightProperty);
nscoord* value = (nscoord*)nsTableFrame::GetProperty(aPresContext, GetFirstInFlow(), nsLayoutAtoms::rowUnpaginatedHeightProperty);
if (value)
return *value;
else

View File

@ -437,8 +437,7 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
kidAvailSize, reason);
InitChildReflowState(*aPresContext, borderCollapse, p2t, kidReflowState);
// If this isn't the first row frame, then we can't be at the top of
// the page anymore...
// If this isn't the first row, then we can't be at the top of the page
if (kidFrame != GetFirstFrame()) {
kidReflowState.mFlags.mIsTopOfPage = PR_FALSE;
}
@ -571,6 +570,20 @@ HasMoreThanOneCell(nsTableCellMap* aCellMap,
return PR_FALSE;
}
static void
CacheRowHeightsForPrinting(nsIPresContext* aPresContext,
nsTableRowFrame* aFirstRow)
{
for (nsTableRowFrame* row = aFirstRow; row; row = row->GetNextRow()) {
if (!row->GetPrevInFlow()) {
nsRect rect;
row->GetRect(rect);
row->SetHasUnpaginatedHeight(PR_TRUE);
row->SetUnpaginatedHeight(aPresContext, rect.height);
}
}
}
// This calculates the height of rows starting at aStartRowFrameIn and takes into account
// style height on the row group, style heights on rows and cells, style heights on rowspans.
// Actual row heights will be adjusted later if the table has a style height.
@ -586,6 +599,9 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
nsTableFrame::GetTableFrame(this, tableFrame);
if (!aPresContext || !tableFrame) return;
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
// all table cells have the same top and bottom margins, namely cellSpacingY
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
float p2t;
@ -639,16 +655,24 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
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++) {
if (rowFrame->HasPctHeight()) {
rowInfo[rowIndex].hasPctHeight = PR_TRUE;
rowInfo[rowIndex].pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t);
nscoord nonPctHeight = rowFrame->GetContentHeight();
if (isPaginated) {
nsRect rowRect;
rowFrame->GetRect(rowRect);
nonPctHeight = PR_MAX(nonPctHeight, rowRect.height);
}
if (!rowFrame->GetPrevInFlow()) {
if (rowFrame->HasPctHeight()) {
rowInfo[rowIndex].hasPctHeight = PR_TRUE;
rowInfo[rowIndex].pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t);
}
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
nonPctHeight = PR_MAX(nonPctHeight, rowFrame->GetFixedHeight());
}
nscoord nonPctHeight = PR_MAX(rowFrame->GetContentHeight(), rowFrame->GetFixedHeight());
UpdateHeights(rowInfo[rowIndex], nonPctHeight, heightOfRows, heightOfUnStyledRows);
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
if (!rowInfo[rowIndex].hasStyleHeight) {
if (HasMoreThanOneCell(tableFrame->GetCellMap(), rowIndex)) {
if (isPaginated || HasMoreThanOneCell(tableFrame->GetCellMap(), rowIndex + startRowIndex)) {
rowInfo[rowIndex].isSpecial = PR_TRUE;
// iteratate the row's cell frames to see if any do not have rowspan > 1
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
@ -674,7 +698,10 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
// Get the height of cells with rowspans and allocate any extra space to the rows they span
// iteratate the child frames and process the row frames among them
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
if (tableFrame->RowHasSpanningCells(startRowIndex + rowIndex)) {
// See if the row has an originating cell with rowspan > 1. We cannot determine this for a row in a
// continued row group by calling RowHasSpanningCells, because the row's fif may not have any originating
// cells yet the row may have a continued cell which originates in it.
if (mPrevInFlow || tableFrame->RowHasSpanningCells(startRowIndex + rowIndex)) {
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
// iteratate the row's cell frames
while (cellFrame) {
@ -790,6 +817,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
}
}
PRBool styleHeightAllocation = PR_FALSE;
nscoord rowGroupHeight = startRowGroupHeight + heightOfRows + ((numRows - 1) * cellSpacingY);
// if we have a style height, allocate the extra height to unconstrained rows
if ((aReflowState.mComputedHeight > rowGroupHeight) &&
@ -800,6 +828,7 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
nscoord divisor = (haveUnStyledRows)
? heightOfUnStyledRows : heightOfRows;
if (divisor > 0) {
styleHeightAllocation = PR_TRUE;
for (rowIndex = 0; rowIndex < numRows; rowIndex++) {
if (!haveUnStyledRows || !rowInfo[rowIndex].hasStyleHeight) {
// The amount of additional space each row gets is based on the
@ -844,6 +873,11 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
yOrigin += rowHeight + cellSpacingY;
}
if (isPaginated && styleHeightAllocation) {
// since the row group has a style height, cache the row heights, so next in flows can honor them
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
DidResizeRows(*aPresContext, aReflowState, startRowFrame);
aDesiredSize.height = rowGroupHeight; // Adjust our desired size
@ -902,6 +936,7 @@ nsTableRowGroupFrame::CreateContinuingRowFrame(nsIPresContext& aPresContext,
nsIFrame& aRowFrame,
nsIFrame** aContRowFrame)
{
// XXX what is the row index?
if (!aContRowFrame) {NS_ASSERTION(PR_FALSE, "bad call"); return;}
// create the continuing frame which will create continuing cell frames
aStyleSet.CreateContinuingFrame(&aPresContext, &aRowFrame, this, aContRowFrame);
@ -917,7 +952,7 @@ nsTableRowGroupFrame::CreateContinuingRowFrame(nsIPresContext& aPresContext,
PushChildren(&aPresContext, *aContRowFrame, &aRowFrame);
}
nscoord
void
nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsIStyleSet& aStyleSet,
@ -929,9 +964,8 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
PRInt32 rowIndex = aRowFrame.GetRowIndex();
PRInt32 colCount = aTableFrame.GetColCount();
nsTableCellFrame* prevCellFrame = nsnull;
nsTableRowFrame* rowToMoveToNextPage = nsnull;
nscoord tallestCell = 0;
for (PRInt32 colX = 0; colX < colCount; colX++) {
nsTableCellFrame* cellFrame = aTableFrame.GetCellInfoAt(rowIndex, colX);
if (!cellFrame) continue;
@ -939,20 +973,19 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
cellFrame = (nsTableCellFrame*)cellFrame->GetLastInFlow();
// See if the cell frame is really in this row, or whether it's a cell spanning from a previous row
PRInt32 realRowIndex;
cellFrame->GetRowIndex(realRowIndex);
if (realRowIndex == rowIndex) {
PRInt32 cellRowIndex;
cellFrame->GetRowIndex(cellRowIndex);
if (cellRowIndex == rowIndex) { // cell originates in this row
prevCellFrame = cellFrame;
}
else {
else { // cell originates in a prior row
nsTableRowFrame* parentFrame;
nsPoint cellOrigin;
nsReflowStatus status;
// Ask the cell frame's parent to reflow it to the height of all the
// rows it spans between its origin and aRowEndY
cellFrame->GetParent((nsIFrame**)&parentFrame);
if (!parentFrame) {NS_ASSERTION(PR_FALSE, "bad parent"); return 0;}
cellFrame->GetParent((nsIFrame**)&parentFrame); if (!parentFrame) ABORT0();
parentFrame->GetOrigin(cellOrigin);
nscoord cellAvailHeight = aRowEndY - cellOrigin.y;
nscoord cellHeight = parentFrame->ReflowCellFrame(&aPresContext, aReflowState, cellFrame,
@ -965,7 +998,7 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
if (contCellFrame) {
if (aContRowFrame) {
aContRowFrame->InsertCellFrame(contCellFrame, colX);
}
}
else {
aRowFrame.InsertCellFrame(contCellFrame, prevCellFrame);
}
@ -978,10 +1011,8 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
aContRowFrame->InsertCellFrame(cellFrame, colX);
prevCellFrame = cellFrame;
}
tallestCell = PR_MAX(tallestCell, cellHeight);
}
}
return tallestCell;
}
nsresult
@ -1008,32 +1039,40 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
nscoord availWidth = nsTableFrame::RoundToPixel(aReflowState.availableWidth, p2t);
nscoord availHeight = nsTableFrame::RoundToPixel(aReflowState.availableHeight, p2t);
nscoord lastDesiredHeight = 0;
// get the page height
nsRect actualRect;
nsRect adjRect;
aPresContext->GetPageDim(&actualRect, &adjRect);
nscoord pageHeight = actualRect.height;
PRBool isTopOfPage = aReflowState.mFlags.mIsTopOfPage;
nscoord cellSpacingY = aTableFrame->GetCellSpacingY();
// Walk each of the row frames looking for the first row frame that
// doesn't fit in the available space
for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
PRBool rowIsOnCurrentPage = PR_TRUE;
PRBool degenerateRow = PR_FALSE;
nsRect bounds;
rowFrame->GetRect(bounds);
if (bounds.YMost() > availHeight) {
nsRect actualRect;
nsRect adjRect;
aPresContext->GetPageDim(&actualRect, &adjRect);
nsIFrame* contRowFrame = nsnull;
nscoord pageHeight = actualRect.height;
// reflow the row in the availabe space and have it split if it is the 1st
// row or there is at least 5% of the current page available
if (!prevRowFrame || (availHeight - aDesiredSize.height > pageHeight / 20)) {
// Reflow the row in the available space and have it split
nsSize availSize(availWidth, PR_MAX(availHeight - bounds.y, 0));
// don't let the available height exceed what CalculateRowHeights set for it
availSize.height = PR_MIN(availSize.height, bounds.height);
nsHTMLReflowState rowReflowState(aPresContext, aReflowState, rowFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, borderCollapse, p2t, rowReflowState);
rowReflowState.mFlags.mIsTopOfPage = isTopOfPage; // set top of page
nsHTMLReflowMetrics desiredSize(nsnull);
// A row that has all originating cells with rowspan>1 will return a desired height
// of the largest cell (in contrast to an unconstrained height reflow which returns 0).
rv = ReflowChild(rowFrame, aPresContext, desiredSize, rowReflowState,
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
rowFrame->SizeTo(aPresContext, desiredSize.width, desiredSize.height);
@ -1042,27 +1081,26 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// the row frame is incomplete and all of the cells' block frames have split
CreateContinuingRowFrame(*aPresContext, *styleSet.get(), *rowFrame, &contRowFrame);
aDesiredSize.height += desiredSize.height;
if (prevRowFrame) {
aDesiredSize.height += aTableFrame->GetCellSpacingY();
}
}
else if (0 == desiredSize.height) {
// the row frame is complete because it had no cells originating in it.
CreateContinuingRowFrame(*aPresContext, *styleSet.get(), *rowFrame, &contRowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
aDesiredSize.height = availHeight;
degenerateRow = PR_TRUE;
}
else {
// the row frame is complete because it's minimum height was greater than the
// the available height we gave it
if (aDesiredSize.height > 0) {
// put the row on the next page since it needs more height than it was given
rowIsOnCurrentPage = PR_FALSE;
if ((desiredSize.height <= rowReflowState.availableHeight) || isTopOfPage) {
// the row stays on this page because either it split ok or we're on the top of page
// if top of page and the height exceeded the avail height,then there will be data loss
NS_WARN_IF_FALSE(desiredSize.height <= rowReflowState.availableHeight,
"data loss - incomplete row needed more height than available, on top of page");
CreateContinuingRowFrame(*aPresContext, *styleSet.get(), *rowFrame, &contRowFrame);
aDesiredSize.height += desiredSize.height;
if (prevRowFrame)
aDesiredSize.height += cellSpacingY;
}
else {
// put the row on the next page to give it more height
rowIsOnCurrentPage = PR_FALSE;
}
}
else {
// The row frame is complete because it's minimum height was greater than the
// the available height we gave it.
if (isTopOfPage) {
// We're on top of the page, so keep the row on this page. There will be data loss.
nsIFrame* nextRowFrame;
// Push the row frame that follows
@ -1070,32 +1108,45 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
if (nextRowFrame) {
PushChildren(aPresContext, nextRowFrame, rowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
}
aStatus = nextRowFrame ? NS_FRAME_NOT_COMPLETE : NS_FRAME_COMPLETE;
aDesiredSize.height = bounds.YMost();
aDesiredSize.height += desiredSize.height;
if (prevRowFrame)
aDesiredSize.height += cellSpacingY;
NS_WARN_IF_FALSE(PR_FALSE, "data loss - complete row needed more height than available, on top of page");
}
else {
// We're not on top of the page, so put the row on the next page to give it more height
rowIsOnCurrentPage = PR_FALSE;
}
}
}
else rowIsOnCurrentPage = PR_FALSE;
if (!rowIsOnCurrentPage) {
// Push this row frame and those that follow to the next-in-flow
PushChildren(aPresContext, rowFrame, prevRowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
else {
// put the row on the next page to give it more height
rowIsOnCurrentPage = PR_FALSE;
}
if (prevRowFrame) {
nscoord tallestCell =
SplitSpanningCells(*aPresContext, aReflowState, *styleSet, *aTableFrame,
*rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
if (degenerateRow) {
aDesiredSize.height = lastDesiredHeight + aTableFrame->GetCellSpacingY() + tallestCell;
PRBool willGetAnotherReflow = PR_FALSE;
if (!rowIsOnCurrentPage) {
if (prevRowFrame) {
PushChildren(aPresContext, rowFrame, prevRowFrame);
aStatus = NS_FRAME_NOT_COMPLETE;
}
else {
// We can't push children, so let our parent reflow us again with more space
aDesiredSize.height = bounds.YMost();
willGetAnotherReflow = PR_TRUE;
}
}
if (prevRowFrame && !willGetAnotherReflow) {
SplitSpanningCells(*aPresContext, aReflowState, *styleSet, *aTableFrame,
*rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
}
break;
}
else {
aDesiredSize.height = bounds.YMost();
lastDesiredHeight = aDesiredSize.height;
prevRowFrame = rowFrame;
// see if there is a page break after the row
nsTableRowFrame* nextRow = rowFrame->GetNextRow();
@ -1105,22 +1156,11 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
break;
}
}
isTopOfPage = PR_FALSE; // after the 1st row, we can't be on top of the page any more.
}
return NS_OK;
}
static void
CacheRowHeightsForPrinting(nsIPresContext* aPresContext,
nsTableRowFrame* aFirstRow)
{
for (nsTableRowFrame* row = aFirstRow; row; row = row->GetNextRow()) {
nsRect rect;
row->GetRect(rect);
row->SetHasUnpaginatedHeight(PR_TRUE);
row->SetUnpaginatedHeight(aPresContext, rect.height);
}
}
/** Layout the entire row group.
* This method stacks rows vertically according to HTML 4.0 rules.
* Rows are responsible for layout of their children.
@ -1157,10 +1197,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
// Check for an overflow list
MoveOverflowToChildList(aPresContext);
if (isPaginated && aReflowState.mFlags.mSpecialHeightReflow) {
// cache row height info for printing, now that row heights are known.
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
// Reflow the existing frames.
PRBool splitDueToPageBreak = PR_FALSE;
rv = ReflowChildren(aPresContext, aDesiredSize, state, aStatus,
@ -1181,6 +1217,9 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
// are row spans unless we do this step
if (aReflowState.mFlags.mSpecialHeightReflow) {
DidResizeRows(*aPresContext, aReflowState);
if (isPaginated) {
CacheRowHeightsForPrinting(aPresContext, GetFirstRow());
}
}
else if ((eReflowReason_Initial != aReflowState.reason) ||
isTableUnconstrainedReflow ||

View File

@ -334,13 +334,13 @@ protected:
nsTableFrame* aTableFrame,
nsReflowStatus& aStatus);
nscoord SplitSpanningCells(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsIStyleSet& aStyleSet,
nsTableFrame& aTableFrame,
nsTableRowFrame& aRowFrame,
nscoord aRowEndY,
nsTableRowFrame* aContRowFrame);
void SplitSpanningCells(nsIPresContext& aPresContext,
const nsHTMLReflowState& aReflowState,
nsIStyleSet& aStyleSet,
nsTableFrame& aTableFrame,
nsTableRowFrame& aRowFrame,
nscoord aRowEndY,
nsTableRowFrame* aContRowFrame);
void CreateContinuingRowFrame(nsIPresContext& aPresContext,
nsIStyleSet& aStyleSet,