diff --git a/mozilla/layout/html/table/src/nsCellMap.cpp b/mozilla/layout/html/table/src/nsCellMap.cpp
index fcac1b2da49..78503a6aba0 100644
--- a/mozilla/layout/html/table/src/nsCellMap.cpp
+++ b/mozilla/layout/html/table/src/nsCellMap.cpp
@@ -30,11 +30,15 @@ static const PRBool gsDebug = PR_FALSE;
nsCellMap::nsCellMap(int aRowCount, int aColCount)
: mRowCount(0),
mColCount(0),
- mTotalRowCount(0)
+ mTotalRowCount(0),
+ mNumCollapsedRows(0),
+ mNumCollapsedCols(0)
{
mRows = nsnull;
mColFrames = nsnull;
mMinColSpans = nsnull;
+ mIsCollapsedRows = nsnull;
+ mIsCollapsedCols = nsnull;
Reset(aRowCount, aColCount);
}
@@ -62,6 +66,16 @@ nsCellMap::~nsCellMap()
// mMinColSpans may be null, it is only set for tables that need it
if (nsnull != mMinColSpans)
delete [] mMinColSpans;
+ if (nsnull != mIsCollapsedRows) {
+ delete [] mIsCollapsedRows;
+ mIsCollapsedRows = nsnull;
+ mNumCollapsedRows = 0;
+ }
+ if (nsnull != mIsCollapsedCols) {
+ delete [] mIsCollapsedCols;
+ mIsCollapsedCols = nsnull;
+ mNumCollapsedCols = 0;
+ }
mRows = nsnull;
mColFrames = nsnull;
mMinColSpans = nsnull;
@@ -97,19 +111,20 @@ void nsCellMap::Reset(int aRowCount, int aColCount)
// if the number of rows has increased, add the extra rows
PRInt32 newRows = aRowCount-mTotalRowCount; // (new row count) - (total row allocation)
- for ( ; newRows>0; newRows--)
- {
+ for ( ; newRows > 0; newRows--) {
nsVoidArray *row;
- if (0!=aColCount)
+ if (0 != aColCount) {
row = new nsVoidArray(aColCount);
- else
+ } else {
row = new nsVoidArray();
+ }
mRows->AppendElement(row);
}
mRowCount = aRowCount;
mTotalRowCount = PR_MAX(mTotalRowCount, mRowCount);
mColCount = aColCount;
+
if (gsDebug) printf("leaving Reset with mRC=%d, mCC=%d, mTRC=%d\n",
mRowCount, mColCount, mTotalRowCount);
}
@@ -413,5 +428,73 @@ PRBool nsCellMap::ColHasSpanningCells(PRInt32 aColIndex)
return result;
}
+PRInt32 nsCellMap::GetNumCollapsedRows()
+{
+ return mNumCollapsedRows;
+}
+PRBool nsCellMap::IsRowCollapsedAt(PRInt32 aRow)
+{
+ if ((aRow >= 0) && (aRow < mTotalRowCount)) {
+ if (mIsCollapsedRows) {
+ return mIsCollapsedRows[aRow];
+ }
+ }
+ return PR_FALSE;
+}
+
+void nsCellMap::SetRowCollapsedAt(PRInt32 aRow, PRBool aValue)
+{
+ if ((aRow >= 0) && (aRow < mRowCount)) {
+ if (nsnull == mIsCollapsedRows) {
+ mIsCollapsedRows = new PRBool[mRowCount];
+ for (PRInt32 i = 0; i < mRowCount; i++) {
+ mIsCollapsedRows[i] = PR_FALSE;
+ }
+ }
+ if (mIsCollapsedRows[aRow] != aValue) {
+ if (PR_TRUE == aValue) {
+ mNumCollapsedRows++;
+ } else {
+ mNumCollapsedRows--;
+ }
+ mIsCollapsedRows[aRow] = aValue;
+ }
+ }
+}
+
+PRInt32 nsCellMap::GetNumCollapsedCols()
+{
+ return mNumCollapsedCols;
+}
+
+PRBool nsCellMap::IsColCollapsedAt(PRInt32 aCol)
+{
+ if ((aCol >= 0) && (aCol < mColCount)) {
+ if (mIsCollapsedCols) {
+ return mIsCollapsedCols[aCol];
+ }
+ }
+ return PR_FALSE;
+}
+
+void nsCellMap::SetColCollapsedAt(PRInt32 aCol, PRBool aValue)
+{
+ if ((aCol >= 0) && (aCol < mColCount)) {
+ if (nsnull == mIsCollapsedCols) {
+ mIsCollapsedCols = new PRBool[mColCount];
+ for (PRInt32 i = 0; i < mColCount; i++) {
+ mIsCollapsedCols[i] = PR_FALSE;
+ }
+ }
+ if (mIsCollapsedCols[aCol] != aValue) {
+ if (PR_TRUE == aValue) {
+ mNumCollapsedCols++;
+ } else {
+ mNumCollapsedCols--;
+ }
+ mIsCollapsedCols[aCol] = aValue;
+ }
+ }
+}
diff --git a/mozilla/layout/html/table/src/nsCellMap.h b/mozilla/layout/html/table/src/nsCellMap.h
index 723536e3aad..800855c2f73 100644
--- a/mozilla/layout/html/table/src/nsCellMap.h
+++ b/mozilla/layout/html/table/src/nsCellMap.h
@@ -53,6 +53,14 @@ protected:
/** a cache of the column frames, by col index */
nsVoidArray * mColFrames;
+ // an array of booleans where the ith element indicates if the ith row is collapsed
+ PRBool* mIsCollapsedRows;
+ PRInt32 mNumCollapsedRows;
+
+ // an array of booleans where the ith element indicates if the ith col is collapsed
+ PRBool* mIsCollapsedCols;
+ PRInt32 mNumCollapsedCols;
+
/** the number of rows. mRows[0] - mRows[mRowCount-1] are non-null. */
PRInt32 mRowCount;
@@ -86,6 +94,14 @@ public:
/** assign aCellData to the cell at (aRow,aColumn) */
void SetCellAt(CellData *aCellData, PRInt32 aRow, PRInt32 aColumn);
+ PRInt32 GetNumCollapsedRows();
+ PRBool IsRowCollapsedAt(PRInt32 aRow);
+ void SetRowCollapsedAt(PRInt32 aRow, PRBool aValue);
+
+ PRInt32 GetNumCollapsedCols();
+ PRBool IsColCollapsedAt(PRInt32 aCol);
+ void SetColCollapsedAt(PRInt32 aCol, PRBool aValue);
+
/** expand the CellMap to have aRowCount rows. The number of columns remains the same */
void GrowToRow(PRInt32 aRowCount);
diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp
index 3831cad5f78..dbd105b8f83 100644
--- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp
@@ -86,6 +86,7 @@ void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
}
}
+ mCollapseOffset = nsPoint(0,0);
}
}
@@ -168,7 +169,21 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
+
+ // if the cell originates in a row and/or col that is collapsed, the bottom and/or
+ // right portion of the cell is painted by translating the rendering context.
+ // XXX What about content that can leak outside the cell?
+ PRBool clipState;
+ aRenderingContext.PushState();
+ nsPoint offset = mCollapseOffset;
+ if ((0 != offset.x) || (0 != offset.y)) {
+ aRenderingContext.Translate(offset.x, offset.y);
+ }
+ aRenderingContext.SetClipRect(nsRect(-offset.x, -offset.y, mRect.width, mRect.height),
+ nsClipCombine_kIntersect, clipState);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
+ aRenderingContext.PopState(clipState);
+
return NS_OK;
}
@@ -1062,3 +1077,19 @@ nsTableCellFrame::GetFrameName(nsString& aResult) const
{
return MakeFrameName("TableCell", aResult);
}
+
+void nsTableCellFrame::SetCollapseOffsetX(nscoord aXOffset)
+{
+ mCollapseOffset.x = aXOffset;
+}
+
+void nsTableCellFrame::SetCollapseOffsetY(nscoord aYOffset)
+{
+ mCollapseOffset.y = aYOffset;
+}
+
+nsPoint nsTableCellFrame::GetCollapseOffset()
+{
+ return mCollapseOffset;
+}
+
diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.h b/mozilla/layout/html/table/src/nsTableCellFrame.h
index 80a42c7c2b8..36467382139 100644
--- a/mozilla/layout/html/table/src/nsTableCellFrame.h
+++ b/mozilla/layout/html/table/src/nsTableCellFrame.h
@@ -143,6 +143,11 @@ public:
PRBool GetContentEmpty();
void SetContentEmpty(PRBool aContentEmpty);
+ // The collapse offset is (0,0) except for cells originating in a row/col which is collapsed
+ void SetCollapseOffsetX(nscoord aXOffset);
+ void SetCollapseOffsetY(nscoord aYOffset);
+ nsPoint GetCollapseOffset();
+
protected:
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@@ -211,6 +216,9 @@ protected:
PRBool mIsContentEmpty; // PR_TRUE if the cell's contents take up no space
//XXX: mIsContentEmpty should get yanked in favor of using free a bit on the frame base class
// the FrameState slot (mState; GetFrameState/SetFrameState)
+
+ nsPoint mCollapseOffset;
+
public:
nsBorderEdges mBorderEdges; // one list of border segments for each side of the table frame
// used only for the collapsing border model
diff --git a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp
index e748b1d1fd0..2394597fbfe 100644
--- a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp
@@ -634,21 +634,22 @@ nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
{
nsTableColFrame *result = nsnull;
- PRInt32 count=0;
+ PRInt32 count = 0;
nsIFrame *childFrame = mFrames.FirstChild();
- while (nsnull!=childFrame)
- {
+
+ while (nsnull!=childFrame) {
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
- if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
- {
+ if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) {
nsTableColFrame *col = (nsTableColFrame *)childFrame;
count += col->GetSpan();
- if (aColIndex<=count)
+ if (aColIndex<=count) {
result = col;
+ }
}
childFrame->GetNextSibling(&childFrame);
}
+
return result;
}
diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp
index 009989a2d54..d80d8ac0486 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableFrame.cpp
@@ -385,13 +385,14 @@ NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFra
{
const nsStyleDisplay *rowDisplay;
nextRow->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay);
- if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
- {
+ if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay) {
rv = ((nsTableRowFrame *)nextRow)->InitChildren();
- if (NS_FAILED(rv))
+ if (NS_FAILED(rv)) {
return rv;
+ }
}
}
+
return rv;
}
@@ -947,74 +948,77 @@ NS_METHOD nsTableFrame::ReBuildCellMap()
void nsTableFrame::DumpCellMap ()
{
printf("dumping CellMap:\n");
- if (nsnull != mCellMap)
- {
+ if (nsnull != mCellMap) {
PRInt32 colIndex;
PRInt32 rowCount = mCellMap->GetRowCount();
PRInt32 colCount = mCellMap->GetColCount();
printf("rowCount=%d, colCount=%d\n", rowCount, colCount);
- for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
- {
- if (gsDebug==PR_TRUE)
- { printf("row %d", rowIndex);
- printf(": ");
- }
- for (colIndex = 0; colIndex < colCount; colIndex++)
- {
- CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex);
- if (cd != nsnull)
- {
- if (cd->mCell != nsnull)
- {
- printf("C%d,%d ", rowIndex, colIndex);
- printf(" ");
- }
- else
- {
- nsTableCellFrame *cell = cd->mRealCell->mCell;
- nsTableRowFrame *row;
- cell->GetParent((nsIFrame **)&row);
- int rr = row->GetRowIndex ();
+
+ for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+ printf("row %d : ", rowIndex);
+ for (colIndex = 0; colIndex < colCount; colIndex++) {
+ CellData* cd = mCellMap->GetCellAt(rowIndex, colIndex);
+ if (cd != nsnull) {
+ if (cd->mCell != nsnull) {
+ printf("C%d,%d ", rowIndex, colIndex);
+ } else {
+ nsTableCellFrame* cell = cd->mRealCell->mCell;
+ nsTableRowFrame* row;
+ cell->GetParent((nsIFrame**)&row);
+ int rr = row->GetRowIndex();
int cc;
cell->GetColIndex(cc);
- printf("S%d,%d ", rr, cc);
- if (cd->mOverlap != nsnull)
- {
+ printf("S%d,%d ", rr, cc);
+ if (cd->mOverlap != nsnull){
cell = cd->mOverlap->mCell;
nsTableRowFrame* row2;
- cell->GetParent((nsIFrame **)&row2);
- rr = row2->GetRowIndex ();
- cell->GetColIndex (cc);
+ cell->GetParent((nsIFrame**)&row2);
+ rr = row2->GetRowIndex();
+ cell->GetColIndex(cc);
printf("O%d,%c ", rr, cc);
- }
- else
- printf(" ");
+ }
}
- }
- else
+ } else {
printf("---- ");
+ }
}
PRBool spanners = RowHasSpanningCells(rowIndex);
PRBool spannedInto = RowIsSpannedInto(rowIndex);
printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F");
}
+
+ // output info mapping Ci,j to cell address
+ PRInt32 cellCount = 0;
+ for (PRInt32 rIndex = 0; rIndex < rowCount; rIndex++) {
+ for (colIndex = 0; colIndex < colCount; colIndex++) {
+ CellData* cd = mCellMap->GetCellAt(rIndex, colIndex);
+ if (cd != nsnull) {
+ if (cd->mCell != nsnull) {
+ printf("C%d,%d=%p ", rIndex, colIndex, cd->mCell);
+ cellCount++;
+ }
+ }
+ if (0 == (cellCount % 4)) {
+ printf("\n");
+ }
+ }
+ }
+
// output colspan info
- for (colIndex=0; colIndexGetColumnFrame(colIndex);
printf ("col index %d has frame=%p\n", colIndex, colFrame);
}
- }
- else
+ } else {
printf ("[nsnull]");
+ }
}
#endif
@@ -2636,7 +2640,10 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
aDesiredSize.width = ComputeDesiredWidth(aReflowState);
nscoord defaultHeight = state.y + borderPadding.top + borderPadding.bottom;
aDesiredSize.height = ComputeDesiredHeight(aPresContext, aReflowState, defaultHeight);
-
+
+ AdjustForCollapsingRows(aPresContext, aDesiredSize.height);
+ AdjustForCollapsingCols(aPresContext, aDesiredSize.width);
+
// once horizontal borders are computed and all row heights are set,
// we need to fix up length of vertical edges
// XXX need to figure start row and end row correctly
@@ -2651,6 +2658,224 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
}
+// collapsing row groups, rows, col groups and cols are accounted for after both passes of
+// reflow so that it has no effect on the calculations of reflow.
+NS_METHOD nsTableFrame::AdjustForCollapsingRows(nsIPresContext& aPresContext,
+ nscoord& aHeight)
+{
+ // determine which row groups and rows are collapsed
+ nsIFrame* childFrame;
+ FirstChild(nsnull, &childFrame);
+ while (nsnull != childFrame) {
+ const nsStyleDisplay* groupDisplay;
+ childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ if (IsRowGroup(groupDisplay->mDisplay)) {
+ PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+
+ nsTableRowFrame* rowFrame = nsnull;
+ childFrame->FirstChild(nsnull, (nsIFrame**)&rowFrame);
+ PRInt32 rowX = 0;
+ while (nsnull != rowFrame) {
+ const nsStyleDisplay *rowDisplay;
+ rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
+ if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
+ mCellMap->SetRowCollapsedAt(rowX, PR_TRUE);
+ }
+ }
+ rowFrame->GetNextSibling((nsIFrame**)&rowFrame);
+ rowX++;
+ }
+ }
+ childFrame->GetNextSibling(&childFrame);
+ }
+
+ if (mCellMap->GetNumCollapsedRows() <= 0) {
+ return NS_OK; // no collapsed rows, we're done
+ }
+
+ // collapse the rows and/or row groups
+ nsIFrame* groupFrame = mFrames.FirstChild();
+ nscoord yGroupOffset = 0; // total offset among rows within a single row group
+ nscoord yTotalOffset = 0; // total offset among all rows in all row groups
+ PRInt32 rowX = 0;
+ PRBool collapseGroup;
+
+ while (nsnull != groupFrame) {
+ const nsStyleDisplay* groupDisplay;
+ groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ if (IsRowGroup(groupDisplay->mDisplay)) {
+ collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+ nsIFrame* rowFrame;
+ groupFrame->FirstChild(nsnull, &rowFrame);
+
+ while (nsnull != rowFrame) {
+ const nsStyleDisplay* rowDisplay;
+ rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
+ nsRect rowRect;
+ rowFrame->GetRect(rowRect);
+ if (collapseGroup || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
+ yGroupOffset += rowRect.height;
+ rowRect.height = 0;
+ rowFrame->SetRect(rowRect);
+ nsIFrame* cellFrame;
+ rowFrame->FirstChild(nsnull, &cellFrame);
+ while (nsnull != cellFrame) {
+ const nsStyleDisplay* cellDisplay;
+ cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
+ nsTableCellFrame* cFrame = (nsTableCellFrame*)cellFrame;
+ nsRect cRect;
+ cFrame->GetRect(cRect);
+ cRect.height -= rowRect.height;
+ cFrame->SetCollapseOffsetY(-yGroupOffset);
+ cFrame->SetRect(cRect);
+ }
+ cellFrame->GetNextSibling(&cellFrame);
+ }
+ // check if a cell above spans into here
+ //if (!collapseGroup) {
+ PRInt32 numCols = mCellMap->GetColCount();
+ nsTableCellFrame* lastCell = nsnull;
+ for (int colX = 0; colX < numCols; colX++) {
+ CellData* cellData = mCellMap->GetCellAt(rowX, colX);
+ if (cellData && !cellData->mCell) { // a cell above is spanning into here
+ // adjust the real cell's rect only once
+ nsTableCellFrame* realCell = cellData->mRealCell->mCell;
+ if (realCell != lastCell) {
+ nsRect realRect;
+ realCell->GetRect(realRect);
+ realRect.height -= rowRect.height;
+ realCell->SetRect(realRect);
+ }
+ lastCell = realCell;
+ }
+ }
+ //}
+ } else { // row is not collapsed but needs to be adjusted by those that are
+ rowRect.y -= yGroupOffset;
+ rowFrame->SetRect(rowRect);
+ }
+ rowX++;
+ }
+ rowFrame->GetNextSibling(&rowFrame);
+ } // end row frame while
+ }
+ nsRect groupRect;
+ groupFrame->GetRect(groupRect);
+ groupRect.height -= yGroupOffset;
+ groupRect.y -= yTotalOffset;
+ groupFrame->SetRect(groupRect);
+
+ yTotalOffset += yGroupOffset;
+ yGroupOffset = 0;
+ groupFrame->GetNextSibling(&groupFrame);
+ } // end group frame while
+
+ aHeight -= yTotalOffset;
+
+ return NS_OK;
+}
+
+NS_METHOD nsTableFrame::AdjustForCollapsingCols(nsIPresContext& aPresContext,
+ nscoord& aWidth)
+{
+ // determine which col groups and cols are collapsed
+ nsIFrame* childFrame = mColGroups.FirstChild();
+ while (nsnull != childFrame) {
+ const nsStyleDisplay* groupDisplay;
+ GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+
+ nsTableColFrame* colFrame = nsnull;
+ childFrame->FirstChild(nsnull, (nsIFrame**)&colFrame);
+ PRInt32 colX = 0;
+ while (nsnull != colFrame) {
+ const nsStyleDisplay *colDisplay;
+ colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
+ if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible)) {
+ mCellMap->SetColCollapsedAt(colX, PR_TRUE);
+ }
+ }
+ colFrame->GetNextSibling((nsIFrame**)&colFrame);
+ colX++;
+ }
+ childFrame->GetNextSibling(&childFrame);
+ }
+
+ if (mCellMap->GetNumCollapsedCols() <= 0) {
+ return NS_OK; // no collapsed cols, we're done
+ }
+
+ // collapse the cols and/or col groups
+ PRInt32 numRows = mCellMap->GetRowCount();
+ nsIFrame* groupFrame = mColGroups.FirstChild();
+ nscoord cellSpacingX = GetCellSpacingX();
+ nscoord xOffset = 0;
+ PRInt32 colX = 0;
+ while (nsnull != groupFrame) {
+ const nsStyleDisplay* groupDisplay;
+ groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ PRBool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+ nsRect zeroRect(0, 0, 0, 0);
+ nsIFrame* colFrame;
+ groupFrame->FirstChild(nsnull, &colFrame);
+ while (nsnull != colFrame) {
+ const nsStyleDisplay* colDisplay;
+ colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
+ PRBool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible);
+ PRInt32 colSpan = ((nsTableColFrame*)colFrame)->GetSpan();
+ for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
+ PRInt32 colWidth = GetColumnWidth(colX+spanX);
+ if (collapseGroup || collapseCol) {
+ xOffset += colWidth + cellSpacingX;
+ }
+ nsTableCellFrame* lastCell = nsnull;
+ nsTableCellFrame* cellFrame = nsnull;
+ for (PRInt32 rowX = 0; rowX < numRows; rowX++) {
+ CellData* cellData = mCellMap->GetCellAt(rowX, colX+spanX);
+ nsRect cellRect;
+ if (cellData) {
+ cellFrame = cellData->mCell;
+ if (cellFrame) { // the cell originates at (rowX, colX)
+ cellFrame->GetRect(cellRect);
+ if (collapseGroup || collapseCol) {
+ if (lastCell != cellFrame) { // do it only once if there is a row span
+ cellRect.width -= colWidth;
+ cellFrame->SetCollapseOffsetX(-xOffset);
+ }
+ } else { // the cell is not in a collapsed col but needs to move
+ cellRect.x -= xOffset;
+ }
+ cellFrame->SetRect(cellRect);
+ // if the cell does not originate at (rowX, colX), adjust the real cells width
+ } else if (collapseGroup || collapseCol) {
+ cellFrame = cellData->mRealCell->mCell;
+ if ((cellFrame) && (lastCell != cellFrame)) {
+ cellFrame->GetRect(cellRect);
+ cellRect.width -= colWidth + cellSpacingX;
+ cellFrame->SetRect(cellRect);
+ }
+ }
+ }
+ lastCell = cellFrame;
+ }
+ }
+ colX += colSpan;
+ }
+ colFrame->GetNextSibling(&colFrame);
+ } // inner while
+ groupFrame->GetNextSibling(&groupFrame);
+ } // outer while
+
+ aWidth -= xOffset;
+
+ return NS_OK;
+}
+
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h
index bc3762a9690..c3982d83d9c 100644
--- a/mozilla/layout/html/table/src/nsTableFrame.h
+++ b/mozilla/layout/html/table/src/nsTableFrame.h
@@ -560,6 +560,12 @@ protected:
InnerTableReflowState& aReflowState,
nsIFrame* aKidFrame,
nscoord aDeltaY);
+
+ NS_METHOD AdjustForCollapsingRows(nsIPresContext& aPresContext,
+ nscoord& aHeight);
+
+ NS_METHOD AdjustForCollapsingCols(nsIPresContext& aPresContext,
+ nscoord& aWidth);
// end incremental reflow methods
/** return the desired width of this table accounting for the current
diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp
index 20e5b752f82..6d7df14e439 100644
--- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp
@@ -1421,16 +1421,6 @@ nsTableRowFrame::Reflow(nsIPresContext& aPresContext,
break;
}
- // check the visibility in the final pass. If it is collapse, set our desired size to 0
- if (nsTableFrame::IsFinalPass(aReflowState)) {
- const nsStyleDisplay *display;
- GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
- if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- }
- }
-
// XXX TROY
#if 0
diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
index b1185b488af..a0cad0ea58b 100644
--- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp
@@ -643,8 +643,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
{
const nsStyleDisplay *childDisplay;
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
- if ((NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay) &&
- (NS_STYLE_VISIBILITY_COLLAPSE != childDisplay->mVisible))
+ if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
// get the height of the tallest cell in the row (excluding cells that span rows)
nscoord maxCellHeight = ((nsTableRowFrame*)rowFrame)->GetTallestChild();
@@ -1031,16 +1030,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
}
}
- // check the visibility in the final pass. If it is collapse, set our desired size to 0
- if (nsTableFrame::IsFinalPass(aReflowState)) {
- const nsStyleDisplay *display;
- GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
- if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- }
- }
-
if (gsDebug==PR_TRUE)
{
if (nsnull!=aDesiredSize.maxElementSize)
diff --git a/mozilla/layout/tables/nsCellMap.cpp b/mozilla/layout/tables/nsCellMap.cpp
index fcac1b2da49..78503a6aba0 100644
--- a/mozilla/layout/tables/nsCellMap.cpp
+++ b/mozilla/layout/tables/nsCellMap.cpp
@@ -30,11 +30,15 @@ static const PRBool gsDebug = PR_FALSE;
nsCellMap::nsCellMap(int aRowCount, int aColCount)
: mRowCount(0),
mColCount(0),
- mTotalRowCount(0)
+ mTotalRowCount(0),
+ mNumCollapsedRows(0),
+ mNumCollapsedCols(0)
{
mRows = nsnull;
mColFrames = nsnull;
mMinColSpans = nsnull;
+ mIsCollapsedRows = nsnull;
+ mIsCollapsedCols = nsnull;
Reset(aRowCount, aColCount);
}
@@ -62,6 +66,16 @@ nsCellMap::~nsCellMap()
// mMinColSpans may be null, it is only set for tables that need it
if (nsnull != mMinColSpans)
delete [] mMinColSpans;
+ if (nsnull != mIsCollapsedRows) {
+ delete [] mIsCollapsedRows;
+ mIsCollapsedRows = nsnull;
+ mNumCollapsedRows = 0;
+ }
+ if (nsnull != mIsCollapsedCols) {
+ delete [] mIsCollapsedCols;
+ mIsCollapsedCols = nsnull;
+ mNumCollapsedCols = 0;
+ }
mRows = nsnull;
mColFrames = nsnull;
mMinColSpans = nsnull;
@@ -97,19 +111,20 @@ void nsCellMap::Reset(int aRowCount, int aColCount)
// if the number of rows has increased, add the extra rows
PRInt32 newRows = aRowCount-mTotalRowCount; // (new row count) - (total row allocation)
- for ( ; newRows>0; newRows--)
- {
+ for ( ; newRows > 0; newRows--) {
nsVoidArray *row;
- if (0!=aColCount)
+ if (0 != aColCount) {
row = new nsVoidArray(aColCount);
- else
+ } else {
row = new nsVoidArray();
+ }
mRows->AppendElement(row);
}
mRowCount = aRowCount;
mTotalRowCount = PR_MAX(mTotalRowCount, mRowCount);
mColCount = aColCount;
+
if (gsDebug) printf("leaving Reset with mRC=%d, mCC=%d, mTRC=%d\n",
mRowCount, mColCount, mTotalRowCount);
}
@@ -413,5 +428,73 @@ PRBool nsCellMap::ColHasSpanningCells(PRInt32 aColIndex)
return result;
}
+PRInt32 nsCellMap::GetNumCollapsedRows()
+{
+ return mNumCollapsedRows;
+}
+PRBool nsCellMap::IsRowCollapsedAt(PRInt32 aRow)
+{
+ if ((aRow >= 0) && (aRow < mTotalRowCount)) {
+ if (mIsCollapsedRows) {
+ return mIsCollapsedRows[aRow];
+ }
+ }
+ return PR_FALSE;
+}
+
+void nsCellMap::SetRowCollapsedAt(PRInt32 aRow, PRBool aValue)
+{
+ if ((aRow >= 0) && (aRow < mRowCount)) {
+ if (nsnull == mIsCollapsedRows) {
+ mIsCollapsedRows = new PRBool[mRowCount];
+ for (PRInt32 i = 0; i < mRowCount; i++) {
+ mIsCollapsedRows[i] = PR_FALSE;
+ }
+ }
+ if (mIsCollapsedRows[aRow] != aValue) {
+ if (PR_TRUE == aValue) {
+ mNumCollapsedRows++;
+ } else {
+ mNumCollapsedRows--;
+ }
+ mIsCollapsedRows[aRow] = aValue;
+ }
+ }
+}
+
+PRInt32 nsCellMap::GetNumCollapsedCols()
+{
+ return mNumCollapsedCols;
+}
+
+PRBool nsCellMap::IsColCollapsedAt(PRInt32 aCol)
+{
+ if ((aCol >= 0) && (aCol < mColCount)) {
+ if (mIsCollapsedCols) {
+ return mIsCollapsedCols[aCol];
+ }
+ }
+ return PR_FALSE;
+}
+
+void nsCellMap::SetColCollapsedAt(PRInt32 aCol, PRBool aValue)
+{
+ if ((aCol >= 0) && (aCol < mColCount)) {
+ if (nsnull == mIsCollapsedCols) {
+ mIsCollapsedCols = new PRBool[mColCount];
+ for (PRInt32 i = 0; i < mColCount; i++) {
+ mIsCollapsedCols[i] = PR_FALSE;
+ }
+ }
+ if (mIsCollapsedCols[aCol] != aValue) {
+ if (PR_TRUE == aValue) {
+ mNumCollapsedCols++;
+ } else {
+ mNumCollapsedCols--;
+ }
+ mIsCollapsedCols[aCol] = aValue;
+ }
+ }
+}
diff --git a/mozilla/layout/tables/nsCellMap.h b/mozilla/layout/tables/nsCellMap.h
index 723536e3aad..800855c2f73 100644
--- a/mozilla/layout/tables/nsCellMap.h
+++ b/mozilla/layout/tables/nsCellMap.h
@@ -53,6 +53,14 @@ protected:
/** a cache of the column frames, by col index */
nsVoidArray * mColFrames;
+ // an array of booleans where the ith element indicates if the ith row is collapsed
+ PRBool* mIsCollapsedRows;
+ PRInt32 mNumCollapsedRows;
+
+ // an array of booleans where the ith element indicates if the ith col is collapsed
+ PRBool* mIsCollapsedCols;
+ PRInt32 mNumCollapsedCols;
+
/** the number of rows. mRows[0] - mRows[mRowCount-1] are non-null. */
PRInt32 mRowCount;
@@ -86,6 +94,14 @@ public:
/** assign aCellData to the cell at (aRow,aColumn) */
void SetCellAt(CellData *aCellData, PRInt32 aRow, PRInt32 aColumn);
+ PRInt32 GetNumCollapsedRows();
+ PRBool IsRowCollapsedAt(PRInt32 aRow);
+ void SetRowCollapsedAt(PRInt32 aRow, PRBool aValue);
+
+ PRInt32 GetNumCollapsedCols();
+ PRBool IsColCollapsedAt(PRInt32 aCol);
+ void SetColCollapsedAt(PRInt32 aCol, PRBool aValue);
+
/** expand the CellMap to have aRowCount rows. The number of columns remains the same */
void GrowToRow(PRInt32 aRowCount);
diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp
index 3831cad5f78..dbd105b8f83 100644
--- a/mozilla/layout/tables/nsTableCellFrame.cpp
+++ b/mozilla/layout/tables/nsTableCellFrame.cpp
@@ -86,6 +86,7 @@ void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
}
}
+ mCollapseOffset = nsPoint(0,0);
}
}
@@ -168,7 +169,21 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height);
}
+
+ // if the cell originates in a row and/or col that is collapsed, the bottom and/or
+ // right portion of the cell is painted by translating the rendering context.
+ // XXX What about content that can leak outside the cell?
+ PRBool clipState;
+ aRenderingContext.PushState();
+ nsPoint offset = mCollapseOffset;
+ if ((0 != offset.x) || (0 != offset.y)) {
+ aRenderingContext.Translate(offset.x, offset.y);
+ }
+ aRenderingContext.SetClipRect(nsRect(-offset.x, -offset.y, mRect.width, mRect.height),
+ nsClipCombine_kIntersect, clipState);
PaintChildren(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
+ aRenderingContext.PopState(clipState);
+
return NS_OK;
}
@@ -1062,3 +1077,19 @@ nsTableCellFrame::GetFrameName(nsString& aResult) const
{
return MakeFrameName("TableCell", aResult);
}
+
+void nsTableCellFrame::SetCollapseOffsetX(nscoord aXOffset)
+{
+ mCollapseOffset.x = aXOffset;
+}
+
+void nsTableCellFrame::SetCollapseOffsetY(nscoord aYOffset)
+{
+ mCollapseOffset.y = aYOffset;
+}
+
+nsPoint nsTableCellFrame::GetCollapseOffset()
+{
+ return mCollapseOffset;
+}
+
diff --git a/mozilla/layout/tables/nsTableCellFrame.h b/mozilla/layout/tables/nsTableCellFrame.h
index 80a42c7c2b8..36467382139 100644
--- a/mozilla/layout/tables/nsTableCellFrame.h
+++ b/mozilla/layout/tables/nsTableCellFrame.h
@@ -143,6 +143,11 @@ public:
PRBool GetContentEmpty();
void SetContentEmpty(PRBool aContentEmpty);
+ // The collapse offset is (0,0) except for cells originating in a row/col which is collapsed
+ void SetCollapseOffsetX(nscoord aXOffset);
+ void SetCollapseOffsetY(nscoord aYOffset);
+ nsPoint GetCollapseOffset();
+
protected:
/** implement abstract method on nsHTMLContainerFrame */
virtual PRIntn GetSkipSides() const;
@@ -211,6 +216,9 @@ protected:
PRBool mIsContentEmpty; // PR_TRUE if the cell's contents take up no space
//XXX: mIsContentEmpty should get yanked in favor of using free a bit on the frame base class
// the FrameState slot (mState; GetFrameState/SetFrameState)
+
+ nsPoint mCollapseOffset;
+
public:
nsBorderEdges mBorderEdges; // one list of border segments for each side of the table frame
// used only for the collapsing border model
diff --git a/mozilla/layout/tables/nsTableColGroupFrame.cpp b/mozilla/layout/tables/nsTableColGroupFrame.cpp
index e748b1d1fd0..2394597fbfe 100644
--- a/mozilla/layout/tables/nsTableColGroupFrame.cpp
+++ b/mozilla/layout/tables/nsTableColGroupFrame.cpp
@@ -634,21 +634,22 @@ nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
nsTableColFrame * nsTableColGroupFrame::GetColumnAt (PRInt32 aColIndex)
{
nsTableColFrame *result = nsnull;
- PRInt32 count=0;
+ PRInt32 count = 0;
nsIFrame *childFrame = mFrames.FirstChild();
- while (nsnull!=childFrame)
- {
+
+ while (nsnull!=childFrame) {
const nsStyleDisplay *childDisplay;
childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
- if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay)
- {
+ if (NS_STYLE_DISPLAY_TABLE_COLUMN == childDisplay->mDisplay) {
nsTableColFrame *col = (nsTableColFrame *)childFrame;
count += col->GetSpan();
- if (aColIndex<=count)
+ if (aColIndex<=count) {
result = col;
+ }
}
childFrame->GetNextSibling(&childFrame);
}
+
return result;
}
diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp
index 009989a2d54..d80d8ac0486 100644
--- a/mozilla/layout/tables/nsTableFrame.cpp
+++ b/mozilla/layout/tables/nsTableFrame.cpp
@@ -385,13 +385,14 @@ NS_IMETHODIMP nsTableFrame::DidAppendRowGroup(nsTableRowGroupFrame *aRowGroupFra
{
const nsStyleDisplay *rowDisplay;
nextRow->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&)rowDisplay);
- if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay)
- {
+ if (NS_STYLE_DISPLAY_TABLE_ROW==rowDisplay->mDisplay) {
rv = ((nsTableRowFrame *)nextRow)->InitChildren();
- if (NS_FAILED(rv))
+ if (NS_FAILED(rv)) {
return rv;
+ }
}
}
+
return rv;
}
@@ -947,74 +948,77 @@ NS_METHOD nsTableFrame::ReBuildCellMap()
void nsTableFrame::DumpCellMap ()
{
printf("dumping CellMap:\n");
- if (nsnull != mCellMap)
- {
+ if (nsnull != mCellMap) {
PRInt32 colIndex;
PRInt32 rowCount = mCellMap->GetRowCount();
PRInt32 colCount = mCellMap->GetColCount();
printf("rowCount=%d, colCount=%d\n", rowCount, colCount);
- for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++)
- {
- if (gsDebug==PR_TRUE)
- { printf("row %d", rowIndex);
- printf(": ");
- }
- for (colIndex = 0; colIndex < colCount; colIndex++)
- {
- CellData *cd =mCellMap->GetCellAt(rowIndex, colIndex);
- if (cd != nsnull)
- {
- if (cd->mCell != nsnull)
- {
- printf("C%d,%d ", rowIndex, colIndex);
- printf(" ");
- }
- else
- {
- nsTableCellFrame *cell = cd->mRealCell->mCell;
- nsTableRowFrame *row;
- cell->GetParent((nsIFrame **)&row);
- int rr = row->GetRowIndex ();
+
+ for (PRInt32 rowIndex = 0; rowIndex < rowCount; rowIndex++) {
+ printf("row %d : ", rowIndex);
+ for (colIndex = 0; colIndex < colCount; colIndex++) {
+ CellData* cd = mCellMap->GetCellAt(rowIndex, colIndex);
+ if (cd != nsnull) {
+ if (cd->mCell != nsnull) {
+ printf("C%d,%d ", rowIndex, colIndex);
+ } else {
+ nsTableCellFrame* cell = cd->mRealCell->mCell;
+ nsTableRowFrame* row;
+ cell->GetParent((nsIFrame**)&row);
+ int rr = row->GetRowIndex();
int cc;
cell->GetColIndex(cc);
- printf("S%d,%d ", rr, cc);
- if (cd->mOverlap != nsnull)
- {
+ printf("S%d,%d ", rr, cc);
+ if (cd->mOverlap != nsnull){
cell = cd->mOverlap->mCell;
nsTableRowFrame* row2;
- cell->GetParent((nsIFrame **)&row2);
- rr = row2->GetRowIndex ();
- cell->GetColIndex (cc);
+ cell->GetParent((nsIFrame**)&row2);
+ rr = row2->GetRowIndex();
+ cell->GetColIndex(cc);
printf("O%d,%c ", rr, cc);
- }
- else
- printf(" ");
+ }
}
- }
- else
+ } else {
printf("---- ");
+ }
}
PRBool spanners = RowHasSpanningCells(rowIndex);
PRBool spannedInto = RowIsSpannedInto(rowIndex);
printf (" spanners=%s spannedInto=%s\n", spanners?"T":"F", spannedInto?"T":"F");
}
+
+ // output info mapping Ci,j to cell address
+ PRInt32 cellCount = 0;
+ for (PRInt32 rIndex = 0; rIndex < rowCount; rIndex++) {
+ for (colIndex = 0; colIndex < colCount; colIndex++) {
+ CellData* cd = mCellMap->GetCellAt(rIndex, colIndex);
+ if (cd != nsnull) {
+ if (cd->mCell != nsnull) {
+ printf("C%d,%d=%p ", rIndex, colIndex, cd->mCell);
+ cellCount++;
+ }
+ }
+ if (0 == (cellCount % 4)) {
+ printf("\n");
+ }
+ }
+ }
+
// output colspan info
- for (colIndex=0; colIndexGetColumnFrame(colIndex);
printf ("col index %d has frame=%p\n", colIndex, colFrame);
}
- }
- else
+ } else {
printf ("[nsnull]");
+ }
}
#endif
@@ -2636,7 +2640,10 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
aDesiredSize.width = ComputeDesiredWidth(aReflowState);
nscoord defaultHeight = state.y + borderPadding.top + borderPadding.bottom;
aDesiredSize.height = ComputeDesiredHeight(aPresContext, aReflowState, defaultHeight);
-
+
+ AdjustForCollapsingRows(aPresContext, aDesiredSize.height);
+ AdjustForCollapsingCols(aPresContext, aDesiredSize.width);
+
// once horizontal borders are computed and all row heights are set,
// we need to fix up length of vertical edges
// XXX need to figure start row and end row correctly
@@ -2651,6 +2658,224 @@ NS_METHOD nsTableFrame::ResizeReflowPass2(nsIPresContext& aPresContext,
}
+// collapsing row groups, rows, col groups and cols are accounted for after both passes of
+// reflow so that it has no effect on the calculations of reflow.
+NS_METHOD nsTableFrame::AdjustForCollapsingRows(nsIPresContext& aPresContext,
+ nscoord& aHeight)
+{
+ // determine which row groups and rows are collapsed
+ nsIFrame* childFrame;
+ FirstChild(nsnull, &childFrame);
+ while (nsnull != childFrame) {
+ const nsStyleDisplay* groupDisplay;
+ childFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ if (IsRowGroup(groupDisplay->mDisplay)) {
+ PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+
+ nsTableRowFrame* rowFrame = nsnull;
+ childFrame->FirstChild(nsnull, (nsIFrame**)&rowFrame);
+ PRInt32 rowX = 0;
+ while (nsnull != rowFrame) {
+ const nsStyleDisplay *rowDisplay;
+ rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
+ if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
+ mCellMap->SetRowCollapsedAt(rowX, PR_TRUE);
+ }
+ }
+ rowFrame->GetNextSibling((nsIFrame**)&rowFrame);
+ rowX++;
+ }
+ }
+ childFrame->GetNextSibling(&childFrame);
+ }
+
+ if (mCellMap->GetNumCollapsedRows() <= 0) {
+ return NS_OK; // no collapsed rows, we're done
+ }
+
+ // collapse the rows and/or row groups
+ nsIFrame* groupFrame = mFrames.FirstChild();
+ nscoord yGroupOffset = 0; // total offset among rows within a single row group
+ nscoord yTotalOffset = 0; // total offset among all rows in all row groups
+ PRInt32 rowX = 0;
+ PRBool collapseGroup;
+
+ while (nsnull != groupFrame) {
+ const nsStyleDisplay* groupDisplay;
+ groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ if (IsRowGroup(groupDisplay->mDisplay)) {
+ collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+ nsIFrame* rowFrame;
+ groupFrame->FirstChild(nsnull, &rowFrame);
+
+ while (nsnull != rowFrame) {
+ const nsStyleDisplay* rowDisplay;
+ rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
+ nsRect rowRect;
+ rowFrame->GetRect(rowRect);
+ if (collapseGroup || (NS_STYLE_VISIBILITY_COLLAPSE == rowDisplay->mVisible)) {
+ yGroupOffset += rowRect.height;
+ rowRect.height = 0;
+ rowFrame->SetRect(rowRect);
+ nsIFrame* cellFrame;
+ rowFrame->FirstChild(nsnull, &cellFrame);
+ while (nsnull != cellFrame) {
+ const nsStyleDisplay* cellDisplay;
+ cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay) {
+ nsTableCellFrame* cFrame = (nsTableCellFrame*)cellFrame;
+ nsRect cRect;
+ cFrame->GetRect(cRect);
+ cRect.height -= rowRect.height;
+ cFrame->SetCollapseOffsetY(-yGroupOffset);
+ cFrame->SetRect(cRect);
+ }
+ cellFrame->GetNextSibling(&cellFrame);
+ }
+ // check if a cell above spans into here
+ //if (!collapseGroup) {
+ PRInt32 numCols = mCellMap->GetColCount();
+ nsTableCellFrame* lastCell = nsnull;
+ for (int colX = 0; colX < numCols; colX++) {
+ CellData* cellData = mCellMap->GetCellAt(rowX, colX);
+ if (cellData && !cellData->mCell) { // a cell above is spanning into here
+ // adjust the real cell's rect only once
+ nsTableCellFrame* realCell = cellData->mRealCell->mCell;
+ if (realCell != lastCell) {
+ nsRect realRect;
+ realCell->GetRect(realRect);
+ realRect.height -= rowRect.height;
+ realCell->SetRect(realRect);
+ }
+ lastCell = realCell;
+ }
+ }
+ //}
+ } else { // row is not collapsed but needs to be adjusted by those that are
+ rowRect.y -= yGroupOffset;
+ rowFrame->SetRect(rowRect);
+ }
+ rowX++;
+ }
+ rowFrame->GetNextSibling(&rowFrame);
+ } // end row frame while
+ }
+ nsRect groupRect;
+ groupFrame->GetRect(groupRect);
+ groupRect.height -= yGroupOffset;
+ groupRect.y -= yTotalOffset;
+ groupFrame->SetRect(groupRect);
+
+ yTotalOffset += yGroupOffset;
+ yGroupOffset = 0;
+ groupFrame->GetNextSibling(&groupFrame);
+ } // end group frame while
+
+ aHeight -= yTotalOffset;
+
+ return NS_OK;
+}
+
+NS_METHOD nsTableFrame::AdjustForCollapsingCols(nsIPresContext& aPresContext,
+ nscoord& aWidth)
+{
+ // determine which col groups and cols are collapsed
+ nsIFrame* childFrame = mColGroups.FirstChild();
+ while (nsnull != childFrame) {
+ const nsStyleDisplay* groupDisplay;
+ GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ PRBool groupIsCollapsed = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+
+ nsTableColFrame* colFrame = nsnull;
+ childFrame->FirstChild(nsnull, (nsIFrame**)&colFrame);
+ PRInt32 colX = 0;
+ while (nsnull != colFrame) {
+ const nsStyleDisplay *colDisplay;
+ colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
+ if (groupIsCollapsed || (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible)) {
+ mCellMap->SetColCollapsedAt(colX, PR_TRUE);
+ }
+ }
+ colFrame->GetNextSibling((nsIFrame**)&colFrame);
+ colX++;
+ }
+ childFrame->GetNextSibling(&childFrame);
+ }
+
+ if (mCellMap->GetNumCollapsedCols() <= 0) {
+ return NS_OK; // no collapsed cols, we're done
+ }
+
+ // collapse the cols and/or col groups
+ PRInt32 numRows = mCellMap->GetRowCount();
+ nsIFrame* groupFrame = mColGroups.FirstChild();
+ nscoord cellSpacingX = GetCellSpacingX();
+ nscoord xOffset = 0;
+ PRInt32 colX = 0;
+ while (nsnull != groupFrame) {
+ const nsStyleDisplay* groupDisplay;
+ groupFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)groupDisplay));
+ PRBool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupDisplay->mVisible);
+ nsRect zeroRect(0, 0, 0, 0);
+ nsIFrame* colFrame;
+ groupFrame->FirstChild(nsnull, &colFrame);
+ while (nsnull != colFrame) {
+ const nsStyleDisplay* colDisplay;
+ colFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)colDisplay));
+ if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
+ PRBool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colDisplay->mVisible);
+ PRInt32 colSpan = ((nsTableColFrame*)colFrame)->GetSpan();
+ for (PRInt32 spanX = 0; spanX < colSpan; spanX++) {
+ PRInt32 colWidth = GetColumnWidth(colX+spanX);
+ if (collapseGroup || collapseCol) {
+ xOffset += colWidth + cellSpacingX;
+ }
+ nsTableCellFrame* lastCell = nsnull;
+ nsTableCellFrame* cellFrame = nsnull;
+ for (PRInt32 rowX = 0; rowX < numRows; rowX++) {
+ CellData* cellData = mCellMap->GetCellAt(rowX, colX+spanX);
+ nsRect cellRect;
+ if (cellData) {
+ cellFrame = cellData->mCell;
+ if (cellFrame) { // the cell originates at (rowX, colX)
+ cellFrame->GetRect(cellRect);
+ if (collapseGroup || collapseCol) {
+ if (lastCell != cellFrame) { // do it only once if there is a row span
+ cellRect.width -= colWidth;
+ cellFrame->SetCollapseOffsetX(-xOffset);
+ }
+ } else { // the cell is not in a collapsed col but needs to move
+ cellRect.x -= xOffset;
+ }
+ cellFrame->SetRect(cellRect);
+ // if the cell does not originate at (rowX, colX), adjust the real cells width
+ } else if (collapseGroup || collapseCol) {
+ cellFrame = cellData->mRealCell->mCell;
+ if ((cellFrame) && (lastCell != cellFrame)) {
+ cellFrame->GetRect(cellRect);
+ cellRect.width -= colWidth + cellSpacingX;
+ cellFrame->SetRect(cellRect);
+ }
+ }
+ }
+ lastCell = cellFrame;
+ }
+ }
+ colX += colSpan;
+ }
+ colFrame->GetNextSibling(&colFrame);
+ } // inner while
+ groupFrame->GetNextSibling(&groupFrame);
+ } // outer while
+
+ aWidth -= xOffset;
+
+ return NS_OK;
+}
+
NS_METHOD nsTableFrame::IncrementalReflow(nsIPresContext& aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h
index bc3762a9690..c3982d83d9c 100644
--- a/mozilla/layout/tables/nsTableFrame.h
+++ b/mozilla/layout/tables/nsTableFrame.h
@@ -560,6 +560,12 @@ protected:
InnerTableReflowState& aReflowState,
nsIFrame* aKidFrame,
nscoord aDeltaY);
+
+ NS_METHOD AdjustForCollapsingRows(nsIPresContext& aPresContext,
+ nscoord& aHeight);
+
+ NS_METHOD AdjustForCollapsingCols(nsIPresContext& aPresContext,
+ nscoord& aWidth);
// end incremental reflow methods
/** return the desired width of this table accounting for the current
diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp
index 20e5b752f82..6d7df14e439 100644
--- a/mozilla/layout/tables/nsTableRowFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowFrame.cpp
@@ -1421,16 +1421,6 @@ nsTableRowFrame::Reflow(nsIPresContext& aPresContext,
break;
}
- // check the visibility in the final pass. If it is collapse, set our desired size to 0
- if (nsTableFrame::IsFinalPass(aReflowState)) {
- const nsStyleDisplay *display;
- GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
- if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- }
- }
-
// XXX TROY
#if 0
diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
index b1185b488af..a0cad0ea58b 100644
--- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp
+++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp
@@ -643,8 +643,7 @@ void nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext& aPresContext,
{
const nsStyleDisplay *childDisplay;
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
- if ((NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay) &&
- (NS_STYLE_VISIBILITY_COLLAPSE != childDisplay->mVisible))
+ if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
// get the height of the tallest cell in the row (excluding cells that span rows)
nscoord maxCellHeight = ((nsTableRowFrame*)rowFrame)->GetTallestChild();
@@ -1031,16 +1030,6 @@ nsTableRowGroupFrame::Reflow(nsIPresContext& aPresContext,
}
}
- // check the visibility in the final pass. If it is collapse, set our desired size to 0
- if (nsTableFrame::IsFinalPass(aReflowState)) {
- const nsStyleDisplay *display;
- GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
- if (NS_STYLE_VISIBILITY_COLLAPSE == display->mVisible) {
- aDesiredSize.width = 0;
- aDesiredSize.height = 0;
- }
- }
-
if (gsDebug==PR_TRUE)
{
if (nsnull!=aDesiredSize.maxElementSize)