1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxPlatformFontList.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1233 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifdef MOZ_LOGGING 1.10 +#define FORCE_PR_LOG /* Allow logging in the release build */ 1.11 +#endif 1.12 +#include "prlog.h" 1.13 + 1.14 +#include "gfxPlatformFontList.h" 1.15 +#include "gfxUserFontSet.h" 1.16 + 1.17 +#include "nsUnicharUtils.h" 1.18 +#include "nsUnicodeRange.h" 1.19 +#include "nsUnicodeProperties.h" 1.20 + 1.21 +#include "mozilla/Attributes.h" 1.22 +#include "mozilla/Likely.h" 1.23 +#include "mozilla/MemoryReporting.h" 1.24 +#include "mozilla/Preferences.h" 1.25 +#include "mozilla/Telemetry.h" 1.26 +#include "mozilla/TimeStamp.h" 1.27 +#include "mozilla/gfx/2D.h" 1.28 + 1.29 +using namespace mozilla; 1.30 + 1.31 +#ifdef PR_LOGGING 1.32 + 1.33 +#define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.34 + PR_LOG_DEBUG, args) 1.35 +#define LOG_FONTLIST_ENABLED() PR_LOG_TEST( \ 1.36 + gfxPlatform::GetLog(eGfxLog_fontlist), \ 1.37 + PR_LOG_DEBUG) 1.38 +#define LOG_FONTINIT(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), \ 1.39 + PR_LOG_DEBUG, args) 1.40 +#define LOG_FONTINIT_ENABLED() PR_LOG_TEST( \ 1.41 + gfxPlatform::GetLog(eGfxLog_fontinit), \ 1.42 + PR_LOG_DEBUG) 1.43 + 1.44 +#endif // PR_LOGGING 1.45 + 1.46 +gfxPlatformFontList *gfxPlatformFontList::sPlatformFontList = nullptr; 1.47 + 1.48 +// Character ranges that require complex-script shaping support in the font, 1.49 +// and so should be masked out by ReadCMAP if the necessary layout tables 1.50 +// are not present. 1.51 +// Currently used by the Mac and FT2 implementations only, but probably should 1.52 +// be supported on Windows as well. 1.53 +const gfxFontEntry::ScriptRange gfxPlatformFontList::sComplexScriptRanges[] = { 1.54 + // Actually, now that harfbuzz supports presentation-forms shaping for 1.55 + // Arabic, we can render it without layout tables. So maybe we don't 1.56 + // want to mask the basic Arabic block here? 1.57 + // This affects the arabic-fallback-*.html reftests, which rely on 1.58 + // loading a font that *doesn't* have any GSUB table. 1.59 + { 0x0600, 0x06FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } }, 1.60 + { 0x0700, 0x074F, { TRUETYPE_TAG('s','y','r','c'), 0, 0 } }, 1.61 + { 0x0750, 0x077F, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } }, 1.62 + { 0x08A0, 0x08FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } }, 1.63 + { 0x0900, 0x097F, { TRUETYPE_TAG('d','e','v','2'), 1.64 + TRUETYPE_TAG('d','e','v','a'), 0 } }, 1.65 + { 0x0980, 0x09FF, { TRUETYPE_TAG('b','n','g','2'), 1.66 + TRUETYPE_TAG('b','e','n','g'), 0 } }, 1.67 + { 0x0A00, 0x0A7F, { TRUETYPE_TAG('g','u','r','2'), 1.68 + TRUETYPE_TAG('g','u','r','u'), 0 } }, 1.69 + { 0x0A80, 0x0AFF, { TRUETYPE_TAG('g','j','r','2'), 1.70 + TRUETYPE_TAG('g','u','j','r'), 0 } }, 1.71 + { 0x0B00, 0x0B7F, { TRUETYPE_TAG('o','r','y','2'), 1.72 + TRUETYPE_TAG('o','r','y','a'), 0 } }, 1.73 + { 0x0B80, 0x0BFF, { TRUETYPE_TAG('t','m','l','2'), 1.74 + TRUETYPE_TAG('t','a','m','l'), 0 } }, 1.75 + { 0x0C00, 0x0C7F, { TRUETYPE_TAG('t','e','l','2'), 1.76 + TRUETYPE_TAG('t','e','l','u'), 0 } }, 1.77 + { 0x0C80, 0x0CFF, { TRUETYPE_TAG('k','n','d','2'), 1.78 + TRUETYPE_TAG('k','n','d','a'), 0 } }, 1.79 + { 0x0D00, 0x0D7F, { TRUETYPE_TAG('m','l','m','2'), 1.80 + TRUETYPE_TAG('m','l','y','m'), 0 } }, 1.81 + { 0x0D80, 0x0DFF, { TRUETYPE_TAG('s','i','n','h'), 0, 0 } }, 1.82 + { 0x0E80, 0x0EFF, { TRUETYPE_TAG('l','a','o',' '), 0, 0 } }, 1.83 + { 0x0F00, 0x0FFF, { TRUETYPE_TAG('t','i','b','t'), 0, 0 } }, 1.84 + { 0x1000, 0x109f, { TRUETYPE_TAG('m','y','m','r'), 1.85 + TRUETYPE_TAG('m','y','m','2'), 0 } }, 1.86 + { 0x1780, 0x17ff, { TRUETYPE_TAG('k','h','m','r'), 0, 0 } }, 1.87 + // Khmer Symbols (19e0..19ff) don't seem to need any special shaping 1.88 + { 0xaa60, 0xaa7f, { TRUETYPE_TAG('m','y','m','r'), 1.89 + TRUETYPE_TAG('m','y','m','2'), 0 } }, 1.90 + // Thai seems to be "renderable" without AAT morphing tables 1.91 + { 0, 0, { 0, 0, 0 } } // terminator 1.92 +}; 1.93 + 1.94 +// prefs for the font info loader 1.95 +#define FONT_LOADER_FAMILIES_PER_SLICE_PREF "gfx.font_loader.families_per_slice" 1.96 +#define FONT_LOADER_DELAY_PREF "gfx.font_loader.delay" 1.97 +#define FONT_LOADER_INTERVAL_PREF "gfx.font_loader.interval" 1.98 + 1.99 +static const char* kObservedPrefs[] = { 1.100 + "font.", 1.101 + "font.name-list.", 1.102 + "intl.accept_languages", // hmmmm... 1.103 + nullptr 1.104 +}; 1.105 + 1.106 +class gfxFontListPrefObserver MOZ_FINAL : public nsIObserver { 1.107 +public: 1.108 + NS_DECL_ISUPPORTS 1.109 + NS_DECL_NSIOBSERVER 1.110 +}; 1.111 + 1.112 +static gfxFontListPrefObserver* gFontListPrefObserver = nullptr; 1.113 + 1.114 +NS_IMPL_ISUPPORTS(gfxFontListPrefObserver, nsIObserver) 1.115 + 1.116 +NS_IMETHODIMP 1.117 +gfxFontListPrefObserver::Observe(nsISupports *aSubject, 1.118 + const char *aTopic, 1.119 + const char16_t *aData) 1.120 +{ 1.121 + NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic"); 1.122 + // XXX this could be made to only clear out the cache for the prefs that were changed 1.123 + // but it probably isn't that big a deal. 1.124 + gfxPlatformFontList::PlatformFontList()->ClearPrefFonts(); 1.125 + gfxFontCache::GetCache()->AgeAllGenerations(); 1.126 + return NS_OK; 1.127 +} 1.128 + 1.129 +MOZ_DEFINE_MALLOC_SIZE_OF(FontListMallocSizeOf) 1.130 + 1.131 +NS_IMPL_ISUPPORTS(gfxPlatformFontList::MemoryReporter, nsIMemoryReporter) 1.132 + 1.133 +NS_IMETHODIMP 1.134 +gfxPlatformFontList::MemoryReporter::CollectReports 1.135 + (nsIMemoryReporterCallback* aCb, 1.136 + nsISupports* aClosure) 1.137 +{ 1.138 + FontListSizes sizes; 1.139 + sizes.mFontListSize = 0; 1.140 + sizes.mFontTableCacheSize = 0; 1.141 + sizes.mCharMapsSize = 0; 1.142 + 1.143 + gfxPlatformFontList::PlatformFontList()->AddSizeOfIncludingThis(&FontListMallocSizeOf, 1.144 + &sizes); 1.145 + 1.146 + aCb->Callback(EmptyCString(), 1.147 + NS_LITERAL_CSTRING("explicit/gfx/font-list"), 1.148 + KIND_HEAP, UNITS_BYTES, sizes.mFontListSize, 1.149 + NS_LITERAL_CSTRING("Memory used to manage the list of font families and faces."), 1.150 + aClosure); 1.151 + 1.152 + aCb->Callback(EmptyCString(), 1.153 + NS_LITERAL_CSTRING("explicit/gfx/font-charmaps"), 1.154 + KIND_HEAP, UNITS_BYTES, sizes.mCharMapsSize, 1.155 + NS_LITERAL_CSTRING("Memory used to record the character coverage of individual fonts."), 1.156 + aClosure); 1.157 + 1.158 + if (sizes.mFontTableCacheSize) { 1.159 + aCb->Callback(EmptyCString(), 1.160 + NS_LITERAL_CSTRING("explicit/gfx/font-tables"), 1.161 + KIND_HEAP, UNITS_BYTES, sizes.mFontTableCacheSize, 1.162 + NS_LITERAL_CSTRING("Memory used for cached font metrics and layout tables."), 1.163 + aClosure); 1.164 + } 1.165 + 1.166 + return NS_OK; 1.167 +} 1.168 + 1.169 +gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames) 1.170 + : mFontFamilies(100), mOtherFamilyNames(30), 1.171 + mPrefFonts(10), mBadUnderlineFamilyNames(10), mSharedCmaps(16), 1.172 + mStartIndex(0), mIncrement(1), mNumFamilies(0) 1.173 +{ 1.174 + mOtherFamilyNamesInitialized = false; 1.175 + 1.176 + if (aNeedFullnamePostscriptNames) { 1.177 + mExtraNames = new ExtraNames(); 1.178 + } 1.179 + mFaceNameListsInitialized = false; 1.180 + 1.181 + LoadBadUnderlineList(); 1.182 + 1.183 + // pref changes notification setup 1.184 + NS_ASSERTION(!gFontListPrefObserver, 1.185 + "There has been font list pref observer already"); 1.186 + gFontListPrefObserver = new gfxFontListPrefObserver(); 1.187 + NS_ADDREF(gFontListPrefObserver); 1.188 + Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs); 1.189 + 1.190 + RegisterStrongMemoryReporter(new MemoryReporter()); 1.191 +} 1.192 + 1.193 +gfxPlatformFontList::~gfxPlatformFontList() 1.194 +{ 1.195 + mSharedCmaps.Clear(); 1.196 + NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer"); 1.197 + Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs); 1.198 + NS_RELEASE(gFontListPrefObserver); 1.199 +} 1.200 + 1.201 +nsresult 1.202 +gfxPlatformFontList::InitFontList() 1.203 +{ 1.204 + mFontFamilies.Clear(); 1.205 + mOtherFamilyNames.Clear(); 1.206 + mOtherFamilyNamesInitialized = false; 1.207 + if (mExtraNames) { 1.208 + mExtraNames->mFullnames.Clear(); 1.209 + mExtraNames->mPostscriptNames.Clear(); 1.210 + } 1.211 + mFaceNameListsInitialized = false; 1.212 + mPrefFonts.Clear(); 1.213 + mReplacementCharFallbackFamily = nullptr; 1.214 + CancelLoader(); 1.215 + 1.216 + // initialize ranges of characters for which system-wide font search should be skipped 1.217 + mCodepointsWithNoFonts.reset(); 1.218 + mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls 1.219 + mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls 1.220 + 1.221 + sPlatformFontList = this; 1.222 + 1.223 + return NS_OK; 1.224 +} 1.225 + 1.226 +void 1.227 +gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult) 1.228 +{ 1.229 + aResult = aKeyName; 1.230 + ToLowerCase(aResult); 1.231 +} 1.232 + 1.233 +struct InitOtherNamesData { 1.234 + InitOtherNamesData(gfxPlatformFontList *aFontList, 1.235 + TimeStamp aStartTime) 1.236 + : mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false) 1.237 + {} 1.238 + 1.239 + gfxPlatformFontList *mFontList; 1.240 + TimeStamp mStartTime; 1.241 + bool mTimedOut; 1.242 +}; 1.243 + 1.244 +void 1.245 +gfxPlatformFontList::InitOtherFamilyNames() 1.246 +{ 1.247 + if (mOtherFamilyNamesInitialized) { 1.248 + return; 1.249 + } 1.250 + 1.251 + TimeStamp start = TimeStamp::Now(); 1.252 + 1.253 + // iterate over all font families and read in other family names 1.254 + InitOtherNamesData otherNamesData(this, start); 1.255 + 1.256 + mFontFamilies.Enumerate(gfxPlatformFontList::InitOtherFamilyNamesProc, 1.257 + &otherNamesData); 1.258 + 1.259 + if (!otherNamesData.mTimedOut) { 1.260 + mOtherFamilyNamesInitialized = true; 1.261 + } 1.262 + TimeStamp end = TimeStamp::Now(); 1.263 + Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES, 1.264 + start, end); 1.265 + 1.266 +#ifdef PR_LOGGING 1.267 + if (LOG_FONTINIT_ENABLED()) { 1.268 + TimeDuration elapsed = end - start; 1.269 + LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s", 1.270 + elapsed.ToMilliseconds(), 1.271 + (otherNamesData.mTimedOut ? "timeout" : ""))); 1.272 + } 1.273 +#endif 1.274 +} 1.275 + 1.276 +#define OTHERNAMES_TIMEOUT 200 1.277 + 1.278 +PLDHashOperator 1.279 +gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey, 1.280 + nsRefPtr<gfxFontFamily>& aFamilyEntry, 1.281 + void* userArg) 1.282 +{ 1.283 + InitOtherNamesData *data = static_cast<InitOtherNamesData*>(userArg); 1.284 + 1.285 + aFamilyEntry->ReadOtherFamilyNames(data->mFontList); 1.286 + TimeDuration elapsed = TimeStamp::Now() - data->mStartTime; 1.287 + if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) { 1.288 + data->mTimedOut = true; 1.289 + return PL_DHASH_STOP; 1.290 + } 1.291 + return PL_DHASH_NEXT; 1.292 +} 1.293 + 1.294 +struct ReadFaceNamesData { 1.295 + ReadFaceNamesData(gfxPlatformFontList *aFontList, TimeStamp aStartTime) 1.296 + : mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false) 1.297 + {} 1.298 + 1.299 + gfxPlatformFontList *mFontList; 1.300 + TimeStamp mStartTime; 1.301 + bool mTimedOut; 1.302 + 1.303 + // if mFirstChar is not empty, only load facenames for families 1.304 + // that start with this character 1.305 + nsString mFirstChar; 1.306 +}; 1.307 + 1.308 +gfxFontEntry* 1.309 +gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName) 1.310 +{ 1.311 + TimeStamp start = TimeStamp::Now(); 1.312 + gfxFontEntry *lookup = nullptr; 1.313 + 1.314 + ReadFaceNamesData faceNameListsData(this, start); 1.315 + 1.316 + // iterate over familes starting with the same letter 1.317 + faceNameListsData.mFirstChar.Assign(aFaceName.CharAt(0)); 1.318 + ToLowerCase(faceNameListsData.mFirstChar); 1.319 + mFontFamilies.Enumerate(gfxPlatformFontList::ReadFaceNamesProc, 1.320 + &faceNameListsData); 1.321 + lookup = FindFaceName(aFaceName); 1.322 + 1.323 + TimeStamp end = TimeStamp::Now(); 1.324 + Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITFACENAMELISTS, 1.325 + start, end); 1.326 +#ifdef PR_LOGGING 1.327 + if (LOG_FONTINIT_ENABLED()) { 1.328 + TimeDuration elapsed = end - start; 1.329 + LOG_FONTINIT(("(fontinit) SearchFamiliesForFaceName took %8.2f ms %s %s", 1.330 + elapsed.ToMilliseconds(), 1.331 + (lookup ? "found name" : ""), 1.332 + (faceNameListsData.mTimedOut ? "timeout" : ""))); 1.333 + } 1.334 +#endif 1.335 + 1.336 + return lookup; 1.337 +} 1.338 + 1.339 +// time limit for loading facename lists (ms) 1.340 +#define NAMELIST_TIMEOUT 200 1.341 + 1.342 +PLDHashOperator 1.343 +gfxPlatformFontList::ReadFaceNamesProc(nsStringHashKey::KeyType aKey, 1.344 + nsRefPtr<gfxFontFamily>& aFamilyEntry, 1.345 + void* userArg) 1.346 +{ 1.347 + ReadFaceNamesData *data = static_cast<ReadFaceNamesData*>(userArg); 1.348 + gfxPlatformFontList *fc = data->mFontList; 1.349 + 1.350 + // when filtering, skip names that don't start with the filter character 1.351 + if (!(data->mFirstChar.IsEmpty())) { 1.352 + char16_t firstChar = aKey.CharAt(0); 1.353 + nsAutoString firstCharStr(&firstChar, 1); 1.354 + ToLowerCase(firstCharStr); 1.355 + if (!firstCharStr.Equals(data->mFirstChar)) { 1.356 + return PL_DHASH_NEXT; 1.357 + } 1.358 + } 1.359 + aFamilyEntry->ReadFaceNames(fc, fc->NeedFullnamePostscriptNames()); 1.360 + 1.361 + TimeDuration elapsed = TimeStamp::Now() - data->mStartTime; 1.362 + if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) { 1.363 + data->mTimedOut = true; 1.364 + return PL_DHASH_STOP; 1.365 + } 1.366 + return PL_DHASH_NEXT; 1.367 +} 1.368 + 1.369 +gfxFontEntry* 1.370 +gfxPlatformFontList::FindFaceName(const nsAString& aFaceName) 1.371 +{ 1.372 + gfxFontEntry *lookup; 1.373 + 1.374 + // lookup in name lookup tables, return null if not found 1.375 + if (mExtraNames && 1.376 + ((lookup = mExtraNames->mPostscriptNames.GetWeak(aFaceName)) || 1.377 + (lookup = mExtraNames->mFullnames.GetWeak(aFaceName)))) { 1.378 + return lookup; 1.379 + } 1.380 + 1.381 + return nullptr; 1.382 +} 1.383 + 1.384 +gfxFontEntry* 1.385 +gfxPlatformFontList::LookupInFaceNameLists(const nsAString& aFaceName) 1.386 +{ 1.387 + gfxFontEntry *lookup = nullptr; 1.388 + 1.389 + // initialize facename lookup tables if needed 1.390 + // note: this can terminate early or time out, in which case 1.391 + // mFaceNameListsInitialized remains false 1.392 + if (!mFaceNameListsInitialized) { 1.393 + lookup = SearchFamiliesForFaceName(aFaceName); 1.394 + if (lookup) { 1.395 + return lookup; 1.396 + } 1.397 + } 1.398 + 1.399 + // lookup in name lookup tables, return null if not found 1.400 + if (!(lookup = FindFaceName(aFaceName))) { 1.401 + // names not completely initialized, so keep track of lookup misses 1.402 + if (!mFaceNameListsInitialized) { 1.403 + if (!mFaceNamesMissed) { 1.404 + mFaceNamesMissed = new nsTHashtable<nsStringHashKey>(4); 1.405 + } 1.406 + mFaceNamesMissed->PutEntry(aFaceName); 1.407 + } 1.408 + } 1.409 + 1.410 + return lookup; 1.411 +} 1.412 + 1.413 +void 1.414 +gfxPlatformFontList::PreloadNamesList() 1.415 +{ 1.416 + nsAutoTArray<nsString, 10> preloadFonts; 1.417 + gfxFontUtils::GetPrefsFontList("font.preload-names-list", preloadFonts); 1.418 + 1.419 + uint32_t numFonts = preloadFonts.Length(); 1.420 + for (uint32_t i = 0; i < numFonts; i++) { 1.421 + nsAutoString key; 1.422 + GenerateFontListKey(preloadFonts[i], key); 1.423 + 1.424 + // only search canonical names! 1.425 + gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key); 1.426 + if (familyEntry) { 1.427 + familyEntry->ReadOtherFamilyNames(this); 1.428 + } 1.429 + } 1.430 + 1.431 +} 1.432 + 1.433 +void 1.434 +gfxPlatformFontList::SetFixedPitch(const nsAString& aFamilyName) 1.435 +{ 1.436 + gfxFontFamily *family = FindFamily(aFamilyName); 1.437 + if (!family) return; 1.438 + 1.439 + family->FindStyleVariations(); 1.440 + nsTArray<nsRefPtr<gfxFontEntry> >& fontlist = family->GetFontList(); 1.441 + 1.442 + uint32_t i, numFonts = fontlist.Length(); 1.443 + 1.444 + for (i = 0; i < numFonts; i++) { 1.445 + fontlist[i]->mFixedPitch = 1; 1.446 + } 1.447 +} 1.448 + 1.449 +void 1.450 +gfxPlatformFontList::LoadBadUnderlineList() 1.451 +{ 1.452 + nsAutoTArray<nsString, 10> blacklist; 1.453 + gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset", blacklist); 1.454 + uint32_t numFonts = blacklist.Length(); 1.455 + for (uint32_t i = 0; i < numFonts; i++) { 1.456 + nsAutoString key; 1.457 + GenerateFontListKey(blacklist[i], key); 1.458 + mBadUnderlineFamilyNames.PutEntry(key); 1.459 + } 1.460 +} 1.461 + 1.462 +bool 1.463 +gfxPlatformFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName) 1.464 +{ 1.465 + gfxFontFamily *family = FindFamily(aFontName); 1.466 + if (family) { 1.467 + aResolvedFontName = family->Name(); 1.468 + return true; 1.469 + } 1.470 + return false; 1.471 +} 1.472 + 1.473 +static PLDHashOperator 1.474 +RebuildLocalFonts(nsPtrHashKey<gfxUserFontSet>* aKey, 1.475 + void* aClosure) 1.476 +{ 1.477 + aKey->GetKey()->RebuildLocalRules(); 1.478 + return PL_DHASH_NEXT; 1.479 +} 1.480 + 1.481 +void 1.482 +gfxPlatformFontList::UpdateFontList() 1.483 +{ 1.484 + InitFontList(); 1.485 + mUserFontSetList.EnumerateEntries(RebuildLocalFonts, nullptr); 1.486 +} 1.487 + 1.488 +struct FontListData { 1.489 + FontListData(nsIAtom *aLangGroup, 1.490 + const nsACString& aGenericFamily, 1.491 + nsTArray<nsString>& aListOfFonts) : 1.492 + mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), 1.493 + mListOfFonts(aListOfFonts) {} 1.494 + nsIAtom *mLangGroup; 1.495 + const nsACString& mGenericFamily; 1.496 + nsTArray<nsString>& mListOfFonts; 1.497 +}; 1.498 + 1.499 +PLDHashOperator 1.500 +gfxPlatformFontList::HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey, 1.501 + nsRefPtr<gfxFontFamily>& aFamilyEntry, 1.502 + void *aUserArg) 1.503 +{ 1.504 + FontListData *data = static_cast<FontListData*>(aUserArg); 1.505 + 1.506 + // use the first variation for now. This data should be the same 1.507 + // for all the variations and should probably be moved up to 1.508 + // the Family 1.509 + gfxFontStyle style; 1.510 + style.language = data->mLangGroup; 1.511 + bool needsBold; 1.512 + nsRefPtr<gfxFontEntry> aFontEntry = aFamilyEntry->FindFontForStyle(style, needsBold); 1.513 + NS_ASSERTION(aFontEntry, "couldn't find any font entry in family"); 1.514 + if (!aFontEntry) 1.515 + return PL_DHASH_NEXT; 1.516 + 1.517 + /* skip symbol fonts */ 1.518 + if (aFontEntry->IsSymbolFont()) 1.519 + return PL_DHASH_NEXT; 1.520 + 1.521 + if (aFontEntry->SupportsLangGroup(data->mLangGroup) && 1.522 + aFontEntry->MatchesGenericFamily(data->mGenericFamily)) { 1.523 + nsAutoString localizedFamilyName; 1.524 + aFamilyEntry->LocalizedName(localizedFamilyName); 1.525 + data->mListOfFonts.AppendElement(localizedFamilyName); 1.526 + } 1.527 + 1.528 + return PL_DHASH_NEXT; 1.529 +} 1.530 + 1.531 +void 1.532 +gfxPlatformFontList::GetFontList(nsIAtom *aLangGroup, 1.533 + const nsACString& aGenericFamily, 1.534 + nsTArray<nsString>& aListOfFonts) 1.535 +{ 1.536 + FontListData data(aLangGroup, aGenericFamily, aListOfFonts); 1.537 + 1.538 + mFontFamilies.Enumerate(gfxPlatformFontList::HashEnumFuncForFamilies, &data); 1.539 + 1.540 + aListOfFonts.Sort(); 1.541 + aListOfFonts.Compact(); 1.542 +} 1.543 + 1.544 +struct FontFamilyListData { 1.545 + FontFamilyListData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 1.546 + : mFamilyArray(aFamilyArray) 1.547 + {} 1.548 + 1.549 + static PLDHashOperator AppendFamily(nsStringHashKey::KeyType aKey, 1.550 + nsRefPtr<gfxFontFamily>& aFamilyEntry, 1.551 + void *aUserArg) 1.552 + { 1.553 + FontFamilyListData *data = static_cast<FontFamilyListData*>(aUserArg); 1.554 + data->mFamilyArray.AppendElement(aFamilyEntry); 1.555 + return PL_DHASH_NEXT; 1.556 + } 1.557 + 1.558 + nsTArray<nsRefPtr<gfxFontFamily> >& mFamilyArray; 1.559 +}; 1.560 + 1.561 +void 1.562 +gfxPlatformFontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 1.563 +{ 1.564 + FontFamilyListData data(aFamilyArray); 1.565 + mFontFamilies.Enumerate(FontFamilyListData::AppendFamily, &data); 1.566 +} 1.567 + 1.568 +gfxFontEntry* 1.569 +gfxPlatformFontList::SystemFindFontForChar(const uint32_t aCh, 1.570 + int32_t aRunScript, 1.571 + const gfxFontStyle* aStyle) 1.572 + { 1.573 + gfxFontEntry* fontEntry = nullptr; 1.574 + 1.575 + // is codepoint with no matching font? return null immediately 1.576 + if (mCodepointsWithNoFonts.test(aCh)) { 1.577 + return nullptr; 1.578 + } 1.579 + 1.580 + // Try to short-circuit font fallback for U+FFFD, used to represent 1.581 + // encoding errors: just use cached family from last time U+FFFD was seen. 1.582 + // This helps speed up pages with lots of encoding errors, binary-as-text, 1.583 + // etc. 1.584 + if (aCh == 0xFFFD && mReplacementCharFallbackFamily) { 1.585 + bool needsBold; // ignored in the system fallback case 1.586 + 1.587 + fontEntry = 1.588 + mReplacementCharFallbackFamily->FindFontForStyle(*aStyle, 1.589 + needsBold); 1.590 + 1.591 + // this should never fail, as we must have found U+FFFD in order to set 1.592 + // mReplacementCharFallbackFamily at all, but better play it safe 1.593 + if (fontEntry && fontEntry->TestCharacterMap(aCh)) { 1.594 + return fontEntry; 1.595 + } 1.596 + } 1.597 + 1.598 + TimeStamp start = TimeStamp::Now(); 1.599 + 1.600 + // search commonly available fonts 1.601 + bool common = true; 1.602 + gfxFontFamily *fallbackFamily = nullptr; 1.603 + fontEntry = CommonFontFallback(aCh, aRunScript, aStyle, &fallbackFamily); 1.604 + 1.605 + // if didn't find a font, do system-wide fallback (except for specials) 1.606 + uint32_t cmapCount = 0; 1.607 + if (!fontEntry) { 1.608 + common = false; 1.609 + fontEntry = GlobalFontFallback(aCh, aRunScript, aStyle, cmapCount, 1.610 + &fallbackFamily); 1.611 + } 1.612 + TimeDuration elapsed = TimeStamp::Now() - start; 1.613 + 1.614 +#ifdef PR_LOGGING 1.615 + PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun); 1.616 + 1.617 + if (MOZ_UNLIKELY(PR_LOG_TEST(log, PR_LOG_WARNING))) { 1.618 + uint32_t unicodeRange = FindCharUnicodeRange(aCh); 1.619 + int32_t script = mozilla::unicode::GetScriptCode(aCh); 1.620 + PR_LOG(log, PR_LOG_WARNING,\ 1.621 + ("(textrun-systemfallback-%s) char: u+%6.6x " 1.622 + "unicode-range: %d script: %d match: [%s]" 1.623 + " time: %dus cmaps: %d\n", 1.624 + (common ? "common" : "global"), aCh, 1.625 + unicodeRange, script, 1.626 + (fontEntry ? NS_ConvertUTF16toUTF8(fontEntry->Name()).get() : 1.627 + "<none>"), 1.628 + int32_t(elapsed.ToMicroseconds()), 1.629 + cmapCount)); 1.630 + } 1.631 +#endif 1.632 + 1.633 + // no match? add to set of non-matching codepoints 1.634 + if (!fontEntry) { 1.635 + mCodepointsWithNoFonts.set(aCh); 1.636 + } else if (aCh == 0xFFFD && fontEntry && fallbackFamily) { 1.637 + mReplacementCharFallbackFamily = fallbackFamily; 1.638 + } 1.639 + 1.640 + // track system fallback time 1.641 + static bool first = true; 1.642 + int32_t intElapsed = int32_t(first ? elapsed.ToMilliseconds() : 1.643 + elapsed.ToMicroseconds()); 1.644 + Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST : 1.645 + Telemetry::SYSTEM_FONT_FALLBACK), 1.646 + intElapsed); 1.647 + first = false; 1.648 + 1.649 + // track the script for which fallback occurred (incremented one make it 1.650 + // 1-based) 1.651 + Telemetry::Accumulate(Telemetry::SYSTEM_FONT_FALLBACK_SCRIPT, aRunScript + 1); 1.652 + 1.653 + return fontEntry; 1.654 +} 1.655 + 1.656 +PLDHashOperator 1.657 +gfxPlatformFontList::FindFontForCharProc(nsStringHashKey::KeyType aKey, nsRefPtr<gfxFontFamily>& aFamilyEntry, 1.658 + void *userArg) 1.659 +{ 1.660 + GlobalFontMatch *data = static_cast<GlobalFontMatch*>(userArg); 1.661 + 1.662 + // evaluate all fonts in this family for a match 1.663 + aFamilyEntry->FindFontForChar(data); 1.664 + 1.665 + return PL_DHASH_NEXT; 1.666 +} 1.667 + 1.668 +#define NUM_FALLBACK_FONTS 8 1.669 + 1.670 +gfxFontEntry* 1.671 +gfxPlatformFontList::CommonFontFallback(const uint32_t aCh, 1.672 + int32_t aRunScript, 1.673 + const gfxFontStyle* aMatchStyle, 1.674 + gfxFontFamily** aMatchedFamily) 1.675 +{ 1.676 + nsAutoTArray<const char*,NUM_FALLBACK_FONTS> defaultFallbacks; 1.677 + uint32_t i, numFallbacks; 1.678 + 1.679 + gfxPlatform::GetPlatform()->GetCommonFallbackFonts(aCh, aRunScript, 1.680 + defaultFallbacks); 1.681 + numFallbacks = defaultFallbacks.Length(); 1.682 + for (i = 0; i < numFallbacks; i++) { 1.683 + nsAutoString familyName; 1.684 + const char *fallbackFamily = defaultFallbacks[i]; 1.685 + 1.686 + familyName.AppendASCII(fallbackFamily); 1.687 + gfxFontFamily *fallback = 1.688 + gfxPlatformFontList::PlatformFontList()->FindFamily(familyName); 1.689 + if (!fallback) 1.690 + continue; 1.691 + 1.692 + gfxFontEntry *fontEntry; 1.693 + bool needsBold; // ignored in the system fallback case 1.694 + 1.695 + // use first font in list that supports a given character 1.696 + fontEntry = fallback->FindFontForStyle(*aMatchStyle, needsBold); 1.697 + if (fontEntry && fontEntry->TestCharacterMap(aCh)) { 1.698 + *aMatchedFamily = fallback; 1.699 + return fontEntry; 1.700 + } 1.701 + } 1.702 + 1.703 + return nullptr; 1.704 +} 1.705 + 1.706 +gfxFontEntry* 1.707 +gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh, 1.708 + int32_t aRunScript, 1.709 + const gfxFontStyle* aMatchStyle, 1.710 + uint32_t& aCmapCount, 1.711 + gfxFontFamily** aMatchedFamily) 1.712 +{ 1.713 + // otherwise, try to find it among local fonts 1.714 + GlobalFontMatch data(aCh, aRunScript, aMatchStyle); 1.715 + 1.716 + // iterate over all font families to find a font that support the character 1.717 + mFontFamilies.Enumerate(gfxPlatformFontList::FindFontForCharProc, &data); 1.718 + 1.719 + aCmapCount = data.mCmapsTested; 1.720 + *aMatchedFamily = data.mMatchedFamily; 1.721 + 1.722 + return data.mBestMatch; 1.723 +} 1.724 + 1.725 +#ifdef XP_WIN 1.726 +#include <windows.h> 1.727 + 1.728 +// crude hack for using when monitoring process 1.729 +static void LogRegistryEvent(const wchar_t *msg) 1.730 +{ 1.731 + HKEY dummyKey; 1.732 + HRESULT hr; 1.733 + wchar_t buf[512]; 1.734 + 1.735 + wsprintfW(buf, L" log %s", msg); 1.736 + hr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey); 1.737 + if (SUCCEEDED(hr)) { 1.738 + RegCloseKey(dummyKey); 1.739 + } 1.740 +} 1.741 +#endif 1.742 + 1.743 +gfxFontFamily* 1.744 +gfxPlatformFontList::CheckFamily(gfxFontFamily *aFamily) 1.745 +{ 1.746 + if (aFamily && !aFamily->HasStyles()) { 1.747 + aFamily->FindStyleVariations(); 1.748 + aFamily->CheckForSimpleFamily(); 1.749 + } 1.750 + 1.751 + if (aFamily && aFamily->GetFontList().Length() == 0) { 1.752 + // failed to load any faces for this family, so discard it 1.753 + nsAutoString key; 1.754 + GenerateFontListKey(aFamily->Name(), key); 1.755 + mFontFamilies.Remove(key); 1.756 + return nullptr; 1.757 + } 1.758 + 1.759 + return aFamily; 1.760 +} 1.761 + 1.762 +gfxFontFamily* 1.763 +gfxPlatformFontList::FindFamily(const nsAString& aFamily) 1.764 +{ 1.765 + nsAutoString key; 1.766 + gfxFontFamily *familyEntry; 1.767 + GenerateFontListKey(aFamily, key); 1.768 + 1.769 + NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly"); 1.770 + 1.771 + // lookup in canonical (i.e. English) family name list 1.772 + if ((familyEntry = mFontFamilies.GetWeak(key))) { 1.773 + return CheckFamily(familyEntry); 1.774 + } 1.775 + 1.776 + // lookup in other family names list (mostly localized names) 1.777 + if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) { 1.778 + return CheckFamily(familyEntry); 1.779 + } 1.780 + 1.781 + // name not found and other family names not yet fully initialized so 1.782 + // initialize the rest of the list and try again. this is done lazily 1.783 + // since reading name table entries is expensive. 1.784 + // although ASCII localized family names are possible they don't occur 1.785 + // in practice so avoid pulling in names at startup 1.786 + if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) { 1.787 + InitOtherFamilyNames(); 1.788 + if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) { 1.789 + return CheckFamily(familyEntry); 1.790 + } else if (!mOtherFamilyNamesInitialized) { 1.791 + // localized family names load timed out, add name to list of 1.792 + // names to check after localized names are loaded 1.793 + if (!mOtherNamesMissed) { 1.794 + mOtherNamesMissed = new nsTHashtable<nsStringHashKey>(4); 1.795 + } 1.796 + mOtherNamesMissed->PutEntry(key); 1.797 + } 1.798 + } 1.799 + 1.800 + return nullptr; 1.801 +} 1.802 + 1.803 +gfxFontEntry* 1.804 +gfxPlatformFontList::FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold) 1.805 +{ 1.806 + gfxFontFamily *familyEntry = FindFamily(aFamily); 1.807 + 1.808 + aNeedsBold = false; 1.809 + 1.810 + if (familyEntry) 1.811 + return familyEntry->FindFontForStyle(*aStyle, aNeedsBold); 1.812 + 1.813 + return nullptr; 1.814 +} 1.815 + 1.816 +bool 1.817 +gfxPlatformFontList::GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array) 1.818 +{ 1.819 + return mPrefFonts.Get(uint32_t(aLangGroup), array); 1.820 +} 1.821 + 1.822 +void 1.823 +gfxPlatformFontList::SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array) 1.824 +{ 1.825 + mPrefFonts.Put(uint32_t(aLangGroup), array); 1.826 +} 1.827 + 1.828 +void 1.829 +gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName) 1.830 +{ 1.831 + nsAutoString key; 1.832 + GenerateFontListKey(aOtherFamilyName, key); 1.833 + 1.834 + if (!mOtherFamilyNames.GetWeak(key)) { 1.835 + mOtherFamilyNames.Put(key, aFamilyEntry); 1.836 +#ifdef PR_LOGGING 1.837 + LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, " 1.838 + "other family: %s\n", 1.839 + NS_ConvertUTF16toUTF8(aFamilyEntry->Name()).get(), 1.840 + NS_ConvertUTF16toUTF8(aOtherFamilyName).get())); 1.841 +#endif 1.842 + if (mBadUnderlineFamilyNames.Contains(key)) 1.843 + aFamilyEntry->SetBadUnderlineFamily(); 1.844 + } 1.845 +} 1.846 + 1.847 +void 1.848 +gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname) 1.849 +{ 1.850 + if (!mExtraNames->mFullnames.GetWeak(aFullname)) { 1.851 + mExtraNames->mFullnames.Put(aFullname, aFontEntry); 1.852 +#ifdef PR_LOGGING 1.853 + LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n", 1.854 + NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(), 1.855 + NS_ConvertUTF16toUTF8(aFullname).get())); 1.856 +#endif 1.857 + } 1.858 +} 1.859 + 1.860 +void 1.861 +gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName) 1.862 +{ 1.863 + if (!mExtraNames->mPostscriptNames.GetWeak(aPostscriptName)) { 1.864 + mExtraNames->mPostscriptNames.Put(aPostscriptName, aFontEntry); 1.865 +#ifdef PR_LOGGING 1.866 + LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n", 1.867 + NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(), 1.868 + NS_ConvertUTF16toUTF8(aPostscriptName).get())); 1.869 +#endif 1.870 + } 1.871 +} 1.872 + 1.873 +bool 1.874 +gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) 1.875 +{ 1.876 + aFamilyName.Truncate(); 1.877 + ResolveFontName(aFontName, aFamilyName); 1.878 + return !aFamilyName.IsEmpty(); 1.879 +} 1.880 + 1.881 +gfxCharacterMap* 1.882 +gfxPlatformFontList::FindCharMap(gfxCharacterMap *aCmap) 1.883 +{ 1.884 + aCmap->CalcHash(); 1.885 + gfxCharacterMap *cmap = AddCmap(aCmap); 1.886 + cmap->mShared = true; 1.887 + return cmap; 1.888 +} 1.889 + 1.890 +// add a cmap to the shared cmap set 1.891 +gfxCharacterMap* 1.892 +gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap) 1.893 +{ 1.894 + CharMapHashKey *found = 1.895 + mSharedCmaps.PutEntry(const_cast<gfxCharacterMap*>(aCharMap)); 1.896 + return found->GetKey(); 1.897 +} 1.898 + 1.899 +// remove the cmap from the shared cmap set 1.900 +void 1.901 +gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap) 1.902 +{ 1.903 + // skip lookups during teardown 1.904 + if (mSharedCmaps.Count() == 0) { 1.905 + return; 1.906 + } 1.907 + 1.908 + // cmap needs to match the entry *and* be the same ptr before removing 1.909 + CharMapHashKey *found = 1.910 + mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap)); 1.911 + if (found && found->GetKey() == aCharMap) { 1.912 + mSharedCmaps.RemoveEntry(const_cast<gfxCharacterMap*>(aCharMap)); 1.913 + } 1.914 +} 1.915 + 1.916 +static PLDHashOperator AppendFamilyToList(nsStringHashKey::KeyType aKey, 1.917 + nsRefPtr<gfxFontFamily>& aFamilyEntry, 1.918 + void *aUserArg) 1.919 +{ 1.920 + nsTArray<nsString> *familyNames = static_cast<nsTArray<nsString> *>(aUserArg); 1.921 + familyNames->AppendElement(aFamilyEntry->Name()); 1.922 + return PL_DHASH_NEXT; 1.923 +} 1.924 + 1.925 +void 1.926 +gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames) 1.927 +{ 1.928 + mFontFamilies.Enumerate(AppendFamilyToList, &aFontFamilyNames); 1.929 +} 1.930 + 1.931 +void 1.932 +gfxPlatformFontList::InitLoader() 1.933 +{ 1.934 + GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad); 1.935 + mStartIndex = 0; 1.936 + mNumFamilies = mFontInfo->mFontFamiliesToLoad.Length(); 1.937 + memset(&(mFontInfo->mLoadStats), 0, sizeof(mFontInfo->mLoadStats)); 1.938 +} 1.939 + 1.940 +#define FONT_LOADER_MAX_TIMESLICE 100 // max time for one pass through RunLoader = 100ms 1.941 + 1.942 +bool 1.943 +gfxPlatformFontList::LoadFontInfo() 1.944 +{ 1.945 + TimeStamp start = TimeStamp::Now(); 1.946 + uint32_t i, endIndex = mNumFamilies; 1.947 + bool loadCmaps = !UsesSystemFallback() || 1.948 + gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback(); 1.949 + 1.950 + // for each font family, load in various font info 1.951 + for (i = mStartIndex; i < endIndex; i++) { 1.952 + nsAutoString key; 1.953 + gfxFontFamily *familyEntry; 1.954 + GenerateFontListKey(mFontInfo->mFontFamiliesToLoad[i], key); 1.955 + 1.956 + // lookup in canonical (i.e. English) family name list 1.957 + if (!(familyEntry = mFontFamilies.GetWeak(key))) { 1.958 + continue; 1.959 + } 1.960 + 1.961 + // read in face names 1.962 + familyEntry->ReadFaceNames(this, NeedFullnamePostscriptNames(), mFontInfo); 1.963 + 1.964 + // load the cmaps if needed 1.965 + if (loadCmaps) { 1.966 + familyEntry->ReadAllCMAPs(mFontInfo); 1.967 + } 1.968 + 1.969 + // limit the time spent reading fonts in one pass 1.970 + TimeDuration elapsed = TimeStamp::Now() - start; 1.971 + if (elapsed.ToMilliseconds() > FONT_LOADER_MAX_TIMESLICE && 1.972 + i + 1 != endIndex) { 1.973 + endIndex = i + 1; 1.974 + break; 1.975 + } 1.976 + } 1.977 + 1.978 + mStartIndex = endIndex; 1.979 + bool done = mStartIndex >= mNumFamilies; 1.980 + 1.981 +#ifdef PR_LOGGING 1.982 + if (LOG_FONTINIT_ENABLED()) { 1.983 + TimeDuration elapsed = TimeStamp::Now() - start; 1.984 + LOG_FONTINIT(("(fontinit) fontloader load pass %8.2f ms done %s\n", 1.985 + elapsed.ToMilliseconds(), (done ? "true" : "false"))); 1.986 + } 1.987 +#endif 1.988 + 1.989 + if (done) { 1.990 + mOtherFamilyNamesInitialized = true; 1.991 + mFaceNameListsInitialized = true; 1.992 + } 1.993 + 1.994 + return done; 1.995 +} 1.996 + 1.997 +struct LookupMissedFaceNamesData { 1.998 + LookupMissedFaceNamesData(gfxPlatformFontList *aFontList) 1.999 + : mFontList(aFontList), mFoundName(false) {} 1.1000 + 1.1001 + gfxPlatformFontList *mFontList; 1.1002 + bool mFoundName; 1.1003 +}; 1.1004 + 1.1005 +/*static*/ PLDHashOperator 1.1006 +gfxPlatformFontList::LookupMissedFaceNamesProc(nsStringHashKey *aKey, 1.1007 + void *aUserArg) 1.1008 +{ 1.1009 + LookupMissedFaceNamesData *data = 1.1010 + reinterpret_cast<LookupMissedFaceNamesData*>(aUserArg); 1.1011 + 1.1012 + if (data->mFontList->FindFaceName(aKey->GetKey())) { 1.1013 + data->mFoundName = true; 1.1014 + return PL_DHASH_STOP; 1.1015 + } 1.1016 + return PL_DHASH_NEXT; 1.1017 +} 1.1018 + 1.1019 +struct LookupMissedOtherNamesData { 1.1020 + LookupMissedOtherNamesData(gfxPlatformFontList *aFontList) 1.1021 + : mFontList(aFontList), mFoundName(false) {} 1.1022 + 1.1023 + gfxPlatformFontList *mFontList; 1.1024 + bool mFoundName; 1.1025 +}; 1.1026 + 1.1027 +/*static*/ PLDHashOperator 1.1028 +gfxPlatformFontList::LookupMissedOtherNamesProc(nsStringHashKey *aKey, 1.1029 + void *aUserArg) 1.1030 +{ 1.1031 + LookupMissedOtherNamesData *data = 1.1032 + reinterpret_cast<LookupMissedOtherNamesData*>(aUserArg); 1.1033 + 1.1034 + if (data->mFontList->FindFamily(aKey->GetKey())) { 1.1035 + data->mFoundName = true; 1.1036 + return PL_DHASH_STOP; 1.1037 + } 1.1038 + return PL_DHASH_NEXT; 1.1039 +} 1.1040 + 1.1041 +void 1.1042 +gfxPlatformFontList::CleanupLoader() 1.1043 +{ 1.1044 + mFontFamiliesToLoad.Clear(); 1.1045 + mNumFamilies = 0; 1.1046 + bool rebuilt = false, forceReflow = false; 1.1047 + 1.1048 + // if had missed face names that are now available, force reflow all 1.1049 + if (mFaceNamesMissed && 1.1050 + mFaceNamesMissed->Count() != 0) { 1.1051 + LookupMissedFaceNamesData namedata(this); 1.1052 + mFaceNamesMissed->EnumerateEntries(LookupMissedFaceNamesProc, &namedata); 1.1053 + if (namedata.mFoundName) { 1.1054 + rebuilt = true; 1.1055 + mUserFontSetList.EnumerateEntries(RebuildLocalFonts, nullptr); 1.1056 + } 1.1057 + mFaceNamesMissed = nullptr; 1.1058 + } 1.1059 + 1.1060 + if (mOtherNamesMissed) { 1.1061 + LookupMissedOtherNamesData othernamesdata(this); 1.1062 + mOtherNamesMissed->EnumerateEntries(LookupMissedOtherNamesProc, 1.1063 + &othernamesdata); 1.1064 + mOtherNamesMissed = nullptr; 1.1065 + if (othernamesdata.mFoundName) { 1.1066 + forceReflow = true; 1.1067 + ForceGlobalReflow(); 1.1068 + } 1.1069 + } 1.1070 + 1.1071 +#ifdef PR_LOGGING 1.1072 + if (LOG_FONTINIT_ENABLED() && mFontInfo) { 1.1073 + LOG_FONTINIT(("(fontinit) fontloader load thread took %8.2f ms " 1.1074 + "%d families %d fonts %d cmaps " 1.1075 + "%d facenames %d othernames %s %s", 1.1076 + mLoadTime.ToMilliseconds(), 1.1077 + mFontInfo->mLoadStats.families, 1.1078 + mFontInfo->mLoadStats.fonts, 1.1079 + mFontInfo->mLoadStats.cmaps, 1.1080 + mFontInfo->mLoadStats.facenames, 1.1081 + mFontInfo->mLoadStats.othernames, 1.1082 + (rebuilt ? "(userfont sets rebuilt)" : ""), 1.1083 + (forceReflow ? "(global reflow)" : ""))); 1.1084 + } 1.1085 +#endif 1.1086 + 1.1087 + gfxFontInfoLoader::CleanupLoader(); 1.1088 +} 1.1089 + 1.1090 +void 1.1091 +gfxPlatformFontList::GetPrefsAndStartLoader() 1.1092 +{ 1.1093 + mIncrement = 1.1094 + std::max(1u, Preferences::GetUint(FONT_LOADER_FAMILIES_PER_SLICE_PREF)); 1.1095 + 1.1096 + uint32_t delay = 1.1097 + std::max(1u, Preferences::GetUint(FONT_LOADER_DELAY_PREF)); 1.1098 + uint32_t interval = 1.1099 + std::max(1u, Preferences::GetUint(FONT_LOADER_INTERVAL_PREF)); 1.1100 + 1.1101 + StartLoader(delay, interval); 1.1102 +} 1.1103 + 1.1104 +void 1.1105 +gfxPlatformFontList::ForceGlobalReflow() 1.1106 +{ 1.1107 + // modify a preference that will trigger reflow everywhere 1.1108 + static const char kPrefName[] = "font.internaluseonly.changed"; 1.1109 + bool fontInternalChange = Preferences::GetBool(kPrefName, false); 1.1110 + Preferences::SetBool(kPrefName, !fontInternalChange); 1.1111 +} 1.1112 + 1.1113 +// Support for memory reporting 1.1114 + 1.1115 +static size_t 1.1116 +SizeOfFamilyEntryExcludingThis(const nsAString& aKey, 1.1117 + const nsRefPtr<gfxFontFamily>& aFamily, 1.1118 + MallocSizeOf aMallocSizeOf, 1.1119 + void* aUserArg) 1.1120 +{ 1.1121 + FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg); 1.1122 + aFamily->AddSizeOfExcludingThis(aMallocSizeOf, sizes); 1.1123 + 1.1124 + sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.1125 + 1.1126 + // we return zero here because the measurements have been added directly 1.1127 + // to the relevant fields of the FontListSizes record 1.1128 + return 0; 1.1129 +} 1.1130 + 1.1131 +// this is also used by subclasses that hold additional hashes of family names 1.1132 +/*static*/ size_t 1.1133 +gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis 1.1134 + (const nsAString& aKey, 1.1135 + const nsRefPtr<gfxFontFamily>& aFamily, 1.1136 + MallocSizeOf aMallocSizeOf, 1.1137 + void* aUserArg) 1.1138 +{ 1.1139 + // we don't count the size of the family here, because this is an *extra* 1.1140 + // reference to a family that will have already been counted in the main list 1.1141 + return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.1142 +} 1.1143 + 1.1144 +static size_t 1.1145 +SizeOfFontNameEntryExcludingThis(const nsAString& aKey, 1.1146 + const nsRefPtr<gfxFontEntry>& aFont, 1.1147 + MallocSizeOf aMallocSizeOf, 1.1148 + void* aUserArg) 1.1149 +{ 1.1150 + // the font itself is counted by its owning family; here we only care about 1.1151 + // the name stored in the hashtable key 1.1152 + return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.1153 +} 1.1154 + 1.1155 +static size_t 1.1156 +SizeOfPrefFontEntryExcludingThis 1.1157 + (const uint32_t& aKey, 1.1158 + const nsTArray<nsRefPtr<gfxFontFamily> >& aList, 1.1159 + MallocSizeOf aMallocSizeOf, 1.1160 + void* aUserArg) 1.1161 +{ 1.1162 + // again, we only care about the size of the array itself; we don't follow 1.1163 + // the refPtrs stored in it, because they point to entries already owned 1.1164 + // and accounted-for by the main font list 1.1165 + return aList.SizeOfExcludingThis(aMallocSizeOf); 1.1166 +} 1.1167 + 1.1168 +static size_t 1.1169 +SizeOfStringEntryExcludingThis(nsStringHashKey* aHashEntry, 1.1170 + MallocSizeOf aMallocSizeOf, 1.1171 + void* aUserArg) 1.1172 +{ 1.1173 + return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf); 1.1174 +} 1.1175 + 1.1176 +static size_t 1.1177 +SizeOfSharedCmapExcludingThis(CharMapHashKey* aHashEntry, 1.1178 + MallocSizeOf aMallocSizeOf, 1.1179 + void* aUserArg) 1.1180 +{ 1.1181 + FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg); 1.1182 + 1.1183 + uint32_t size = aHashEntry->GetKey()->SizeOfIncludingThis(aMallocSizeOf); 1.1184 + sizes->mCharMapsSize += size; 1.1185 + 1.1186 + // we return zero here because the measurements have been added directly 1.1187 + // to the relevant fields of the FontListSizes record 1.1188 + return 0; 1.1189 +} 1.1190 + 1.1191 +void 1.1192 +gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf, 1.1193 + FontListSizes* aSizes) const 1.1194 +{ 1.1195 + aSizes->mFontListSize += 1.1196 + mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis, 1.1197 + aMallocSizeOf, aSizes); 1.1198 + 1.1199 + aSizes->mFontListSize += 1.1200 + mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis, 1.1201 + aMallocSizeOf); 1.1202 + 1.1203 + if (mExtraNames) { 1.1204 + aSizes->mFontListSize += 1.1205 + mExtraNames->mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis, 1.1206 + aMallocSizeOf); 1.1207 + aSizes->mFontListSize += 1.1208 + mExtraNames->mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis, 1.1209 + aMallocSizeOf); 1.1210 + } 1.1211 + 1.1212 + aSizes->mFontListSize += 1.1213 + mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf); 1.1214 + aSizes->mFontListSize += 1.1215 + mFontFamiliesToLoad.SizeOfExcludingThis(aMallocSizeOf); 1.1216 + 1.1217 + aSizes->mFontListSize += 1.1218 + mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis, 1.1219 + aMallocSizeOf); 1.1220 + 1.1221 + aSizes->mFontListSize += 1.1222 + mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis, 1.1223 + aMallocSizeOf); 1.1224 + 1.1225 + aSizes->mFontListSize += 1.1226 + mSharedCmaps.SizeOfExcludingThis(SizeOfSharedCmapExcludingThis, 1.1227 + aMallocSizeOf, aSizes); 1.1228 +} 1.1229 + 1.1230 +void 1.1231 +gfxPlatformFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, 1.1232 + FontListSizes* aSizes) const 1.1233 +{ 1.1234 + aSizes->mFontListSize += aMallocSizeOf(this); 1.1235 + AddSizeOfExcludingThis(aMallocSizeOf, aSizes); 1.1236 +}