Bug 1725555 - patch 3 - Also use continuations array to accelerate nsTextFrame::SelectionStateChanged. r=emilio

After CollectClientRectsAndText is eliminated from the profiles here, SelectionStateChanged
is the next obvious hotspot, and it can similarly be accelerated by binary-searching the continuations.

Depends on D122999

Differential Revision: https://phabricator.services.mozilla.com/D123000
This commit is contained in:
Jonathan Kew 2021-08-23 12:56:19 +00:00
Родитель a2a210e2f2
Коммит c02e51c6af
3 изменённых файлов: 42 добавлений и 37 удалений

Просмотреть файл

@ -2648,32 +2648,8 @@ static nsresult GetPartialTextRect(RectCallback* aCallback,
nsIFrame* relativeTo =
nsLayoutUtils::GetContainingBlockForClientRect(textFrame);
// Try to binary-search the list of continuations for the starting point.
// (GetContinuations is fallible; if it returns nullptr, we'll just start
// from the beginning.)
nsTArray<nsTextFrame*>* continuations = textFrame->GetContinuations();
nsTextFrame* f = textFrame;
if (continuations) {
size_t index;
if (BinarySearchIf(
*continuations, 0, continuations->Length(),
[=](nsTextFrame* aFrame) -> int {
if (aStartOffset < aFrame->GetContentOffset()) {
return -1;
}
if (aStartOffset > aFrame->GetContentOffset()) {
return 1;
}
return 0;
},
&index)) {
f = (*continuations)[index];
} else {
f = (*continuations)[index ? index - 1 : 0];
}
}
for (; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
for (nsTextFrame* f = textFrame->FindContinuationForOffset(aStartOffset); f;
f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
int32_t fstart = f->GetContentOffset(), fend = f->GetContentEnd();
if (fend <= aStartOffset) {
continue;

Просмотреть файл

@ -4494,8 +4494,6 @@ class nsContinuingTextFrame final : public nsTextFrame {
nsIFrame* FirstInFlow() const final;
nsTextFrame* FirstContinuation() const final { return mFirstContinuation; };
nsTArray<nsTextFrame*>* GetContinuations() final { return nullptr; }
void AddInlineMinISize(gfxContext* aRenderingContext,
InlineMinISizeData* aData) final;
void AddInlinePrefISize(gfxContext* aRenderingContext,
@ -7503,6 +7501,33 @@ bool nsTextFrame::IsFrameSelected() const {
return mIsSelected == nsTextFrame::SelectionState::Selected;
}
nsTextFrame* nsTextFrame::FindContinuationForOffset(int32_t aOffset) {
// Use a continuations array to accelerate finding the first continuation
// of interest, if possible.
MOZ_ASSERT(!GetPrevContinuation(), "should be called on the primary frame");
auto* continuations = GetContinuations();
nsTextFrame* f = this;
if (continuations) {
size_t index;
if (BinarySearchIf(
*continuations, 0, continuations->Length(),
[=](nsTextFrame* aFrame) -> int {
return aOffset - aFrame->GetContentOffset();
},
&index)) {
f = (*continuations)[index];
} else {
f = (*continuations)[index ? index - 1 : 0];
}
}
while (f && f->GetContentEnd() <= aOffset) {
f = f->GetNextContinuation();
}
return f;
}
void nsTextFrame::SelectionStateChanged(uint32_t aStart, uint32_t aEnd,
bool aSelected,
SelectionType aSelectionType) {
@ -7513,13 +7538,12 @@ void nsTextFrame::SelectionStateChanged(uint32_t aStart, uint32_t aEnd,
InvalidateSelectionState();
// Selection is collapsed, which can't affect text frame rendering
if (aStart == aEnd) return;
nsTextFrame* f = this;
while (f && f->GetContentEnd() <= int32_t(aStart)) {
f = f->GetNextContinuation();
if (aStart == aEnd) {
return;
}
nsTextFrame* f = FindContinuationForOffset(aStart);
nsPresContext* presContext = PresContext();
while (f && f->GetContentOffset() < int32_t(aEnd)) {
// We may need to reflow to recompute the overflow area for

Просмотреть файл

@ -784,10 +784,11 @@ class nsTextFrame : public nsIFrame {
nsRect WebRenderBounds();
// Return pointer to an array of all frames in the continuation chain, or
// null if we're too short of memory. (This is only meant to be called on the
// first text frame in the chain; continuations will always return null.)
virtual nsTArray<nsTextFrame*>* GetContinuations();
// Find the continuation (which may be this frame itself) containing the
// given offset. Note that this may return null, if the offset is beyond the
// text covered by the continuation chain.
// (To be used only on the first textframe in the chain.)
nsTextFrame* FindContinuationForOffset(int32_t aOffset);
protected:
virtual ~nsTextFrame();
@ -1010,6 +1011,10 @@ class nsTextFrame : public nsIFrame {
void ClearMetrics(ReflowOutput& aMetrics);
// Return pointer to an array of all frames in the continuation chain, or
// null if we're too short of memory.
nsTArray<nsTextFrame*>* GetContinuations();
// Clear any cached continuations array; this should be called whenever the
// chain is modified.
void ClearCachedContinuations() {