gfx/thebes/gfxPlatformFontList.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifdef MOZ_LOGGING
     7 #define FORCE_PR_LOG /* Allow logging in the release build */
     8 #endif
     9 #include "prlog.h"
    11 #include "gfxPlatformFontList.h"
    12 #include "gfxUserFontSet.h"
    14 #include "nsUnicharUtils.h"
    15 #include "nsUnicodeRange.h"
    16 #include "nsUnicodeProperties.h"
    18 #include "mozilla/Attributes.h"
    19 #include "mozilla/Likely.h"
    20 #include "mozilla/MemoryReporting.h"
    21 #include "mozilla/Preferences.h"
    22 #include "mozilla/Telemetry.h"
    23 #include "mozilla/TimeStamp.h"
    24 #include "mozilla/gfx/2D.h"
    26 using namespace mozilla;
    28 #ifdef PR_LOGGING
    30 #define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
    31                                PR_LOG_DEBUG, args)
    32 #define LOG_FONTLIST_ENABLED() PR_LOG_TEST( \
    33                                    gfxPlatform::GetLog(eGfxLog_fontlist), \
    34                                    PR_LOG_DEBUG)
    35 #define LOG_FONTINIT(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), \
    36                                PR_LOG_DEBUG, args)
    37 #define LOG_FONTINIT_ENABLED() PR_LOG_TEST( \
    38                                    gfxPlatform::GetLog(eGfxLog_fontinit), \
    39                                    PR_LOG_DEBUG)
    41 #endif // PR_LOGGING
    43 gfxPlatformFontList *gfxPlatformFontList::sPlatformFontList = nullptr;
    45 // Character ranges that require complex-script shaping support in the font,
    46 // and so should be masked out by ReadCMAP if the necessary layout tables
    47 // are not present.
    48 // Currently used by the Mac and FT2 implementations only, but probably should
    49 // be supported on Windows as well.
    50 const gfxFontEntry::ScriptRange gfxPlatformFontList::sComplexScriptRanges[] = {
    51     // Actually, now that harfbuzz supports presentation-forms shaping for
    52     // Arabic, we can render it without layout tables. So maybe we don't
    53     // want to mask the basic Arabic block here?
    54     // This affects the arabic-fallback-*.html reftests, which rely on
    55     // loading a font that *doesn't* have any GSUB table.
    56     { 0x0600, 0x06FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
    57     { 0x0700, 0x074F, { TRUETYPE_TAG('s','y','r','c'), 0, 0 } },
    58     { 0x0750, 0x077F, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
    59     { 0x08A0, 0x08FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
    60     { 0x0900, 0x097F, { TRUETYPE_TAG('d','e','v','2'),
    61                         TRUETYPE_TAG('d','e','v','a'), 0 } },
    62     { 0x0980, 0x09FF, { TRUETYPE_TAG('b','n','g','2'),
    63                         TRUETYPE_TAG('b','e','n','g'), 0 } },
    64     { 0x0A00, 0x0A7F, { TRUETYPE_TAG('g','u','r','2'),
    65                         TRUETYPE_TAG('g','u','r','u'), 0 } },
    66     { 0x0A80, 0x0AFF, { TRUETYPE_TAG('g','j','r','2'),
    67                         TRUETYPE_TAG('g','u','j','r'), 0 } },
    68     { 0x0B00, 0x0B7F, { TRUETYPE_TAG('o','r','y','2'),
    69                         TRUETYPE_TAG('o','r','y','a'), 0 } },
    70     { 0x0B80, 0x0BFF, { TRUETYPE_TAG('t','m','l','2'),
    71                         TRUETYPE_TAG('t','a','m','l'), 0 } },
    72     { 0x0C00, 0x0C7F, { TRUETYPE_TAG('t','e','l','2'),
    73                         TRUETYPE_TAG('t','e','l','u'), 0 } },
    74     { 0x0C80, 0x0CFF, { TRUETYPE_TAG('k','n','d','2'),
    75                         TRUETYPE_TAG('k','n','d','a'), 0 } },
    76     { 0x0D00, 0x0D7F, { TRUETYPE_TAG('m','l','m','2'),
    77                         TRUETYPE_TAG('m','l','y','m'), 0 } },
    78     { 0x0D80, 0x0DFF, { TRUETYPE_TAG('s','i','n','h'), 0, 0 } },
    79     { 0x0E80, 0x0EFF, { TRUETYPE_TAG('l','a','o',' '), 0, 0 } },
    80     { 0x0F00, 0x0FFF, { TRUETYPE_TAG('t','i','b','t'), 0, 0 } },
    81     { 0x1000, 0x109f, { TRUETYPE_TAG('m','y','m','r'),
    82                         TRUETYPE_TAG('m','y','m','2'), 0 } },
    83     { 0x1780, 0x17ff, { TRUETYPE_TAG('k','h','m','r'), 0, 0 } },
    84     // Khmer Symbols (19e0..19ff) don't seem to need any special shaping
    85     { 0xaa60, 0xaa7f, { TRUETYPE_TAG('m','y','m','r'),
    86                         TRUETYPE_TAG('m','y','m','2'), 0 } },
    87     // Thai seems to be "renderable" without AAT morphing tables
    88     { 0, 0, { 0, 0, 0 } } // terminator
    89 };
    91 // prefs for the font info loader
    92 #define FONT_LOADER_FAMILIES_PER_SLICE_PREF "gfx.font_loader.families_per_slice"
    93 #define FONT_LOADER_DELAY_PREF              "gfx.font_loader.delay"
    94 #define FONT_LOADER_INTERVAL_PREF           "gfx.font_loader.interval"
    96 static const char* kObservedPrefs[] = {
    97     "font.",
    98     "font.name-list.",
    99     "intl.accept_languages",  // hmmmm...
   100     nullptr
   101 };
   103 class gfxFontListPrefObserver MOZ_FINAL : public nsIObserver {
   104 public:
   105     NS_DECL_ISUPPORTS
   106     NS_DECL_NSIOBSERVER
   107 };
   109 static gfxFontListPrefObserver* gFontListPrefObserver = nullptr;
   111 NS_IMPL_ISUPPORTS(gfxFontListPrefObserver, nsIObserver)
   113 NS_IMETHODIMP
   114 gfxFontListPrefObserver::Observe(nsISupports     *aSubject,
   115                                  const char      *aTopic,
   116                                  const char16_t *aData)
   117 {
   118     NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic");
   119     // XXX this could be made to only clear out the cache for the prefs that were changed
   120     // but it probably isn't that big a deal.
   121     gfxPlatformFontList::PlatformFontList()->ClearPrefFonts();
   122     gfxFontCache::GetCache()->AgeAllGenerations();
   123     return NS_OK;
   124 }
   126 MOZ_DEFINE_MALLOC_SIZE_OF(FontListMallocSizeOf)
   128 NS_IMPL_ISUPPORTS(gfxPlatformFontList::MemoryReporter, nsIMemoryReporter)
   130 NS_IMETHODIMP
   131 gfxPlatformFontList::MemoryReporter::CollectReports
   132     (nsIMemoryReporterCallback* aCb,
   133      nsISupports* aClosure)
   134 {
   135     FontListSizes sizes;
   136     sizes.mFontListSize = 0;
   137     sizes.mFontTableCacheSize = 0;
   138     sizes.mCharMapsSize = 0;
   140     gfxPlatformFontList::PlatformFontList()->AddSizeOfIncludingThis(&FontListMallocSizeOf,
   141                                                                     &sizes);
   143     aCb->Callback(EmptyCString(),
   144                   NS_LITERAL_CSTRING("explicit/gfx/font-list"),
   145                   KIND_HEAP, UNITS_BYTES, sizes.mFontListSize,
   146                   NS_LITERAL_CSTRING("Memory used to manage the list of font families and faces."),
   147                   aClosure);
   149     aCb->Callback(EmptyCString(),
   150                   NS_LITERAL_CSTRING("explicit/gfx/font-charmaps"),
   151                   KIND_HEAP, UNITS_BYTES, sizes.mCharMapsSize,
   152                   NS_LITERAL_CSTRING("Memory used to record the character coverage of individual fonts."),
   153                   aClosure);
   155     if (sizes.mFontTableCacheSize) {
   156         aCb->Callback(EmptyCString(),
   157                       NS_LITERAL_CSTRING("explicit/gfx/font-tables"),
   158                       KIND_HEAP, UNITS_BYTES, sizes.mFontTableCacheSize,
   159                       NS_LITERAL_CSTRING("Memory used for cached font metrics and layout tables."),
   160                       aClosure);
   161     }
   163     return NS_OK;
   164 }
   166 gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
   167     : mFontFamilies(100), mOtherFamilyNames(30),
   168       mPrefFonts(10), mBadUnderlineFamilyNames(10), mSharedCmaps(16),
   169       mStartIndex(0), mIncrement(1), mNumFamilies(0)
   170 {
   171     mOtherFamilyNamesInitialized = false;
   173     if (aNeedFullnamePostscriptNames) {
   174         mExtraNames = new ExtraNames();
   175     }
   176     mFaceNameListsInitialized = false;
   178     LoadBadUnderlineList();
   180     // pref changes notification setup
   181     NS_ASSERTION(!gFontListPrefObserver,
   182                  "There has been font list pref observer already");
   183     gFontListPrefObserver = new gfxFontListPrefObserver();
   184     NS_ADDREF(gFontListPrefObserver);
   185     Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs);
   187     RegisterStrongMemoryReporter(new MemoryReporter());
   188 }
   190 gfxPlatformFontList::~gfxPlatformFontList()
   191 {
   192     mSharedCmaps.Clear();
   193     NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
   194     Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
   195     NS_RELEASE(gFontListPrefObserver);
   196 }
   198 nsresult
   199 gfxPlatformFontList::InitFontList()
   200 {
   201     mFontFamilies.Clear();
   202     mOtherFamilyNames.Clear();
   203     mOtherFamilyNamesInitialized = false;
   204     if (mExtraNames) {
   205         mExtraNames->mFullnames.Clear();
   206         mExtraNames->mPostscriptNames.Clear();
   207     }
   208     mFaceNameListsInitialized = false;
   209     mPrefFonts.Clear();
   210     mReplacementCharFallbackFamily = nullptr;
   211     CancelLoader();
   213     // initialize ranges of characters for which system-wide font search should be skipped
   214     mCodepointsWithNoFonts.reset();
   215     mCodepointsWithNoFonts.SetRange(0,0x1f);     // C0 controls
   216     mCodepointsWithNoFonts.SetRange(0x7f,0x9f);  // C1 controls
   218     sPlatformFontList = this;
   220     return NS_OK;
   221 }
   223 void
   224 gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult)
   225 {
   226     aResult = aKeyName;
   227     ToLowerCase(aResult);
   228 }
   230 struct InitOtherNamesData {
   231     InitOtherNamesData(gfxPlatformFontList *aFontList,
   232                        TimeStamp aStartTime)
   233         : mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false)
   234     {}
   236     gfxPlatformFontList *mFontList;
   237     TimeStamp mStartTime;
   238     bool mTimedOut;
   239 };
   241 void 
   242 gfxPlatformFontList::InitOtherFamilyNames()
   243 {
   244     if (mOtherFamilyNamesInitialized) {
   245         return;
   246     }
   248     TimeStamp start = TimeStamp::Now();
   250     // iterate over all font families and read in other family names
   251     InitOtherNamesData otherNamesData(this, start);
   253     mFontFamilies.Enumerate(gfxPlatformFontList::InitOtherFamilyNamesProc,
   254                             &otherNamesData);
   256     if (!otherNamesData.mTimedOut) {
   257         mOtherFamilyNamesInitialized = true;
   258     }
   259     TimeStamp end = TimeStamp::Now();
   260     Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES,
   261                                    start, end);
   263 #ifdef PR_LOGGING
   264     if (LOG_FONTINIT_ENABLED()) {
   265         TimeDuration elapsed = end - start;
   266         LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s",
   267                       elapsed.ToMilliseconds(),
   268                       (otherNamesData.mTimedOut ? "timeout" : "")));
   269     }
   270 #endif
   271 }
   273 #define OTHERNAMES_TIMEOUT 200
   275 PLDHashOperator
   276 gfxPlatformFontList::InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey,
   277                                               nsRefPtr<gfxFontFamily>& aFamilyEntry,
   278                                               void* userArg)
   279 {
   280     InitOtherNamesData *data = static_cast<InitOtherNamesData*>(userArg);
   282     aFamilyEntry->ReadOtherFamilyNames(data->mFontList);
   283     TimeDuration elapsed = TimeStamp::Now() - data->mStartTime;
   284     if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
   285         data->mTimedOut = true;
   286         return PL_DHASH_STOP;
   287     }
   288     return PL_DHASH_NEXT;
   289 }
   291 struct ReadFaceNamesData {
   292     ReadFaceNamesData(gfxPlatformFontList *aFontList, TimeStamp aStartTime)
   293         : mFontList(aFontList), mStartTime(aStartTime), mTimedOut(false)
   294     {}
   296     gfxPlatformFontList *mFontList;
   297     TimeStamp mStartTime;
   298     bool mTimedOut;
   300     // if mFirstChar is not empty, only load facenames for families
   301     // that start with this character
   302     nsString mFirstChar;
   303 };
   305 gfxFontEntry*
   306 gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName)
   307 {
   308     TimeStamp start = TimeStamp::Now();
   309     gfxFontEntry *lookup = nullptr;
   311     ReadFaceNamesData faceNameListsData(this, start);
   313     // iterate over familes starting with the same letter
   314     faceNameListsData.mFirstChar.Assign(aFaceName.CharAt(0));
   315     ToLowerCase(faceNameListsData.mFirstChar);
   316     mFontFamilies.Enumerate(gfxPlatformFontList::ReadFaceNamesProc,
   317                             &faceNameListsData);
   318     lookup = FindFaceName(aFaceName);
   320     TimeStamp end = TimeStamp::Now();
   321     Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITFACENAMELISTS,
   322                                    start, end);
   323 #ifdef PR_LOGGING
   324     if (LOG_FONTINIT_ENABLED()) {
   325         TimeDuration elapsed = end - start;
   326         LOG_FONTINIT(("(fontinit) SearchFamiliesForFaceName took %8.2f ms %s %s",
   327                       elapsed.ToMilliseconds(),
   328                       (lookup ? "found name" : ""),
   329                       (faceNameListsData.mTimedOut ? "timeout" : "")));
   330     }
   331 #endif
   333     return lookup;
   334 }
   336 // time limit for loading facename lists (ms)
   337 #define NAMELIST_TIMEOUT  200
   339 PLDHashOperator
   340 gfxPlatformFontList::ReadFaceNamesProc(nsStringHashKey::KeyType aKey,
   341                                        nsRefPtr<gfxFontFamily>& aFamilyEntry,
   342                                        void* userArg)
   343 {
   344     ReadFaceNamesData *data = static_cast<ReadFaceNamesData*>(userArg);
   345     gfxPlatformFontList *fc = data->mFontList;
   347     // when filtering, skip names that don't start with the filter character
   348     if (!(data->mFirstChar.IsEmpty())) {
   349         char16_t firstChar = aKey.CharAt(0);
   350         nsAutoString firstCharStr(&firstChar, 1);
   351         ToLowerCase(firstCharStr);
   352         if (!firstCharStr.Equals(data->mFirstChar)) {
   353             return PL_DHASH_NEXT;
   354         }
   355     }
   356     aFamilyEntry->ReadFaceNames(fc, fc->NeedFullnamePostscriptNames());
   358     TimeDuration elapsed = TimeStamp::Now() - data->mStartTime;
   359     if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) {
   360         data->mTimedOut = true;
   361         return PL_DHASH_STOP;
   362     }
   363     return PL_DHASH_NEXT;
   364 }
   366 gfxFontEntry*
   367 gfxPlatformFontList::FindFaceName(const nsAString& aFaceName)
   368 {
   369     gfxFontEntry *lookup;
   371     // lookup in name lookup tables, return null if not found
   372     if (mExtraNames &&
   373         ((lookup = mExtraNames->mPostscriptNames.GetWeak(aFaceName)) ||
   374          (lookup = mExtraNames->mFullnames.GetWeak(aFaceName)))) {
   375         return lookup;
   376     }
   378     return nullptr;
   379 }
   381 gfxFontEntry*
   382 gfxPlatformFontList::LookupInFaceNameLists(const nsAString& aFaceName)
   383 {
   384     gfxFontEntry *lookup = nullptr;
   386     // initialize facename lookup tables if needed
   387     // note: this can terminate early or time out, in which case
   388     //       mFaceNameListsInitialized remains false
   389     if (!mFaceNameListsInitialized) {
   390         lookup = SearchFamiliesForFaceName(aFaceName);
   391         if (lookup) {
   392             return lookup;
   393         }
   394     }
   396     // lookup in name lookup tables, return null if not found
   397     if (!(lookup = FindFaceName(aFaceName))) {
   398         // names not completely initialized, so keep track of lookup misses
   399         if (!mFaceNameListsInitialized) {
   400             if (!mFaceNamesMissed) {
   401                 mFaceNamesMissed = new nsTHashtable<nsStringHashKey>(4);
   402             }
   403             mFaceNamesMissed->PutEntry(aFaceName);
   404         }
   405     }
   407     return lookup;
   408 }
   410 void
   411 gfxPlatformFontList::PreloadNamesList()
   412 {
   413     nsAutoTArray<nsString, 10> preloadFonts;
   414     gfxFontUtils::GetPrefsFontList("font.preload-names-list", preloadFonts);
   416     uint32_t numFonts = preloadFonts.Length();
   417     for (uint32_t i = 0; i < numFonts; i++) {
   418         nsAutoString key;
   419         GenerateFontListKey(preloadFonts[i], key);
   421         // only search canonical names!
   422         gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key);
   423         if (familyEntry) {
   424             familyEntry->ReadOtherFamilyNames(this);
   425         }
   426     }
   428 }
   430 void 
   431 gfxPlatformFontList::SetFixedPitch(const nsAString& aFamilyName)
   432 {
   433     gfxFontFamily *family = FindFamily(aFamilyName);
   434     if (!family) return;
   436     family->FindStyleVariations();
   437     nsTArray<nsRefPtr<gfxFontEntry> >& fontlist = family->GetFontList();
   439     uint32_t i, numFonts = fontlist.Length();
   441     for (i = 0; i < numFonts; i++) {
   442         fontlist[i]->mFixedPitch = 1;
   443     }
   444 }
   446 void
   447 gfxPlatformFontList::LoadBadUnderlineList()
   448 {
   449     nsAutoTArray<nsString, 10> blacklist;
   450     gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset", blacklist);
   451     uint32_t numFonts = blacklist.Length();
   452     for (uint32_t i = 0; i < numFonts; i++) {
   453         nsAutoString key;
   454         GenerateFontListKey(blacklist[i], key);
   455         mBadUnderlineFamilyNames.PutEntry(key);
   456     }
   457 }
   459 bool 
   460 gfxPlatformFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName)
   461 {
   462     gfxFontFamily *family = FindFamily(aFontName);
   463     if (family) {
   464         aResolvedFontName = family->Name();
   465         return true;
   466     }
   467     return false;
   468 }
   470 static PLDHashOperator
   471 RebuildLocalFonts(nsPtrHashKey<gfxUserFontSet>* aKey,
   472                   void* aClosure)
   473 {
   474     aKey->GetKey()->RebuildLocalRules();
   475     return PL_DHASH_NEXT;
   476 }
   478 void
   479 gfxPlatformFontList::UpdateFontList()
   480 {
   481     InitFontList();
   482     mUserFontSetList.EnumerateEntries(RebuildLocalFonts, nullptr);
   483 }
   485 struct FontListData {
   486     FontListData(nsIAtom *aLangGroup,
   487                  const nsACString& aGenericFamily,
   488                  nsTArray<nsString>& aListOfFonts) :
   489         mLangGroup(aLangGroup), mGenericFamily(aGenericFamily),
   490         mListOfFonts(aListOfFonts) {}
   491     nsIAtom *mLangGroup;
   492     const nsACString& mGenericFamily;
   493     nsTArray<nsString>& mListOfFonts;
   494 };
   496 PLDHashOperator
   497 gfxPlatformFontList::HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey,
   498                                              nsRefPtr<gfxFontFamily>& aFamilyEntry,
   499                                              void *aUserArg)
   500 {
   501     FontListData *data = static_cast<FontListData*>(aUserArg);
   503     // use the first variation for now.  This data should be the same
   504     // for all the variations and should probably be moved up to
   505     // the Family
   506     gfxFontStyle style;
   507     style.language = data->mLangGroup;
   508     bool needsBold;
   509     nsRefPtr<gfxFontEntry> aFontEntry = aFamilyEntry->FindFontForStyle(style, needsBold);
   510     NS_ASSERTION(aFontEntry, "couldn't find any font entry in family");
   511     if (!aFontEntry)
   512         return PL_DHASH_NEXT;
   514     /* skip symbol fonts */
   515     if (aFontEntry->IsSymbolFont())
   516         return PL_DHASH_NEXT;
   518     if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
   519         aFontEntry->MatchesGenericFamily(data->mGenericFamily)) {
   520         nsAutoString localizedFamilyName;
   521         aFamilyEntry->LocalizedName(localizedFamilyName);
   522         data->mListOfFonts.AppendElement(localizedFamilyName);
   523     }
   525     return PL_DHASH_NEXT;
   526 }
   528 void
   529 gfxPlatformFontList::GetFontList(nsIAtom *aLangGroup,
   530                                  const nsACString& aGenericFamily,
   531                                  nsTArray<nsString>& aListOfFonts)
   532 {
   533     FontListData data(aLangGroup, aGenericFamily, aListOfFonts);
   535     mFontFamilies.Enumerate(gfxPlatformFontList::HashEnumFuncForFamilies, &data);
   537     aListOfFonts.Sort();
   538     aListOfFonts.Compact();
   539 }
   541 struct FontFamilyListData {
   542     FontFamilyListData(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray) 
   543         : mFamilyArray(aFamilyArray)
   544     {}
   546     static PLDHashOperator AppendFamily(nsStringHashKey::KeyType aKey,
   547                                         nsRefPtr<gfxFontFamily>& aFamilyEntry,
   548                                         void *aUserArg)
   549     {
   550         FontFamilyListData *data = static_cast<FontFamilyListData*>(aUserArg);
   551         data->mFamilyArray.AppendElement(aFamilyEntry);
   552         return PL_DHASH_NEXT;
   553     }
   555     nsTArray<nsRefPtr<gfxFontFamily> >& mFamilyArray;
   556 };
   558 void
   559 gfxPlatformFontList::GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray)
   560 {
   561     FontFamilyListData data(aFamilyArray);
   562     mFontFamilies.Enumerate(FontFamilyListData::AppendFamily, &data);
   563 }
   565 gfxFontEntry*
   566 gfxPlatformFontList::SystemFindFontForChar(const uint32_t aCh,
   567                                            int32_t aRunScript,
   568                                            const gfxFontStyle* aStyle)
   569  {
   570     gfxFontEntry* fontEntry = nullptr;
   572     // is codepoint with no matching font? return null immediately
   573     if (mCodepointsWithNoFonts.test(aCh)) {
   574         return nullptr;
   575     }
   577     // Try to short-circuit font fallback for U+FFFD, used to represent
   578     // encoding errors: just use cached family from last time U+FFFD was seen.
   579     // This helps speed up pages with lots of encoding errors, binary-as-text,
   580     // etc.
   581     if (aCh == 0xFFFD && mReplacementCharFallbackFamily) {
   582         bool needsBold;  // ignored in the system fallback case
   584         fontEntry =
   585             mReplacementCharFallbackFamily->FindFontForStyle(*aStyle,
   586                                                              needsBold);
   588         // this should never fail, as we must have found U+FFFD in order to set
   589         // mReplacementCharFallbackFamily at all, but better play it safe
   590         if (fontEntry && fontEntry->TestCharacterMap(aCh)) {
   591             return fontEntry;
   592         }
   593     }
   595     TimeStamp start = TimeStamp::Now();
   597     // search commonly available fonts
   598     bool common = true;
   599     gfxFontFamily *fallbackFamily = nullptr;
   600     fontEntry = CommonFontFallback(aCh, aRunScript, aStyle, &fallbackFamily);
   602     // if didn't find a font, do system-wide fallback (except for specials)
   603     uint32_t cmapCount = 0;
   604     if (!fontEntry) {
   605         common = false;
   606         fontEntry = GlobalFontFallback(aCh, aRunScript, aStyle, cmapCount,
   607                                        &fallbackFamily);
   608     }
   609     TimeDuration elapsed = TimeStamp::Now() - start;
   611 #ifdef PR_LOGGING
   612     PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun);
   614     if (MOZ_UNLIKELY(PR_LOG_TEST(log, PR_LOG_WARNING))) {
   615         uint32_t unicodeRange = FindCharUnicodeRange(aCh);
   616         int32_t script = mozilla::unicode::GetScriptCode(aCh);
   617         PR_LOG(log, PR_LOG_WARNING,\
   618                ("(textrun-systemfallback-%s) char: u+%6.6x "
   619                  "unicode-range: %d script: %d match: [%s]"
   620                 " time: %dus cmaps: %d\n",
   621                 (common ? "common" : "global"), aCh,
   622                  unicodeRange, script,
   623                 (fontEntry ? NS_ConvertUTF16toUTF8(fontEntry->Name()).get() :
   624                     "<none>"),
   625                 int32_t(elapsed.ToMicroseconds()),
   626                 cmapCount));
   627     }
   628 #endif
   630     // no match? add to set of non-matching codepoints
   631     if (!fontEntry) {
   632         mCodepointsWithNoFonts.set(aCh);
   633     } else if (aCh == 0xFFFD && fontEntry && fallbackFamily) {
   634         mReplacementCharFallbackFamily = fallbackFamily;
   635     }
   637     // track system fallback time
   638     static bool first = true;
   639     int32_t intElapsed = int32_t(first ? elapsed.ToMilliseconds() :
   640                                          elapsed.ToMicroseconds());
   641     Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST :
   642                                    Telemetry::SYSTEM_FONT_FALLBACK),
   643                           intElapsed);
   644     first = false;
   646     // track the script for which fallback occurred (incremented one make it
   647     // 1-based)
   648     Telemetry::Accumulate(Telemetry::SYSTEM_FONT_FALLBACK_SCRIPT, aRunScript + 1);
   650     return fontEntry;
   651 }
   653 PLDHashOperator 
   654 gfxPlatformFontList::FindFontForCharProc(nsStringHashKey::KeyType aKey, nsRefPtr<gfxFontFamily>& aFamilyEntry,
   655      void *userArg)
   656 {
   657     GlobalFontMatch *data = static_cast<GlobalFontMatch*>(userArg);
   659     // evaluate all fonts in this family for a match
   660     aFamilyEntry->FindFontForChar(data);
   662     return PL_DHASH_NEXT;
   663 }
   665 #define NUM_FALLBACK_FONTS        8
   667 gfxFontEntry*
   668 gfxPlatformFontList::CommonFontFallback(const uint32_t aCh,
   669                                         int32_t aRunScript,
   670                                         const gfxFontStyle* aMatchStyle,
   671                                         gfxFontFamily** aMatchedFamily)
   672 {
   673     nsAutoTArray<const char*,NUM_FALLBACK_FONTS> defaultFallbacks;
   674     uint32_t i, numFallbacks;
   676     gfxPlatform::GetPlatform()->GetCommonFallbackFonts(aCh, aRunScript,
   677                                                        defaultFallbacks);
   678     numFallbacks = defaultFallbacks.Length();
   679     for (i = 0; i < numFallbacks; i++) {
   680         nsAutoString familyName;
   681         const char *fallbackFamily = defaultFallbacks[i];
   683         familyName.AppendASCII(fallbackFamily);
   684         gfxFontFamily *fallback =
   685                 gfxPlatformFontList::PlatformFontList()->FindFamily(familyName);
   686         if (!fallback)
   687             continue;
   689         gfxFontEntry *fontEntry;
   690         bool needsBold;  // ignored in the system fallback case
   692         // use first font in list that supports a given character
   693         fontEntry = fallback->FindFontForStyle(*aMatchStyle, needsBold);
   694         if (fontEntry && fontEntry->TestCharacterMap(aCh)) {
   695             *aMatchedFamily = fallback;
   696             return fontEntry;
   697         }
   698     }
   700     return nullptr;
   701 }
   703 gfxFontEntry*
   704 gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh,
   705                                         int32_t aRunScript,
   706                                         const gfxFontStyle* aMatchStyle,
   707                                         uint32_t& aCmapCount,
   708                                         gfxFontFamily** aMatchedFamily)
   709 {
   710     // otherwise, try to find it among local fonts
   711     GlobalFontMatch data(aCh, aRunScript, aMatchStyle);
   713     // iterate over all font families to find a font that support the character
   714     mFontFamilies.Enumerate(gfxPlatformFontList::FindFontForCharProc, &data);
   716     aCmapCount = data.mCmapsTested;
   717     *aMatchedFamily = data.mMatchedFamily;
   719     return data.mBestMatch;
   720 }
   722 #ifdef XP_WIN
   723 #include <windows.h>
   725 // crude hack for using when monitoring process
   726 static void LogRegistryEvent(const wchar_t *msg)
   727 {
   728   HKEY dummyKey;
   729   HRESULT hr;
   730   wchar_t buf[512];
   732   wsprintfW(buf, L" log %s", msg);
   733   hr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
   734   if (SUCCEEDED(hr)) {
   735     RegCloseKey(dummyKey);
   736   }
   737 }
   738 #endif
   740 gfxFontFamily*
   741 gfxPlatformFontList::CheckFamily(gfxFontFamily *aFamily)
   742 {
   743     if (aFamily && !aFamily->HasStyles()) {
   744         aFamily->FindStyleVariations();
   745         aFamily->CheckForSimpleFamily();
   746     }
   748     if (aFamily && aFamily->GetFontList().Length() == 0) {
   749         // failed to load any faces for this family, so discard it
   750         nsAutoString key;
   751         GenerateFontListKey(aFamily->Name(), key);
   752         mFontFamilies.Remove(key);
   753         return nullptr;
   754     }
   756     return aFamily;
   757 }
   759 gfxFontFamily* 
   760 gfxPlatformFontList::FindFamily(const nsAString& aFamily)
   761 {
   762     nsAutoString key;
   763     gfxFontFamily *familyEntry;
   764     GenerateFontListKey(aFamily, key);
   766     NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly");
   768     // lookup in canonical (i.e. English) family name list
   769     if ((familyEntry = mFontFamilies.GetWeak(key))) {
   770         return CheckFamily(familyEntry);
   771     }
   773     // lookup in other family names list (mostly localized names)
   774     if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) {
   775         return CheckFamily(familyEntry);
   776     }
   778     // name not found and other family names not yet fully initialized so
   779     // initialize the rest of the list and try again.  this is done lazily
   780     // since reading name table entries is expensive.
   781     // although ASCII localized family names are possible they don't occur
   782     // in practice so avoid pulling in names at startup
   783     if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
   784         InitOtherFamilyNames();
   785         if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) {
   786             return CheckFamily(familyEntry);
   787         } else if (!mOtherFamilyNamesInitialized) {
   788             // localized family names load timed out, add name to list of
   789             // names to check after localized names are loaded
   790             if (!mOtherNamesMissed) {
   791                 mOtherNamesMissed = new nsTHashtable<nsStringHashKey>(4);
   792             }
   793             mOtherNamesMissed->PutEntry(key);
   794         }
   795     }
   797     return nullptr;
   798 }
   800 gfxFontEntry*
   801 gfxPlatformFontList::FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold)
   802 {
   803     gfxFontFamily *familyEntry = FindFamily(aFamily);
   805     aNeedsBold = false;
   807     if (familyEntry)
   808         return familyEntry->FindFontForStyle(*aStyle, aNeedsBold);
   810     return nullptr;
   811 }
   813 bool
   814 gfxPlatformFontList::GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array)
   815 {
   816     return mPrefFonts.Get(uint32_t(aLangGroup), array);
   817 }
   819 void
   820 gfxPlatformFontList::SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array)
   821 {
   822     mPrefFonts.Put(uint32_t(aLangGroup), array);
   823 }
   825 void 
   826 gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
   827 {
   828     nsAutoString key;
   829     GenerateFontListKey(aOtherFamilyName, key);
   831     if (!mOtherFamilyNames.GetWeak(key)) {
   832         mOtherFamilyNames.Put(key, aFamilyEntry);
   833 #ifdef PR_LOGGING
   834         LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, "
   835                       "other family: %s\n",
   836                       NS_ConvertUTF16toUTF8(aFamilyEntry->Name()).get(),
   837                       NS_ConvertUTF16toUTF8(aOtherFamilyName).get()));
   838 #endif
   839         if (mBadUnderlineFamilyNames.Contains(key))
   840             aFamilyEntry->SetBadUnderlineFamily();
   841     }
   842 }
   844 void
   845 gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
   846 {
   847     if (!mExtraNames->mFullnames.GetWeak(aFullname)) {
   848         mExtraNames->mFullnames.Put(aFullname, aFontEntry);
   849 #ifdef PR_LOGGING
   850         LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
   851                       NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(),
   852                       NS_ConvertUTF16toUTF8(aFullname).get()));
   853 #endif
   854     }
   855 }
   857 void
   858 gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName)
   859 {
   860     if (!mExtraNames->mPostscriptNames.GetWeak(aPostscriptName)) {
   861         mExtraNames->mPostscriptNames.Put(aPostscriptName, aFontEntry);
   862 #ifdef PR_LOGGING
   863         LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
   864                       NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(),
   865                       NS_ConvertUTF16toUTF8(aPostscriptName).get()));
   866 #endif
   867     }
   868 }
   870 bool
   871 gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
   872 {
   873     aFamilyName.Truncate();
   874     ResolveFontName(aFontName, aFamilyName);
   875     return !aFamilyName.IsEmpty();
   876 }
   878 gfxCharacterMap*
   879 gfxPlatformFontList::FindCharMap(gfxCharacterMap *aCmap)
   880 {
   881     aCmap->CalcHash();
   882     gfxCharacterMap *cmap = AddCmap(aCmap);
   883     cmap->mShared = true;
   884     return cmap;
   885 }
   887 // add a cmap to the shared cmap set
   888 gfxCharacterMap*
   889 gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap)
   890 {
   891     CharMapHashKey *found =
   892         mSharedCmaps.PutEntry(const_cast<gfxCharacterMap*>(aCharMap));
   893     return found->GetKey();
   894 }
   896 // remove the cmap from the shared cmap set
   897 void
   898 gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
   899 {
   900     // skip lookups during teardown
   901     if (mSharedCmaps.Count() == 0) {
   902         return;
   903     }
   905     // cmap needs to match the entry *and* be the same ptr before removing
   906     CharMapHashKey *found =
   907         mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap));
   908     if (found && found->GetKey() == aCharMap) {
   909         mSharedCmaps.RemoveEntry(const_cast<gfxCharacterMap*>(aCharMap));
   910     }
   911 }
   913 static PLDHashOperator AppendFamilyToList(nsStringHashKey::KeyType aKey,
   914                                           nsRefPtr<gfxFontFamily>& aFamilyEntry,
   915                                           void *aUserArg)
   916 {
   917     nsTArray<nsString> *familyNames = static_cast<nsTArray<nsString> *>(aUserArg);
   918     familyNames->AppendElement(aFamilyEntry->Name());
   919     return PL_DHASH_NEXT;
   920 }
   922 void
   923 gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
   924 {
   925     mFontFamilies.Enumerate(AppendFamilyToList, &aFontFamilyNames);
   926 }
   928 void 
   929 gfxPlatformFontList::InitLoader()
   930 {
   931     GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad);
   932     mStartIndex = 0;
   933     mNumFamilies = mFontInfo->mFontFamiliesToLoad.Length();
   934     memset(&(mFontInfo->mLoadStats), 0, sizeof(mFontInfo->mLoadStats));
   935 }
   937 #define FONT_LOADER_MAX_TIMESLICE 100  // max time for one pass through RunLoader = 100ms
   939 bool
   940 gfxPlatformFontList::LoadFontInfo()
   941 {
   942     TimeStamp start = TimeStamp::Now();
   943     uint32_t i, endIndex = mNumFamilies;
   944     bool loadCmaps = !UsesSystemFallback() ||
   945         gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
   947     // for each font family, load in various font info
   948     for (i = mStartIndex; i < endIndex; i++) {
   949         nsAutoString key;
   950         gfxFontFamily *familyEntry;
   951         GenerateFontListKey(mFontInfo->mFontFamiliesToLoad[i], key);
   953         // lookup in canonical (i.e. English) family name list
   954         if (!(familyEntry = mFontFamilies.GetWeak(key))) {
   955             continue;
   956         }
   958         // read in face names
   959         familyEntry->ReadFaceNames(this, NeedFullnamePostscriptNames(), mFontInfo);
   961         // load the cmaps if needed
   962         if (loadCmaps) {
   963             familyEntry->ReadAllCMAPs(mFontInfo);
   964         }
   966         // limit the time spent reading fonts in one pass
   967         TimeDuration elapsed = TimeStamp::Now() - start;
   968         if (elapsed.ToMilliseconds() > FONT_LOADER_MAX_TIMESLICE &&
   969                 i + 1 != endIndex) {
   970             endIndex = i + 1;
   971             break;
   972         }
   973     }
   975     mStartIndex = endIndex;
   976     bool done = mStartIndex >= mNumFamilies;
   978 #ifdef PR_LOGGING
   979     if (LOG_FONTINIT_ENABLED()) {
   980         TimeDuration elapsed = TimeStamp::Now() - start;
   981         LOG_FONTINIT(("(fontinit) fontloader load pass %8.2f ms done %s\n",
   982                       elapsed.ToMilliseconds(), (done ? "true" : "false")));
   983     }
   984 #endif
   986     if (done) {
   987         mOtherFamilyNamesInitialized = true;
   988         mFaceNameListsInitialized = true;
   989     }
   991     return done;
   992 }
   994 struct LookupMissedFaceNamesData {
   995     LookupMissedFaceNamesData(gfxPlatformFontList *aFontList)
   996         : mFontList(aFontList), mFoundName(false) {}
   998     gfxPlatformFontList *mFontList;
   999     bool mFoundName;
  1000 };
  1002 /*static*/ PLDHashOperator
  1003 gfxPlatformFontList::LookupMissedFaceNamesProc(nsStringHashKey *aKey,
  1004                                                void *aUserArg)
  1006     LookupMissedFaceNamesData *data =
  1007         reinterpret_cast<LookupMissedFaceNamesData*>(aUserArg);
  1009     if (data->mFontList->FindFaceName(aKey->GetKey())) {
  1010         data->mFoundName = true;
  1011         return PL_DHASH_STOP;
  1013     return PL_DHASH_NEXT;
  1016 struct LookupMissedOtherNamesData {
  1017     LookupMissedOtherNamesData(gfxPlatformFontList *aFontList)
  1018         : mFontList(aFontList), mFoundName(false) {}
  1020     gfxPlatformFontList *mFontList;
  1021     bool mFoundName;
  1022 };
  1024 /*static*/ PLDHashOperator
  1025 gfxPlatformFontList::LookupMissedOtherNamesProc(nsStringHashKey *aKey,
  1026                                                 void *aUserArg)
  1028     LookupMissedOtherNamesData *data =
  1029         reinterpret_cast<LookupMissedOtherNamesData*>(aUserArg);
  1031     if (data->mFontList->FindFamily(aKey->GetKey())) {
  1032         data->mFoundName = true;
  1033         return PL_DHASH_STOP;
  1035     return PL_DHASH_NEXT;
  1038 void 
  1039 gfxPlatformFontList::CleanupLoader()
  1041     mFontFamiliesToLoad.Clear();
  1042     mNumFamilies = 0;
  1043     bool rebuilt = false, forceReflow = false;
  1045     // if had missed face names that are now available, force reflow all
  1046     if (mFaceNamesMissed &&
  1047         mFaceNamesMissed->Count() != 0) {
  1048         LookupMissedFaceNamesData namedata(this);
  1049         mFaceNamesMissed->EnumerateEntries(LookupMissedFaceNamesProc, &namedata);
  1050         if (namedata.mFoundName) {
  1051             rebuilt = true;
  1052             mUserFontSetList.EnumerateEntries(RebuildLocalFonts, nullptr);
  1054         mFaceNamesMissed = nullptr;
  1057     if (mOtherNamesMissed) {
  1058         LookupMissedOtherNamesData othernamesdata(this);
  1059         mOtherNamesMissed->EnumerateEntries(LookupMissedOtherNamesProc,
  1060                                             &othernamesdata);
  1061         mOtherNamesMissed = nullptr;
  1062         if (othernamesdata.mFoundName) {
  1063             forceReflow = true;
  1064             ForceGlobalReflow();
  1068 #ifdef PR_LOGGING
  1069     if (LOG_FONTINIT_ENABLED() && mFontInfo) {
  1070         LOG_FONTINIT(("(fontinit) fontloader load thread took %8.2f ms "
  1071                       "%d families %d fonts %d cmaps "
  1072                       "%d facenames %d othernames %s %s",
  1073                       mLoadTime.ToMilliseconds(),
  1074                       mFontInfo->mLoadStats.families,
  1075                       mFontInfo->mLoadStats.fonts,
  1076                       mFontInfo->mLoadStats.cmaps,
  1077                       mFontInfo->mLoadStats.facenames,
  1078                       mFontInfo->mLoadStats.othernames,
  1079                       (rebuilt ? "(userfont sets rebuilt)" : ""),
  1080                       (forceReflow ? "(global reflow)" : "")));
  1082 #endif
  1084     gfxFontInfoLoader::CleanupLoader();
  1087 void
  1088 gfxPlatformFontList::GetPrefsAndStartLoader()
  1090     mIncrement =
  1091         std::max(1u, Preferences::GetUint(FONT_LOADER_FAMILIES_PER_SLICE_PREF));
  1093     uint32_t delay =
  1094         std::max(1u, Preferences::GetUint(FONT_LOADER_DELAY_PREF));
  1095     uint32_t interval =
  1096         std::max(1u, Preferences::GetUint(FONT_LOADER_INTERVAL_PREF));
  1098     StartLoader(delay, interval);
  1101 void
  1102 gfxPlatformFontList::ForceGlobalReflow()
  1104     // modify a preference that will trigger reflow everywhere
  1105     static const char kPrefName[] = "font.internaluseonly.changed";
  1106     bool fontInternalChange = Preferences::GetBool(kPrefName, false);
  1107     Preferences::SetBool(kPrefName, !fontInternalChange);
  1110 // Support for memory reporting
  1112 static size_t
  1113 SizeOfFamilyEntryExcludingThis(const nsAString&               aKey,
  1114                                const nsRefPtr<gfxFontFamily>& aFamily,
  1115                                MallocSizeOf                   aMallocSizeOf,
  1116                                void*                          aUserArg)
  1118     FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
  1119     aFamily->AddSizeOfExcludingThis(aMallocSizeOf, sizes);
  1121     sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  1123     // we return zero here because the measurements have been added directly
  1124     // to the relevant fields of the FontListSizes record
  1125     return 0;
  1128 // this is also used by subclasses that hold additional hashes of family names
  1129 /*static*/ size_t
  1130 gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis
  1131     (const nsAString&               aKey,
  1132      const nsRefPtr<gfxFontFamily>& aFamily,
  1133      MallocSizeOf                   aMallocSizeOf,
  1134      void*                          aUserArg)
  1136     // we don't count the size of the family here, because this is an *extra*
  1137     // reference to a family that will have already been counted in the main list
  1138     return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  1141 static size_t
  1142 SizeOfFontNameEntryExcludingThis(const nsAString&              aKey,
  1143                                  const nsRefPtr<gfxFontEntry>& aFont,
  1144                                  MallocSizeOf                  aMallocSizeOf,
  1145                                  void*                         aUserArg)
  1147     // the font itself is counted by its owning family; here we only care about
  1148     // the name stored in the hashtable key
  1149     return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  1152 static size_t
  1153 SizeOfPrefFontEntryExcludingThis
  1154     (const uint32_t&                           aKey,
  1155      const nsTArray<nsRefPtr<gfxFontFamily> >& aList,
  1156      MallocSizeOf                              aMallocSizeOf,
  1157      void*                                     aUserArg)
  1159     // again, we only care about the size of the array itself; we don't follow
  1160     // the refPtrs stored in it, because they point to entries already owned
  1161     // and accounted-for by the main font list
  1162     return aList.SizeOfExcludingThis(aMallocSizeOf);
  1165 static size_t
  1166 SizeOfStringEntryExcludingThis(nsStringHashKey*  aHashEntry,
  1167                                MallocSizeOf      aMallocSizeOf,
  1168                                void*             aUserArg)
  1170     return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  1173 static size_t
  1174 SizeOfSharedCmapExcludingThis(CharMapHashKey*   aHashEntry,
  1175                               MallocSizeOf      aMallocSizeOf,
  1176                               void*             aUserArg)
  1178     FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
  1180     uint32_t size = aHashEntry->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
  1181     sizes->mCharMapsSize += size;
  1183     // we return zero here because the measurements have been added directly
  1184     // to the relevant fields of the FontListSizes record
  1185     return 0;
  1188 void
  1189 gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
  1190                                             FontListSizes* aSizes) const
  1192     aSizes->mFontListSize +=
  1193         mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis,
  1194                                           aMallocSizeOf, aSizes);
  1196     aSizes->mFontListSize +=
  1197         mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
  1198                                               aMallocSizeOf);
  1200     if (mExtraNames) {
  1201         aSizes->mFontListSize +=
  1202             mExtraNames->mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
  1203                                                         aMallocSizeOf);
  1204         aSizes->mFontListSize +=
  1205             mExtraNames->mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
  1206                                                               aMallocSizeOf);
  1209     aSizes->mFontListSize +=
  1210         mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
  1211     aSizes->mFontListSize +=
  1212         mFontFamiliesToLoad.SizeOfExcludingThis(aMallocSizeOf);
  1214     aSizes->mFontListSize +=
  1215         mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis,
  1216                                        aMallocSizeOf);
  1218     aSizes->mFontListSize +=
  1219         mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
  1220                                                      aMallocSizeOf);
  1222     aSizes->mFontListSize +=
  1223         mSharedCmaps.SizeOfExcludingThis(SizeOfSharedCmapExcludingThis,
  1224                                          aMallocSizeOf, aSizes);
  1227 void
  1228 gfxPlatformFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
  1229                                             FontListSizes* aSizes) const
  1231     aSizes->mFontListSize += aMallocSizeOf(this);
  1232     AddSizeOfExcludingThis(aMallocSizeOf, aSizes);

mercurial