зеркало из 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*
|
static nsCellMap*
|
||||||
nsTableCellMap::GetMapFor(nsTableRowGroupFrame& aRowGroup)
|
FindMapFor(const nsTableRowGroupFrame* aRowGroup,
|
||||||
|
nsCellMap* aStart,
|
||||||
|
const nsCellMap* aEnd)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(!aRowGroup.GetPrevInFlow(), "GetMapFor called with continuation");
|
for (nsCellMap* map = aStart; map != aEnd; map = map->GetNextSibling()) {
|
||||||
for (nsCellMap* map = mFirstMap; map; map = map->GetNextSibling()) {
|
if (aRowGroup == map->GetRowGroup()) {
|
||||||
if (&aRowGroup == map->GetRowGroup()) {
|
|
||||||
return map;
|
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 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());
|
nsTableFrame* fifTable = NS_STATIC_CAST(nsTableFrame*, mTableFrame.GetFirstInFlow());
|
||||||
|
|
||||||
nsAutoVoidArray rowGroups;
|
nsAutoVoidArray rowGroups;
|
||||||
|
@ -280,16 +303,12 @@ nsTableCellMap::GetMapFor(nsTableRowGroupFrame& aRowGroup)
|
||||||
// find the original header/footer
|
// find the original header/footer
|
||||||
fifTable->OrderRowGroups(rowGroups, numRowGroups, &thead, &tfoot);
|
fifTable->OrderRowGroups(rowGroups, numRowGroups, &thead, &tfoot);
|
||||||
|
|
||||||
const nsStyleDisplay* display = aRowGroup.GetStyleDisplay();
|
const nsStyleDisplay* display = aRowGroup->GetStyleDisplay();
|
||||||
nsTableRowGroupFrame* rgOrig =
|
nsTableRowGroupFrame* rgOrig =
|
||||||
(NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay) ? thead : tfoot;
|
(NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay) ? thead : tfoot;
|
||||||
// find the row group cell map using the original header/footer
|
// find the row group cell map using the original header/footer
|
||||||
if (rgOrig) {
|
if (rgOrig && rgOrig != aRowGroup) {
|
||||||
for (nsCellMap* map = mFirstMap; map; map = map->GetNextSibling()) {
|
return GetMapFor(rgOrig, aStartHint);
|
||||||
if (rgOrig == map->GetRowGroup()) {
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,11 +329,13 @@ nsTableCellMap::Synchronize(nsTableFrame* aTableFrame)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scope |map| outside the loop so we can use it as a hint.
|
||||||
|
nsCellMap* map = nsnull;
|
||||||
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
||||||
nsTableRowGroupFrame* rgFrame =
|
nsTableRowGroupFrame* rgFrame =
|
||||||
nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
|
nsTableFrame::GetRowGroupFrame((nsIFrame*)orderedRowGroups.ElementAt(rgX));
|
||||||
if (rgFrame) {
|
if (rgFrame) {
|
||||||
nsCellMap* map = GetMapFor(*rgFrame);
|
map = GetMapFor(rgFrame, map);
|
||||||
if (map) {
|
if (map) {
|
||||||
if (!maps.AppendElement(map)) {
|
if (!maps.AppendElement(map)) {
|
||||||
delete map;
|
delete map;
|
||||||
|
|
|
@ -94,7 +94,16 @@ public:
|
||||||
void InsertGroupCellMap(nsTableRowGroupFrame& aNewRowGroup,
|
void InsertGroupCellMap(nsTableRowGroupFrame& aNewRowGroup,
|
||||||
nsTableRowGroupFrame*& aPrevRowGroup);
|
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 **/
|
/** synchronize the cellmaps with the rowgroups again **/
|
||||||
void Synchronize(nsTableFrame* aTableFrame);
|
void Synchronize(nsTableFrame* aTableFrame);
|
||||||
|
|
|
@ -4172,14 +4172,16 @@ BCMapCellIterator::SetNewRowGroup(PRBool aFindFirstDamagedRow)
|
||||||
mAtEnd = PR_TRUE;
|
mAtEnd = PR_TRUE;
|
||||||
mRowGroupIndex++;
|
mRowGroupIndex++;
|
||||||
PRInt32 numRowGroups = mRowGroups.Count();
|
PRInt32 numRowGroups = mRowGroups.Count();
|
||||||
|
mCellMap = nsnull;
|
||||||
for (PRInt32 rgX = mRowGroupIndex; rgX < numRowGroups; rgX++) {
|
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);
|
mRowGroup = mTableFrame.GetRowGroupFrame(frame); if (!mRowGroup) ABORT1(PR_FALSE);
|
||||||
PRInt32 rowCount = mRowGroup->GetRowCount();
|
PRInt32 rowCount = mRowGroup->GetRowCount();
|
||||||
mRowGroupStart = mRowGroup->GetStartRowIndex();
|
mRowGroupStart = mRowGroup->GetStartRowIndex();
|
||||||
mRowGroupEnd = mRowGroupStart + rowCount - 1;
|
mRowGroupEnd = mRowGroupStart + rowCount - 1;
|
||||||
if (rowCount > 0) {
|
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();
|
nsTableRowFrame* firstRow = mRowGroup->GetFirstRow();
|
||||||
if (aFindFirstDamagedRow) {
|
if (aFindFirstDamagedRow) {
|
||||||
if ((mAreaStart.y >= mRowGroupStart) && (mAreaStart.y <= mRowGroupEnd)) {
|
if ((mAreaStart.y >= mRowGroupStart) && (mAreaStart.y <= mRowGroupEnd)) {
|
||||||
|
@ -4306,7 +4308,7 @@ BCMapCellIterator::PeekBottom(BCMapCellInfo& aRefInfo,
|
||||||
nsIFrame* frame = (nsTableRowGroupFrame*)mRowGroups.ElementAt(nextRgIndex); if (!frame) ABORT0();
|
nsIFrame* frame = (nsTableRowGroupFrame*)mRowGroups.ElementAt(nextRgIndex); if (!frame) ABORT0();
|
||||||
rg = mTableFrame.GetRowGroupFrame(frame);
|
rg = mTableFrame.GetRowGroupFrame(frame);
|
||||||
if (rg) {
|
if (rg) {
|
||||||
cellMap = mTableCellMap->GetMapFor(*rg); if (!cellMap) ABORT0();
|
cellMap = mTableCellMap->GetMapFor(rg, cellMap); if (!cellMap) ABORT0();
|
||||||
rgRowIndex = 0;
|
rgRowIndex = 0;
|
||||||
nextRow = rg->GetFirstRow();
|
nextRow = rg->GetFirstRow();
|
||||||
}
|
}
|
||||||
|
@ -4917,6 +4919,9 @@ nsTableFrame::ExpandBCDamageArea(nsRect& aRect) const
|
||||||
PRUint32 numRowGroups;
|
PRUint32 numRowGroups;
|
||||||
nsVoidArray rowGroups;
|
nsVoidArray rowGroups;
|
||||||
OrderRowGroups(rowGroups, numRowGroups);
|
OrderRowGroups(rowGroups, numRowGroups);
|
||||||
|
|
||||||
|
// Scope outside loop to be used as hint.
|
||||||
|
nsCellMap* cellMap = nsnull;
|
||||||
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
||||||
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);
|
nsIFrame* kidFrame = (nsIFrame*)rowGroups.ElementAt(rgX);
|
||||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame); if (!rgFrame) ABORT0();
|
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame(kidFrame); if (!rgFrame) ABORT0();
|
||||||
|
@ -4924,7 +4929,8 @@ nsTableFrame::ExpandBCDamageArea(nsRect& aRect) const
|
||||||
PRInt32 rgEndY = rgStartY + rgFrame->GetRowCount() - 1;
|
PRInt32 rgEndY = rgStartY + rgFrame->GetRowCount() - 1;
|
||||||
if (dEndY < rgStartY)
|
if (dEndY < rgStartY)
|
||||||
break;
|
break;
|
||||||
nsCellMap* cellMap = tableCellMap->GetMapFor(*rgFrame); if (!cellMap) ABORT0();
|
cellMap = tableCellMap->GetMapFor(rgFrame, cellMap);
|
||||||
|
if (!cellMap) ABORT0();
|
||||||
// check for spanners from above and below
|
// check for spanners from above and below
|
||||||
if ((dStartY > 0) && (dStartY >= rgStartY) && (dStartY <= rgEndY)) {
|
if ((dStartY > 0) && (dStartY >= rgStartY) && (dStartY <= rgEndY)) {
|
||||||
if (PRUint32(dStartY - rgStartY) >= cellMap->mRows.Length())
|
if (PRUint32(dStartY - rgStartY) >= cellMap->mRows.Length())
|
||||||
|
@ -5815,7 +5821,10 @@ BCMapBorderIterator::SetNewRowGroup()
|
||||||
rowGroupEnd = rowGroupStart + rg->GetRowCount() - 1;
|
rowGroupEnd = rowGroupStart + rg->GetRowCount() - 1;
|
||||||
|
|
||||||
if (SetNewRow(rg->GetFirstRow())) {
|
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 && table->GetPrevInFlow() && !rg->GetPrevInFlow()) {
|
||||||
// if rg doesn't have a prev in flow, then it may be a repeated header or footer
|
// if rg doesn't have a prev in flow, then it may be a repeated header or footer
|
||||||
|
|
Загрузка…
Ссылка в новой задаче