зеркало из https://github.com/mozilla/gecko-dev.git
Make it possible for callers who want to iterate all the row groups and
GetMapFor() for all of them do so in about O(N) time instead of O(N^2) (in number of row groups). Bug 366892, r=bernd, sr=roc
This commit is contained in:
Родитель
8318e48ec4
Коммит
ed9ad7b7bf
|
@ -261,17 +261,40 @@ void nsTableCellMap::RemoveGroupCellMap(nsTableRowGroupFrame* aGroup)
|
|||
}
|
||||
}
|
||||
|
||||
nsCellMap*
|
||||
nsTableCellMap::GetMapFor(nsTableRowGroupFrame& aRowGroup)
|
||||
static nsCellMap*
|
||||
FindMapFor(const nsTableRowGroupFrame* aRowGroup,
|
||||
nsCellMap* aStart,
|
||||
const nsCellMap* aEnd)
|
||||
{
|
||||
NS_ASSERTION(!aRowGroup.GetPrevInFlow(), "GetMapFor called with continuation");
|
||||
for (nsCellMap* map = mFirstMap; map; map = map->GetNextSibling()) {
|
||||
if (&aRowGroup == map->GetRowGroup()) {
|
||||
for (nsCellMap* map = aStart; map != aEnd; map = map->GetNextSibling()) {
|
||||
if (aRowGroup == map->GetRowGroup()) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCellMap*
|
||||
nsTableCellMap::GetMapFor(const nsTableRowGroupFrame* aRowGroup,
|
||||
nsCellMap* aStartHint) const
|
||||
{
|
||||
NS_PRECONDITION(aRowGroup, "Must have a rowgroup");
|
||||
NS_ASSERTION(!aRowGroup->GetPrevInFlow(), "GetMapFor called with continuation");
|
||||
if (aStartHint) {
|
||||
nsCellMap* map = FindMapFor(aRowGroup, aStartHint, nsnull);
|
||||
if (map) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
nsCellMap* map = FindMapFor(aRowGroup, mFirstMap, aStartHint);
|
||||
if (map) {
|
||||
return map;
|
||||
}
|
||||
|
||||
// if aRowGroup is a repeated header or footer find the header or footer it was repeated from
|
||||
if (aRowGroup.IsRepeatable()) {
|
||||
if (aRowGroup->IsRepeatable()) {
|
||||
nsTableFrame* fifTable = NS_STATIC_CAST(nsTableFrame*, mTableFrame.GetFirstInFlow());
|
||||
|
||||
nsAutoVoidArray rowGroups;
|
||||
|
@ -280,16 +303,12 @@ nsTableCellMap::GetMapFor(nsTableRowGroupFrame& aRowGroup)
|
|||
// find the original header/footer
|
||||
fifTable->OrderRowGroups(rowGroups, numRowGroups, &thead, &tfoot);
|
||||
|
||||
const nsStyleDisplay* display = aRowGroup.GetStyleDisplay();
|
||||
const nsStyleDisplay* display = aRowGroup->GetStyleDisplay();
|
||||
nsTableRowGroupFrame* rgOrig =
|
||||
(NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay) ? thead : tfoot;
|
||||
// find the row group cell map using the original header/footer
|
||||
if (rgOrig) {
|
||||
for (nsCellMap* map = mFirstMap; map; map = map->GetNextSibling()) {
|
||||
if (rgOrig == map->GetRowGroup()) {
|
||||
return map;
|
||||
}
|
||||
}
|
||||
if (rgOrig && rgOrig != aRowGroup) {
|
||||
return GetMapFor(rgOrig, aStartHint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,11 +329,13 @@ nsTableCellMap::Synchronize(nsTableFrame* aTableFrame)
|
|||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
nsCellMap* map = GetMapFor(*rgFrame);
|
||||
map = GetMapFor(rgFrame, map);
|
||||
if (map) {
|
||||
if (!maps.AppendElement(map)) {
|
||||
delete map;
|
||||
|
|
|
@ -94,7 +94,16 @@ public:
|
|||
void InsertGroupCellMap(nsTableRowGroupFrame& aNewRowGroup,
|
||||
nsTableRowGroupFrame*& aPrevRowGroup);
|
||||
|
||||
nsCellMap* GetMapFor(nsTableRowGroupFrame& aRowGroup);
|
||||
/**
|
||||
* Get the nsCellMap for the given row group. If aStartHint is non-null,
|
||||
* will start looking with that cellmap and only fall back to starting at the
|
||||
* beginning of the list if that doesn't find us the right nsCellMap.
|
||||
* Otherwise, just start at the beginning.
|
||||
*
|
||||
* aRowGroup must not be null.
|
||||
*/
|
||||
nsCellMap* GetMapFor(const nsTableRowGroupFrame* aRowGroup,
|
||||
nsCellMap* aStartHint) const;
|
||||
|
||||
/** synchronize the cellmaps with the rowgroups again **/
|
||||
void Synchronize(nsTableFrame* aTableFrame);
|
||||
|
|
|
@ -4172,14 +4172,16 @@ BCMapCellIterator::SetNewRowGroup(PRBool aFindFirstDamagedRow)
|
|||
mAtEnd = PR_TRUE;
|
||||
mRowGroupIndex++;
|
||||
PRInt32 numRowGroups = mRowGroups.Count();
|
||||
mCellMap = nsnull;
|
||||
for (PRInt32 rgX = mRowGroupIndex; rgX < numRowGroups; rgX++) {
|
||||
nsIFrame* frame = (nsTableRowGroupFrame*)mRowGroups.ElementAt(mRowGroupIndex); if (!frame) ABORT1(PR_FALSE);
|
||||
nsIFrame* frame = (nsIFrame*)mRowGroups.ElementAt(mRowGroupIndex); if (!frame) ABORT1(PR_FALSE);
|
||||
mRowGroup = mTableFrame.GetRowGroupFrame(frame); if (!mRowGroup) ABORT1(PR_FALSE);
|
||||
PRInt32 rowCount = mRowGroup->GetRowCount();
|
||||
mRowGroupStart = mRowGroup->GetStartRowIndex();
|
||||
mRowGroupEnd = mRowGroupStart + rowCount - 1;
|
||||
if (rowCount > 0) {
|
||||
mCellMap = mTableCellMap->GetMapFor(*mRowGroup); if (!mCellMap) ABORT1(PR_FALSE);
|
||||
mCellMap = mTableCellMap->GetMapFor(mRowGroup, mCellMap);
|
||||
if (!mCellMap) ABORT1(PR_FALSE);
|
||||
nsTableRowFrame* firstRow = mRowGroup->GetFirstRow();
|
||||
if (aFindFirstDamagedRow) {
|
||||
if ((mAreaStart.y >= mRowGroupStart) && (mAreaStart.y <= mRowGroupEnd)) {
|
||||
|
@ -4306,7 +4308,7 @@ BCMapCellIterator::PeekBottom(BCMapCellInfo& aRefInfo,
|
|||
nsIFrame* frame = (nsTableRowGroupFrame*)mRowGroups.ElementAt(nextRgIndex); if (!frame) ABORT0();
|
||||
rg = mTableFrame.GetRowGroupFrame(frame);
|
||||
if (rg) {
|
||||
cellMap = mTableCellMap->GetMapFor(*rg); if (!cellMap) ABORT0();
|
||||
cellMap = mTableCellMap->GetMapFor(rg, cellMap); if (!cellMap) ABORT0();
|
||||
rgRowIndex = 0;
|
||||
nextRow = rg->GetFirstRow();
|
||||
}
|
||||
|
@ -4917,6 +4919,9 @@ nsTableFrame::ExpandBCDamageArea(nsRect& aRect) const
|
|||
PRUint32 numRowGroups;
|
||||
nsVoidArray rowGroups;
|
||||
OrderRowGroups(rowGroups, numRowGroups);
|
||||
|
||||
// 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();
|
||||
|
@ -4924,7 +4929,8 @@ nsTableFrame::ExpandBCDamageArea(nsRect& aRect) const
|
|||
PRInt32 rgEndY = rgStartY + rgFrame->GetRowCount() - 1;
|
||||
if (dEndY < rgStartY)
|
||||
break;
|
||||
nsCellMap* cellMap = tableCellMap->GetMapFor(*rgFrame); if (!cellMap) ABORT0();
|
||||
cellMap = tableCellMap->GetMapFor(rgFrame, cellMap);
|
||||
if (!cellMap) ABORT0();
|
||||
// check for spanners from above and below
|
||||
if ((dStartY > 0) && (dStartY >= rgStartY) && (dStartY <= rgEndY)) {
|
||||
if (PRUint32(dStartY - rgStartY) >= cellMap->mRows.Length())
|
||||
|
@ -5815,7 +5821,10 @@ BCMapBorderIterator::SetNewRowGroup()
|
|||
rowGroupEnd = rowGroupStart + rg->GetRowCount() - 1;
|
||||
|
||||
if (SetNewRow(rg->GetFirstRow())) {
|
||||
cellMap = tableCellMap->GetMapFor(*(nsTableRowGroupFrame*)rg->GetFirstInFlow()); if (!cellMap) ABORT1(PR_FALSE);
|
||||
cellMap =
|
||||
tableCellMap->GetMapFor((nsTableRowGroupFrame*)rg->GetFirstInFlow(),
|
||||
nsnull);
|
||||
if (!cellMap) ABORT1(PR_FALSE);
|
||||
}
|
||||
if (rg && table->GetPrevInFlow() && !rg->GetPrevInFlow()) {
|
||||
// if rg doesn't have a prev in flow, then it may be a repeated header or footer
|
||||
|
|
Загрузка…
Ссылка в новой задаче