nsFontCache.h (3449B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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/. */ 5 6 #ifndef _NS_FONTCACHE_H_ 7 #define _NS_FONTCACHE_H_ 8 9 #include <stdint.h> 10 #include <sys/types.h> 11 #include "mozilla/RefPtr.h" 12 #include "nsCOMPtr.h" 13 #include "nsFontMetrics.h" 14 #include "nsIObserver.h" 15 #include "nsISupports.h" 16 #include "nsTArray.h" 17 #include "nsThreadUtils.h" 18 #include "prtime.h" 19 20 class gfxUserFontSet; 21 class nsAtom; 22 class nsPresContext; 23 struct nsFont; 24 25 class nsFontCache final : public nsIObserver { 26 public: 27 nsFontCache() 28 : mContext(nullptr), mMissedFontFamilyNames("MissedFontFamilyNames") {} 29 30 NS_DECL_THREADSAFE_ISUPPORTS 31 NS_DECL_NSIOBSERVER 32 33 void Init(nsPresContext* aContext); 34 void Destroy(); 35 36 already_AddRefed<nsFontMetrics> GetMetricsFor( 37 const nsFont& aFont, const nsFontMetrics::Params& aParams); 38 39 void FontMetricsDeleted(const nsFontMetrics* aFontMetrics); 40 void Compact(); 41 42 // Flush aFlushCount oldest entries, or all if aFlushCount is negative 43 void Flush(int32_t aFlushCount = -1); 44 45 void UpdateUserFonts(gfxUserFontSet* aUserFontSet); 46 47 protected: 48 // If the array of cached entries is about to exceed this threshold, 49 // we'll discard the oldest ones so as to keep the size reasonable. 50 // In practice, the great majority of cache hits are among the last 51 // few entries; keeping thousands of older entries becomes counter- 52 // productive because it can then take too long to scan the cache. 53 static constexpr int32_t kMaxCacheEntries = 128; 54 55 // Number of cache misses before we assume that a font fingerprinting attempt 56 // is being made. 57 static constexpr int32_t kFingerprintingCacheMissThreshold = 10; 58 // We assume that fingerprinters will lookup a large number of fonts in a 59 // short amount of time. 60 static constexpr PRTime kFingerprintingLastNSec = 61 PRTime(PR_USEC_PER_SEC) * 6; // 6 seconds 62 63 static_assert(kFingerprintingCacheMissThreshold < kMaxCacheEntries); 64 65 ~nsFontCache() = default; 66 67 nsPresContext* mContext; // owner 68 RefPtr<nsAtom> mLocaleLanguage; 69 70 // We may not flush older entries immediately the array reaches 71 // kMaxCacheEntries length, because this usually happens on a stylo 72 // thread where we can't safely delete metrics objects. So we allocate an 73 // oversized autoarray buffer here, so that we're unlikely to overflow 74 // it and need separate heap allocation before the flush happens on the 75 // main thread. 76 AutoTArray<nsFontMetrics*, kMaxCacheEntries * 2> mFontMetrics; 77 78 bool mFlushPending = false; 79 80 class FlushFontMetricsTask : public mozilla::Runnable { 81 public: 82 explicit FlushFontMetricsTask(nsFontCache* aCache) 83 : mozilla::Runnable("FlushFontMetricsTask"), mCache(aCache) {} 84 NS_IMETHOD Run() override { 85 // Partially flush the cache, leaving the kMaxCacheEntries/2 most 86 // recent entries. 87 mCache->Flush(mCache->mFontMetrics.Length() - kMaxCacheEntries / 2); 88 mCache->mFlushPending = false; 89 return NS_OK; 90 } 91 92 private: 93 RefPtr<nsFontCache> mCache; 94 }; 95 96 void DetectFontFingerprinting(const nsFont& aFont); 97 98 mozilla::DataMutex<nsTHashMap<nsStringHashKey, PRTime>> 99 mMissedFontFamilyNames; 100 bool mReportedProbableFingerprinting = false; 101 }; 102 103 #endif /* _NS_FONTCACHE_H_ */