From cc5a0b94accbe2a841857cc4375fe24f10eef56e Mon Sep 17 00:00:00 2001 From: John Daggett Date: Wed, 23 Apr 2014 14:20:21 +0900 Subject: [PATCH] Bug 752394 - time out localized font family name initialization, reflow if needed after font loader thread completes. r=jfkthame --- gfx/thebes/gfxPlatformFontList.cpp | 91 ++++++++++++++++++++++++++---- gfx/thebes/gfxPlatformFontList.h | 8 ++- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 597140de6977..7098a7bfab3d 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -181,37 +181,67 @@ gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& a ToLowerCase(aResult); } +struct InitOtherNamesData { + InitOtherNamesData(gfxPlatformFontList *aFontList, + TimeStamp aStartTime) + : mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false) + {} + + gfxPlatformFontList *mFontList; + TimeStamp mStartTime; + bool mTimedOut; +}; + void gfxPlatformFontList::InitOtherFamilyNames() { - mOtherFamilyNamesInitialized = true; + if (mOtherFamilyNamesInitialized) { + return; + } + TimeStamp start = TimeStamp::Now(); // iterate over all font families and read in other family names - mFontFamilies.Enumerate(gfxPlatformFontList::InitOtherFamilyNamesProc, this); + InitOtherNamesData otherNamesData(this, start); + mFontFamilies.Enumerate(gfxPlatformFontList::InitOtherFamilyNamesProc, + &otherNamesData); + + if (!otherNamesData.mTimedOut) { + mOtherFamilyNamesInitialized = true; + } TimeStamp end = TimeStamp::Now(); Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES, start, end); + #ifdef PR_LOGGING if (LOG_FONTINIT_ENABLED()) { TimeDuration elapsed = end - start; - LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms", - elapsed.ToMilliseconds())); + LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s", + elapsed.ToMilliseconds(), + (otherNamesData.mTimedOut ? "timeout" : ""))); } #endif } +#define OTHERNAMES_TIMEOUT 200 + PLDHashOperator gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey, nsRefPtr& aFamilyEntry, void* userArg) { - gfxPlatformFontList *fc = static_cast(userArg); - aFamilyEntry->ReadOtherFamilyNames(fc); + InitOtherNamesData *data = static_cast(userArg); + + aFamilyEntry->ReadOtherFamilyNames(data->mFontList); + TimeDuration elapsed = TimeStamp::Now() - data->mStartTime; + if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) { + data->mTimedOut = true; + return PL_DHASH_STOP; + } return PL_DHASH_NEXT; } - + struct ReadFaceNamesData { ReadFaceNamesData(gfxPlatformFontList *aFontList, TimeStamp aStartTime) : mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false) @@ -708,6 +738,13 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily) InitOtherFamilyNames(); if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) { return CheckFamily(familyEntry); + } else if (!mOtherFamilyNamesInitialized) { + // localized family names load timed out, add name to list of + // names to check after localized names are loaded + if (!mOtherNamesMissed) { + mOtherNamesMissed = new nsTHashtable(4); + } + mOtherNamesMissed->PutEntry(key); } } @@ -930,12 +967,34 @@ gfxPlatformFontList::LookupMissedFaceNamesProc(nsStringHashKey *aKey, return PL_DHASH_NEXT; } +struct LookupMissedOtherNamesData { + LookupMissedOtherNamesData(gfxPlatformFontList *aFontList) + : mFontList(aFontList), mFoundName(false) {} + + gfxPlatformFontList *mFontList; + bool mFoundName; +}; + +/*static*/ PLDHashOperator +gfxPlatformFontList::LookupMissedOtherNamesProc(nsStringHashKey *aKey, + void *aUserArg) +{ + LookupMissedOtherNamesData *data = + reinterpret_cast(aUserArg); + + if (data->mFontList->FindFamily(aKey->GetKey())) { + data->mFoundName = true; + return PL_DHASH_STOP; + } + return PL_DHASH_NEXT; +} + void gfxPlatformFontList::CleanupLoader() { mFontFamiliesToLoad.Clear(); mNumFamilies = 0; - bool rebuilt = false; + bool rebuilt = false, forceReflow = false; // if had missed face names that are now available, force reflow all if (mFaceNamesMissed && @@ -949,18 +1008,30 @@ gfxPlatformFontList::CleanupLoader() mFaceNamesMissed = nullptr; } + if (mOtherNamesMissed) { + LookupMissedOtherNamesData othernamesdata(this); + mOtherNamesMissed->EnumerateEntries(LookupMissedOtherNamesProc, + &othernamesdata); + mOtherNamesMissed = nullptr; + if (othernamesdata.mFoundName) { + forceReflow = true; + ForceGlobalReflow(); + } + } + #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 %s", + "%d facenames %d othernames %s %s", mLoadTime.ToMilliseconds(), mFontInfo->mLoadStats.families, mFontInfo->mLoadStats.fonts, mFontInfo->mLoadStats.cmaps, mFontInfo->mLoadStats.facenames, mFontInfo->mLoadStats.othernames, - (rebuilt ? "(userfont sets rebuilt)" : ""))); + (rebuilt ? "(userfont sets rebuilt)" : ""), + (forceReflow ? "(global reflow)" : ""))); } #endif diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 77dd07c20221..4ade7dc5ee6a 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -225,7 +225,7 @@ protected: // verifies that a family contains a non-zero font count gfxFontFamily* CheckFamily(gfxFontFamily *aFamily); - // separate initialization for reading in name tables, since this is expensive + // initialize localized family names void InitOtherFamilyNames(); static PLDHashOperator @@ -253,6 +253,9 @@ protected: static PLDHashOperator LookupMissedFaceNamesProc(nsStringHashKey *aKey, void *aUserArg); + static PLDHashOperator LookupMissedOtherNamesProc(nsStringHashKey *aKey, + void *aUserArg); + // commonly used fonts for which the name table should be loaded at startup virtual void PreloadNamesList(); @@ -314,6 +317,9 @@ protected: // face names missed when face name loading takes a long time nsAutoPtr > mFaceNamesMissed; + // localized family names missed when face name loading takes a long time + nsAutoPtr > mOtherNamesMissed; + // cached pref font lists // maps list of family names ==> array of family entries, one per lang group nsDataHashtable > > mPrefFonts;