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
;
71 // used for system fonts with explicit patterns
72 explicit gfxFontconfigFontEntry(const nsACString
& aFaceName
,
73 FcPattern
* aFontPattern
,
74 bool aIgnoreFcCharmap
);
76 // used for data fonts where the fontentry takes ownership
77 // of the font data and the FT_Face
78 explicit gfxFontconfigFontEntry(const nsACString
& aFaceName
,
79 WeightRange aWeight
, StretchRange aStretch
,
80 SlantStyleRange aStyle
,
81 RefPtr
<mozilla::gfx::SharedFTFace
>&& aFace
);
83 // used for @font-face local system fonts with explicit patterns
84 explicit gfxFontconfigFontEntry(const nsACString
& aFaceName
,
85 FcPattern
* aFontPattern
, WeightRange aWeight
,
86 StretchRange aStretch
,
87 SlantStyleRange aStyle
);
89 gfxFontEntry
* Clone() const override
;
91 FcPattern
* GetPattern() { return mFontPattern
; }
93 nsresult
ReadCMAP(FontInfoData
* aFontInfoData
= nullptr) override
;
94 bool TestCharacterMap(uint32_t aCh
) override
;
96 const RefPtr
<mozilla::gfx::SharedFTFace
>& GetFTFace();
97 FTUserFontData
* GetUserFontData();
99 FT_MM_Var
* GetMMVar() override
;
101 bool HasVariations() override
;
102 void GetVariationAxes(nsTArray
<gfxFontVariationAxis
>& aAxes
) override
;
103 void GetVariationInstances(
104 nsTArray
<gfxFontVariationInstance
>& aInstances
) override
;
106 bool HasFontTable(uint32_t aTableTag
) override
;
107 nsresult
CopyFontTable(uint32_t aTableTag
, nsTArray
<uint8_t>&) override
;
108 hb_blob_t
* GetFontTable(uint32_t aTableTag
) override
;
110 double GetAspect(uint8_t aSizeAdjustBasis
);
113 virtual ~gfxFontconfigFontEntry();
115 gfxFont
* CreateFontInstance(const gfxFontStyle
* aFontStyle
) override
;
117 // pattern for a single face of a family
118 RefPtr
<FcPattern
> mFontPattern
;
120 // FTFace - initialized when needed
121 RefPtr
<mozilla::gfx::SharedFTFace
> mFTFace
;
122 bool mFTFaceInitialized
;
124 // Whether TestCharacterMap should check the actual cmap rather than asking
125 // fontconfig about character coverage.
126 // We do this for app-bundled (rather than system) fonts, as they may
127 // include color glyphs that fontconfig would overlook, and for fonts
128 // loaded via @font-face.
129 bool mIgnoreFcCharmap
;
131 // Whether the face supports variations. For system-installed fonts, we
132 // query fontconfig for this (so they will only work if fontconfig is
133 // recent enough to include support); for downloaded user-fonts we query
134 // the FreeType face.
136 bool mHasVariationsInitialized
;
138 class UnscaledFontCache
{
140 already_AddRefed
<mozilla::gfx::UnscaledFontFontconfig
> Lookup(
141 const std::string
& aFile
, uint32_t aIndex
);
144 const RefPtr
<mozilla::gfx::UnscaledFontFontconfig
>& aUnscaledFont
) {
145 mUnscaledFonts
[kNumEntries
- 1] = aUnscaledFont
;
146 MoveToFront(kNumEntries
- 1);
150 void MoveToFront(size_t aIndex
);
152 static const size_t kNumEntries
= 3;
153 mozilla::ThreadSafeWeakPtr
<mozilla::gfx::UnscaledFontFontconfig
>
154 mUnscaledFonts
[kNumEntries
];
157 UnscaledFontCache mUnscaledFontCache
;
159 // Because of FreeType bug 52955, we keep the FT_MM_Var struct when it is
160 // first loaded, rather than releasing it and re-fetching it as needed.
161 FT_MM_Var
* mMMVar
= nullptr;
162 bool mMMVarInitialized
= false;
165 class gfxFontconfigFontFamily final
: public gfxFontFamily
{
167 gfxFontconfigFontFamily(const nsACString
& aName
, FontVisibility aVisibility
)
168 : gfxFontFamily(aName
, aVisibility
),
169 mContainsAppFonts(false),
170 mHasNonScalableFaces(false),
171 mForceScalable(false) {}
173 template <typename Func
>
174 void AddFacesToFontList(Func aAddPatternFunc
);
176 void FindStyleVariations(FontInfoData
* aFontInfoData
= nullptr) override
;
178 // Families are constructed initially with just references to patterns.
179 // When necessary, these are enumerated within FindStyleVariations.
180 void AddFontPattern(FcPattern
* aFontPattern
, bool aSingleName
);
182 void SetFamilyContainsAppFonts(bool aContainsAppFonts
) {
183 mContainsAppFonts
= aContainsAppFonts
;
186 void FindAllFontsForStyle(const gfxFontStyle
& aFontStyle
,
187 nsTArray
<gfxFontEntry
*>& aFontEntryList
,
188 bool aIgnoreSizeTolerance
) override
;
190 bool FilterForFontList(nsAtom
* aLangGroup
,
191 const nsACString
& aGeneric
) const final
{
192 return SupportsLangGroup(aLangGroup
);
196 virtual ~gfxFontconfigFontFamily();
198 // helper for FilterForFontList
199 bool SupportsLangGroup(nsAtom
* aLangGroup
) const;
201 nsTArray
<RefPtr
<FcPattern
>> mFontPatterns
;
203 // Number of faces that have a single name. Faces that have multiple names are
205 uint32_t mUniqueNameFaceCount
= 0;
206 bool mContainsAppFonts
: 1;
207 bool mHasNonScalableFaces
: 1;
208 bool mForceScalable
: 1;
211 class gfxFontconfigFont final
: public gfxFT2FontBase
{
214 const RefPtr
<mozilla::gfx::UnscaledFontFontconfig
>& aUnscaledFont
,
215 RefPtr
<mozilla::gfx::SharedFTFace
>&& aFTFace
, FcPattern
* aPattern
,
216 gfxFloat aAdjustedSize
, gfxFontEntry
* aFontEntry
,
217 const gfxFontStyle
* aFontStyle
, int aLoadFlags
, bool aEmbolden
);
219 FontType
GetType() const override
{ return FONT_TYPE_FONTCONFIG
; }
220 FcPattern
* GetPattern() const { return mPattern
; }
222 already_AddRefed
<mozilla::gfx::ScaledFont
> GetScaledFont(
223 DrawTarget
* aTarget
) override
;
225 bool ShouldHintMetrics() const override
;
228 virtual ~gfxFontconfigFont();
230 RefPtr
<FcPattern
> mPattern
;
233 class gfxFcPlatformFontList final
: public gfxPlatformFontList
{
234 using FontPatternListEntry
= mozilla::dom::SystemFontListEntry
;
237 gfxFcPlatformFontList();
239 static gfxFcPlatformFontList
* PlatformFontList() {
240 return static_cast<gfxFcPlatformFontList
*>(
241 gfxPlatformFontList::PlatformFontList());
244 // initialize font lists
245 nsresult
InitFontListForPlatform() override
;
246 void InitSharedFontListForPlatform() override
;
248 void GetFontList(nsAtom
* aLangGroup
, const nsACString
& aGenericFamily
,
249 nsTArray
<nsString
>& aListOfFonts
) override
;
251 void ReadSystemFontList(mozilla::dom::SystemFontList
*);
253 gfxFontEntry
* CreateFontEntry(
254 mozilla::fontlist::Face
* aFace
,
255 const mozilla::fontlist::Family
* aFamily
) override
;
257 gfxFontEntry
* LookupLocalFont(nsPresContext
* aPresContext
,
258 const nsACString
& aFontName
,
259 WeightRange aWeightForEntry
,
260 StretchRange aStretchForEntry
,
261 SlantStyleRange aStyleForEntry
) override
;
263 gfxFontEntry
* MakePlatformFont(const nsACString
& aFontName
,
264 WeightRange aWeightForEntry
,
265 StretchRange aStretchForEntry
,
266 SlantStyleRange aStyleForEntry
,
267 const uint8_t* aFontData
,
268 uint32_t aLength
) override
;
270 bool FindAndAddFamilies(
271 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGeneric
,
272 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
273 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
= nullptr,
274 nsAtom
* aLanguage
= nullptr, gfxFloat aDevToCssSize
= 1.0) override
;
276 bool GetStandardFamilyName(const nsCString
& aFontName
,
277 nsACString
& aFamilyName
) override
;
279 FcConfig
* GetLastConfig() const { return mLastConfig
; }
281 // override to use fontconfig lookup for generics
282 void AddGenericFonts(nsPresContext
* aPresContext
,
283 mozilla::StyleGenericFontFamily
, nsAtom
* aLanguage
,
284 nsTArray
<FamilyAndGeneric
>& aFamilyList
) override
;
286 void ClearLangGroupPrefFonts() override
;
288 // clear out cached generic-lang ==> family-list mappings
289 void ClearGenericMappings() { mGenericMappings
.Clear(); }
291 // map lang group ==> lang string
292 // When aForFontEnumerationThread is true, this method will avoid using
293 // LanguageService::LookupLanguage, because it is not safe for off-main-
294 // thread use (except by stylo traversal, which does the necessary locking)
295 void GetSampleLangForGroup(nsAtom
* aLanguage
, nsACString
& aLangStr
,
296 bool aForFontEnumerationThread
= false);
299 virtual ~gfxFcPlatformFontList();
301 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
302 typedef mozilla::SandboxBroker::Policy SandboxPolicy
;
304 // Dummy type just so we can still have a SandboxPolicy* parameter.
305 struct SandboxPolicy
{};
308 // Add all the font families found in a font set.
309 // aAppFonts indicates whether this is the system or application fontset.
310 void AddFontSetFamilies(FcFontSet
* aFontSet
, const SandboxPolicy
* aPolicy
,
313 // Helper for above, to add a single font pattern.
314 void AddPatternToFontList(FcPattern
* aFont
, FcChar8
*& aLastFamilyName
,
315 nsACString
& aFamilyName
,
316 RefPtr
<gfxFontconfigFontFamily
>& aFontFamily
,
319 // figure out which families fontconfig maps a generic to
320 // (aGeneric assumed already lowercase)
321 PrefFontList
* FindGenericFamilies(nsPresContext
* aPresContext
,
322 const nsCString
& aGeneric
,
325 // are all pref font settings set to use fontconfig generics?
326 bool PrefFontListsUseOnlyGenerics();
328 static void CheckFontUpdates(nsITimer
* aTimer
, void* aThis
);
330 FontFamily
GetDefaultFontForPlatform(nsPresContext
* aPresContext
,
331 const gfxFontStyle
* aStyle
,
332 nsAtom
* aLanguage
= nullptr) override
;
334 enum class DistroID
: int8_t {
338 // To be extended with any distros that ship a useful base set of fonts
339 // that we want to explicitly support.
341 DistroID
GetDistroID() const; // -> DistroID::Unknown if we can't tell
343 FontVisibility
GetVisibilityForFamily(const nsACString
& aName
) const;
345 gfxFontFamily
* CreateFontFamily(const nsACString
& aName
,
346 FontVisibility aVisibility
) const override
;
348 // helper method for finding an appropriate lang string
349 bool TryLangForGroup(const nsACString
& aOSLang
, nsAtom
* aLangGroup
,
350 nsACString
& aLang
, bool aForFontEnumerationThread
);
352 #ifdef MOZ_BUNDLED_FONTS
353 void ActivateBundledFonts();
354 nsCString mBundledFontsPath
;
355 bool mBundledFontsInitialized
;
358 // to avoid enumerating all fonts, maintain a mapping of local font
360 nsTHashMap
<nsCString
, RefPtr
<FcPattern
>> mLocalNames
;
362 // caching generic/lang ==> font family list
363 nsClassHashtable
<nsCStringHashKey
, PrefFontList
> mGenericMappings
;
365 // Caching family lookups as found by FindAndAddFamilies after resolving
366 // substitutions. The gfxFontFamily objects cached here are owned by the
367 // gfxFcPlatformFontList via its mFamilies table; note that if the main
368 // font list is rebuilt (e.g. due to a fontconfig configuration change),
369 // these pointers will be invalidated. InitFontList() flushes the cache
371 nsTHashMap
<nsCStringHashKey
, nsTArray
<FamilyAndGeneric
>> mFcSubstituteCache
;
373 nsCOMPtr
<nsITimer
> mCheckFontUpdatesTimer
;
374 RefPtr
<FcConfig
> mLastConfig
;
376 // The current system font options in effect.
377 #ifdef MOZ_WIDGET_GTK
378 // NOTE(emilio): This is a *system cairo* cairo_font_options_t object. As
379 // such, it can't be used outside of the few functions defined here.
380 cairo_font_options_t
* mSystemFontOptions
= nullptr;
381 int32_t mFreetypeLcdSetting
= -1; // -1 for not set
383 void ClearSystemFontOptions();
385 // Returns whether options actually changed.
386 // TODO(emilio): We could call this when gsettings change or such, but
387 // historically we haven't reacted to these settings changes, so keeping it
389 bool UpdateSystemFontOptions();
391 void UpdateSystemFontOptionsFromIpc(const mozilla::dom::SystemFontOptions
&);
392 void SystemFontOptionsToIpc(mozilla::dom::SystemFontOptions
&);
395 void SubstituteSystemFontOptions(FcPattern
*);
400 // By default, font prefs under Linux are set to simply lookup
401 // via fontconfig the appropriate font for serif/sans-serif/monospace.
402 // Rather than check each time a font pref is used, check them all at startup
403 // and set a boolean to flag the case that non-default user font prefs exist
404 // Note: langGroup == x-math is handled separately
405 bool mAlwaysUseFontconfigGenerics
;
407 static FT_Library sFTLibrary
;
410 #endif /* GFXPLATFORMFONTLIST_H_ */