1 /* -*- Mode: C++; tab-width: 20; 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/. */
6 #ifndef GFXFCPLATFORMFONTLIST_H_
7 #define GFXFCPLATFORMFONTLIST_H_
9 #include "gfxFT2FontBase.h"
10 #include "gfxPlatformFontList.h"
11 #include "mozilla/FontPropertyTypes.h"
12 #include "mozilla/mozalloc.h"
13 #include "mozilla/RefPtr.h"
14 #include "mozilla/UniquePtr.h"
15 #include "nsClassHashtable.h"
16 #include "nsTHashMap.h"
18 #include <fontconfig/fontconfig.h>
20 #include FT_FREETYPE_H
21 #include FT_TRUETYPE_TABLES_H
22 #include FT_MULTIPLE_MASTERS_H
24 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
25 # include "mozilla/SandboxBroker.h"
30 class SystemFontListEntry
;
32 class SystemFontOptions
;
36 class RefPtrTraits
<FcPattern
> {
38 static void Release(FcPattern
* ptr
) { FcPatternDestroy(ptr
); }
39 static void AddRef(FcPattern
* ptr
) { FcPatternReference(ptr
); }
43 class RefPtrTraits
<FcConfig
> {
45 static void Release(FcConfig
* ptr
) { FcConfigDestroy(ptr
); }
46 static void AddRef(FcConfig
* ptr
) { FcConfigReference(ptr
); }
50 class DefaultDelete
<FcFontSet
> {
52 void operator()(FcFontSet
* aPtr
) { FcFontSetDestroy(aPtr
); }
56 class DefaultDelete
<FcObjectSet
> {
58 void operator()(FcObjectSet
* aPtr
) { FcObjectSetDestroy(aPtr
); }
61 }; // namespace mozilla
63 // The names for the font entry and font classes should really
64 // the common 'Fc' abbreviation but the gfxPangoFontGroup code already
65 // defines versions of these, so use the verbose name for now.
67 class gfxFontconfigFontEntry final
: public gfxFT2FontEntryBase
{
68 friend class gfxFcPlatformFontList
;
69 using FTUserFontData
= mozilla::gfx::FTUserFontData
;
72 // used for system fonts with explicit patterns
73 explicit gfxFontconfigFontEntry(const nsACString
& aFaceName
,
74 FcPattern
* aFontPattern
,
75 bool aIgnoreFcCharmap
);
77 // used for data fonts where the fontentry takes ownership
78 // of the font data and the FT_Face
79 explicit gfxFontconfigFontEntry(const nsACString
& aFaceName
,
80 WeightRange aWeight
, StretchRange aStretch
,
81 SlantStyleRange aStyle
,
82 RefPtr
<mozilla::gfx::SharedFTFace
>&& aFace
);
84 // used for @font-face local system fonts with explicit patterns
85 explicit gfxFontconfigFontEntry(const nsACString
& aFaceName
,
86 FcPattern
* aFontPattern
, WeightRange aWeight
,
87 StretchRange aStretch
,
88 SlantStyleRange aStyle
);
90 gfxFontEntry
* Clone() const override
;
92 FcPattern
* GetPattern() { return mFontPattern
; }
94 nsresult
ReadCMAP(FontInfoData
* aFontInfoData
= nullptr) override
;
95 bool TestCharacterMap(uint32_t aCh
) override
;
97 const RefPtr
<mozilla::gfx::SharedFTFace
>& GetFTFace();
98 FTUserFontData
* GetUserFontData();
100 FT_MM_Var
* GetMMVar() override
;
102 bool HasVariations() override
;
103 void GetVariationAxes(nsTArray
<gfxFontVariationAxis
>& aAxes
) override
;
104 void GetVariationInstances(
105 nsTArray
<gfxFontVariationInstance
>& aInstances
) override
;
107 bool HasFontTable(uint32_t aTableTag
) override
;
108 nsresult
CopyFontTable(uint32_t aTableTag
, nsTArray
<uint8_t>&) override
;
109 hb_blob_t
* GetFontTable(uint32_t aTableTag
) override
;
111 double GetAspect(uint8_t aSizeAdjustBasis
);
114 virtual ~gfxFontconfigFontEntry();
116 gfxFont
* CreateFontInstance(const gfxFontStyle
* aFontStyle
) override
;
118 void GetUserFontFeatures(FcPattern
* aPattern
);
120 // pattern for a single face of a family
121 RefPtr
<FcPattern
> mFontPattern
;
123 // FTFace - initialized when needed
124 RefPtr
<mozilla::gfx::SharedFTFace
> mFTFace
;
125 bool mFTFaceInitialized
;
127 // Whether TestCharacterMap should check the actual cmap rather than asking
128 // fontconfig about character coverage.
129 // We do this for app-bundled (rather than system) fonts, as they may
130 // include color glyphs that fontconfig would overlook, and for fonts
131 // loaded via @font-face.
132 bool mIgnoreFcCharmap
;
134 // Whether the face supports variations. For system-installed fonts, we
135 // query fontconfig for this (so they will only work if fontconfig is
136 // recent enough to include support); for downloaded user-fonts we query
137 // the FreeType face.
139 bool mHasVariationsInitialized
;
141 class UnscaledFontCache
{
143 already_AddRefed
<mozilla::gfx::UnscaledFontFontconfig
> Lookup(
144 const std::string
& aFile
, uint32_t aIndex
);
147 const RefPtr
<mozilla::gfx::UnscaledFontFontconfig
>& aUnscaledFont
) {
148 mUnscaledFonts
[kNumEntries
- 1] = aUnscaledFont
;
149 MoveToFront(kNumEntries
- 1);
153 void MoveToFront(size_t aIndex
);
155 static const size_t kNumEntries
= 3;
156 mozilla::ThreadSafeWeakPtr
<mozilla::gfx::UnscaledFontFontconfig
>
157 mUnscaledFonts
[kNumEntries
];
160 UnscaledFontCache mUnscaledFontCache
;
162 // Because of FreeType bug 52955, we keep the FT_MM_Var struct when it is
163 // first loaded, rather than releasing it and re-fetching it as needed.
164 FT_MM_Var
* mMMVar
= nullptr;
165 bool mMMVarInitialized
= false;
168 class gfxFontconfigFontFamily final
: public gfxFontFamily
{
170 gfxFontconfigFontFamily(const nsACString
& aName
, FontVisibility aVisibility
)
171 : gfxFontFamily(aName
, aVisibility
),
172 mContainsAppFonts(false),
173 mHasNonScalableFaces(false),
174 mForceScalable(false) {}
176 template <typename Func
>
177 void AddFacesToFontList(Func aAddPatternFunc
);
179 void FindStyleVariationsLocked(FontInfoData
* aFontInfoData
= nullptr)
180 MOZ_REQUIRES(mLock
) override
;
182 // Families are constructed initially with just references to patterns.
183 // When necessary, these are enumerated within FindStyleVariations.
184 void AddFontPattern(FcPattern
* aFontPattern
, bool aSingleName
);
186 void SetFamilyContainsAppFonts(bool aContainsAppFonts
) {
187 mContainsAppFonts
= aContainsAppFonts
;
190 void FindAllFontsForStyle(const gfxFontStyle
& aFontStyle
,
191 nsTArray
<gfxFontEntry
*>& aFontEntryList
,
192 bool aIgnoreSizeTolerance
) override
;
194 bool FilterForFontList(nsAtom
* aLangGroup
,
195 const nsACString
& aGeneric
) const final
{
196 return SupportsLangGroup(aLangGroup
);
200 virtual ~gfxFontconfigFontFamily();
202 // helper for FilterForFontList
203 bool SupportsLangGroup(nsAtom
* aLangGroup
) const;
205 nsTArray
<RefPtr
<FcPattern
>> mFontPatterns
;
207 // Number of faces that have a single name. Faces that have multiple names are
209 uint32_t mUniqueNameFaceCount
= 0;
210 bool mContainsAppFonts
: 1;
211 bool mHasNonScalableFaces
: 1;
212 bool mForceScalable
: 1;
215 class gfxFontconfigFont final
: public gfxFT2FontBase
{
218 const RefPtr
<mozilla::gfx::UnscaledFontFontconfig
>& aUnscaledFont
,
219 RefPtr
<mozilla::gfx::SharedFTFace
>&& aFTFace
, FcPattern
* aPattern
,
220 gfxFloat aAdjustedSize
, gfxFontEntry
* aFontEntry
,
221 const gfxFontStyle
* aFontStyle
, int aLoadFlags
, bool aEmbolden
);
223 FontType
GetType() const override
{ return FONT_TYPE_FONTCONFIG
; }
224 FcPattern
* GetPattern() const { return mPattern
; }
226 already_AddRefed
<mozilla::gfx::ScaledFont
> GetScaledFont(
227 const TextRunDrawParams
& aRunParams
) override
;
229 bool ShouldHintMetrics() const override
;
232 ~gfxFontconfigFont() override
;
234 RefPtr
<FcPattern
> mPattern
;
237 class gfxFcPlatformFontList final
: public gfxPlatformFontList
{
238 using FontPatternListEntry
= mozilla::dom::SystemFontListEntry
;
241 gfxFcPlatformFontList();
243 static gfxFcPlatformFontList
* PlatformFontList() {
244 return static_cast<gfxFcPlatformFontList
*>(
245 gfxPlatformFontList::PlatformFontList());
248 // initialize font lists
249 nsresult
InitFontListForPlatform() MOZ_REQUIRES(mLock
) override
;
250 void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock
) override
;
252 void GetFontList(nsAtom
* aLangGroup
, const nsACString
& aGenericFamily
,
253 nsTArray
<nsString
>& aListOfFonts
) override
;
255 void ReadSystemFontList(mozilla::dom::SystemFontList
*);
257 gfxFontEntry
* CreateFontEntry(
258 mozilla::fontlist::Face
* aFace
,
259 const mozilla::fontlist::Family
* aFamily
) override
;
261 gfxFontEntry
* LookupLocalFont(nsPresContext
* aPresContext
,
262 const nsACString
& aFontName
,
263 WeightRange aWeightForEntry
,
264 StretchRange aStretchForEntry
,
265 SlantStyleRange aStyleForEntry
) override
;
267 gfxFontEntry
* MakePlatformFont(const nsACString
& aFontName
,
268 WeightRange aWeightForEntry
,
269 StretchRange aStretchForEntry
,
270 SlantStyleRange aStyleForEntry
,
271 const uint8_t* aFontData
,
272 uint32_t aLength
) override
;
274 bool FindAndAddFamiliesLocked(
275 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGeneric
,
276 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
277 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
= nullptr,
278 nsAtom
* aLanguage
= nullptr, gfxFloat aDevToCssSize
= 1.0)
279 MOZ_REQUIRES(mLock
) override
;
281 bool GetStandardFamilyName(const nsCString
& aFontName
,
282 nsACString
& aFamilyName
) override
;
284 FcConfig
* GetLastConfig() const { return mLastConfig
; }
286 // override to use fontconfig lookup for generics
287 void AddGenericFonts(nsPresContext
* aPresContext
,
288 mozilla::StyleGenericFontFamily
, nsAtom
* aLanguage
,
289 nsTArray
<FamilyAndGeneric
>& aFamilyList
) override
;
291 void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock
) override
;
293 // clear out cached generic-lang ==> family-list mappings
294 void ClearGenericMappings() {
295 AutoLock
lock(mLock
);
296 ClearGenericMappingsLocked();
298 void ClearGenericMappingsLocked() MOZ_REQUIRES(mLock
) {
299 mGenericMappings
.Clear();
302 // map lang group ==> lang string
303 // When aForFontEnumerationThread is true, this method will avoid using
304 // LanguageService::LookupLanguage, because it is not safe for off-main-
305 // thread use (except by stylo traversal, which does the necessary locking)
306 void GetSampleLangForGroup(nsAtom
* aLanguage
, nsACString
& aLangStr
,
307 bool aForFontEnumerationThread
= false);
310 virtual ~gfxFcPlatformFontList();
312 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
313 typedef mozilla::SandboxBroker::Policy SandboxPolicy
;
315 // Dummy type just so we can still have a SandboxPolicy* parameter.
316 struct SandboxPolicy
{};
319 // Add all the font families found in a font set.
320 // aAppFonts indicates whether this is the system or application fontset.
321 void AddFontSetFamilies(FcFontSet
* aFontSet
, const SandboxPolicy
* aPolicy
,
322 bool aAppFonts
) MOZ_REQUIRES(mLock
);
324 // Helper for above, to add a single font pattern.
325 void AddPatternToFontList(FcPattern
* aFont
, FcChar8
*& aLastFamilyName
,
326 nsACString
& aFamilyName
,
327 RefPtr
<gfxFontconfigFontFamily
>& aFontFamily
,
328 bool aAppFonts
) MOZ_REQUIRES(mLock
);
330 // figure out which families fontconfig maps a generic to
331 // (aGeneric assumed already lowercase)
332 PrefFontList
* FindGenericFamilies(nsPresContext
* aPresContext
,
333 const nsCString
& aGeneric
,
334 nsAtom
* aLanguage
) MOZ_REQUIRES(mLock
);
336 // are all pref font settings set to use fontconfig generics?
337 bool PrefFontListsUseOnlyGenerics() MOZ_REQUIRES(mLock
);
339 static void CheckFontUpdates(nsITimer
* aTimer
, void* aThis
);
341 FontFamily
GetDefaultFontForPlatform(nsPresContext
* aPresContext
,
342 const gfxFontStyle
* aStyle
,
343 nsAtom
* aLanguage
= nullptr)
344 MOZ_REQUIRES(mLock
) override
;
346 enum class DistroID
: int8_t {
350 // To be extended with any distros that ship a useful base set of fonts
351 // that we want to explicitly support.
353 DistroID
GetDistroID() const; // -> DistroID::Unknown if we can't tell
355 FontVisibility
GetVisibilityForFamily(const nsACString
& aName
) const;
357 gfxFontFamily
* CreateFontFamily(const nsACString
& aName
,
358 FontVisibility aVisibility
) const override
;
360 // helper method for finding an appropriate lang string
361 bool TryLangForGroup(const nsACString
& aOSLang
, nsAtom
* aLangGroup
,
362 nsACString
& aLang
, bool aForFontEnumerationThread
);
364 #ifdef MOZ_BUNDLED_FONTS
365 void ActivateBundledFonts();
366 nsCString mBundledFontsPath
;
367 bool mBundledFontsInitialized
;
370 // to avoid enumerating all fonts, maintain a mapping of local font
372 nsTHashMap
<nsCString
, RefPtr
<FcPattern
>> mLocalNames
;
374 // caching generic/lang ==> font family list
375 nsClassHashtable
<nsCStringHashKey
, PrefFontList
> mGenericMappings
;
377 // Caching family lookups as found by FindAndAddFamilies after resolving
378 // substitutions. The gfxFontFamily objects cached here are owned by the
379 // gfxFcPlatformFontList via its mFamilies table; note that if the main
380 // font list is rebuilt (e.g. due to a fontconfig configuration change),
381 // these pointers will be invalidated. InitFontList() flushes the cache
383 nsTHashMap
<nsCStringHashKey
, nsTArray
<FamilyAndGeneric
>> mFcSubstituteCache
;
385 nsCOMPtr
<nsITimer
> mCheckFontUpdatesTimer
;
386 RefPtr
<FcConfig
> mLastConfig
;
388 // The current system font options in effect.
389 #ifdef MOZ_WIDGET_GTK
390 // NOTE(emilio): This is a *system cairo* cairo_font_options_t object. As
391 // such, it can't be used outside of the few functions defined here.
392 cairo_font_options_t
* mSystemFontOptions
= nullptr;
393 int32_t mFreetypeLcdSetting
= -1; // -1 for not set
395 void ClearSystemFontOptions();
397 // Returns whether options actually changed.
398 // TODO(emilio): We could call this when gsettings change or such, but
399 // historically we haven't reacted to these settings changes, so keeping it
401 bool UpdateSystemFontOptions();
403 void UpdateSystemFontOptionsFromIpc(const mozilla::dom::SystemFontOptions
&);
404 void SystemFontOptionsToIpc(mozilla::dom::SystemFontOptions
&);
407 void SubstituteSystemFontOptions(FcPattern
*);
412 // Cache for most recently used language code in FindAndAddFamiliesLocked,
413 // and the result of checking whether to use lang-specific lookups.
414 RefPtr
<nsAtom
> mPrevLanguage
;
415 nsCString mSampleLang
;
416 bool mUseCustomLookups
= false;
418 // By default, font prefs under Linux are set to simply lookup
419 // via fontconfig the appropriate font for serif/sans-serif/monospace.
420 // Rather than check each time a font pref is used, check them all at startup
421 // and set a boolean to flag the case that non-default user font prefs exist
422 // Note: langGroup == x-math is handled separately
423 bool mAlwaysUseFontconfigGenerics
;
425 static FT_Library sFTLibrary
;
428 #endif /* GFXPLATFORMFONTLIST_H_ */