Bug 1749103 - Avoid thrashing gfxDWriteFont's ScaledFonts between canvas and content. r=jfkthame

This is essentially a partial revert of a cleanup done in bug 1742896. If canvas and content
are using the same underlying gfxDWriteFont and simultaneously retrieving a ScaledFont, this
may cause the ScaledFont to get repeatedly destroyed and re-instantiated every time we switch
from one context to the other. If this destruction happens at an inopportune time while WR
is still using a blob image with the font, it can potentially trigger undesirable assertions.

For now, duplicate the part of Bas' original patch from bug 1730722 that separatedly cached
the GDI and non-GDI versions of the ScaledFont. This way, both will exist for the lifetime
of the underlying gfxDWriteFont and thus avoid the thrashing.

Differential Revision: https://phabricator.services.mozilla.com/D135442
This commit is contained in:
Lee Salzman 2022-01-13 16:18:47 +00:00
Родитель 09dc5b2ce7
Коммит 93d24303eb
4 изменённых файлов: 26 добавлений и 17 удалений

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

@ -84,8 +84,7 @@ gfxDWriteFont::gfxDWriteFont(const RefPtr<UnscaledFontDWrite>& aUnscaledFont,
mMetrics(nullptr),
mUseSubpixelPositions(false),
mAllowManualShowGlyphs(true),
mAzureScaledFontUsedClearType(false),
mAzureScaledFontForcedGDI(false) {
mAzureScaledFontUsedClearType(false) {
// If the IDWriteFontFace1 interface is available, we can use that for
// faster glyph width retrieval.
mFontFace->QueryInterface(__uuidof(IDWriteFontFace1),
@ -754,12 +753,14 @@ void gfxDWriteFont::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
already_AddRefed<ScaledFont> gfxDWriteFont::GetScaledFont(
const TextRunDrawParams& aRunParams) {
bool forceGDI = aRunParams.allowGDI && GetForceGDIClassic();
if (mAzureScaledFontUsedClearType != UsingClearType() ||
mAzureScaledFontForcedGDI != forceGDI) {
if (mAzureScaledFontUsedClearType != UsingClearType()) {
mAzureScaledFont = nullptr;
mAzureScaledFontGDI = nullptr;
}
if (!mAzureScaledFont) {
bool forceGDI = aRunParams.allowGDI && GetForceGDIClassic();
RefPtr<ScaledFont>& azureScaledFont =
forceGDI ? mAzureScaledFontGDI : mAzureScaledFont;
if (!azureScaledFont) {
gfxDWriteFontEntry* fe = static_cast<gfxDWriteFontEntry*>(mFontEntry.get());
bool useEmbeddedBitmap =
(gfxVars::SystemTextRenderingMode() == DWRITE_RENDERING_MODE_DEFAULT ||
@ -767,19 +768,17 @@ already_AddRefed<ScaledFont> gfxDWriteFont::GetScaledFont(
fe->IsCJKFont() && HasBitmapStrikeForSize(NS_lround(mAdjustedSize));
const gfxFontStyle* fontStyle = GetStyle();
mAzureScaledFont = Factory::CreateScaledFontForDWriteFont(
azureScaledFont = Factory::CreateScaledFontForDWriteFont(
mFontFace, fontStyle, GetUnscaledFont(), GetAdjustedSize(),
useEmbeddedBitmap, forceGDI);
if (!mAzureScaledFont) {
if (!azureScaledFont) {
return nullptr;
}
InitializeScaledFont();
InitializeScaledFont(azureScaledFont);
mAzureScaledFontUsedClearType = UsingClearType();
mAzureScaledFontForcedGDI = forceGDI;
}
RefPtr<ScaledFont> scaledFont(mAzureScaledFont);
return scaledFont.forget();
return do_AddRef(azureScaledFont);
}
bool gfxDWriteFont::ShouldRoundXOffset(cairo_t* aCairo) const {

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

@ -103,7 +103,11 @@ class gfxDWriteFont final : public gfxFont {
// Used to record the sUseClearType setting at the time mAzureScaledFont
// was set up, so we can tell if it's stale and needs to be re-created.
bool mAzureScaledFontUsedClearType;
bool mAzureScaledFontForcedGDI;
// Cache the GDI version of the ScaledFont so that font keys and other
// meta-data can remain stable even if there is thrashing between GDI and
// non-GDI usage.
RefPtr<mozilla::gfx::ScaledFont> mAzureScaledFontGDI;
bool UsingClearType() {
return mozilla::gfx::gfxVars::SystemTextQuality() == CLEARTYPE_QUALITY;

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

@ -1552,14 +1552,15 @@ already_AddRefed<mozilla::gfx::ScaledFont> gfxFont::GetScaledFont(
return GetScaledFont(params);
}
void gfxFont::InitializeScaledFont() {
if (!mAzureScaledFont) {
void gfxFont::InitializeScaledFont(
const RefPtr<mozilla::gfx::ScaledFont>& aScaledFont) {
if (!aScaledFont) {
return;
}
float angle = AngleForSyntheticOblique();
if (angle != 0.0f) {
mAzureScaledFont->SetSyntheticObliqueAngle(angle);
aScaledFont->SetSyntheticObliqueAngle(angle);
}
}

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

@ -1901,7 +1901,12 @@ class gfxFont {
already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont(
mozilla::gfx::DrawTarget* aDrawTarget);
void InitializeScaledFont();
// gfxFont implementations may cache ScaledFont versions other than the
// default, so InitializeScaledFont must support explicitly specifying
// other ScaledFonts than the default to initialize.
void InitializeScaledFont(
const RefPtr<mozilla::gfx::ScaledFont>& aScaledFont);
void InitializeScaledFont() { InitializeScaledFont(mAzureScaledFont); }
bool KerningDisabled() { return mKerningSet && !mKerningEnabled; }