Bug 1304556 part 1 - Add AutoLineCursorSetup RAII class for local line cursor setup. r=dbaron
MozReview-Commit-ID: G5xeCkxsm8N
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1405,22 +1405,21 @@ nsBlockFrame::Reflow(nsPresContext*
}
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();
+ AutoLineCursorSetup autoLineCursor(this);
absoluteContainer->Reflow(this, aPresContext, *reflowInput,
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.
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -148,18 +148,22 @@ public:
virtual nsFrameState GetDebugStateBits() const override;
const char* LineReflowStatusToString(LineReflowStatus aLineReflowStatus) const;
#endif
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
- // line cursor methods to speed up searching for the line(s)
- // containing a point. The basic idea is that we set the cursor
+ // Line cursor methods to speed up line searching in which one query
+ // result is expected to be close to the next in general. This is
+ // mainly for searching line(s) containing a point. It is also used
+ // as a cache for local computation. Use AutoLineCursorSetup for the
+ // latter case so that it wouldn't interact unexpectedly with the
+ // former. The basic idea for the former is that we set the cursor
// property if the lines' overflowArea.VisualOverflow().ys and
// overflowArea.VisualOverflow().yMosts are non-decreasing
// (considering only non-empty overflowArea.VisualOverflow()s; empty
// overflowArea.VisualOverflow()s never participate in event handling
// or painting), and the block has sufficient number of lines. The
// cursor property points to a "recently used" line. If we get a
// series of requests that work on lines
// "near" the cursor, then we can find those nearby lines quickly by
@@ -174,16 +178,46 @@ public:
// 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 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();
+ /**
+ * Helper RAII class for automatically set and clear line cursor for
+ * temporary use. If the frame already has line cursor, this would be
+ * a no-op.
+ */
+ class MOZ_STACK_CLASS AutoLineCursorSetup
+ {
+ public:
+ explicit AutoLineCursorSetup(nsBlockFrame* aFrame)
+ : mFrame(aFrame)
+ , mOrigCursor(aFrame->GetLineCursor())
+ {
+ if (!mOrigCursor) {
+ mFrame->SetupLineCursor();
+ }
+ }
+ ~AutoLineCursorSetup()
+ {
+ if (mOrigCursor) {
+ mFrame->Properties().Set(LineCursorProperty(), mOrigCursor);
+ } else {
+ mFrame->ClearLineCursor();
+ }
+ }
+
+ private:
+ nsBlockFrame* mFrame;
+ nsLineBox* mOrigCursor;
+ };
+
virtual void ChildIsDirty(nsIFrame* aChild) override;
virtual bool IsVisibleInSelection(nsISelection* aSelection) override;
virtual bool IsEmpty() override;
virtual bool CachedIsEmpty() override;
virtual bool IsSelfEmpty() override;
// Given that we have a bullet, does it actually draw something, i.e.,
@@ -363,19 +397,19 @@ protected:
}
virtual ~nsBlockFrame();
#ifdef DEBUG
already_AddRefed<nsStyleContext> GetFirstLetterStyle(nsPresContext* aPresContext);
#endif
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(LineCursorProperty, nsLineBox)
+ bool HasLineCursor() { return GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR; }
nsLineBox* GetLineCursor() {
- return (GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR) ?
- Properties().Get(LineCursorProperty()) : nullptr;
+ return HasLineCursor() ? Properties().Get(LineCursorProperty()) : nullptr;
}
nsLineBox* NewLineBox(nsIFrame* aFrame, bool aIsBlock) {
return NS_NewLineBox(PresContext()->PresShell(), aFrame, aIsBlock);
}
nsLineBox* NewLineBox(nsLineBox* aFromLine, nsIFrame* aFrame, int32_t aCount) {
return NS_NewLineBox(PresContext()->PresShell(), aFromLine, aFrame, aCount);
}