зеркало из https://github.com/mozilla/gecko-dev.git
Bug 752394 - time out font facename list initialization, reflow if needed after font loader thread completes. r=jfkthame
This commit is contained in:
Родитель
e83a63f806
Коммит
284c6bfc7d
|
@ -749,17 +749,11 @@ gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
|||
{
|
||||
gfxFontEntry *lookup;
|
||||
|
||||
// initialize name lookup tables if needed
|
||||
if (!mFaceNamesInitialized) {
|
||||
InitFaceNameLists();
|
||||
}
|
||||
|
||||
// lookup in name lookup tables, return null if not found
|
||||
if (!(lookup = mExtraNames->mPostscriptNames.GetWeak(aFullname)) &&
|
||||
!(lookup = mExtraNames->mFullnames.GetWeak(aFullname)))
|
||||
{
|
||||
lookup = LookupInFaceNameLists(aFullname);
|
||||
if (!lookup) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfxDWriteFontEntry* dwriteLookup = static_cast<gfxDWriteFontEntry*>(lookup);
|
||||
gfxDWriteFontEntry *fe =
|
||||
new gfxDWriteFontEntry(lookup->Name(),
|
||||
|
|
|
@ -726,15 +726,8 @@ gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
|
|||
{
|
||||
gfxFontEntry *lookup;
|
||||
|
||||
// initialize name lookup tables if needed
|
||||
if (!mFaceNamesInitialized) {
|
||||
InitFaceNameLists();
|
||||
}
|
||||
|
||||
// lookup in name lookup tables, return null if not found
|
||||
if (!(lookup = mExtraNames->mPostscriptNames.GetWeak(aFullname)) &&
|
||||
!(lookup = mExtraNames->mFullnames.GetWeak(aFullname)))
|
||||
{
|
||||
lookup = LookupInFaceNameLists(aFullname);
|
||||
if (!lookup) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
|||
if (aNeedFullnamePostscriptNames) {
|
||||
mExtraNames = new ExtraNames();
|
||||
}
|
||||
mFaceNamesInitialized = false;
|
||||
mFaceNameListsInitialized = false;
|
||||
|
||||
LoadBadUnderlineList();
|
||||
|
||||
|
@ -159,7 +159,7 @@ gfxPlatformFontList::InitFontList()
|
|||
mExtraNames->mFullnames.Clear();
|
||||
mExtraNames->mPostscriptNames.Clear();
|
||||
}
|
||||
mFaceNamesInitialized = false;
|
||||
mFaceNameListsInitialized = false;
|
||||
mPrefFonts.Clear();
|
||||
mReplacementCharFallbackFamily = nullptr;
|
||||
CancelLoader();
|
||||
|
@ -201,7 +201,7 @@ gfxPlatformFontList::InitOtherFamilyNames()
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PLDHashOperator
|
||||
gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
|
@ -212,15 +212,34 @@ gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
|||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::InitFaceNameLists()
|
||||
struct ReadFaceNamesData {
|
||||
ReadFaceNamesData(gfxPlatformFontList *aFontList, TimeStamp aStartTime)
|
||||
: mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false)
|
||||
{}
|
||||
|
||||
gfxPlatformFontList *mFontList;
|
||||
TimeStamp mStartTime;
|
||||
bool mTimedOut;
|
||||
|
||||
// if mFirstChar is not empty, only load facenames for families
|
||||
// that start with this character
|
||||
nsString mFirstChar;
|
||||
};
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName)
|
||||
{
|
||||
mFaceNamesInitialized = true;
|
||||
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
gfxFontEntry *lookup = nullptr;
|
||||
|
||||
// iterate over all font families and read in other family names
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::InitFaceNameListsProc, this);
|
||||
ReadFaceNamesData faceNameListsData(this, start);
|
||||
|
||||
// iterate over familes starting with the same letter
|
||||
faceNameListsData.mFirstChar.Assign(aFaceName.CharAt(0));
|
||||
ToLowerCase(faceNameListsData.mFirstChar);
|
||||
mFontFamilies.Enumerate(gfxPlatformFontList::ReadFaceNamesProc,
|
||||
&faceNameListsData);
|
||||
lookup = FindFaceName(aFaceName);
|
||||
|
||||
TimeStamp end = TimeStamp::Now();
|
||||
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITFACENAMELISTS,
|
||||
|
@ -228,22 +247,90 @@ gfxPlatformFontList::InitFaceNameLists()
|
|||
#ifdef PR_LOGGING
|
||||
if (LOG_FONTINIT_ENABLED()) {
|
||||
TimeDuration elapsed = end - start;
|
||||
LOG_FONTINIT(("(fontinit) InitFaceNameLists took %8.2f ms",
|
||||
elapsed.ToMilliseconds()));
|
||||
LOG_FONTINIT(("(fontinit) SearchFamiliesForFaceName took %8.2f ms %s %s",
|
||||
elapsed.ToMilliseconds(),
|
||||
(lookup ? "found name" : ""),
|
||||
(faceNameListsData.mTimedOut ? "timeout" : "")));
|
||||
}
|
||||
#endif
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
// time limit for loading facename lists (ms)
|
||||
#define NAMELIST_TIMEOUT 200
|
||||
|
||||
PLDHashOperator
|
||||
gfxPlatformFontList::InitFaceNameListsProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg)
|
||||
gfxPlatformFontList::ReadFaceNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg)
|
||||
{
|
||||
gfxPlatformFontList *fc = static_cast<gfxPlatformFontList*>(userArg);
|
||||
ReadFaceNamesData *data = static_cast<ReadFaceNamesData*>(userArg);
|
||||
gfxPlatformFontList *fc = data->mFontList;
|
||||
|
||||
// when filtering, skip names that don't start with the filter character
|
||||
if (!(data->mFirstChar.IsEmpty())) {
|
||||
char16_t firstChar = aKey.CharAt(0);
|
||||
nsAutoString firstCharStr(&firstChar, 1);
|
||||
ToLowerCase(firstCharStr);
|
||||
if (!firstCharStr.Equals(data->mFirstChar)) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
}
|
||||
aFamilyEntry->ReadFaceNames(fc, fc->NeedFullnamePostscriptNames());
|
||||
|
||||
TimeDuration elapsed = TimeStamp::Now() - data->mStartTime;
|
||||
if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) {
|
||||
data->mTimedOut = true;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformFontList::FindFaceName(const nsAString& aFaceName)
|
||||
{
|
||||
gfxFontEntry *lookup;
|
||||
|
||||
// lookup in name lookup tables, return null if not found
|
||||
if (mExtraNames &&
|
||||
((lookup = mExtraNames->mPostscriptNames.GetWeak(aFaceName)) ||
|
||||
(lookup = mExtraNames->mFullnames.GetWeak(aFaceName)))) {
|
||||
return lookup;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfxFontEntry*
|
||||
gfxPlatformFontList::LookupInFaceNameLists(const nsAString& aFaceName)
|
||||
{
|
||||
gfxFontEntry *lookup = nullptr;
|
||||
|
||||
// initialize facename lookup tables if needed
|
||||
// note: this can terminate early or time out, in which case
|
||||
// mFaceNameListsInitialized remains false
|
||||
if (!mFaceNameListsInitialized) {
|
||||
lookup = SearchFamiliesForFaceName(aFaceName);
|
||||
if (lookup) {
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
|
||||
// lookup in name lookup tables, return null if not found
|
||||
if (!(lookup = FindFaceName(aFaceName))) {
|
||||
// names not completely initialized, so keep track of lookup misses
|
||||
if (!mFaceNameListsInitialized) {
|
||||
if (!mFaceNamesMissed) {
|
||||
mFaceNamesMissed = new nsTHashtable<nsStringHashKey>(4);
|
||||
}
|
||||
mFaceNamesMissed->PutEntry(aFaceName);
|
||||
}
|
||||
}
|
||||
|
||||
return lookup;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::PreloadNamesList()
|
||||
{
|
||||
|
@ -815,29 +902,65 @@ gfxPlatformFontList::LoadFontInfo()
|
|||
|
||||
if (done) {
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
mFaceNamesInitialized = true;
|
||||
mFaceNameListsInitialized = true;
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
struct LookupMissedFaceNamesData {
|
||||
LookupMissedFaceNamesData(gfxPlatformFontList *aFontList)
|
||||
: mFontList(aFontList), mFoundName(false) {}
|
||||
|
||||
gfxPlatformFontList *mFontList;
|
||||
bool mFoundName;
|
||||
};
|
||||
|
||||
/*static*/ PLDHashOperator
|
||||
gfxPlatformFontList::LookupMissedFaceNamesProc(nsStringHashKey *aKey,
|
||||
void *aUserArg)
|
||||
{
|
||||
LookupMissedFaceNamesData *data =
|
||||
reinterpret_cast<LookupMissedFaceNamesData*>(aUserArg);
|
||||
|
||||
if (data->mFontList->FindFaceName(aKey->GetKey())) {
|
||||
data->mFoundName = true;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::CleanupLoader()
|
||||
{
|
||||
mFontFamiliesToLoad.Clear();
|
||||
mNumFamilies = 0;
|
||||
bool rebuilt = false;
|
||||
|
||||
// if had missed face names that are now available, force reflow all
|
||||
if (mFaceNamesMissed &&
|
||||
mFaceNamesMissed->Count() != 0) {
|
||||
LookupMissedFaceNamesData namedata(this);
|
||||
mFaceNamesMissed->EnumerateEntries(LookupMissedFaceNamesProc, &namedata);
|
||||
if (namedata.mFoundName) {
|
||||
rebuilt = true;
|
||||
mUserFontSetList.EnumerateEntries(RebuildLocalFonts, nullptr);
|
||||
}
|
||||
mFaceNamesMissed = nullptr;
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_FONTINIT_ENABLED() && mFontInfo) {
|
||||
LOG_FONTINIT(("(fontinit) fontloader load thread took %8.2f ms "
|
||||
"%d families %d fonts %d cmaps "
|
||||
"%d facenames %d othernames",
|
||||
"%d facenames %d othernames %s",
|
||||
mLoadTime.ToMilliseconds(),
|
||||
mFontInfo->mLoadStats.families,
|
||||
mFontInfo->mLoadStats.fonts,
|
||||
mFontInfo->mLoadStats.cmaps,
|
||||
mFontInfo->mLoadStats.facenames,
|
||||
mFontInfo->mLoadStats.othernames));
|
||||
mFontInfo->mLoadStats.othernames,
|
||||
(rebuilt ? "(userfont sets rebuilt)" : "")));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -228,16 +228,30 @@ protected:
|
|||
// separate initialization for reading in name tables, since this is expensive
|
||||
void InitOtherFamilyNames();
|
||||
|
||||
static PLDHashOperator InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
static PLDHashOperator
|
||||
InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
|
||||
// read in all fullname/Postscript names for all font faces
|
||||
void InitFaceNameLists();
|
||||
// search through font families, looking for a given name, initializing
|
||||
// facename lists along the way. first checks all families with names
|
||||
// close to face name, then searchs all families if not found.
|
||||
gfxFontEntry* SearchFamiliesForFaceName(const nsAString& aFaceName);
|
||||
|
||||
static PLDHashOperator InitFaceNameListsProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
static PLDHashOperator
|
||||
ReadFaceNamesProc(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* userArg);
|
||||
|
||||
// helper method for finding fullname/postscript names in facename lists
|
||||
gfxFontEntry* FindFaceName(const nsAString& aFaceName);
|
||||
|
||||
// look up a font by name, for cases where platform font list
|
||||
// maintains explicit mappings of fullname/psname ==> font
|
||||
virtual gfxFontEntry* LookupInFaceNameLists(const nsAString& aFontName);
|
||||
|
||||
static PLDHashOperator LookupMissedFaceNamesProc(nsStringHashKey *aKey,
|
||||
void *aUserArg);
|
||||
|
||||
// commonly used fonts for which the name table should be loaded at startup
|
||||
virtual void PreloadNamesList();
|
||||
|
@ -286,7 +300,7 @@ protected:
|
|||
bool mOtherFamilyNamesInitialized;
|
||||
|
||||
// flag set after fullname and Postcript name lists are populated
|
||||
bool mFaceNamesInitialized;
|
||||
bool mFaceNameListsInitialized;
|
||||
|
||||
struct ExtraNames {
|
||||
ExtraNames() : mFullnames(100), mPostscriptNames(100) {}
|
||||
|
@ -297,6 +311,9 @@ protected:
|
|||
};
|
||||
nsAutoPtr<ExtraNames> mExtraNames;
|
||||
|
||||
// face names missed when face name loading takes a long time
|
||||
nsAutoPtr<nsTHashtable<nsStringHashKey> > mFaceNamesMissed;
|
||||
|
||||
// cached pref font lists
|
||||
// maps list of family names ==> array of family entries, one per lang group
|
||||
nsDataHashtable<nsUint32HashKey, nsTArray<nsRefPtr<gfxFontFamily> > > mPrefFonts;
|
||||
|
|
Загрузка…
Ссылка в новой задаче