Bug 752394 - time out font facename list initialization, reflow if needed after font loader thread completes. r=jfkthame

This commit is contained in:
John Daggett 2014-04-23 14:20:20 +09:00
Родитель e83a63f806
Коммит 284c6bfc7d
4 изменённых файлов: 172 добавлений и 45 удалений

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

@ -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;