|
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 GFX_FONT_INFO_LOADER_H |
|
7 #define GFX_FONT_INFO_LOADER_H |
|
8 |
|
9 #include "nsAutoPtr.h" |
|
10 #include "nsCOMPtr.h" |
|
11 #include "nsIObserver.h" |
|
12 #include "nsITimer.h" |
|
13 #include "nsIThread.h" |
|
14 #include "nsRefPtrHashtable.h" |
|
15 #include "nsString.h" |
|
16 #include "gfxFont.h" |
|
17 #include "nsIRunnable.h" |
|
18 #include "mozilla/TimeStamp.h" |
|
19 #include "nsISupportsImpl.h" |
|
20 |
|
21 // data retrieved for a given face |
|
22 |
|
23 struct FontFaceData { |
|
24 FontFaceData() : mUVSOffset(0), mSymbolFont(false) {} |
|
25 |
|
26 FontFaceData(const FontFaceData& aFontFaceData) { |
|
27 mFullName = aFontFaceData.mFullName; |
|
28 mPostscriptName = aFontFaceData.mPostscriptName; |
|
29 mCharacterMap = aFontFaceData.mCharacterMap; |
|
30 mUVSOffset = aFontFaceData.mUVSOffset; |
|
31 mSymbolFont = aFontFaceData.mSymbolFont; |
|
32 } |
|
33 |
|
34 nsString mFullName; |
|
35 nsString mPostscriptName; |
|
36 nsRefPtr<gfxCharacterMap> mCharacterMap; |
|
37 uint32_t mUVSOffset; |
|
38 bool mSymbolFont; |
|
39 }; |
|
40 |
|
41 // base class used to contain cached system-wide font info. |
|
42 // methods in this class are called on off-main threads so |
|
43 // all methods use only static methods or other thread-safe |
|
44 // font data access API's. specifically, no use is made of |
|
45 // gfxPlatformFontList, gfxFontFamily, gfxFamily or any |
|
46 // harfbuzz API methods within FontInfoData subclasses. |
|
47 |
|
48 class FontInfoData { |
|
49 public: |
|
50 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FontInfoData) |
|
51 |
|
52 FontInfoData(bool aLoadOtherNames, |
|
53 bool aLoadFaceNames, |
|
54 bool aLoadCmaps) : |
|
55 mLoadOtherNames(aLoadOtherNames), |
|
56 mLoadFaceNames(aLoadFaceNames), |
|
57 mLoadCmaps(aLoadCmaps) |
|
58 { |
|
59 MOZ_COUNT_CTOR(FontInfoData); |
|
60 } |
|
61 |
|
62 protected: |
|
63 // Protected destructor, to discourage deletion outside of Release(): |
|
64 virtual ~FontInfoData() { |
|
65 MOZ_COUNT_DTOR(FontInfoData); |
|
66 } |
|
67 |
|
68 public: |
|
69 virtual void Load(); |
|
70 |
|
71 // loads font data for all fonts of a given family |
|
72 // (called on async thread) |
|
73 virtual void LoadFontFamilyData(const nsAString& aFamilyName) = 0; |
|
74 |
|
75 // -- methods overriden by platform-specific versions -- |
|
76 |
|
77 // fetches cmap data for a particular font from cached font data |
|
78 virtual already_AddRefed<gfxCharacterMap> |
|
79 GetCMAP(const nsAString& aFontName, |
|
80 uint32_t& aUVSOffset, |
|
81 bool& aSymbolFont) |
|
82 { |
|
83 FontFaceData faceData; |
|
84 if (!mFontFaceData.Get(aFontName, &faceData) || |
|
85 !faceData.mCharacterMap) { |
|
86 return nullptr; |
|
87 } |
|
88 |
|
89 aUVSOffset = faceData.mUVSOffset; |
|
90 aSymbolFont = faceData.mSymbolFont; |
|
91 nsRefPtr<gfxCharacterMap> cmap = faceData.mCharacterMap; |
|
92 return cmap.forget(); |
|
93 } |
|
94 |
|
95 // fetches fullname/postscript names from cached font data |
|
96 virtual void GetFaceNames(const nsAString& aFontName, |
|
97 nsAString& aFullName, |
|
98 nsAString& aPostscriptName) |
|
99 { |
|
100 FontFaceData faceData; |
|
101 if (!mFontFaceData.Get(aFontName, &faceData)) { |
|
102 return; |
|
103 } |
|
104 |
|
105 aFullName = faceData.mFullName; |
|
106 aPostscriptName = faceData.mPostscriptName; |
|
107 } |
|
108 |
|
109 // fetches localized family name data from cached font data |
|
110 virtual bool GetOtherFamilyNames(const nsAString& aFamilyName, |
|
111 nsTArray<nsString>& aOtherFamilyNames) |
|
112 { |
|
113 return mOtherFamilyNames.Get(aFamilyName, &aOtherFamilyNames); |
|
114 } |
|
115 |
|
116 nsTArray<nsString> mFontFamiliesToLoad; |
|
117 |
|
118 // time spent on the loader thread |
|
119 mozilla::TimeDuration mLoadTime; |
|
120 |
|
121 struct FontCounts { |
|
122 uint32_t families; |
|
123 uint32_t fonts; |
|
124 uint32_t cmaps; |
|
125 uint32_t facenames; |
|
126 uint32_t othernames; |
|
127 }; |
|
128 |
|
129 FontCounts mLoadStats; |
|
130 |
|
131 bool mLoadOtherNames; |
|
132 bool mLoadFaceNames; |
|
133 bool mLoadCmaps; |
|
134 |
|
135 // face name ==> per-face data |
|
136 nsDataHashtable<nsStringHashKey, FontFaceData> mFontFaceData; |
|
137 |
|
138 // canonical family name ==> array of localized family names |
|
139 nsDataHashtable<nsStringHashKey, nsTArray<nsString> > mOtherFamilyNames; |
|
140 }; |
|
141 |
|
142 // gfxFontInfoLoader - helper class for loading font info on async thread |
|
143 // For large, "all fonts on system" data, data needed on a given platform |
|
144 // (e.g. localized names, face names, cmaps) are loaded async. |
|
145 |
|
146 // helper class for loading in font info on a separate async thread |
|
147 // once async thread completes, completion process is run on regular |
|
148 // intervals to prevent tying up the main thread |
|
149 |
|
150 class gfxFontInfoLoader { |
|
151 public: |
|
152 |
|
153 // state transitions: |
|
154 // initial ---StartLoader with delay---> timer on delay |
|
155 // initial ---StartLoader without delay---> timer on interval |
|
156 // timer on delay ---LoaderTimerFire---> timer on interval |
|
157 // timer on delay ---CancelLoader---> timer off |
|
158 // timer on interval ---CancelLoader---> timer off |
|
159 // timer off ---StartLoader with delay---> timer on delay |
|
160 // timer off ---StartLoader without delay---> timer on interval |
|
161 typedef enum { |
|
162 stateInitial, |
|
163 stateTimerOnDelay, |
|
164 stateAsyncLoad, |
|
165 stateTimerOnInterval, |
|
166 stateTimerOff |
|
167 } TimerState; |
|
168 |
|
169 gfxFontInfoLoader() : |
|
170 mInterval(0), mState(stateInitial) |
|
171 { |
|
172 } |
|
173 |
|
174 virtual ~gfxFontInfoLoader(); |
|
175 |
|
176 // start timer with an initial delay, then call Run method at regular intervals |
|
177 void StartLoader(uint32_t aDelay, uint32_t aInterval); |
|
178 |
|
179 // Finalize - async load complete, transfer data (on intervals if necessary) |
|
180 virtual void FinalizeLoader(FontInfoData *aFontInfo); |
|
181 |
|
182 // cancel the timer and cleanup |
|
183 void CancelLoader(); |
|
184 |
|
185 uint32_t GetInterval() { return mInterval; } |
|
186 |
|
187 protected: |
|
188 class ShutdownObserver : public nsIObserver |
|
189 { |
|
190 public: |
|
191 NS_DECL_ISUPPORTS |
|
192 NS_DECL_NSIOBSERVER |
|
193 |
|
194 ShutdownObserver(gfxFontInfoLoader *aLoader) |
|
195 : mLoader(aLoader) |
|
196 { } |
|
197 |
|
198 virtual ~ShutdownObserver() |
|
199 { } |
|
200 |
|
201 protected: |
|
202 gfxFontInfoLoader *mLoader; |
|
203 }; |
|
204 |
|
205 // CreateFontInfo - create platform-specific object used |
|
206 // to load system-wide font info |
|
207 virtual already_AddRefed<FontInfoData> CreateFontInfoData() { |
|
208 return nullptr; |
|
209 } |
|
210 |
|
211 // Init - initialization before async loader thread runs |
|
212 virtual void InitLoader() = 0; |
|
213 |
|
214 // LoadFontInfo - transfer font info data within a time limit, return |
|
215 // true when done |
|
216 virtual bool LoadFontInfo() = 0; |
|
217 |
|
218 // Cleanup - finish and cleanup after done, including possible reflows |
|
219 virtual void CleanupLoader() { |
|
220 mFontInfo = nullptr; |
|
221 } |
|
222 |
|
223 // Timer interval callbacks |
|
224 static void LoadFontInfoCallback(nsITimer *aTimer, void *aThis) { |
|
225 gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis); |
|
226 loader->LoadFontInfoTimerFire(); |
|
227 } |
|
228 |
|
229 static void DelayedStartCallback(nsITimer *aTimer, void *aThis) { |
|
230 gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis); |
|
231 loader->StartLoader(0, loader->GetInterval()); |
|
232 } |
|
233 |
|
234 void LoadFontInfoTimerFire(); |
|
235 |
|
236 void AddShutdownObserver(); |
|
237 void RemoveShutdownObserver(); |
|
238 |
|
239 nsCOMPtr<nsITimer> mTimer; |
|
240 nsCOMPtr<nsIObserver> mObserver; |
|
241 nsCOMPtr<nsIThread> mFontLoaderThread; |
|
242 uint32_t mInterval; |
|
243 TimerState mState; |
|
244 |
|
245 // after async font loader completes, data is stored here |
|
246 nsRefPtr<FontInfoData> mFontInfo; |
|
247 |
|
248 // time spent on the loader thread |
|
249 mozilla::TimeDuration mLoadTime; |
|
250 }; |
|
251 |
|
252 #endif /* GFX_FONT_INFO_LOADER_H */ |