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 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. Once mFTFaceInitialized is true,
124 // the face can be accessed without locking.
125 // Note that mFTFace owns a reference to the SharedFTFace, but is not
126 // a RefPtr because we need it to be an atomic.
127 mozilla::Atomic
<mozilla::gfx::SharedFTFace
*> mFTFace
;
128 mozilla::Atomic
<bool> mFTFaceInitialized
;
130 // Whether TestCharacterMap should check the actual cmap rather than asking
131 // fontconfig about character coverage.
132 // We do this for app-bundled (rather than system) fonts, as they may
133 // include color glyphs that fontconfig would overlook, and for fonts
134 // loaded via @font-face.
135 bool mIgnoreFcCharmap
;
137 // Whether the face supports variations. For system-installed fonts, we
138 // query fontconfig for this (so they will only work if fontconfig is
139 // recent enough to include support); for downloaded user-fonts we query
140 // the FreeType face.
141 enum class HasVariationsState
: int8_t {
146 std::atomic
<HasVariationsState
> mHasVariations
=
147 HasVariationsState::Uninitialized
;
149 class UnscaledFontCache
{
151 already_AddRefed
<mozilla::gfx::UnscaledFontFontconfig
> Lookup(
152 const std::string
& aFile
, uint32_t aIndex
);
155 const RefPtr
<mozilla::gfx::UnscaledFontFontconfig
>& aUnscaledFont
) {
156 mUnscaledFonts
[kNumEntries
- 1] = aUnscaledFont
;
157 MoveToFront(kNumEntries
- 1);
161 void MoveToFront(size_t aIndex
);
163 static const size_t kNumEntries
= 3;
164 mozilla::ThreadSafeWeakPtr
<mozilla::gfx::UnscaledFontFontconfig
>
165 mUnscaledFonts
[kNumEntries
];
168 UnscaledFontCache mUnscaledFontCache
;
170 // Because of FreeType bug 52955, we keep the FT_MM_Var struct when it is
171 // first loaded, rather than releasing it and re-fetching it as needed.
172 FT_MM_Var
* mMMVar
= nullptr;
173 bool mMMVarInitialized
= false;
176 class gfxFontconfigFontFamily final
: public gfxFontFamily
{
178 gfxFontconfigFontFamily(const nsACString
& aName
, FontVisibility aVisibility
)
179 : gfxFontFamily(aName
, aVisibility
),
180 mContainsAppFonts(false),
181 mHasNonScalableFaces(false),
182 mForceScalable(false) {}
184 template <typename Func
>
185 void AddFacesToFontList(Func aAddPatternFunc
);
187 void FindStyleVariationsLocked(FontInfoData
* aFontInfoData
= nullptr)
188 MOZ_REQUIRES(mLock
) override
;
190 // Families are constructed initially with just references to patterns.
191 // When necessary, these are enumerated within FindStyleVariations.
192 void AddFontPattern(FcPattern
* aFontPattern
, bool aSingleName
);
194 void SetFamilyContainsAppFonts(bool aContainsAppFonts
) {
195 mContainsAppFonts
= aContainsAppFonts
;
198 void FindAllFontsForStyle(const gfxFontStyle
& aFontStyle
,
199 nsTArray
<gfxFontEntry
*>& aFontEntryList
,
200 bool aIgnoreSizeTolerance
) override
;
202 bool FilterForFontList(nsAtom
* aLangGroup
,
203 const nsACString
& aGeneric
) const final
{
204 return SupportsLangGroup(aLangGroup
);
208 virtual ~gfxFontconfigFontFamily();
210 // helper for FilterForFontList
211 bool SupportsLangGroup(nsAtom
* aLangGroup
) const;
213 nsTArray
<RefPtr
<FcPattern
>> mFontPatterns
;
215 // Number of faces that have a single name. Faces that have multiple names are
217 uint32_t mUniqueNameFaceCount
= 0;
218 bool mContainsAppFonts
: 1;
219 bool mHasNonScalableFaces
: 1;
220 bool mForceScalable
: 1;
223 class gfxFontconfigFont final
: public gfxFT2FontBase
{
226 const RefPtr
<mozilla::gfx::UnscaledFontFontconfig
>& aUnscaledFont
,
227 RefPtr
<mozilla::gfx::SharedFTFace
>&& aFTFace
, FcPattern
* aPattern
,
228 gfxFloat aAdjustedSize
, gfxFontEntry
* aFontEntry
,
229 const gfxFontStyle
* aFontStyle
, int aLoadFlags
, bool aEmbolden
);
231 FontType
GetType() const override
{ return FONT_TYPE_FONTCONFIG
; }
232 FcPattern
* GetPattern() const { return mPattern
; }
234 already_AddRefed
<mozilla::gfx::ScaledFont
> GetScaledFont(
235 const TextRunDrawParams
& aRunParams
) override
;
237 bool ShouldHintMetrics() const override
;
240 ~gfxFontconfigFont() override
;
242 RefPtr
<FcPattern
> mPattern
;
245 class gfxFcPlatformFontList final
: public gfxPlatformFontList
{
246 using FontPatternListEntry
= mozilla::dom::SystemFontListEntry
;
249 gfxFcPlatformFontList();
251 static gfxFcPlatformFontList
* PlatformFontList() {
252 return static_cast<gfxFcPlatformFontList
*>(
253 gfxPlatformFontList::PlatformFontList());
256 // initialize font lists
257 nsresult
InitFontListForPlatform() MOZ_REQUIRES(mLock
) override
;
258 void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock
) override
;
260 void GetFontList(nsAtom
* aLangGroup
, const nsACString
& aGenericFamily
,
261 nsTArray
<nsString
>& aListOfFonts
) override
;
263 void ReadSystemFontList(mozilla::dom::SystemFontList
*);
265 gfxFontEntry
* CreateFontEntry(
266 mozilla::fontlist::Face
* aFace
,
267 const mozilla::fontlist::Family
* aFamily
) override
;
269 gfxFontEntry
* LookupLocalFont(nsPresContext
* aPresContext
,
270 const nsACString
& aFontName
,
271 WeightRange aWeightForEntry
,
272 StretchRange aStretchForEntry
,
273 SlantStyleRange aStyleForEntry
) override
;
275 gfxFontEntry
* MakePlatformFont(const nsACString
& aFontName
,
276 WeightRange aWeightForEntry
,
277 StretchRange aStretchForEntry
,
278 SlantStyleRange aStyleForEntry
,
279 const uint8_t* aFontData
,
280 uint32_t aLength
) override
;
282 bool FindAndAddFamiliesLocked(
283 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGeneric
,
284 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
285 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
= nullptr,
286 nsAtom
* aLanguage
= nullptr, gfxFloat aDevToCssSize
= 1.0)
287 MOZ_REQUIRES(mLock
) override
;
289 bool GetStandardFamilyName(const nsCString
& aFontName
,
290 nsACString
& aFamilyName
) override
;
292 FcConfig
* GetLastConfig() const { return mLastConfig
; }
294 // override to use fontconfig lookup for generics
295 void AddGenericFonts(nsPresContext
* aPresContext
,
296 mozilla::StyleGenericFontFamily
, nsAtom
* aLanguage
,
297 nsTArray
<FamilyAndGeneric
>& aFamilyList
) override
;
299 void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock
) override
;
301 // clear out cached generic-lang ==> family-list mappings
302 void ClearGenericMappings() {
303 AutoLock
lock(mLock
);
304 ClearGenericMappingsLocked();
306 void ClearGenericMappingsLocked() MOZ_REQUIRES(mLock
) {
307 mGenericMappings
.Clear();
310 // map lang group ==> lang string
311 // When aForFontEnumerationThread is true, this method will avoid using
312 // LanguageService::LookupLanguage, because it is not safe for off-main-
313 // thread use (except by stylo traversal, which does the necessary locking)
314 void GetSampleLangForGroup(nsAtom
* aLanguage
, nsACString
& aLangStr
,
315 bool aForFontEnumerationThread
= false);
318 virtual ~gfxFcPlatformFontList();
320 nsTArray
<std::pair
<const char**, uint32_t>> GetFilteredPlatformFontLists()
323 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
324 typedef mozilla::SandboxBroker::Policy SandboxPolicy
;
326 // Dummy type just so we can still have a SandboxPolicy* parameter.
327 struct SandboxPolicy
{};
330 // Add all the font families found in a font set.
331 // aAppFonts indicates whether this is the system or application fontset.
332 void AddFontSetFamilies(FcFontSet
* aFontSet
, const SandboxPolicy
* aPolicy
,
333 bool aAppFonts
) MOZ_REQUIRES(mLock
);
335 // Helper for above, to add a single font pattern.
336 void AddPatternToFontList(FcPattern
* aFont
, FcChar8
*& aLastFamilyName
,
337 nsACString
& aFamilyName
,
338 RefPtr
<gfxFontconfigFontFamily
>& aFontFamily
,
339 bool aAppFonts
) MOZ_REQUIRES(mLock
);
341 // figure out which families fontconfig maps a generic to
342 // (aGeneric assumed already lowercase)
343 PrefFontList
* FindGenericFamilies(nsPresContext
* aPresContext
,
344 const nsCString
& aGeneric
,
345 nsAtom
* aLanguage
) MOZ_REQUIRES(mLock
);
347 // are all pref font settings set to use fontconfig generics?
348 bool PrefFontListsUseOnlyGenerics() MOZ_REQUIRES(mLock
);
350 static void CheckFontUpdates(nsITimer
* aTimer
, void* aThis
);
352 FontFamily
GetDefaultFontForPlatform(nsPresContext
* aPresContext
,
353 const gfxFontStyle
* aStyle
,
354 nsAtom
* aLanguage
= nullptr)
355 MOZ_REQUIRES(mLock
) override
;
357 FontVisibility
GetVisibilityForFamily(const nsACString
& aName
) const;
359 gfxFontFamily
* CreateFontFamily(const nsACString
& aName
,
360 FontVisibility aVisibility
) const override
;
362 // helper method for finding an appropriate lang string
363 bool TryLangForGroup(const nsACString
& aOSLang
, nsAtom
* aLangGroup
,
364 nsACString
& aLang
, bool aForFontEnumerationThread
);
366 #ifdef MOZ_BUNDLED_FONTS
367 void ActivateBundledFonts();
368 nsCString mBundledFontsPath
;
369 bool mBundledFontsInitialized
;
372 // to avoid enumerating all fonts, maintain a mapping of local font
374 nsTHashMap
<nsCString
, RefPtr
<FcPattern
>> mLocalNames
;
376 // caching generic/lang ==> font family list
377 nsClassHashtable
<nsCStringHashKey
, PrefFontList
> mGenericMappings
;
379 // Caching family lookups as found by FindAndAddFamilies after resolving
380 // substitutions. The gfxFontFamily objects cached here are owned by the
381 // gfxFcPlatformFontList via its mFamilies table; note that if the main
382 // font list is rebuilt (e.g. due to a fontconfig configuration change),
383 // these pointers will be invalidated. InitFontList() flushes the cache
385 nsTHashMap
<nsCStringHashKey
, nsTArray
<FamilyAndGeneric
>> mFcSubstituteCache
;
387 nsCOMPtr
<nsITimer
> mCheckFontUpdatesTimer
;
388 RefPtr
<FcConfig
> mLastConfig
;
390 // The current system font options in effect.
391 #ifdef MOZ_WIDGET_GTK
392 // NOTE(emilio): This is a *system cairo* cairo_font_options_t object. As
393 // such, it can't be used outside of the few functions defined here.
394 cairo_font_options_t
* mSystemFontOptions
= nullptr;
395 int32_t mFreetypeLcdSetting
= -1; // -1 for not set
397 void ClearSystemFontOptions();
399 // Returns whether options actually changed.
400 // TODO(emilio): We could call this when gsettings change or such, but
401 // historically we haven't reacted to these settings changes, so keeping it
403 bool UpdateSystemFontOptions();
405 void UpdateSystemFontOptionsFromIpc(const mozilla::dom::SystemFontOptions
&);
406 void SystemFontOptionsToIpc(mozilla::dom::SystemFontOptions
&);
409 void SubstituteSystemFontOptions(FcPattern
*);
414 // Cache for most recently used language code in FindAndAddFamiliesLocked,
415 // and the result of checking whether to use lang-specific lookups.
416 RefPtr
<nsAtom
> mPrevLanguage
;
417 nsCString mSampleLang
;
418 bool mUseCustomLookups
= false;
420 // By default, font prefs under Linux are set to simply lookup
421 // via fontconfig the appropriate font for serif/sans-serif/monospace.
422 // Rather than check each time a font pref is used, check them all at startup
423 // and set a boolean to flag the case that non-default user font prefs exist
424 // Note: langGroup == x-math is handled separately
425 bool mAlwaysUseFontconfigGenerics
;
427 static FT_Library sFTLibrary
;
430 #endif /* GFXPLATFORMFONTLIST_H_ */