зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
a2a210e2f2
Коммит
c02e51c6af
|
@ -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() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче