Bug 1725555 - patch 2 - Enable the primary nsTextFrame to provide, and cache, an array of all the continuations in the chain. r=emilio

This allows us to binary-search the continuations from nsRange::CollectClientRectsAndText,
instead of linear-searching the linked list for every range we need to look up.

Depends on D122998

Differential Revision: https://phabricator.services.mozilla.com/D122999
This commit is contained in:
Jonathan Kew
2021-08-27 16:23:24 +00:00
parent d15b7edad6
commit faaee485c4
3 changed files with 103 additions and 5 deletions

View File

@@ -4384,6 +4384,35 @@ void nsTextFrame::DestroyFrom(nsIFrame* aDestructRoot,
nsIFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}
nsTArray<nsTextFrame*>* nsTextFrame::GetContinuations() {
MOZ_ASSERT(NS_IsMainThread());
// Only for use on the primary frame, which has no prev-continuation.
MOZ_ASSERT(!GetPrevContinuation());
if (!mNextContinuation) {
return nullptr;
}
if (mHasContinuationsProperty) {
return GetProperty(ContinuationsProperty());
}
size_t count = 0;
for (nsIFrame* f = this; f; f = f->GetNextContinuation()) {
++count;
}
auto* continuations = new nsTArray<nsTextFrame*>;
if (continuations->SetCapacity(count, fallible)) {
for (nsTextFrame* f = this; f;
f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
continuations->AppendElement(f);
}
} else {
delete continuations;
continuations = nullptr;
}
AddProperty(ContinuationsProperty(), continuations);
mHasContinuationsProperty = true;
return continuations;
}
class nsContinuingTextFrame final : public nsTextFrame {
public:
NS_DECL_FRAMEARENA_HELPERS(nsContinuingTextFrame)
@@ -4410,10 +4439,16 @@ class nsContinuingTextFrame final : public nsTextFrame {
nsTextFrame* prevFirst = mFirstContinuation;
if (mPrevContinuation) {
mFirstContinuation = mPrevContinuation->FirstContinuation();
if (mFirstContinuation) {
mFirstContinuation->ClearCachedContinuations();
}
} else {
mFirstContinuation = nullptr;
}
if (mFirstContinuation != prevFirst) {
if (prevFirst) {
prevFirst->ClearCachedContinuations();
}
auto* f = static_cast<nsContinuingTextFrame*>(mNextContinuation);
while (f) {
f->mFirstContinuation = mFirstContinuation;
@@ -4438,10 +4473,16 @@ class nsContinuingTextFrame final : public nsTextFrame {
nsTextFrame* prevFirst = mFirstContinuation;
if (mPrevContinuation) {
mFirstContinuation = mPrevContinuation->FirstContinuation();
if (mFirstContinuation) {
mFirstContinuation->ClearCachedContinuations();
}
} else {
mFirstContinuation = nullptr;
}
if (mFirstContinuation != prevFirst) {
if (prevFirst) {
prevFirst->ClearCachedContinuations();
}
auto* f = static_cast<nsContinuingTextFrame*>(mNextContinuation);
while (f) {
f->mFirstContinuation = mFirstContinuation;
@@ -4457,6 +4498,8 @@ class nsContinuingTextFrame final : public nsTextFrame {
return mFirstContinuation;
};
nsTArray<nsTextFrame*>* GetContinuations() final { return nullptr; }
void AddInlineMinISize(gfxContext* aRenderingContext,
InlineMinISizeData* aData) final;
void AddInlinePrefISize(gfxContext* aRenderingContext,
@@ -9121,6 +9164,12 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
RemoveStateBits(TEXT_REFLOW_FLAGS | TEXT_WHITESPACE_FLAGS);
mReflowRequestedForCharDataChange = false;
RemoveProperty(WebRenderTextBounds());
// Discard cached continuations array that will be invalidated by the reflow.
if (nsTextFrame* first = FirstContinuation()) {
first->ClearCachedContinuations();
}
// Temporarily map all possible content while we construct our new textrun.
// so that when doing reflow our styles prevail over any part of the
// textrun we look at. Note that next-in-flows may be mapping the same