Make OrderRowGroups type-safe. Bug 367706, r=bernd, sr=roc

This commit is contained in:
2007-06-05 11:55:26 -07:00
parent 1aa880f06f
commit 1a1ab905a5
4 changed files with 346 additions and 236 deletions

View File

@@ -76,18 +76,14 @@ nsTableCellMap::nsTableCellMap(nsTableFrame& aTableFrame,
{
MOZ_COUNT_CTOR(nsTableCellMap);
nsAutoVoidArray orderedRowGroups;
PRUint32 numRowGroups;
aTableFrame.OrderRowGroups(orderedRowGroups, numRowGroups);
nsTableFrame::RowGroupArray orderedRowGroups;
aTableFrame.OrderRowGroups(orderedRowGroups);
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame =
nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
if (rgFrame) {
nsTableRowGroupFrame* prior = (0 == rgX)
? nsnull : nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX - 1));
InsertGroupCellMap(*rgFrame, prior);
}
nsTableRowGroupFrame* prior = nsnull;
for (PRUint32 rgX = 0; rgX < orderedRowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgX];
InsertGroupCellMap(*rgFrame, prior);
prior = rgFrame;
}
if (aBorderCollapse) {
mBCInfo = new BCInfo();
@@ -296,15 +292,10 @@ nsTableCellMap::GetMapFor(const nsTableRowGroupFrame* aRowGroup,
if (aRowGroup->IsRepeatable()) {
nsTableFrame* fifTable = NS_STATIC_CAST(nsTableFrame*, mTableFrame.GetFirstInFlow());
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
nsTableRowGroupFrame *thead, *tfoot;
// find the original header/footer
fifTable->OrderRowGroups(rowGroups, numRowGroups, &thead, &tfoot);
const nsStyleDisplay* display = aRowGroup->GetStyleDisplay();
nsTableRowGroupFrame* rgOrig =
(NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay) ? thead : tfoot;
(NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay) ?
fifTable->GetTHead() : fifTable->GetTFoot();
// find the row group cell map using the original header/footer
if (rgOrig && rgOrig != aRowGroup) {
return GetMapFor(rgOrig, aStartHint);
@@ -317,37 +308,36 @@ nsTableCellMap::GetMapFor(const nsTableRowGroupFrame* aRowGroup,
void
nsTableCellMap::Synchronize(nsTableFrame* aTableFrame)
{
nsAutoVoidArray orderedRowGroups;
nsAutoVoidArray maps;
PRUint32 numRowGroups;
PRInt32 mapIndex;
nsTableFrame::RowGroupArray orderedRowGroups;
nsAutoTPtrArray<nsCellMap, 8> maps;
maps.Clear();
aTableFrame->OrderRowGroups(orderedRowGroups, numRowGroups);
if (!numRowGroups) {
aTableFrame->OrderRowGroups(orderedRowGroups);
if (!orderedRowGroups.Length()) {
return;
}
// XXXbz this fails if orderedRowGroups is missing some row groups
// (due to OOM when appending to the array, e.g. -- we leak maps in
// that case).
// Scope |map| outside the loop so we can use it as a hint.
nsCellMap* map = nsnull;
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame =
nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
if (rgFrame) {
map = GetMapFor(rgFrame, map);
if (map) {
if (!maps.AppendElement(map)) {
delete map;
NS_WARNING("Could not AppendElement");
}
for (PRUint32 rgX = 0; rgX < orderedRowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgX];
map = GetMapFor(rgFrame, map);
if (map) {
if (!maps.AppendElement(map)) {
delete map;
NS_WARNING("Could not AppendElement");
}
}
}
mapIndex = maps.Count() - 1;
nsCellMap* nextMap = (nsCellMap*) maps.ElementAt(mapIndex);
PRInt32 mapIndex = maps.Length() - 1; // Might end up -1
nsCellMap* nextMap = maps.ElementAt(mapIndex);
nextMap->SetNextSibling(nsnull);
for (mapIndex-- ; mapIndex >= 0; mapIndex--) {
nsCellMap* map = (nsCellMap*) maps.ElementAt(mapIndex);
nsCellMap* map = maps.ElementAt(mapIndex);
map->SetNextSibling(nextMap);
nextMap = map;
}

View File

@@ -540,14 +540,11 @@ void nsTableFrame::AdjustRowIndices(PRInt32 aRowIndex,
{
// Iterate over the row groups and adjust the row indices of all rows
// whose index is >= aRowIndex.
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
OrderRowGroups(rowGroups, numRowGroups);
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame);
rgFrame->AdjustRowIndices(aRowIndex, aAdjustment);
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
rowGroups[rgX]->AdjustRowIndices(aRowIndex, aAdjustment);
}
}
@@ -557,9 +554,8 @@ void nsTableFrame::ResetRowIndices(nsIFrame* aFirstRowGroupFrame,
{
// Iterate over the row groups and adjust the row indices of all rows
// omit the rowgroups that will be inserted later
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
OrderRowGroups(rowGroups, numRowGroups, nsnull);
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
PRInt32 rowIndex = 0;
nsTableRowGroupFrame* newRgFrame = nsnull;
@@ -570,9 +566,8 @@ void nsTableFrame::ResetRowIndices(nsIFrame* aFirstRowGroupFrame,
omitRgFrame = nsnull;
}
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame);
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
if (rgFrame == newRgFrame) {
// omit the new rowgroup
if (omitRgFrame) {
@@ -983,13 +978,12 @@ void nsTableFrame::RemoveCell(nsTableCellFrame* aCellFrame,
PRInt32
nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame& aRowGroupFrame)
{
nsAutoVoidArray orderedRowGroups;
PRUint32 numRowGroups;
OrderRowGroups(orderedRowGroups, numRowGroups);
RowGroupArray orderedRowGroups;
OrderRowGroups(orderedRowGroups);
PRInt32 rowIndex = 0;
for (PRUint32 rgIndex = 0; rgIndex < numRowGroups; rgIndex++) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgIndex));
for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
if (rgFrame == &aRowGroupFrame) {
break;
}
@@ -1177,21 +1171,21 @@ nsTableFrame::InsertRowGroups(nsIFrame* aFirstRowGroupFrame,
#endif
nsTableCellMap* cellMap = GetCellMap();
if (cellMap) {
nsAutoVoidArray orderedRowGroups;
PRUint32 numRowGroups;
OrderRowGroups(orderedRowGroups, numRowGroups);
RowGroupArray orderedRowGroups;
OrderRowGroups(orderedRowGroups);
nsAutoVoidArray rows;
// Loop over the rowgroups and check if some of them are new, if they are
// insert cellmaps in the order that is predefined by OrderRowGroups,
PRUint32 rgIndex;
for (rgIndex = 0; rgIndex < numRowGroups; rgIndex++) {
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
nsIFrame* kidFrame = aFirstRowGroupFrame;
while (kidFrame) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame);
if (GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgIndex)) == rgFrame) {
nsTableRowGroupFrame* priorRG = (0 == rgIndex)
? nsnull : GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgIndex - 1));
if (orderedRowGroups[rgIndex] == rgFrame) {
nsTableRowGroupFrame* priorRG =
(0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1];
// create and add the cell map for the row group
cellMap->InsertGroupCellMap(*rgFrame, priorRG);
@@ -1209,14 +1203,14 @@ nsTableFrame::InsertRowGroups(nsIFrame* aFirstRowGroupFrame,
ResetRowIndices(aFirstRowGroupFrame, aLastRowGroupFrame);
//now that the cellmaps are reordered too insert the rows
for (rgIndex = 0; rgIndex < numRowGroups; rgIndex++) {
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
nsIFrame* kidFrame = aFirstRowGroupFrame;
while (kidFrame) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame);
if (GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgIndex)) == rgFrame) {
nsTableRowGroupFrame* priorRG = (0 == rgIndex)
? nsnull : GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgIndex - 1));
if (orderedRowGroups[rgIndex] == rgFrame) {
nsTableRowGroupFrame* priorRG =
(0 == rgIndex) ? nsnull : orderedRowGroups[rgIndex - 1];
// collect the new row frames in an array and add them to the table
PRInt32 numRows = CollectRows(kidFrame, rows);
if (numRows > 0) {
@@ -1559,13 +1553,12 @@ ProcessRowInserted(nsTableFrame& aTableFrame,
nscoord aNewHeight)
{
aTableFrame.SetRowInserted(PR_FALSE); // reset the bit that got us here
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame.OrderRowGroups(rowGroups, numRowGroups);
nsTableFrame::RowGroupArray rowGroups;
aTableFrame.OrderRowGroups(rowGroups);
// find the row group containing the inserted row
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame = (nsTableRowGroupFrame*)rowGroups.ElementAt(rgX);
if (!rgFrame) continue; // should never happen
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
NS_ASSERTION(rgFrame, "Must have rgFrame here");
nsIFrame* childFrame = rgFrame->GetFirstChild(nsnull);
// find the row that was inserted first
while (childFrame) {
@@ -2070,7 +2063,7 @@ nsTableFrame::GetFirstBodyRowGroupFrame()
// Table specific version that takes into account repeated header and footer
// frames when continuing table frames
void
nsTableFrame::PushChildren(const nsAutoVoidArray& aFrames,
nsTableFrame::PushChildren(const FrameArray& aFrames,
PRInt32 aPushFrom)
{
NS_PRECONDITION(aPushFrom > 0, "pushing first child");
@@ -2079,13 +2072,16 @@ nsTableFrame::PushChildren(const nsAutoVoidArray& aFrames,
nsFrameList frames;
nsIFrame* lastFrame = nsnull;
PRUint32 childX;
nsIFrame* prevSiblingHint =
NS_STATIC_CAST(nsIFrame*, aFrames.ElementAt(aPushFrom - 1));
for (childX = aPushFrom; childX < aFrames.Count(); ++childX) {
nsIFrame* f = NS_STATIC_CAST(nsIFrame*, aFrames.FastElementAt(childX));
// Don't push repeatable frames, do push non-rowgroup frames
if (f->GetType() != nsGkAtoms::tableRowGroupFrame ||
!NS_STATIC_CAST(nsTableRowGroupFrame*, f)->IsRepeatable()) {
nsIFrame* prevSiblingHint = aFrames.SafeElementAt(aPushFrom - 1);
for (childX = aPushFrom; childX < aFrames.Length(); ++childX) {
nsIFrame* f = aFrames[childX];
// Don't push repeatable frames, do push non-rowgroup frames.
// XXXbz Need to push the non-rowgroup frames, even though we don't reflow
// them, so that we don't lose them. Of course there shouldn't be any
// non-rowgroup frames here...
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(f);
NS_ASSERTION(rgFrame, "Unexpected non-row-group frame");
if (!rgFrame || !rgFrame->IsRepeatable()) {
mFrames.RemoveFrame(f, prevSiblingHint);
frames.InsertFrame(nsnull, lastFrame, f);
lastFrame = f;
@@ -2165,17 +2161,15 @@ nsTableFrame::AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize,
// collapse the rows and/or row groups as necessary
// Get the ordered children
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
OrderRowGroups(rowGroups, numRowGroups);
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
nscoord width = GetCollapsedWidth(aBorderPadding);
nscoord rgWidth = width - 2 * GetCellSpacingX();
nsRect overflowArea(0, 0, 0, 0);
// Walk the list of children
for (PRUint32 childX = 0; childX < numRowGroups; childX++) {
nsIFrame* childFrame = (nsIFrame*)rowGroups.ElementAt(childX);
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(childFrame);
if (!rgFrame) continue; // skip foreign frame types
for (PRUint32 childX = 0; childX < rowGroups.Length(); childX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[childX];
NS_ASSERTION(rgFrame, "Must have row group frame here");
yTotalOffset += rgFrame->CollapseRowGroupIfNecessary(yTotalOffset, rgWidth);
ConsiderChildOverflow(overflowArea, rgFrame);
}
@@ -2430,8 +2424,6 @@ nsTableFrame::RemoveFrame(nsIAtom* aListName,
NS_ASSERTION(!aListName, "unexpected child list");
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(aOldFrame);
if (rgFrame) {
PRInt32 startRowIndex = rgFrame->GetStartRowIndex();
PRInt32 numRows = rgFrame->GetRowCount();
// remove the row group from the cell map
nsTableCellMap* cellMap = GetCellMap();
if (cellMap) {
@@ -2635,54 +2627,43 @@ void nsTableFrame::PlaceChild(nsTableReflowState& aReflowState,
}
void
nsTableFrame::OrderRowGroups(nsVoidArray& aChildren,
PRUint32& aNumRowGroups,
nsTableRowGroupFrame** aHead,
nsTableRowGroupFrame** aFoot) const
nsTableFrame::OrderRowGroups(RowGroupArray& aChildren) const
{
aChildren.Clear();
nsIFrame* head = nsnull;
nsIFrame* foot = nsnull;
// initialize out parameters, if present
if (aHead) *aHead = nsnull;
if (aFoot) *aFoot = nsnull;
nsTableRowGroupFrame* head = nsnull;
nsTableRowGroupFrame* foot = nsnull;
nsIFrame* kidFrame = mFrames.FirstChild();
nsAutoVoidArray nonRowGroups;
// put the tbodies first, and the non row groups last
while (kidFrame) {
const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
if (IsRowGroup(kidDisplay->mDisplay)) {
nsTableRowGroupFrame* rowGroup = GetRowGroupFrame(kidFrame);
if (NS_LIKELY(rowGroup)) {
switch(kidDisplay->mDisplay) {
case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
if (head) { // treat additional thead like tbody
aChildren.AppendElement(kidFrame);
aChildren.AppendElement(rowGroup);
}
else {
head = kidFrame;
if (aHead) {
*aHead = (nsTableRowGroupFrame*)head;
}
head = rowGroup;
}
break;
case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
if (foot) {
aChildren.AppendElement(kidFrame);
if (foot) { // treat additional tfoot like tbody
aChildren.AppendElement(rowGroup);
}
else {
foot = kidFrame;
if (aFoot) {
*aFoot = (nsTableRowGroupFrame*)foot;
}
foot = rowGroup;
}
break;
case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
aChildren.AppendElement(rowGroup);
break;
default:
aChildren.AppendElement(kidFrame);
NS_NOTREACHED("How did this produce an nsTableRowGroupFrame?");
// Just ignore it
break;
}
}
else {
nonRowGroups.AppendElement(kidFrame);
}
// Get the next sibling but skip it if it's also the next-in-flow, since
// a next-in-flow will not be part of the current table.
while (kidFrame) {
@@ -2692,22 +2673,145 @@ nsTableFrame::OrderRowGroups(nsVoidArray& aChildren,
break;
}
}
aNumRowGroups = aChildren.Count();
// put the thead first
if (head) {
aChildren.InsertElementAt(head, 0);
aNumRowGroups++;
aChildren.InsertElementAt(0, head);
}
// put the tfoot after the last tbody
if (foot) {
aChildren.InsertElementAt(foot, aNumRowGroups);
aNumRowGroups++;
aChildren.AppendElement(foot);
}
// put the non row groups at the end
PRInt32 numNonRowGroups = nonRowGroups.Count();
for (PRInt32 i = 0; i < numNonRowGroups; i++) {
aChildren.AppendElement(nonRowGroups.ElementAt(i));
}
PRUint32
nsTableFrame::OrderRowGroups(FrameArray& aChildren,
nsTableRowGroupFrame** aHead,
nsTableRowGroupFrame** aFoot) const
{
aChildren.Clear();
// initialize out parameters
*aHead = nsnull;
*aFoot = nsnull;
FrameArray nonRowGroups;
nsIFrame* head = nsnull;
nsIFrame* foot = nsnull;
nsIFrame* kidFrame = mFrames.FirstChild();
while (kidFrame) {
const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
nsTableRowGroupFrame* rowGroup = GetRowGroupFrame(kidFrame);
if (NS_LIKELY(rowGroup)) {
switch(kidDisplay->mDisplay) {
case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
if (head) { // treat additional thead like tbody
aChildren.AppendElement(kidFrame);
}
else {
head = kidFrame;
*aHead = rowGroup;
}
break;
case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
if (foot) { // treat additional tfoot like tbody
aChildren.AppendElement(kidFrame);
}
else {
foot = kidFrame;
*aFoot = rowGroup;
}
break;
case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
aChildren.AppendElement(kidFrame);
break;
default:
break;
}
} else {
NS_NOTREACHED("Non-row-group primary frame list child of an "
"nsTableFrame? How come?");
nonRowGroups.AppendElement(kidFrame);
}
// Get the next sibling but skip it if it's also the next-in-flow, since
// a next-in-flow will not be part of the current table.
while (kidFrame) {
nsIFrame* nif = kidFrame->GetNextInFlow();
kidFrame = kidFrame->GetNextSibling();
if (kidFrame != nif)
break;
}
}
// put the thead first
if (head) {
aChildren.InsertElementAt(0, head);
}
// put the tfoot after the last tbody
if (foot) {
aChildren.AppendElement(foot);
}
PRUint32 rowGroupCount = aChildren.Length();
aChildren.AppendElements(nonRowGroups);
return rowGroupCount;
}
nsTableRowGroupFrame*
nsTableFrame::GetTHead() const
{
nsIFrame* kidFrame = mFrames.FirstChild();
while (kidFrame) {
if (kidFrame->GetStyleDisplay()->mDisplay ==
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) {
nsTableRowGroupFrame* rg = GetRowGroupFrame(kidFrame);
if (rg) {
return rg;
}
}
// Get the next sibling but skip it if it's also the next-in-flow, since
// a next-in-flow will not be part of the current table.
while (kidFrame) {
nsIFrame* nif = kidFrame->GetNextInFlow();
kidFrame = kidFrame->GetNextSibling();
if (kidFrame != nif)
break;
}
}
return nsnull;
}
nsTableRowGroupFrame*
nsTableFrame::GetTFoot() const
{
nsIFrame* kidFrame = mFrames.FirstChild();
while (kidFrame) {
if (kidFrame->GetStyleDisplay()->mDisplay ==
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP) {
nsTableRowGroupFrame* rg = GetRowGroupFrame(kidFrame);
if (rg) {
return rg;
}
}
// Get the next sibling but skip it if it's also the next-in-flow, since
// a next-in-flow will not be part of the current table.
while (kidFrame) {
nsIFrame* nif = kidFrame->GetNextInFlow();
kidFrame = kidFrame->GetNextSibling();
if (kidFrame != nif)
break;
}
}
return nsnull;
}
static PRBool
@@ -2742,13 +2846,12 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
mBits.mResizedColumns ||
IsGeometryDirty();
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
FrameArray rowGroups;
nsTableRowGroupFrame *thead, *tfoot;
OrderRowGroups(rowGroups, numRowGroups, &thead, &tfoot);
PRUint32 numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
PRBool pageBreak = PR_FALSE;
for (PRUint32 childX = 0; childX < numRowGroups; childX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(childX);
nsIFrame* kidFrame = rowGroups[childX];
// Get the frame state bits
// See if we should only reflow the dirty child frames
if (reflowAllKids ||
@@ -2770,8 +2873,10 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
nscoord repeatedFooterHeight = 0;
if (isPaginated && (NS_UNCONSTRAINEDSIZE != kidAvailSize.height)) {
if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == kidFrame->GetStyleDisplay()->mDisplay) { // the child is a tbody
nsIFrame* lastChild = (nsIFrame*)rowGroups.ElementAt(numRowGroups - 1);
nsIFrame* lastChild = rowGroups[rowGroups.Length() - 1];
if (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == lastChild->GetStyleDisplay()->mDisplay) { // the last child is a tfoot
// XXXbz what if lastChild is a scrollable tfoot? Bogus!!
// dbaron is right -- this should be using thead/tfoot!
if (((nsTableRowGroupFrame*)lastChild)->IsRepeatable()) {
repeatedFooterHeight = lastChild->GetSize().height;
if (repeatedFooterHeight + cellSpacingY < kidAvailSize.height) {
@@ -2817,10 +2922,11 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
if (reorder) {
// reorder row groups the reflow may have changed the nextinflows
OrderRowGroups(rowGroups, numRowGroups, &thead, &tfoot);
for (childX = 0; childX < numRowGroups; childX++) {
if (kidFrame == (nsIFrame*)rowGroups.ElementAt(childX))
break;
numRowGroups = OrderRowGroups(rowGroups, &thead, &tfoot);
childX = rowGroups.IndexOf(kidFrame);
if (childX == RowGroupArray::NoIndex) {
// XXXbz can this happen?
childX = numRowGroups;
}
}
// see if the rowgroup did not fit on this page might be pushed on
@@ -2830,8 +2936,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
kidReflowState.availableHeight < desiredSize.height) {
// if we are on top of the page place with dataloss
if (kidReflowState.mFlags.mIsTopOfPage) {
if (childX+1 < numRowGroups) {
nsIFrame* nextRowGroupFrame = (nsIFrame*) rowGroups.ElementAt(childX +1);
if (childX+1 < rowGroups.Length()) {
nsIFrame* nextRowGroupFrame = rowGroups[childX + 1];
if (nextRowGroupFrame) {
PlaceChild(aReflowState, kidFrame, desiredSize);
aStatus = NS_FRAME_NOT_COMPLETE;
@@ -2857,7 +2963,8 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
// see if there is a page break after this row group or before the next one
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
nsIFrame* nextKid = (childX + 1 < numRowGroups) ? (nsIFrame*)rowGroups.ElementAt(childX + 1) : nsnull;
nsIFrame* nextKid =
(childX + 1 < numRowGroups) ? rowGroups[childX + 1] : nsnull;
pageBreak = PageBreakAfter(*kidFrame, nextKid);
}
@@ -2890,11 +2997,11 @@ nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
// would have been if we had called OrderRowGroups
// again. Note that rowGroups doesn't get used again after
// we PushChildren below, anyway.
rowGroups.InsertElementAt(continuingFrame, childX + 1);
rowGroups.InsertElementAt(childX + 1, continuingFrame);
}
else {
// put the nextinflow so that it will get pushed
rowGroups.InsertElementAt(kidNextInFlow, childX + 1);
rowGroups.InsertElementAt(childX + 1, kidNextInFlow);
}
// We've used up all of our available space so push the remaining
// children to the next-in-flow
@@ -2992,10 +3099,9 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLRef
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
// get the natural height based on the last child's (row group or scroll frame) rect
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
OrderRowGroups(rowGroups, numRowGroups);
if (numRowGroups <= 0) {
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
if (rowGroups.Length() == 0) {
// tables can be used as rectangular items without content
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
if ((NS_UNCONSTRAINEDSIZE != tableSpecifiedHeight) &&
@@ -3013,11 +3119,8 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLRef
nscoord desiredHeight = borderPadding.top + borderPadding.bottom;
if (rowCount > 0 && colCount > 0) {
desiredHeight += cellSpacingY;
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsIFrame* rg = (nsIFrame*)rowGroups.ElementAt(rgX);
if (rg) {
desiredHeight += rg->GetSize().height + cellSpacingY;
}
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
desiredHeight += rowGroups[rgX]->GetSize().height + cellSpacingY;
}
}
@@ -3043,9 +3146,8 @@ nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLRef
static
void ResizeCells(nsTableFrame& aTableFrame)
{
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame.OrderRowGroups(rowGroups, numRowGroups);
nsTableFrame::RowGroupArray rowGroups;
aTableFrame.OrderRowGroups(rowGroups);
nsHTMLReflowMetrics tableDesiredSize;
nsRect tableRect = aTableFrame.GetRect();
tableDesiredSize.width = tableRect.width;
@@ -3053,8 +3155,8 @@ void ResizeCells(nsTableFrame& aTableFrame)
tableDesiredSize.mOverflowArea = nsRect(0, 0, tableRect.width,
tableRect.height);
for (PRUint32 rgX = 0; (rgX < numRowGroups); rgX++) {
nsTableRowGroupFrame* rgFrame = aTableFrame.GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
nsRect rowGroupRect = rgFrame->GetRect();
nsHTMLReflowMetrics groupDesiredSize;
@@ -3087,9 +3189,8 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
nsVoidArray rowGroups;
PRUint32 numRowGroups;
OrderRowGroups(rowGroups, numRowGroups);
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
nscoord amountUsed = 0;
// distribute space to each pct height row whose row group doesn't have a computed
@@ -3099,12 +3200,12 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
nscoord yOriginRG = borderPadding.top + GetCellSpacingY();
nscoord yEndRG = yOriginRG;
PRUint32 rgX;
for (rgX = 0; (rgX < numRowGroups); rgX++) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
for (rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
nscoord amountUsedByRG = 0;
nscoord yOriginRow = 0;
nsRect rgRect = rgFrame->GetRect();
if (rgFrame && !rgFrame->HasStyleHeight()) {
if (!rgFrame->HasStyleHeight()) {
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
while (rowFrame) {
nsRect rowRect = rowFrame->GetRect();
@@ -3154,9 +3255,9 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
// get the first row without a style height where its row group has an unconstrianed height
nsTableRowGroupFrame* firstUnStyledRG = nsnull;
nsTableRowFrame* firstUnStyledRow = nsnull;
for (rgX = 0; (rgX < numRowGroups) && !firstUnStyledRG; rgX++) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
if (rgFrame && !rgFrame->HasStyleHeight()) {
for (rgX = 0; rgX < rowGroups.Length() && !firstUnStyledRG; rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
if (!rgFrame->HasStyleHeight()) {
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
while (rowFrame) {
if (!rowFrame->HasStyleHeight()) {
@@ -3173,9 +3274,9 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
// accumulate the correct divisor. This will be the total of all unstyled rows inside
// unstyled row groups, unless there are none, in which case, it will be all rows
nscoord divisor = 0;
for (rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
if (rgFrame && (!firstUnStyledRG || !rgFrame->HasStyleHeight())) {
for (rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
if (!firstUnStyledRG || !rgFrame->HasStyleHeight()) {
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
while (rowFrame) {
if (!firstUnStyledRG || !rowFrame->HasStyleHeight()) {
@@ -3195,9 +3296,8 @@ nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
pctBasis = aAmount - amountUsed;
yOriginRG = borderPadding.top + cellSpacingY;
yEndRG = yOriginRG;
for (rgX = 0; rgX < numRowGroups; rgX++) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
if (!rgFrame) continue;
for (rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
nscoord amountUsedByRG = 0;
nscoord yOriginRow = 0;
nsRect rgRect = rgFrame->GetRect();
@@ -3330,12 +3430,13 @@ nscoord nsTableFrame::GetCellSpacingY()
nsTableFrame::GetBaseline() const
{
nscoord ascent = 0;
nsAutoVoidArray orderedRowGroups;
PRUint32 numRowGroups;
OrderRowGroups(orderedRowGroups, numRowGroups);
RowGroupArray orderedRowGroups;
OrderRowGroups(orderedRowGroups);
nsTableRowFrame* firstRow = nsnull;
for (PRUint32 rgIndex = 0; rgIndex < numRowGroups; rgIndex++) {
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgIndex));
for (PRUint32 rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
// XXXbz Do we really want to just let through the scrollable
// rowgroups and use their ascent?
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
if (rgFrame->GetRowCount()) {
firstRow = rgFrame->GetFirstRow();
ascent = rgFrame->GetRect().y + firstRow->GetRect().y + firstRow->GetRowBaseline();
@@ -3895,7 +3996,7 @@ private:
nsTableFrame& mTableFrame;
nsTableCellMap* mTableCellMap;
nsVoidArray mRowGroups;
nsTableFrame::RowGroupArray mRowGroups;
nsTableRowGroupFrame* mRowGroup;
PRInt32 mRowGroupIndex;
PRUint32 mNumRows;
@@ -3928,8 +4029,7 @@ BCMapCellIterator::BCMapCellIterator(nsTableFrame& aTableFrame,
mRowGroupIndex = -1;
// Get the ordered row groups
PRUint32 numRowGroups;
aTableFrame.OrderRowGroups(mRowGroups, numRowGroups);
aTableFrame.OrderRowGroups(mRowGroups);
mAtEnd = PR_TRUE; // gets reset when First() is called
}
@@ -4065,15 +4165,19 @@ BCMapCellIterator::SetNewRowGroup(PRBool aFindFirstDamagedRow)
{
mAtEnd = PR_TRUE;
mRowGroupIndex++;
PRInt32 numRowGroups = mRowGroups.Count();
PRInt32 numRowGroups = mRowGroups.Length();
mCellMap = nsnull;
for (PRInt32 rgX = mRowGroupIndex; rgX < numRowGroups; rgX++) {
nsIFrame* frame = (nsIFrame*)mRowGroups.ElementAt(mRowGroupIndex); if (!frame) ABORT1(PR_FALSE);
mRowGroup = mTableFrame.GetRowGroupFrame(frame); if (!mRowGroup) ABORT1(PR_FALSE);
// XXXbz do we really want the group at mRowGroupIndex? If so, what's the
// point of this rgX loop variable, exactly? Why not just do a while
// (mRowGroupIndex < numRowGroups) loop or something? I suspect this means
// to be getting the rowgroup at rgX.
mRowGroup = mRowGroups[mRowGroupIndex];
PRInt32 rowCount = mRowGroup->GetRowCount();
mRowGroupStart = mRowGroup->GetStartRowIndex();
mRowGroupEnd = mRowGroupStart + rowCount - 1;
if (rowCount > 0) {
if (rowCount > 0) { // XXXbz and if it's not we just keep looping? What's
// the point?
mCellMap = mTableCellMap->GetMapFor(mRowGroup, mCellMap);
if (!mCellMap) ABORT1(PR_FALSE);
nsTableRowFrame* firstRow = mRowGroup->GetFirstRow();
@@ -4084,7 +4188,8 @@ BCMapCellIterator::SetNewRowGroup(PRBool aFindFirstDamagedRow)
// find the correct first damaged row
PRInt32 numRows = mAreaStart.y - mRowGroupStart;
for (PRInt32 i = 0; i < numRows; i++) {
firstRow = firstRow->GetNextRow(); if (!frame) ABORT1(PR_FALSE);
firstRow = firstRow->GetNextRow();
if (!firstRow) ABORT1(PR_FALSE);
}
}
}
@@ -4199,8 +4304,7 @@ BCMapCellIterator::PeekBottom(BCMapCellInfo& aRefInfo,
PRInt32 nextRgIndex = mRowGroupIndex;
do {
nextRgIndex++;
nsIFrame* frame = (nsTableRowGroupFrame*)mRowGroups.ElementAt(nextRgIndex); if (!frame) ABORT0();
rg = mTableFrame.GetRowGroupFrame(frame);
rg = mRowGroups.SafeElementAt(nextRgIndex);
if (rg) {
cellMap = mTableCellMap->GetMapFor(rg, cellMap); if (!cellMap) ABORT0();
rgRowIndex = 0;
@@ -4803,15 +4907,13 @@ nsTableFrame::ExpandBCDamageArea(nsRect& aRect) const
if ((dStartX > 0) || (dEndX < (numCols - 1)) || (dStartY > 0) || (dEndY < (numRows - 1))) {
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT0();
// Get the ordered row groups
PRUint32 numRowGroups;
nsVoidArray rowGroups;
OrderRowGroups(rowGroups, numRowGroups);
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
// Scope outside loop to be used as hint.
nsCellMap* cellMap = nsnull;
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame); if (!rgFrame) ABORT0();
for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
PRInt32 rgStartY = rgFrame->GetStartRowIndex();
PRInt32 rgEndY = rgStartY + rgFrame->GetRowCount() - 1;
if (dEndY < rgStartY)
@@ -5532,7 +5634,7 @@ public:
nsTableCellMap* tableCellMap;
nsCellMap* cellMap;
nsVoidArray rowGroups;
nsTableFrame::RowGroupArray rowGroups;
nsTableRowGroupFrame* prevRg;
nsTableRowGroupFrame* rg;
PRInt32 rowGroupIndex;
@@ -5620,8 +5722,7 @@ BCMapBorderIterator::Reset(nsTableFrame& aTable,
bcData = nsnull;
// Get the ordered row groups
PRUint32 numRowGroups;
table->OrderRowGroups(rowGroups, numRowGroups);
table->OrderRowGroups(rowGroups);
}
void
@@ -5698,10 +5799,9 @@ BCMapBorderIterator::SetNewRowGroup()
isRepeatedHeader = PR_FALSE;
isRepeatedFooter = PR_FALSE;
if (rowGroupIndex < rowGroups.Count()) {
if (rowGroupIndex < rowGroups.Length()) {
prevRg = rg;
nsIFrame* frame = (nsTableRowGroupFrame*)rowGroups.ElementAt(rowGroupIndex); if (!frame) ABORT1(PR_FALSE);
rg = table->GetRowGroupFrame(frame); if (!rg) ABORT1(PR_FALSE);
rg = rowGroups[rowGroupIndex];
fifRowGroupStart = ((nsTableRowGroupFrame*)rg->GetFirstInFlow())->GetStartRowIndex();
rowGroupStart = rg->GetStartRowIndex();
rowGroupEnd = rowGroupStart + rg->GetRowCount() - 1;
@@ -5736,25 +5836,22 @@ BCMapBorderIterator::First()
atEnd = PR_FALSE;
PRUint32 numRowGroups = rowGroups.Count();
PRUint32 numRowGroups = rowGroups.Length();
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
nsIFrame* frame = (nsIFrame*)rowGroups.ElementAt(rgX);
nsTableRowGroupFrame* rowG = table->GetRowGroupFrame(frame);
if (rowG) {
PRInt32 start = rowG->GetStartRowIndex();
PRInt32 end = start + rowG->GetRowCount() - 1;
if ((startY >= start) && (startY <= end)) {
rowGroupIndex = rgX - 1; // SetNewRowGroup increments rowGroupIndex
if (SetNewRowGroup()) {
while ((y < startY) && !atEnd) {
SetNewRow();
}
if (!atEnd) {
SetNewData(startY, startX);
}
nsTableRowGroupFrame* rowG = rowGroups[rgX];
PRInt32 start = rowG->GetStartRowIndex();
PRInt32 end = start + rowG->GetRowCount() - 1;
if ((startY >= start) && (startY <= end)) {
rowGroupIndex = rgX - 1; // SetNewRowGroup increments rowGroupIndex
if (SetNewRowGroup()) {
while ((y < startY) && !atEnd) {
SetNewRow();
}
if (!atEnd) {
SetNewData(startY, startX);
}
return;
}
return;
}
}
atEnd = PR_TRUE;
@@ -6031,9 +6128,8 @@ nsTableFrame::PaintBCBorders(nsIRenderingContext& aRenderingContext,
PRUint32 startRowIndex, endRowIndex, startColIndex, endColIndex;
startRowIndex = endRowIndex = startColIndex = endColIndex = 0;
nsAutoVoidArray rowGroups;
PRUint32 numRowGroups;
OrderRowGroups(rowGroups, numRowGroups);
RowGroupArray rowGroups;
OrderRowGroups(rowGroups);
PRBool done = PR_FALSE;
PRBool haveIntersect = PR_FALSE;
nsTableRowGroupFrame* inFlowRG = nsnull;
@@ -6041,10 +6137,10 @@ nsTableFrame::PaintBCBorders(nsIRenderingContext& aRenderingContext,
// find startRowIndex, endRowIndex, startRowY
nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
PRInt32 rowY = startRowY;
for (PRUint32 rgX = 0; (rgX < numRowGroups) && !done; rgX++) {
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame); if (!rgFrame) ABORT0();
for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
for (PRUint32 rgX = 0; rgX < rowGroups.Length() && !done; rgX++) {
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); rowFrame;
rowFrame = rowFrame->GetNextRow()) {
// conservatively estimate the half border widths outside the row
nscoord topBorderHalf = (GetPrevInFlow()) ? 0 : nsPresContext::CSSPixelsToAppUnits(rowFrame->GetTopBCBorderWidth() + 1);
nscoord bottomBorderHalf = (GetNextInFlow()) ? 0 : nsPresContext::CSSPixelsToAppUnits(rowFrame->GetBottomBCBorderWidth() + 1);

View File

@@ -558,16 +558,43 @@ protected:
* frame at aPushFrom to the end of the array. The frames are put on our overflow
* list or moved directly to our next-in-flow if one exists.
*/
void PushChildren(const nsAutoVoidArray& aFrames, PRInt32 aPushFrom);
typedef nsAutoTPtrArray<nsIFrame, 8> FrameArray;
void PushChildren(const FrameArray& aFrames, PRInt32 aPushFrom);
public:
// put the children frames in the display order (e.g. thead before tbody before tfoot)
// and put the non row group frames at the end. Also return the number of row group frames.
void OrderRowGroups(nsVoidArray& aChildren,
PRUint32& aNumRowGroups,
nsTableRowGroupFrame** aHead = nsnull,
nsTableRowGroupFrame** aFoot = nsnull) const;
// put the children frames in the display order (e.g. thead before tbodies
// before tfoot). This will handle calling GetRowGroupFrame() on the
// children, and not append nulls, so the array is guaranteed to contain
// nsTableRowGroupFrames. If there are multiple theads or tfoots, all but
// the first one are treated as tbodies instead.
typedef nsAutoTPtrArray<nsTableRowGroupFrame, 8> RowGroupArray;
void OrderRowGroups(RowGroupArray& aChildren) const;
// Return the thead, if any
nsTableRowGroupFrame* GetTHead() const;
// Return the tfoot, if any
nsTableRowGroupFrame* GetTFoot() const;
protected:
// As above, but does NOT actually call GetRowGroupFrame() on the kids, so
// returns an array of nsIFrames. This is to be used when you really want
// the flowable kids of the table, not the rowgroups. This outputs the thead
// and tfoot if they happen to be rowgroups. All the child nsIFrames of the
// table that return null if you call GetRowGroupFrame() on them will appear
// at the end of the array, after the tfoot, if any.
//
// aHead and aFoot must not be null.
//
// @return the number of frames in aChildren which return non-null if you
// call GetRowGroupFrame() on them.
//
// XXXbz why do we really care about the non-rowgroup kids?
PRUint32 OrderRowGroups(FrameArray& aChildren,
nsTableRowGroupFrame** aHead,
nsTableRowGroupFrame** aFoot) const;
public:
// Returns PR_TRUE if there are any cells above the row at
// aRowIndex and spanning into the row at aRowIndex, the number of
// effective columns limits the search up to that column

View File

@@ -352,19 +352,16 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
{
NS_PRECONDITION(aTableFrame, "null table frame");
nsVoidArray rowGroups;
PRUint32 numRowGroups;
aTableFrame->OrderRowGroups(rowGroups, numRowGroups);
nsTableFrame::RowGroupArray rowGroups;
aTableFrame->OrderRowGroups(rowGroups);
if (numRowGroups < 1) { //degenerate case
PaintTableFrame(aTableFrame,nsnull, nsnull, nsnull);
if (rowGroups.Length() < 1) { //degenerate case
PaintTableFrame(aTableFrame, nsnull, nsnull, nsnull);
/* No cells; nothing else to paint */
return NS_OK;
}
PaintTableFrame(aTableFrame,
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(0))),
aTableFrame->GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(numRowGroups - 1))),
PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1],
aDeflate);
/*Set up column background/border data*/
@@ -438,8 +435,8 @@ TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
}
}
for (PRUint32 i = 0; i < numRowGroups; i++) {
nsTableRowGroupFrame* rg = nsTableFrame::GetRowGroupFrame(NS_STATIC_CAST(nsIFrame*, rowGroups.ElementAt(i)));
for (PRUint32 i = 0; i < rowGroups.Length(); i++) {
nsTableRowGroupFrame* rg = rowGroups[i];
mRowGroup.SetFrame(rg);
// Need to compute the right rect via GetOffsetTo, since the row
// group may not be a child of the table.