Line data Source code
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 GFXFCPLATFORMFONTLIST_H_
7 : #define GFXFCPLATFORMFONTLIST_H_
8 :
9 : #include "gfxFont.h"
10 : #include "gfxFontEntry.h"
11 : #include "gfxFT2FontBase.h"
12 : #include "gfxPlatformFontList.h"
13 : #include "mozilla/mozalloc.h"
14 : #include "nsClassHashtable.h"
15 :
16 : #include <fontconfig/fontconfig.h>
17 : #include "ft2build.h"
18 : #include FT_FREETYPE_H
19 : #include FT_TRUETYPE_TABLES_H
20 : #include <cairo.h>
21 : #include <cairo-ft.h>
22 :
23 : #include "gfxFontconfigUtils.h" // xxx - only for nsAutoRefTraits<FcPattern>, etc.
24 :
25 : template <>
26 0 : class nsAutoRefTraits<FcObjectSet> : public nsPointerRefTraits<FcObjectSet>
27 : {
28 : public:
29 0 : static void Release(FcObjectSet *ptr) { FcObjectSetDestroy(ptr); }
30 : };
31 :
32 : template <>
33 9 : class nsAutoRefTraits<FcConfig> : public nsPointerRefTraits<FcConfig>
34 : {
35 : public:
36 3 : static void Release(FcConfig *ptr) { FcConfigDestroy(ptr); }
37 6 : static void AddRef(FcConfig *ptr) { FcConfigReference(ptr); }
38 : };
39 :
40 : // Helper classes used for clearning out user font data when cairo font
41 : // face is destroyed. Since multiple faces may use the same data, be
42 : // careful to assure that the data is only cleared out when all uses
43 : // expire. The font entry object contains a refptr to FTUserFontData and
44 : // each cairo font created from that font entry contains a
45 : // FTUserFontDataRef with a refptr to that same FTUserFontData object.
46 :
47 : class FTUserFontData {
48 : public:
49 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FTUserFontData)
50 :
51 0 : explicit FTUserFontData(FT_Face aFace, const uint8_t* aData)
52 0 : : mFace(aFace), mFontData(aData)
53 : {
54 0 : }
55 :
56 : const uint8_t *FontData() const { return mFontData; }
57 :
58 : private:
59 0 : ~FTUserFontData()
60 0 : {
61 0 : mozilla::gfx::Factory::ReleaseFTFace(mFace);
62 0 : if (mFontData) {
63 0 : NS_Free((void*)mFontData);
64 : }
65 0 : }
66 :
67 : FT_Face mFace;
68 : const uint8_t *mFontData;
69 : };
70 :
71 : // The names for the font entry and font classes should really
72 : // the common 'Fc' abbreviation but the gfxPangoFontGroup code already
73 : // defines versions of these, so use the verbose name for now.
74 :
75 : class gfxFontconfigFontEntry : public gfxFontEntry {
76 : public:
77 : // used for system fonts with explicit patterns
78 : explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
79 : FcPattern* aFontPattern,
80 : bool aIgnoreFcCharmap);
81 :
82 : // used for data fonts where the fontentry takes ownership
83 : // of the font data and the FT_Face
84 : explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
85 : uint16_t aWeight,
86 : int16_t aStretch,
87 : uint8_t aStyle,
88 : const uint8_t *aData,
89 : FT_Face aFace);
90 :
91 : // used for @font-face local system fonts with explicit patterns
92 : explicit gfxFontconfigFontEntry(const nsAString& aFaceName,
93 : FcPattern* aFontPattern,
94 : uint16_t aWeight,
95 : int16_t aStretch,
96 : uint8_t aStyle);
97 :
98 16 : FcPattern* GetPattern() { return mFontPattern; }
99 :
100 : bool SupportsLangGroup(nsIAtom *aLangGroup) const override;
101 :
102 : nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override;
103 : bool TestCharacterMap(uint32_t aCh) override;
104 :
105 : hb_blob_t* GetFontTable(uint32_t aTableTag) override;
106 :
107 : void ForgetHBFace() override;
108 : void ReleaseGrFace(gr_face* aFace) override;
109 :
110 : double GetAspect();
111 :
112 : protected:
113 : virtual ~gfxFontconfigFontEntry();
114 :
115 : gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
116 : bool aNeedsBold) override;
117 :
118 : // helper method for creating cairo font from pattern
119 : cairo_scaled_font_t*
120 : CreateScaledFont(FcPattern* aRenderPattern,
121 : gfxFloat aAdjustedSize,
122 : const gfxFontStyle *aStyle,
123 : bool aNeedsBold);
124 :
125 : // override to pull data from FTFace
126 : virtual nsresult
127 : CopyFontTable(uint32_t aTableTag,
128 : nsTArray<uint8_t>& aBuffer) override;
129 :
130 : // if HB or GR faces are gone, close down the FT_Face
131 : void MaybeReleaseFTFace();
132 :
133 : // pattern for a single face of a family
134 : nsCountedRef<FcPattern> mFontPattern;
135 :
136 : // user font data, when needed
137 : RefPtr<FTUserFontData> mUserFontData;
138 :
139 : // FTFace - initialized when needed
140 : FT_Face mFTFace;
141 : bool mFTFaceInitialized;
142 :
143 : // Whether TestCharacterMap should check the actual cmap rather than asking
144 : // fontconfig about character coverage.
145 : // We do this for app-bundled (rather than system) fonts, as they may
146 : // include color glyphs that fontconfig would overlook, and for fonts
147 : // loaded via @font-face.
148 : bool mIgnoreFcCharmap;
149 :
150 : double mAspect;
151 :
152 : // data font
153 : const uint8_t* mFontData;
154 :
155 107 : class UnscaledFontCache
156 : {
157 : public:
158 : already_AddRefed<mozilla::gfx::UnscaledFontFontconfig>
159 : Lookup(const char* aFile, uint32_t aIndex);
160 :
161 6 : void Add(const RefPtr<mozilla::gfx::UnscaledFontFontconfig>& aUnscaledFont) {
162 6 : mUnscaledFonts[kNumEntries-1] = aUnscaledFont;
163 6 : MoveToFront(kNumEntries-1);
164 6 : }
165 :
166 : private:
167 : void MoveToFront(size_t aIndex);
168 :
169 : static const size_t kNumEntries = 3;
170 : mozilla::WeakPtr<mozilla::gfx::UnscaledFont> mUnscaledFonts[kNumEntries];
171 : };
172 :
173 : UnscaledFontCache mUnscaledFontCache;
174 : };
175 :
176 : class gfxFontconfigFontFamily : public gfxFontFamily {
177 : public:
178 558 : explicit gfxFontconfigFontFamily(const nsAString& aName) :
179 : gfxFontFamily(aName),
180 : mContainsAppFonts(false),
181 : mHasNonScalableFaces(false),
182 558 : mForceScalable(false)
183 558 : { }
184 :
185 : void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) override;
186 :
187 : // Families are constructed initially with just references to patterns.
188 : // When necessary, these are enumerated within FindStyleVariations.
189 : void AddFontPattern(FcPattern* aFontPattern);
190 :
191 3 : void SetFamilyContainsAppFonts(bool aContainsAppFonts)
192 : {
193 3 : mContainsAppFonts = aContainsAppFonts;
194 3 : }
195 :
196 : void
197 : FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
198 : nsTArray<gfxFontEntry*>& aFontEntryList,
199 : bool& aNeedsSyntheticBold) override;
200 :
201 : protected:
202 : virtual ~gfxFontconfigFontFamily();
203 :
204 : nsTArray<nsCountedRef<FcPattern> > mFontPatterns;
205 :
206 : bool mContainsAppFonts;
207 : bool mHasNonScalableFaces;
208 : bool mForceScalable;
209 : };
210 :
211 : class gfxFontconfigFont : public gfxFontconfigFontBase {
212 : public:
213 : gfxFontconfigFont(const RefPtr<mozilla::gfx::UnscaledFontFontconfig> &aUnscaledFont,
214 : cairo_scaled_font_t *aScaledFont,
215 : FcPattern *aPattern,
216 : gfxFloat aAdjustedSize,
217 : gfxFontEntry *aFontEntry,
218 : const gfxFontStyle *aFontStyle,
219 : bool aNeedsBold);
220 :
221 : protected:
222 : virtual ~gfxFontconfigFont();
223 : };
224 :
225 : class gfxFcPlatformFontList : public gfxPlatformFontList {
226 : public:
227 : gfxFcPlatformFontList();
228 :
229 0 : static gfxFcPlatformFontList* PlatformFontList() {
230 0 : return static_cast<gfxFcPlatformFontList*>(sPlatformFontList);
231 : }
232 :
233 : // initialize font lists
234 : virtual nsresult InitFontListForPlatform() override;
235 :
236 : void GetFontList(nsIAtom *aLangGroup,
237 : const nsACString& aGenericFamily,
238 : nsTArray<nsString>& aListOfFonts) override;
239 :
240 :
241 : gfxFontEntry*
242 : LookupLocalFont(const nsAString& aFontName, uint16_t aWeight,
243 : int16_t aStretch, uint8_t aStyle) override;
244 :
245 : gfxFontEntry*
246 : MakePlatformFont(const nsAString& aFontName, uint16_t aWeight,
247 : int16_t aStretch,
248 : uint8_t aStyle,
249 : const uint8_t* aFontData,
250 : uint32_t aLength) override;
251 :
252 : bool FindAndAddFamilies(const nsAString& aFamily,
253 : nsTArray<gfxFontFamily*>* aOutput,
254 : gfxFontStyle* aStyle = nullptr,
255 : gfxFloat aDevToCssSize = 1.0) override;
256 :
257 : bool GetStandardFamilyName(const nsAString& aFontName,
258 : nsAString& aFamilyName) override;
259 :
260 0 : FcConfig* GetLastConfig() const { return mLastConfig; }
261 :
262 : // override to use fontconfig lookup for generics
263 : void AddGenericFonts(mozilla::FontFamilyType aGenericType,
264 : nsIAtom* aLanguage,
265 : nsTArray<gfxFontFamily*>& aFamilyList) override;
266 :
267 : void ClearLangGroupPrefFonts() override;
268 :
269 : // clear out cached generic-lang ==> family-list mappings
270 3 : void ClearGenericMappings() {
271 3 : mGenericMappings.Clear();
272 3 : }
273 :
274 : static FT_Library GetFTLibrary();
275 :
276 : protected:
277 : virtual ~gfxFcPlatformFontList();
278 :
279 : // Add all the font families found in a font set.
280 : // aAppFonts indicates whether this is the system or application fontset.
281 : void AddFontSetFamilies(FcFontSet* aFontSet, bool aAppFonts);
282 :
283 : // figure out which families fontconfig maps a generic to
284 : // (aGeneric assumed already lowercase)
285 : PrefFontList* FindGenericFamilies(const nsAString& aGeneric,
286 : nsIAtom* aLanguage);
287 :
288 : // are all pref font settings set to use fontconfig generics?
289 : bool PrefFontListsUseOnlyGenerics();
290 :
291 : static void CheckFontUpdates(nsITimer *aTimer, void *aThis);
292 :
293 : virtual gfxFontFamily*
294 : GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override;
295 :
296 : #ifdef MOZ_BUNDLED_FONTS
297 : void ActivateBundledFonts();
298 : nsCString mBundledFontsPath;
299 : bool mBundledFontsInitialized;
300 : #endif
301 :
302 : // to avoid enumerating all fonts, maintain a mapping of local font
303 : // names to family
304 : nsBaseHashtable<nsStringHashKey,
305 : nsCountedRef<FcPattern>,
306 : FcPattern*> mLocalNames;
307 :
308 : // caching generic/lang ==> font family list
309 : nsClassHashtable<nsCStringHashKey,
310 : PrefFontList> mGenericMappings;
311 :
312 : // Caching family lookups as found by FindAndAddFamilies after resolving
313 : // substitutions. The gfxFontFamily objects cached here are owned by the
314 : // gfxFcPlatformFontList via its mFamilies table; note that if the main
315 : // font list is rebuilt (e.g. due to a fontconfig configuration change),
316 : // these pointers will be invalidated. InitFontList() flushes the cache
317 : // in this case.
318 : nsDataHashtable<nsCStringHashKey,
319 : nsTArray<gfxFontFamily*>> mFcSubstituteCache;
320 :
321 : nsCOMPtr<nsITimer> mCheckFontUpdatesTimer;
322 : nsCountedRef<FcConfig> mLastConfig;
323 :
324 : // By default, font prefs under Linux are set to simply lookup
325 : // via fontconfig the appropriate font for serif/sans-serif/monospace.
326 : // Rather than check each time a font pref is used, check them all at startup
327 : // and set a boolean to flag the case that non-default user font prefs exist
328 : // Note: langGroup == x-math is handled separately
329 : bool mAlwaysUseFontconfigGenerics;
330 :
331 : static FT_Library sCairoFTLibrary;
332 : };
333 :
334 : #endif /* GFXPLATFORMFONTLIST_H_ */
|