Bug 683952. Speed up iterating over the continuations of the frame when scrolling to it. r=roc

This commit is contained in:
Boris Zbarsky 2011-09-06 22:57:46 -04:00
parent 8da3fa5aad
commit 73e9ae8488
6 changed files with 44 additions and 18 deletions

View File

@ -4044,13 +4044,19 @@ PresShell::ScrollToAnchor()
* we should include the top of the line in the added rectangle
* @param aRect [inout] rect into which its bounds should be unioned
* @param aHaveRect [inout] whether aRect contains data yet
* @param aPrevBlock [inout] the block aLines is a line iterator for
* @param aLines [inout] the line iterator we're using
* @param aCurLine [inout] the line to start looking from in this iterator
*/
static void
AccumulateFrameBounds(nsIFrame* aContainerFrame,
nsIFrame* aFrame,
PRBool aUseWholeLineHeightForInlines,
nsRect& aRect,
PRBool& aHaveRect)
PRBool& aHaveRect,
nsIFrame*& aPrevBlock,
nsAutoLineIterator& aLines,
PRInt32& aCurLine)
{
nsRect frameBounds = aFrame->GetRect() +
aFrame->GetParent()->GetOffsetTo(aContainerFrame);
@ -4073,17 +4079,22 @@ AccumulateFrameBounds(nsIFrame* aContainerFrame,
f &&
frameType == nsGkAtoms::blockFrame) {
// find the line containing aFrame and increase the top of |offset|.
nsAutoLineIterator lines = f->GetLineIterator();
if (lines) {
PRInt32 index = lines->FindLineContaining(prevFrame);
if (f != aPrevBlock) {
aLines = f->GetLineIterator();
aPrevBlock = f;
aCurLine = 0;
}
if (aLines) {
PRInt32 index = aLines->FindLineContaining(prevFrame, aCurLine);
if (index >= 0) {
aCurLine = index;
nsIFrame *trash1;
PRInt32 trash2;
nsRect lineBounds;
PRUint32 trash3;
if (NS_SUCCEEDED(lines->GetLine(index, &trash1, &trash2,
lineBounds, &trash3))) {
if (NS_SUCCEEDED(aLines->GetLine(index, &trash1, &trash2,
lineBounds, &trash3))) {
lineBounds += f->GetOffsetTo(aContainerFrame);
if (lineBounds.y < frameBounds.y) {
frameBounds.height = frameBounds.YMost() - lineBounds.y;
@ -4286,9 +4297,16 @@ PresShell::DoScrollContentIntoView(nsIContent* aContent,
nsRect frameBounds;
PRBool haveRect = PR_FALSE;
PRBool useWholeLineHeightForInlines = aVPercent != NS_PRESSHELL_SCROLL_ANYWHERE;
// Reuse the same line iterator across calls to AccumulateFrameBounds. We set
// it every time we detect a new block (stored in prevBlock).
nsIFrame* prevBlock = nsnull;
nsAutoLineIterator lines;
// The last line we found a continuation on in |lines|. We assume that later
// continuations cannot come on earlier lines.
PRInt32 curLine = 0;
do {
AccumulateFrameBounds(container, frame, useWholeLineHeightForInlines,
frameBounds, haveRect);
frameBounds, haveRect, prevBlock, lines, curLine);
} while ((frame = frame->GetNextContinuation()));
ScrollFrameRectIntoView(container, frameBounds, aVPercent, aHPercent,

View File

@ -104,9 +104,12 @@ public:
/**
* Given a frame that's a child of the block, find which line its on
* and return that line index. Returns -1 if the frame cannot be found.
* and return that line index, as long as it's at least as big as
* aStartLine. Returns -1 if the frame cannot be found on lines
* starting with aStartLine.
*/
virtual PRInt32 FindLineContaining(nsIFrame* aFrame) = 0;
virtual PRInt32 FindLineContaining(nsIFrame* aFrame,
PRInt32 aStartLine = 0) = 0;
// Given a line number and an X coordinate, find the frame on the
// line that is nearest to the X coordinate. The

View File

@ -626,15 +626,16 @@ nsLineIterator::GetLine(PRInt32 aLineNumber,
}
PRInt32
nsLineIterator::FindLineContaining(nsIFrame* aFrame)
nsLineIterator::FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine)
{
nsLineBox* line = mLines[0];
PRInt32 lineNumber = 0;
NS_PRECONDITION(aStartLine <= mNumLines, "Bogus line numbers");
PRInt32 lineNumber = aStartLine;
while (lineNumber != mNumLines) {
nsLineBox* line = mLines[lineNumber];
if (line->Contains(aFrame)) {
return lineNumber;
}
line = mLines[++lineNumber];
++lineNumber;
}
return -1;
}

View File

@ -1581,7 +1581,7 @@ public:
PRInt32* aNumFramesOnLine,
nsRect& aLineBounds,
PRUint32* aLineFlags);
virtual PRInt32 FindLineContaining(nsIFrame* aFrame);
virtual PRInt32 FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine = 0);
NS_IMETHOD FindFrameAt(PRInt32 aLineNumber,
nscoord aX,
nsIFrame** aFrameFound,

View File

@ -1706,14 +1706,16 @@ nsTableRowGroupFrame::GetLine(PRInt32 aLineNumber,
}
PRInt32
nsTableRowGroupFrame::FindLineContaining(nsIFrame* aFrame)
nsTableRowGroupFrame::FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine)
{
NS_ENSURE_ARG_POINTER(aFrame);
nsTableRowFrame *rowFrame = do_QueryFrame(aFrame);
NS_ASSERTION(rowFrame, "RowGroup contains a frame that is not a row");
return rowFrame->GetRowIndex() - GetStartRowIndex();
PRInt32 rowIndexInGroup = rowFrame->GetRowIndex() - GetStartRowIndex();
return rowIndexInGroup >= aStartLine ? rowIndexInGroup : -1;
}
#ifdef IBMBIDI

View File

@ -258,10 +258,12 @@ public:
/** Given a frame that's a child of the rowgroup, find which line its on.
* @param aFrame - frame, should be a row
* @param aStartLine - minimal index to return
* @return row index relative to the row group if this a row
* frame. -1 if the frame cannot be found.
* frame and the index is at least aStartLine.
* -1 if the frame cannot be found.
*/
virtual PRInt32 FindLineContaining(nsIFrame* aFrame);
virtual PRInt32 FindLineContaining(nsIFrame* aFrame, PRInt32 aStartLine = 0);
/** Find the orginating cell frame on a row that is the nearest to the
* coordinate X.