Bug 1765093 - patch 1 - Avoid measuring entire textrun in SVGTextFrame's GetBaselinePosition function. r=dholbert

This aims to prevent an O(n^2) performance situation when per-glyph
positioning is in use.

This reduces the time to load the testcase here from around 70s to 17s
in my local build. Still not great, but at least it's less of a disaster.

Differential Revision: https://phabricator.services.mozilla.com/D145631
This commit is contained in:
Jonathan Kew 2022-05-06 17:47:22 +00:00
Родитель db341d7b94
Коммит a29c0bcdbe
3 изменённых файлов: 26 добавлений и 13 удалений

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

@ -834,6 +834,21 @@ gfxTextRun::Metrics gfxTextRun::MeasureText(
return accumulatedMetrics;
}
void gfxTextRun::GetLineHeightMetrics(gfxFloat& aAscent,
gfxFloat& aDescent) const {
Metrics accumulatedMetrics;
GlyphRunIterator iter(this, Range(this));
while (iter.NextRun()) {
gfxFont* font = iter.GetGlyphRun()->mFont;
auto metrics =
font->Measure(this, 0, 0, gfxFont::LOOSE_INK_EXTENTS, nullptr, nullptr,
iter.GetGlyphRun()->mOrientation);
accumulatedMetrics.CombineWith(metrics, false);
}
aAscent = accumulatedMetrics.mAscent;
aDescent = accumulatedMetrics.mDescent;
}
#define MEASUREMENT_BUFFER_SIZE 100
void gfxTextRun::ClassifyAutoHyphenations(uint32_t aStart, Range aRange,

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

@ -312,6 +312,8 @@ class gfxTextRun : public gfxShapedText {
aDrawTargetForTightBoundingBox, aProvider);
}
void GetLineHeightMetrics(gfxFloat& aAscent, gfxFloat& aDescent) const;
/**
* Computes just the advance width for a substring.
* Uses GetSpacing from aBreakProvider.

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

@ -279,26 +279,23 @@ static nscoord GetBaselinePosition(nsTextFrame* aFrame, gfxTextRun* aTextRun,
StyleDominantBaseline aDominantBaseline,
float aFontSizeScaleFactor) {
WritingMode writingMode = aFrame->GetWritingMode();
// We pass in null for the PropertyProvider since letter-spacing and
// word-spacing should not affect the ascent and descent values we get.
gfxTextRun::Metrics metrics =
aTextRun->MeasureText(gfxFont::LOOSE_INK_EXTENTS, nullptr);
gfxFloat ascent, descent;
aTextRun->GetLineHeightMetrics(ascent, descent);
auto convertIfVerticalRL = [&](gfxFloat dominantBaseline) {
return writingMode.IsVerticalRL()
? metrics.mAscent + metrics.mDescent - dominantBaseline
: dominantBaseline;
return writingMode.IsVerticalRL() ? ascent + descent - dominantBaseline
: dominantBaseline;
};
switch (aDominantBaseline) {
case StyleDominantBaseline::Hanging:
return convertIfVerticalRL(metrics.mAscent * 0.2);
return convertIfVerticalRL(ascent * 0.2);
case StyleDominantBaseline::TextBeforeEdge:
return convertIfVerticalRL(0);
case StyleDominantBaseline::Alphabetic:
return writingMode.IsVerticalRL()
? metrics.mAscent * 0.5
? ascent * 0.5
: aFrame->GetLogicalBaseline(writingMode);
case StyleDominantBaseline::Auto:
@ -312,13 +309,12 @@ static nscoord GetBaselinePosition(nsTextFrame* aFrame, gfxTextRun* aTextRun,
case StyleDominantBaseline::TextAfterEdge:
case StyleDominantBaseline::Ideographic:
return writingMode.IsVerticalLR() ? 0
: metrics.mAscent + metrics.mDescent;
return writingMode.IsVerticalLR() ? 0 : ascent + descent;
case StyleDominantBaseline::Central:
return (metrics.mAscent + metrics.mDescent) / 2.0;
return (ascent + descent) / 2.0;
case StyleDominantBaseline::Mathematical:
return convertIfVerticalRL(metrics.mAscent / 2.0);
return convertIfVerticalRL(ascent / 2.0);
}
MOZ_ASSERT_UNREACHABLE("unexpected dominant-baseline value");