Bug 1235321 - Enable using line cursor to optimize reflowing absolute frames. r=bz
MozReview-Commit-ID: 4tVq5S4eTtS
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1391,20 +1391,26 @@ nsBlockFrame::Reflow(nsPresContext*
containingBlockSize.GetPhysicalSize(parentWM));
AbsPosReflowFlags flags = AbsPosReflowFlags::eConstrainHeight;
if (cbWidthChanged) {
flags |= AbsPosReflowFlags::eCBWidthChanged;
}
if (cbHeightChanged) {
flags |= AbsPosReflowFlags::eCBHeightChanged;
}
+ // Setup the line cursor here to optimize line searching for
+ // calculating hypothetical position of absolutely-positioned
+ // frames. The line cursor is immediately cleared afterward to
+ // avoid affecting the display list generation.
+ SetupLineCursor();
absoluteContainer->Reflow(this, aPresContext, *reflowState,
state.mReflowStatus,
containingBlock, flags,
&aMetrics.mOverflowAreas);
+ ClearLineCursor();
}
}
FinishAndStoreOverflow(&aMetrics);
// Clear the float manager pointer in the block reflow state so we
// don't waste time translating the coordinate system back on a dead
// float manager.
@@ -5486,65 +5492,69 @@ nsBlockInFlowLineIterator::nsBlockInFlow
: mFrame(aFrame), mLineList(&aFrame->mLines)
{
*aFoundValidLine = false;
nsIFrame* child = FindChildContaining(aFrame, aFindFrame);
if (!child)
return;
+ line_iterator line_end = aFrame->end_lines();
// Try to use the cursor if it exists, otherwise fall back to the first line
- nsLineBox* cursor = aFrame->GetLineCursor();
- if (!cursor) {
- line_iterator iter = aFrame->begin_lines();
- if (iter != aFrame->end_lines()) {
- cursor = iter;
- }
- }
-
- if (cursor) {
+ if (nsLineBox* const cursor = aFrame->GetLineCursor()) {
+ mLine = line_end;
// Perform a simultaneous forward and reverse search starting from the
// line cursor.
nsBlockFrame::line_iterator line = aFrame->line(cursor);
nsBlockFrame::reverse_line_iterator rline = aFrame->rline(cursor);
- nsBlockFrame::line_iterator line_end = aFrame->end_lines();
nsBlockFrame::reverse_line_iterator rline_end = aFrame->rend_lines();
// rline is positioned on the line containing 'cursor', so it's not
// rline_end. So we can safely increment it (i.e. move it to one line
// earlier) to start searching there.
++rline;
while (line != line_end || rline != rline_end) {
if (line != line_end) {
if (line->Contains(child)) {
- *aFoundValidLine = true;
mLine = line;
- return;
+ break;
}
++line;
}
if (rline != rline_end) {
if (rline->Contains(child)) {
- *aFoundValidLine = true;
mLine = rline;
- return;
+ break;
}
++rline;
}
}
- // Didn't find the line
- }
+ if (mLine != line_end) {
+ *aFoundValidLine = true;
+ if (mLine != cursor) {
+ aFrame->Properties().Set(nsBlockFrame::LineCursorProperty(), mLine);
+ }
+ return;
+ }
+ } else {
+ for (mLine = aFrame->begin_lines(); mLine != line_end; ++mLine) {
+ if (mLine->Contains(child)) {
+ *aFoundValidLine = true;
+ return;
+ }
+ }
+ }
+ // Didn't find the line
+ MOZ_ASSERT(mLine == line_end, "mLine should be line_end at this point");
// If we reach here, it means that we have not been able to find the
// desired frame in our in-flow lines. So we should start looking at
// our overflow lines. In order to do that, we set mLine to the end
// iterator so that FindValidLine starts to look at overflow lines,
// if any.
- mLine = aFrame->end_lines();
-
if (!FindValidLine())
return;
do {
if (mLine->Contains(child)) {
*aFoundValidLine = true;
return;
}
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -167,18 +167,19 @@ public:
void ClearLineCursor();
// Get the first line that might contain y-coord 'y', or nullptr if you must search
// all lines. If nonnull is returned then we guarantee that the lines'
// combinedArea.ys and combinedArea.yMosts are non-decreasing.
// The actual line returned might not contain 'y', but if not, it is guaranteed
// to be before any line which does contain 'y'.
nsLineBox* GetFirstLineContaining(nscoord y);
// Set the line cursor to our first line. Only call this if you
- // guarantee that the lines' combinedArea.ys and combinedArea.yMosts
- // are non-decreasing.
+ // guarantee that either the lines' combinedArea.ys and combinedArea.
+ // yMosts are non-decreasing, or the line cursor is cleared before
+ // building the display list of this frame.
void SetupLineCursor();
virtual void ChildIsDirty(nsIFrame* aChild) override;
virtual bool IsVisibleInSelection(nsISelection* aSelection) override;
virtual bool IsEmpty() override;
virtual bool CachedIsEmpty() override;
virtual bool IsSelfEmpty() override;