Bug 1919511 - Rename gfxFontGroup::BuildFontList to EnsureFontList, and defer calling it until we really need the resolved font instances. r=layout-reviewers,emilio

This is preparation for splitting out separate per-script resolved font lists in gfxFontGroup.
By itself, it should not change behavior.

Differential Revision: https://phabricator.services.mozilla.com/D222748
This commit is contained in:
Jonathan Kew
2024-10-12 15:37:18 +00:00
parent f60983e284
commit a93a779c56
6 changed files with 92 additions and 55 deletions

View File

@@ -4494,7 +4494,6 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
mSetTextCount++;
auto* pfl = gfxPlatformFontList::PlatformFontList();
pfl->Lock();
mFontgrp->CheckForUpdatedPlatformList();
mFontgrp->UpdateUserFonts(); // ensure user font generation is current
// adjust flags for current direction run
gfx::ShapedTextFlags flags = mTextRunFlags;
@@ -5128,9 +5127,6 @@ gfxFontGroup* CanvasRenderingContext2D::GetCurrentFontStyle() {
NS_ERROR("Default canvas font is invalid");
}
}
} else {
// The fontgroup needs to check if its cached families/faces are valid.
fontGroup->CheckForUpdatedPlatformList();
}
return fontGroup;

View File

@@ -1871,9 +1871,8 @@ gfxFontGroup::gfxFontGroup(nsPresContext* aPresContext,
break;
}
// We don't use SetUserFontSet() here, as we want to unconditionally call
// BuildFontList() rather than only do UpdateUserFonts() if it changed.
mCurrGeneration = GetGeneration();
BuildFontList();
// EnsureFontList() rather than only do UpdateUserFonts() if it changed.
mCurrGeneration = 0;
}
gfxFontGroup::~gfxFontGroup() {
@@ -1887,11 +1886,58 @@ static StyleGenericFontFamily GetDefaultGeneric(nsAtom* aLanguage) {
->GetDefaultGeneric();
}
void gfxFontGroup::BuildFontList() {
// initialize fonts in the font family list
class DeferredClearResolvedFonts final : public nsIRunnable {
public:
NS_DECL_THREADSAFE_ISUPPORTS
DeferredClearResolvedFonts() = delete;
explicit DeferredClearResolvedFonts(
const DeferredClearResolvedFonts& aOther) = delete;
explicit DeferredClearResolvedFonts(
nsTArray<gfxFontGroup::FamilyFace>&& aFontList)
: mFontList(std::move(aFontList)) {}
protected:
virtual ~DeferredClearResolvedFonts() {}
NS_IMETHOD Run(void) override {
mFontList.Clear();
return NS_OK;
}
nsTArray<gfxFontGroup::FamilyFace> mFontList;
};
NS_IMPL_ISUPPORTS(DeferredClearResolvedFonts, nsIRunnable)
void gfxFontGroup::EnsureFontList() {
// Ensure resolved font instances are valid; discard them if necessary.
auto* pfl = gfxPlatformFontList::PlatformFontList();
if (mFontListGeneration != pfl->GetGeneration()) {
// Forget cached fonts that may no longer be valid.
mLastPrefFamily = FontFamily();
mLastPrefFont = nullptr;
mDefaultFont = nullptr;
mResolvedFonts = false;
}
// If we have already resolved the font list, just return.
if (mResolvedFonts) {
return;
}
// Discard existing fonts; but if we're in servo traversal, defer the actual
// deletion.
// XXX(jfkthame) is this really necessary, or is the assertion in
// ~gfxUserFontFamily() obsolete?
if (gfxFontUtils::IsInServoTraversal()) {
NS_DispatchToMainThread(new DeferredClearResolvedFonts(std::move(mFonts)));
} else {
mFonts.Clear();
}
// (Re-)build the list of fonts.
AutoTArray<FamilyAndGeneric, 10> fonts;
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
mFontListGeneration = pfl->GetGeneration();
// lookup fonts in the fontlist
for (const StyleSingleFontFamily& name : mFamilyList.list.AsSpan()) {
@@ -1935,6 +1981,9 @@ void gfxFontGroup::BuildFontList() {
AddFamilyToFontList(f.mFamily.mUnshared, f.mGeneric);
}
}
mFontListGeneration = pfl->GetGeneration();
mResolvedFonts = true;
}
void gfxFontGroup::AddPlatformFont(const nsACString& aName, bool aQuotedName,
@@ -2228,8 +2277,7 @@ already_AddRefed<gfxFont> gfxFontGroup::GetDefaultFont() {
already_AddRefed<gfxFont> gfxFontGroup::GetFirstValidFont(
uint32_t aCh, StyleGenericFontFamily* aGeneric, bool* aIsFirst) {
// Ensure cached font instances are valid.
CheckForUpdatedPlatformList();
EnsureFontList();
uint32_t count = mFonts.Length();
bool loading = false;
@@ -2313,6 +2361,7 @@ already_AddRefed<gfxFont> gfxFontGroup::GetFirstValidFont(
}
already_AddRefed<gfxFont> gfxFontGroup::GetFirstMathFont() {
EnsureFontList();
uint32_t count = mFonts.Length();
for (uint32_t i = 0; i < count; ++i) {
RefPtr<gfxFont> font = GetFontAt(i);
@@ -3625,26 +3674,22 @@ void gfxFontGroup::SetUserFontSet(gfxUserFontSet* aUserFontSet) {
}
uint64_t gfxFontGroup::GetGeneration() {
if (!mUserFontSet) return 0;
return mUserFontSet->GetGeneration();
return mUserFontSet ? mUserFontSet->GetGeneration() : 0;
}
uint64_t gfxFontGroup::GetRebuildGeneration() {
if (!mUserFontSet) return 0;
return mUserFontSet->GetRebuildGeneration();
return mUserFontSet ? mUserFontSet->GetRebuildGeneration() : 0;
}
void gfxFontGroup::UpdateUserFonts() {
if (mCurrGeneration < GetRebuildGeneration()) {
// fonts in userfont set changed, need to redo the fontlist
mFonts.Clear();
mResolvedFonts = false;
ClearCachedData();
BuildFontList();
mCurrGeneration = GetGeneration();
} else if (mCurrGeneration != GetGeneration()) {
// load state change occurred, verify load state and validity of fonts
ClearCachedData();
uint32_t len = mFonts.Length();
for (uint32_t i = 0; i < len; i++) {
FamilyFace& ff = mFonts[i];
@@ -3653,14 +3698,16 @@ void gfxFontGroup::UpdateUserFonts() {
}
ff.CheckState(mSkipDrawing);
}
mCurrGeneration = GetGeneration();
}
}
bool gfxFontGroup::ContainsUserFont(const gfxUserFontEntry* aUserFont) {
UpdateUserFonts();
// search through the fonts list for a specific user font
// If we have resolved the font list to concrete font faces, search through
// the list for a specific user font face.
if (mResolvedFonts) {
uint32_t len = mFonts.Length();
for (uint32_t i = 0; i < len; i++) {
FamilyFace& ff = mFonts[i];
@@ -3671,6 +3718,12 @@ bool gfxFontGroup::ContainsUserFont(const gfxUserFontEntry* aUserFont) {
return false;
}
// If the font list is currently not resolved, we assume it might use the
// given face. (This method is only called when we have already seen that
// the family name is present in the list.)
return true;
}
already_AddRefed<gfxFont> gfxFontGroup::WhichPrefFontSupportsChar(
uint32_t aCh, uint32_t aNextCh, eFontPresentation aPresentation) {
eFontPrefLang charLang;

View File

@@ -904,6 +904,8 @@ class gfxFontGroup final : public gfxTextRunFactory {
public:
typedef mozilla::intl::Script Script;
typedef gfxShapedText::CompressedGlyph CompressedGlyph;
friend class MathMLTextRunFactory;
friend class nsCaseTransformTextRunFactory;
static void
Shutdown(); // platform must call this to release the languageAtomService
@@ -1062,18 +1064,6 @@ class gfxFontGroup final : public gfxTextRunFactory {
int32_t aAppUnitsPerDevPixel, mozilla::gfx::ShapedTextFlags aFlags,
LazyReferenceDrawTargetGetter& aRefDrawTargetGetter);
void CheckForUpdatedPlatformList() {
auto* pfl = gfxPlatformFontList::PlatformFontList();
if (mFontListGeneration != pfl->GetGeneration()) {
// Forget cached fonts that may no longer be valid.
mLastPrefFamily = FontFamily();
mLastPrefFont = nullptr;
mDefaultFont = nullptr;
mFonts.Clear();
BuildFontList();
}
}
nsAtom* Language() const { return mLanguage.get(); }
// Get font metrics to be used as the basis for CSS font-relative units.
@@ -1086,6 +1076,7 @@ class gfxFontGroup final : public gfxTextRunFactory {
protected:
friend class mozilla::PostTraversalTask;
friend class DeferredClearResolvedFonts;
struct TextRange {
TextRange(uint32_t aStart, uint32_t aEnd, gfxFont* aFont,
@@ -1401,6 +1392,8 @@ class gfxFontGroup final : public gfxTextRunFactory {
bool mExplicitLanguage; // Does mLanguage come from an explicit attribute?
bool mResolvedFonts = false; // Whether the mFonts array has been set up.
eFontPresentation mEmojiPresentation = eFontPresentation::Any;
// Generic font family used to select among font prefs during fallback.
@@ -1427,8 +1420,9 @@ class gfxFontGroup final : public gfxTextRunFactory {
const T* aString, uint32_t aLength, const Parameters* aParams,
mozilla::gfx::ShapedTextFlags aFlags, nsTextFrameUtils::Flags aFlags2);
// Initialize the list of fonts
void BuildFontList();
// Ensure the font-family list & style properties from CSS/prefs/defaults is
// resolved to the array of available font faces we'll actually use.
void EnsureFontList();
// Get the font at index i within the fontlist, for character aCh (in case
// of fonts with multiple resources and unicode-range partitioning).

View File

@@ -519,8 +519,8 @@ void MathMLTextRunFactory::RebuildTextRun(
StyleMathVariant mathVar = StyleMathVariant::None;
bool doMathvariantStyling = true;
// Ensure it will be safe to call FindFontForChar in the loop below.
fontGroup->CheckForUpdatedPlatformList();
// Ensure the fontGroup is ready to be searched.
fontGroup->EnsureFontList();
for (uint32_t i = 0; i < length; ++i) {
int extraChars = 0;

View File

@@ -2385,14 +2385,7 @@ already_AddRefed<gfxTextRun> BuildTextRunsScanner::BuildTextRunForFrames(
fontInflation = nsLayoutUtils::FontSizeInflationFor(firstFrame);
fontGroup = GetInflatedFontGroupForFrame(firstFrame);
}
if (fontGroup) {
// Refresh fontgroup if necessary, before trying to build textruns.
fontGroup->CheckForUpdatedPlatformList();
} else {
DestroyUserData(userDataToDestroy);
return nullptr;
}
MOZ_ASSERT(fontGroup);
if (flags2 & nsTextFrameUtils::Flags::HasTab) {
flags |= gfx::ShapedTextFlags::TEXT_ENABLE_SPACING;

View File

@@ -770,9 +770,10 @@ bool nsCaseTransformTextRunFactory::TransformString(
// Bug 930504. Some platforms do not have fonts for Mathematical
// Alphanumeric Symbols. Hence we only perform the transform if a
// character is actually available.
auto* fontGroup = aTextRun->GetFontGroup();
fontGroup->EnsureFontList();
FontMatchType matchType;
RefPtr<gfxFont> mathFont =
aTextRun->GetFontGroup()->FindFontForChar(
RefPtr<gfxFont> mathFont = fontGroup->FindFontForChar(
ch2, 0, 0, intl::Script::COMMON, nullptr, &matchType);
if (mathFont) {
ch = ch2;