|
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/. */ |
|
5 |
|
6 #ifndef GFXPLATFORMFONTLIST_H_ |
|
7 #define GFXPLATFORMFONTLIST_H_ |
|
8 |
|
9 #include "nsDataHashtable.h" |
|
10 #include "nsRefPtrHashtable.h" |
|
11 #include "nsTHashtable.h" |
|
12 |
|
13 #include "gfxFontUtils.h" |
|
14 #include "gfxFontInfoLoader.h" |
|
15 #include "gfxFont.h" |
|
16 #include "gfxPlatform.h" |
|
17 |
|
18 #include "nsIMemoryReporter.h" |
|
19 #include "mozilla/Attributes.h" |
|
20 #include "mozilla/MemoryReporting.h" |
|
21 |
|
22 class CharMapHashKey : public PLDHashEntryHdr |
|
23 { |
|
24 public: |
|
25 typedef gfxCharacterMap* KeyType; |
|
26 typedef const gfxCharacterMap* KeyTypePointer; |
|
27 |
|
28 CharMapHashKey(const gfxCharacterMap *aCharMap) : |
|
29 mCharMap(const_cast<gfxCharacterMap*>(aCharMap)) |
|
30 { |
|
31 MOZ_COUNT_CTOR(CharMapHashKey); |
|
32 } |
|
33 CharMapHashKey(const CharMapHashKey& toCopy) : |
|
34 mCharMap(toCopy.mCharMap) |
|
35 { |
|
36 MOZ_COUNT_CTOR(CharMapHashKey); |
|
37 } |
|
38 ~CharMapHashKey() |
|
39 { |
|
40 MOZ_COUNT_DTOR(CharMapHashKey); |
|
41 } |
|
42 |
|
43 gfxCharacterMap* GetKey() const { return mCharMap; } |
|
44 |
|
45 bool KeyEquals(const gfxCharacterMap *aCharMap) const { |
|
46 NS_ASSERTION(!aCharMap->mBuildOnTheFly && !mCharMap->mBuildOnTheFly, |
|
47 "custom cmap used in shared cmap hashtable"); |
|
48 // cmaps built on the fly never match |
|
49 if (aCharMap->mHash != mCharMap->mHash) |
|
50 { |
|
51 return false; |
|
52 } |
|
53 return mCharMap->Equals(aCharMap); |
|
54 } |
|
55 |
|
56 static const gfxCharacterMap* KeyToPointer(gfxCharacterMap *aCharMap) { |
|
57 return aCharMap; |
|
58 } |
|
59 static PLDHashNumber HashKey(const gfxCharacterMap *aCharMap) { |
|
60 return aCharMap->mHash; |
|
61 } |
|
62 |
|
63 enum { ALLOW_MEMMOVE = true }; |
|
64 |
|
65 protected: |
|
66 gfxCharacterMap *mCharMap; |
|
67 }; |
|
68 |
|
69 // gfxPlatformFontList is an abstract class for the global font list on the system; |
|
70 // concrete subclasses for each platform implement the actual interface to the system fonts. |
|
71 // This class exists because we cannot rely on the platform font-finding APIs to behave |
|
72 // in sensible/similar ways, particularly with rich, complex OpenType families, |
|
73 // so we do our own font family/style management here instead. |
|
74 |
|
75 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms. |
|
76 |
|
77 struct FontListSizes { |
|
78 uint32_t mFontListSize; // size of the font list and dependent objects |
|
79 // (font family and face names, etc), but NOT |
|
80 // including the font table cache and the cmaps |
|
81 uint32_t mFontTableCacheSize; // memory used for the gfxFontEntry table caches |
|
82 uint32_t mCharMapsSize; // memory used for cmap coverage info |
|
83 }; |
|
84 |
|
85 class gfxUserFontSet; |
|
86 |
|
87 class gfxPlatformFontList : public gfxFontInfoLoader |
|
88 { |
|
89 public: |
|
90 static gfxPlatformFontList* PlatformFontList() { |
|
91 return sPlatformFontList; |
|
92 } |
|
93 |
|
94 static nsresult Init() { |
|
95 NS_ASSERTION(!sPlatformFontList, "What's this doing here?"); |
|
96 gfxPlatform::GetPlatform()->CreatePlatformFontList(); |
|
97 if (!sPlatformFontList) { |
|
98 return NS_ERROR_OUT_OF_MEMORY; |
|
99 } |
|
100 return NS_OK; |
|
101 } |
|
102 |
|
103 static void Shutdown() { |
|
104 delete sPlatformFontList; |
|
105 sPlatformFontList = nullptr; |
|
106 } |
|
107 |
|
108 virtual ~gfxPlatformFontList(); |
|
109 |
|
110 // initialize font lists |
|
111 virtual nsresult InitFontList(); |
|
112 |
|
113 void GetFontList (nsIAtom *aLangGroup, |
|
114 const nsACString& aGenericFamily, |
|
115 nsTArray<nsString>& aListOfFonts); |
|
116 |
|
117 virtual bool ResolveFontName(const nsAString& aFontName, |
|
118 nsAString& aResolvedFontName); |
|
119 |
|
120 void UpdateFontList(); |
|
121 |
|
122 void ClearPrefFonts() { mPrefFonts.Clear(); } |
|
123 |
|
124 virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray); |
|
125 |
|
126 virtual gfxFontEntry* |
|
127 SystemFindFontForChar(const uint32_t aCh, |
|
128 int32_t aRunScript, |
|
129 const gfxFontStyle* aStyle); |
|
130 |
|
131 // TODO: make this virtual, for lazily adding to the font list |
|
132 virtual gfxFontFamily* FindFamily(const nsAString& aFamily); |
|
133 |
|
134 gfxFontEntry* FindFontForFamily(const nsAString& aFamily, const gfxFontStyle* aStyle, bool& aNeedsBold); |
|
135 |
|
136 bool GetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> > *array); |
|
137 void SetPrefFontFamilyEntries(eFontPrefLang aLangGroup, nsTArray<nsRefPtr<gfxFontFamily> >& array); |
|
138 |
|
139 // name lookup table methods |
|
140 |
|
141 void AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName); |
|
142 |
|
143 void AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname); |
|
144 |
|
145 void AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName); |
|
146 |
|
147 bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; } |
|
148 |
|
149 // pure virtual functions, to be provided by concrete subclasses |
|
150 |
|
151 // get the system default font family |
|
152 virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle) = 0; |
|
153 |
|
154 // look up a font by name on the host platform |
|
155 virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, |
|
156 const nsAString& aFontName) = 0; |
|
157 |
|
158 // create a new platform font from downloaded data (@font-face) |
|
159 // this method is responsible to ensure aFontData is NS_Free()'d |
|
160 virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, |
|
161 const uint8_t *aFontData, |
|
162 uint32_t aLength) = 0; |
|
163 |
|
164 // get the standard family name on the platform for a given font name |
|
165 // (platforms may override, eg Mac) |
|
166 virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); |
|
167 |
|
168 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
|
169 FontListSizes* aSizes) const; |
|
170 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
|
171 FontListSizes* aSizes) const; |
|
172 |
|
173 // search for existing cmap that matches the input |
|
174 // return the input if no match is found |
|
175 gfxCharacterMap* FindCharMap(gfxCharacterMap *aCmap); |
|
176 |
|
177 // add a cmap to the shared cmap set |
|
178 gfxCharacterMap* AddCmap(const gfxCharacterMap *aCharMap); |
|
179 |
|
180 // remove the cmap from the shared cmap set |
|
181 void RemoveCmap(const gfxCharacterMap *aCharMap); |
|
182 |
|
183 // keep track of userfont sets to notify when global fontlist changes occur |
|
184 void AddUserFontSet(gfxUserFontSet *aUserFontSet) { |
|
185 mUserFontSetList.PutEntry(aUserFontSet); |
|
186 } |
|
187 |
|
188 void RemoveUserFontSet(gfxUserFontSet *aUserFontSet) { |
|
189 mUserFontSetList.RemoveEntry(aUserFontSet); |
|
190 } |
|
191 |
|
192 static const gfxFontEntry::ScriptRange sComplexScriptRanges[]; |
|
193 |
|
194 protected: |
|
195 class MemoryReporter MOZ_FINAL : public nsIMemoryReporter |
|
196 { |
|
197 public: |
|
198 NS_DECL_ISUPPORTS |
|
199 NS_DECL_NSIMEMORYREPORTER |
|
200 }; |
|
201 |
|
202 gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true); |
|
203 |
|
204 static gfxPlatformFontList *sPlatformFontList; |
|
205 |
|
206 static PLDHashOperator FindFontForCharProc(nsStringHashKey::KeyType aKey, |
|
207 nsRefPtr<gfxFontFamily>& aFamilyEntry, |
|
208 void* userArg); |
|
209 |
|
210 // returns default font for a given character, null otherwise |
|
211 gfxFontEntry* CommonFontFallback(const uint32_t aCh, |
|
212 int32_t aRunScript, |
|
213 const gfxFontStyle* aMatchStyle, |
|
214 gfxFontFamily** aMatchedFamily); |
|
215 |
|
216 // search fonts system-wide for a given character, null otherwise |
|
217 virtual gfxFontEntry* GlobalFontFallback(const uint32_t aCh, |
|
218 int32_t aRunScript, |
|
219 const gfxFontStyle* aMatchStyle, |
|
220 uint32_t& aCmapCount, |
|
221 gfxFontFamily** aMatchedFamily); |
|
222 |
|
223 // whether system-based font fallback is used or not |
|
224 // if system fallback is used, no need to load all cmaps |
|
225 virtual bool UsesSystemFallback() { return false; } |
|
226 |
|
227 // verifies that a family contains a non-zero font count |
|
228 gfxFontFamily* CheckFamily(gfxFontFamily *aFamily); |
|
229 |
|
230 // initialize localized family names |
|
231 void InitOtherFamilyNames(); |
|
232 |
|
233 static PLDHashOperator |
|
234 InitOtherFamilyNamesProc(nsStringHashKey::KeyType aKey, |
|
235 nsRefPtr<gfxFontFamily>& aFamilyEntry, |
|
236 void* userArg); |
|
237 |
|
238 // search through font families, looking for a given name, initializing |
|
239 // facename lists along the way. first checks all families with names |
|
240 // close to face name, then searchs all families if not found. |
|
241 gfxFontEntry* SearchFamiliesForFaceName(const nsAString& aFaceName); |
|
242 |
|
243 static PLDHashOperator |
|
244 ReadFaceNamesProc(nsStringHashKey::KeyType aKey, |
|
245 nsRefPtr<gfxFontFamily>& aFamilyEntry, |
|
246 void* userArg); |
|
247 |
|
248 // helper method for finding fullname/postscript names in facename lists |
|
249 gfxFontEntry* FindFaceName(const nsAString& aFaceName); |
|
250 |
|
251 // look up a font by name, for cases where platform font list |
|
252 // maintains explicit mappings of fullname/psname ==> font |
|
253 virtual gfxFontEntry* LookupInFaceNameLists(const nsAString& aFontName); |
|
254 |
|
255 static PLDHashOperator LookupMissedFaceNamesProc(nsStringHashKey *aKey, |
|
256 void *aUserArg); |
|
257 |
|
258 static PLDHashOperator LookupMissedOtherNamesProc(nsStringHashKey *aKey, |
|
259 void *aUserArg); |
|
260 |
|
261 // commonly used fonts for which the name table should be loaded at startup |
|
262 virtual void PreloadNamesList(); |
|
263 |
|
264 // load the bad underline blacklist from pref. |
|
265 void LoadBadUnderlineList(); |
|
266 |
|
267 // explicitly set fixed-pitch flag for all faces |
|
268 void SetFixedPitch(const nsAString& aFamilyName); |
|
269 |
|
270 void GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult); |
|
271 |
|
272 static PLDHashOperator |
|
273 HashEnumFuncForFamilies(nsStringHashKey::KeyType aKey, |
|
274 nsRefPtr<gfxFontFamily>& aFamilyEntry, |
|
275 void* aUserArg); |
|
276 |
|
277 virtual void GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames); |
|
278 |
|
279 // gfxFontInfoLoader overrides, used to load in font cmaps |
|
280 virtual void InitLoader(); |
|
281 virtual bool LoadFontInfo(); |
|
282 virtual void CleanupLoader(); |
|
283 |
|
284 // read the loader initialization prefs, and start it |
|
285 void GetPrefsAndStartLoader(); |
|
286 |
|
287 // for font list changes that affect all documents |
|
288 void ForceGlobalReflow(); |
|
289 |
|
290 // used by memory reporter to accumulate sizes of family names in the hash |
|
291 static size_t |
|
292 SizeOfFamilyNameEntryExcludingThis(const nsAString& aKey, |
|
293 const nsRefPtr<gfxFontFamily>& aFamily, |
|
294 mozilla::MallocSizeOf aMallocSizeOf, |
|
295 void* aUserArg); |
|
296 |
|
297 // canonical family name ==> family entry (unique, one name per family entry) |
|
298 nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mFontFamilies; |
|
299 |
|
300 // other family name ==> family entry (not unique, can have multiple names per |
|
301 // family entry, only names *other* than the canonical names are stored here) |
|
302 nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mOtherFamilyNames; |
|
303 |
|
304 // flag set after InitOtherFamilyNames is called upon first name lookup miss |
|
305 bool mOtherFamilyNamesInitialized; |
|
306 |
|
307 // flag set after fullname and Postcript name lists are populated |
|
308 bool mFaceNameListsInitialized; |
|
309 |
|
310 struct ExtraNames { |
|
311 ExtraNames() : mFullnames(100), mPostscriptNames(100) {} |
|
312 // fullname ==> font entry (unique, one name per font entry) |
|
313 nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> mFullnames; |
|
314 // Postscript name ==> font entry (unique, one name per font entry) |
|
315 nsRefPtrHashtable<nsStringHashKey, gfxFontEntry> mPostscriptNames; |
|
316 }; |
|
317 nsAutoPtr<ExtraNames> mExtraNames; |
|
318 |
|
319 // face names missed when face name loading takes a long time |
|
320 nsAutoPtr<nsTHashtable<nsStringHashKey> > mFaceNamesMissed; |
|
321 |
|
322 // localized family names missed when face name loading takes a long time |
|
323 nsAutoPtr<nsTHashtable<nsStringHashKey> > mOtherNamesMissed; |
|
324 |
|
325 // cached pref font lists |
|
326 // maps list of family names ==> array of family entries, one per lang group |
|
327 nsDataHashtable<nsUint32HashKey, nsTArray<nsRefPtr<gfxFontFamily> > > mPrefFonts; |
|
328 |
|
329 // when system-wide font lookup fails for a character, cache it to skip future searches |
|
330 gfxSparseBitSet mCodepointsWithNoFonts; |
|
331 |
|
332 // the family to use for U+FFFD fallback, to avoid expensive search every time |
|
333 // on pages with lots of problems |
|
334 nsRefPtr<gfxFontFamily> mReplacementCharFallbackFamily; |
|
335 |
|
336 nsTHashtable<nsStringHashKey> mBadUnderlineFamilyNames; |
|
337 |
|
338 // character map data shared across families |
|
339 // contains weak ptrs to cmaps shared by font entry objects |
|
340 nsTHashtable<CharMapHashKey> mSharedCmaps; |
|
341 |
|
342 // data used as part of the font cmap loading process |
|
343 nsTArray<nsRefPtr<gfxFontFamily> > mFontFamiliesToLoad; |
|
344 uint32_t mStartIndex; |
|
345 uint32_t mIncrement; |
|
346 uint32_t mNumFamilies; |
|
347 |
|
348 nsTHashtable<nsPtrHashKey<gfxUserFontSet> > mUserFontSetList; |
|
349 }; |
|
350 |
|
351 #endif /* GFXPLATFORMFONTLIST_H_ */ |