diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp
index a454a90210c..9ada62184bf 100644
--- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp
@@ -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 {
diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp
index 9c593670d77..680bb511dce 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableFrame.cpp
@@ -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
diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp
index 86536e5933a..36b85db32c2 100644
--- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp
@@ -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);
diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp
index d81b50d1a33..85ce78ccdb2 100644
--- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp
@@ -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
diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
index 23024fc1e7f..bbd3a58c104 100644
--- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
@@ -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 ||
diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.h b/mozilla/layout/html/table/src/nsTableRowGroupFrame.h
index 789152b5a7e..489243c682d 100644
--- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.h
+++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.h
@@ -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,
diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp
index a454a90210c..9ada62184bf 100644
--- a/mozilla/layout/tables/nsTableCellFrame.cpp
+++ b/mozilla/layout/tables/nsTableCellFrame.cpp
@@ -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 {
diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp
index 9c593670d77..680bb511dce 100644
--- a/mozilla/layout/tables/nsTableFrame.cpp
+++ b/mozilla/layout/tables/nsTableFrame.cpp
@@ -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
diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp
index 86536e5933a..36b85db32c2 100644
--- a/mozilla/layout/tables/nsTableOuterFrame.cpp
+++ b/mozilla/layout/tables/nsTableOuterFrame.cpp
@@ -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);
diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp
index d81b50d1a33..85ce78ccdb2 100644
--- a/mozilla/layout/tables/nsTableRowFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowFrame.cpp
@@ -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
diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
index 23024fc1e7f..bbd3a58c104 100644
--- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
@@ -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 ||
diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.h b/mozilla/layout/tables/nsTableRowGroupFrame.h
index 789152b5a7e..489243c682d 100644
--- a/mozilla/layout/tables/nsTableRowGroupFrame.h
+++ b/mozilla/layout/tables/nsTableRowGroupFrame.h
@@ -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,