Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 #ifndef GFX_FONT_INFO_LOADER_H
7 #define GFX_FONT_INFO_LOADER_H
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"
21 // data retrieved for a given face
23 struct FontFaceData {
24 FontFaceData() : mUVSOffset(0), mSymbolFont(false) {}
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 }
34 nsString mFullName;
35 nsString mPostscriptName;
36 nsRefPtr<gfxCharacterMap> mCharacterMap;
37 uint32_t mUVSOffset;
38 bool mSymbolFont;
39 };
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.
48 class FontInfoData {
49 public:
50 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FontInfoData)
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 }
62 protected:
63 // Protected destructor, to discourage deletion outside of Release():
64 virtual ~FontInfoData() {
65 MOZ_COUNT_DTOR(FontInfoData);
66 }
68 public:
69 virtual void Load();
71 // loads font data for all fonts of a given family
72 // (called on async thread)
73 virtual void LoadFontFamilyData(const nsAString& aFamilyName) = 0;
75 // -- methods overriden by platform-specific versions --
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 }
89 aUVSOffset = faceData.mUVSOffset;
90 aSymbolFont = faceData.mSymbolFont;
91 nsRefPtr<gfxCharacterMap> cmap = faceData.mCharacterMap;
92 return cmap.forget();
93 }
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 }
105 aFullName = faceData.mFullName;
106 aPostscriptName = faceData.mPostscriptName;
107 }
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 }
116 nsTArray<nsString> mFontFamiliesToLoad;
118 // time spent on the loader thread
119 mozilla::TimeDuration mLoadTime;
121 struct FontCounts {
122 uint32_t families;
123 uint32_t fonts;
124 uint32_t cmaps;
125 uint32_t facenames;
126 uint32_t othernames;
127 };
129 FontCounts mLoadStats;
131 bool mLoadOtherNames;
132 bool mLoadFaceNames;
133 bool mLoadCmaps;
135 // face name ==> per-face data
136 nsDataHashtable<nsStringHashKey, FontFaceData> mFontFaceData;
138 // canonical family name ==> array of localized family names
139 nsDataHashtable<nsStringHashKey, nsTArray<nsString> > mOtherFamilyNames;
140 };
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.
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
150 class gfxFontInfoLoader {
151 public:
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;
169 gfxFontInfoLoader() :
170 mInterval(0), mState(stateInitial)
171 {
172 }
174 virtual ~gfxFontInfoLoader();
176 // start timer with an initial delay, then call Run method at regular intervals
177 void StartLoader(uint32_t aDelay, uint32_t aInterval);
179 // Finalize - async load complete, transfer data (on intervals if necessary)
180 virtual void FinalizeLoader(FontInfoData *aFontInfo);
182 // cancel the timer and cleanup
183 void CancelLoader();
185 uint32_t GetInterval() { return mInterval; }
187 protected:
188 class ShutdownObserver : public nsIObserver
189 {
190 public:
191 NS_DECL_ISUPPORTS
192 NS_DECL_NSIOBSERVER
194 ShutdownObserver(gfxFontInfoLoader *aLoader)
195 : mLoader(aLoader)
196 { }
198 virtual ~ShutdownObserver()
199 { }
201 protected:
202 gfxFontInfoLoader *mLoader;
203 };
205 // CreateFontInfo - create platform-specific object used
206 // to load system-wide font info
207 virtual already_AddRefed<FontInfoData> CreateFontInfoData() {
208 return nullptr;
209 }
211 // Init - initialization before async loader thread runs
212 virtual void InitLoader() = 0;
214 // LoadFontInfo - transfer font info data within a time limit, return
215 // true when done
216 virtual bool LoadFontInfo() = 0;
218 // Cleanup - finish and cleanup after done, including possible reflows
219 virtual void CleanupLoader() {
220 mFontInfo = nullptr;
221 }
223 // Timer interval callbacks
224 static void LoadFontInfoCallback(nsITimer *aTimer, void *aThis) {
225 gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
226 loader->LoadFontInfoTimerFire();
227 }
229 static void DelayedStartCallback(nsITimer *aTimer, void *aThis) {
230 gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
231 loader->StartLoader(0, loader->GetInterval());
232 }
234 void LoadFontInfoTimerFire();
236 void AddShutdownObserver();
237 void RemoveShutdownObserver();
239 nsCOMPtr<nsITimer> mTimer;
240 nsCOMPtr<nsIObserver> mObserver;
241 nsCOMPtr<nsIThread> mFontLoaderThread;
242 uint32_t mInterval;
243 TimerState mState;
245 // after async font loader completes, data is stored here
246 nsRefPtr<FontInfoData> mFontInfo;
248 // time spent on the loader thread
249 mozilla::TimeDuration mLoadTime;
250 };
252 #endif /* GFX_FONT_INFO_LOADER_H */