Skip to content

Commit f282b6b

Browse files
committed
Bug 1991689 - Cache advances of text ranges measured by TextRenderedRun::GetClipEdges in the root SVGTextFrame to accelerate ReflowSVG. r=firefox-svg-reviewers,longsonr
Differential Revision: https://phabricator.services.mozilla.com/D267439 UltraBlame original commit: d39196d226907fe609fdf756f6d8a6485f635de3
1 parent aed724e commit f282b6b

File tree

3 files changed

+98
-11
lines changed

3 files changed

+98
-11
lines changed

gfx/thebes/gfxTextRun.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ class gfxTextRun : public gfxShapedText {
163163
Range(uint32_t aStart, uint32_t aEnd) : start(aStart), end(aEnd) {}
164164
explicit Range(const gfxTextRun* aTextRun)
165165
: Range(0, aTextRun->GetLength()) {}
166+
167+
bool Intersects(const Range& aOther) const {
168+
return start < aOther.end && end > aOther.start;
169+
}
166170
};
167171

168172

layout/svg/SVGTextFrame.cpp

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -409,15 +409,16 @@ struct TextRenderedRun {
409409

410410

411411

412-
TextRenderedRun(nsTextFrame* aFrame, const gfxPoint& aPosition,
413-
float aLengthAdjustScaleFactor, double aRotate,
412+
TextRenderedRun(nsTextFrame* aFrame, SVGTextFrame* aSVGTextFrame,
413+
const gfxPoint& aPosition, double aRotate,
414414
float aFontSizeScaleFactor, nscoord aBaseline,
415415
uint32_t aTextFrameContentOffset,
416416
uint32_t aTextFrameContentLength,
417417
uint32_t aTextElementCharIndex)
418418
: mFrame(aFrame),
419+
mRoot(aSVGTextFrame),
419420
mPosition(aPosition),
420-
mLengthAdjustScaleFactor(aLengthAdjustScaleFactor),
421+
mLengthAdjustScaleFactor(mRoot->mLengthAdjustScaleFactor),
421422
mRotate(static_cast<float>(aRotate)),
422423
mFontSizeScaleFactor(aFontSizeScaleFactor),
423424
mBaseline(aBaseline),
@@ -664,6 +665,11 @@ struct TextRenderedRun {
664665

665666

666667

668+
SVGTextFrame* mRoot;
669+
670+
671+
672+
667673

668674

669675

@@ -964,13 +970,61 @@ void TextRenderedRun::GetClipEdges(nscoord& aVisIStartEdge,
964970

965971

966972

967-
nscoord startEdge = textRun->GetAdvanceWidth(
968-
Range(frameRange.start, runRange.start), &provider);
973+
auto MeasureUsingCache = [&](SVGTextFrame::CachedMeasuredRange& aCachedRange,
974+
const Range& aRange) -> nscoord {
975+
if (aRange.Intersects(aCachedRange.mRange)) {
976+
977+
978+
Range startDelta, endDelta;
979+
int startSign = 0, endSign = 0;
980+
if (aRange.start < aCachedRange.mRange.start) {
981+
982+
startSign = 1;
983+
startDelta = Range(aRange.start, aCachedRange.mRange.start);
984+
} else if (aRange.start > aCachedRange.mRange.start) {
985+
986+
startSign = -1;
987+
startDelta = Range(aCachedRange.mRange.start, aRange.start);
988+
}
989+
if (aRange.end > aCachedRange.mRange.end) {
990+
991+
endSign = 1;
992+
endDelta = Range(aCachedRange.mRange.end, aRange.end);
993+
} else if (aRange.end < aCachedRange.mRange.end) {
994+
995+
endSign = -1;
996+
endDelta = Range(aRange.end, aCachedRange.mRange.end);
997+
}
998+
999+
1000+
1001+
if (startDelta.Length() + endDelta.Length() < aRange.Length()) {
1002+
if (startSign) {
1003+
aCachedRange.mAdvance +=
1004+
startSign * textRun->GetAdvanceWidth(startDelta, &provider);
1005+
}
1006+
if (endSign) {
1007+
aCachedRange.mAdvance +=
1008+
endSign * textRun->GetAdvanceWidth(endDelta, &provider);
1009+
}
1010+
} else {
1011+
aCachedRange.mAdvance = textRun->GetAdvanceWidth(aRange, &provider);
1012+
}
1013+
} else {
1014+
1015+
aCachedRange.mAdvance = textRun->GetAdvanceWidth(aRange, &provider);
1016+
}
1017+
aCachedRange.mRange = aRange;
1018+
return aCachedRange.mAdvance;
1019+
};
9691020

970-
971-
1021+
mRoot->SetCurrentFrameForCaching(mFrame);
1022+
nscoord startEdge =
1023+
MeasureUsingCache(mRoot->CachedRange(SVGTextFrame::WhichRange::Before),
1024+
Range(frameRange.start, runRange.start));
9721025
nscoord endEdge =
973-
textRun->GetAdvanceWidth(Range(runRange.end, frameRange.end), &provider);
1026+
MeasureUsingCache(mRoot->CachedRange(SVGTextFrame::WhichRange::After),
1027+
Range(runRange.end, frameRange.end));
9741028

9751029
if (textRun->IsRightToLeft()) {
9761030
aVisIStartEdge = endEdge;
@@ -1900,9 +1954,8 @@ TextRenderedRun TextRenderedRunIterator::Next() {
19001954
}
19011955
}
19021956

1903-
mCurrent = TextRenderedRun(frame, pt, Root()->mLengthAdjustScaleFactor,
1904-
rotate, mFontSizeScaleFactor, baseline, offset,
1905-
length, charIndex);
1957+
mCurrent = TextRenderedRun(frame, Root(), pt, rotate, mFontSizeScaleFactor,
1958+
baseline, offset, length, charIndex);
19061959
return mCurrent;
19071960
}
19081961

@@ -5108,6 +5161,9 @@ void SVGTextFrame::DoReflow() {
51085161
RemoveStateBits(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN);
51095162
}
51105163

5164+
5165+
mFrameForCachedRanges = nullptr;
5166+
51115167
nsPresContext* presContext = PresContext();
51125168
nsIFrame* kid = PrincipalChildList().FirstChild();
51135169
if (!kid) {

layout/svg/SVGTextFrame.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,33 @@ class SVGTextFrame final : public SVGDisplayContainerFrame {
586586

587587

588588
float mLengthAdjustScaleFactor = 1.0f;
589+
590+
public:
591+
struct CachedMeasuredRange {
592+
Range mRange;
593+
nscoord mAdvance;
594+
};
595+
596+
void SetCurrentFrameForCaching(const nsTextFrame* aFrame) {
597+
if (mFrameForCachedRanges != aFrame) {
598+
PodArrayZero(mCachedRanges);
599+
mFrameForCachedRanges = aFrame;
600+
}
601+
}
602+
603+
enum WhichRange {
604+
Before,
605+
After,
606+
CachedRangeCount,
607+
};
608+
609+
CachedMeasuredRange& CachedRange(WhichRange aWhichRange) {
610+
return mCachedRanges[aWhichRange];
611+
}
612+
613+
private:
614+
const nsTextFrame* mFrameForCachedRanges = nullptr;
615+
CachedMeasuredRange mCachedRanges[CachedRangeCount];
589616
};
590617

591618
}

0 commit comments

Comments
 (0)