gfxFcPlatformFontList.h (15344B)
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/. */ 5 6 #ifndef GFXFCPLATFORMFONTLIST_H_ 7 #define GFXFCPLATFORMFONTLIST_H_ 8 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 "nsClassHashtable.h" 15 #include "nsTHashMap.h" 16 17 #include <fontconfig/fontconfig.h> 18 #include "ft2build.h" 19 #include FT_FREETYPE_H 20 #include FT_TRUETYPE_TABLES_H 21 #include FT_MULTIPLE_MASTERS_H 22 23 #if defined(MOZ_SANDBOX) && defined(XP_LINUX) 24 # include "mozilla/SandboxBroker.h" 25 #endif 26 27 namespace mozilla { 28 namespace dom { 29 class SystemFontListEntry; 30 class SystemFontList; 31 class SystemFontOptions; 32 }; // namespace dom 33 34 template <> 35 class RefPtrTraits<FcPattern> { 36 public: 37 static void Release(FcPattern* ptr) { FcPatternDestroy(ptr); } 38 static void AddRef(FcPattern* ptr) { FcPatternReference(ptr); } 39 }; 40 41 template <> 42 class RefPtrTraits<FcConfig> { 43 public: 44 static void Release(FcConfig* ptr) { FcConfigDestroy(ptr); } 45 static void AddRef(FcConfig* ptr) { FcConfigReference(ptr); } 46 }; 47 48 } // namespace mozilla 49 50 namespace std { 51 template <> 52 struct default_delete<FcFontSet> { 53 void operator()(FcFontSet* aPtr) { FcFontSetDestroy(aPtr); } 54 }; 55 56 template <> 57 struct default_delete<FcObjectSet> { 58 void operator()(FcObjectSet* aPtr) { FcObjectSetDestroy(aPtr); } 59 }; 60 61 } // namespace std 62 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. 66 67 class gfxFontconfigFontEntry final : public gfxFT2FontEntryBase { 68 friend class gfxFcPlatformFontList; 69 using FTUserFontData = mozilla::gfx::FTUserFontData; 70 71 public: 72 // used for system fonts with explicit patterns 73 explicit gfxFontconfigFontEntry(const nsACString& aFaceName, 74 FcPattern* aFontPattern, 75 bool aIgnoreFcCharmap); 76 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); 83 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); 89 90 gfxFontEntry* Clone() const override; 91 92 FcPattern* GetPattern() { return mFontPattern; } 93 94 nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override; 95 bool TestCharacterMap(uint32_t aCh) override; 96 97 mozilla::gfx::SharedFTFace* GetFTFace(); 98 FTUserFontData* GetUserFontData() override; 99 100 FT_MM_Var* GetMMVar() override; 101 102 bool HasVariations() override; 103 void GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes) override; 104 void GetVariationInstances( 105 nsTArray<gfxFontVariationInstance>& aInstances) override; 106 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; 110 111 double GetAspect(uint8_t aSizeAdjustBasis); 112 113 protected: 114 virtual ~gfxFontconfigFontEntry(); 115 116 gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override; 117 118 void GetUserFontFeatures(FcPattern* aPattern); 119 120 // pattern for a single face of a family 121 RefPtr<FcPattern> mFontPattern; 122 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; 129 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; 136 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 { 142 Uninitialized = -1, 143 No = 0, 144 Yes = 1, 145 }; 146 std::atomic<HasVariationsState> mHasVariations = 147 HasVariationsState::Uninitialized; 148 149 class UnscaledFontCache { 150 public: 151 already_AddRefed<mozilla::gfx::UnscaledFontFontconfig> Lookup( 152 const std::string& aFile, uint32_t aIndex); 153 154 void Add( 155 const RefPtr<mozilla::gfx::UnscaledFontFontconfig>& aUnscaledFont) { 156 mUnscaledFonts[kNumEntries - 1] = aUnscaledFont; 157 MoveToFront(kNumEntries - 1); 158 } 159 160 private: 161 void MoveToFront(size_t aIndex); 162 163 static const size_t kNumEntries = 3; 164 mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontFontconfig> 165 mUnscaledFonts[kNumEntries]; 166 }; 167 168 UnscaledFontCache mUnscaledFontCache; 169 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; 174 }; 175 176 class gfxFontconfigFontFamily final : public gfxFontFamily { 177 public: 178 gfxFontconfigFontFamily(const nsACString& aName, FontVisibility aVisibility) 179 : gfxFontFamily(aName, aVisibility), 180 mContainsAppFonts(false), 181 mHasNonScalableFaces(false), 182 mForceScalable(false) {} 183 184 template <typename Func> 185 void AddFacesToFontList(Func aAddPatternFunc); 186 187 void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) 188 MOZ_REQUIRES(mLock) override; 189 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); 193 194 void SetFamilyContainsAppFonts(bool aContainsAppFonts) { 195 mContainsAppFonts = aContainsAppFonts; 196 } 197 198 void FindAllFontsForStyle(const gfxFontStyle& aFontStyle, 199 nsTArray<gfxFontEntry*>& aFontEntryList, 200 bool aIgnoreSizeTolerance) override; 201 202 bool FilterForFontList(nsAtom* aLangGroup, 203 const nsACString& aGeneric) const final { 204 return SupportsLangGroup(aLangGroup); 205 } 206 207 protected: 208 virtual ~gfxFontconfigFontFamily(); 209 210 // helper for FilterForFontList 211 bool SupportsLangGroup(nsAtom* aLangGroup) const; 212 213 nsTArray<RefPtr<FcPattern>> mFontPatterns; 214 215 // Number of faces that have a single name. Faces that have multiple names are 216 // sorted last. 217 uint32_t mUniqueNameFaceCount = 0; 218 bool mContainsAppFonts : 1; 219 bool mHasNonScalableFaces : 1; 220 bool mForceScalable : 1; 221 }; 222 223 class gfxFontconfigFont final : public gfxFT2FontBase { 224 public: 225 gfxFontconfigFont( 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); 230 231 FontType GetType() const override { return FONT_TYPE_FONTCONFIG; } 232 FcPattern* GetPattern() const { return mPattern; } 233 234 already_AddRefed<mozilla::gfx::ScaledFont> GetScaledFont( 235 const TextRunDrawParams& aRunParams) override; 236 237 bool ShouldHintMetrics() const override; 238 239 private: 240 ~gfxFontconfigFont() override; 241 242 RefPtr<FcPattern> mPattern; 243 }; 244 245 class gfxFcPlatformFontList final : public gfxPlatformFontList { 246 using FontPatternListEntry = mozilla::dom::SystemFontListEntry; 247 248 public: 249 gfxFcPlatformFontList(); 250 251 static gfxFcPlatformFontList* PlatformFontList() { 252 return static_cast<gfxFcPlatformFontList*>( 253 gfxPlatformFontList::PlatformFontList()); 254 } 255 256 // initialize font lists 257 nsresult InitFontListForPlatform() MOZ_REQUIRES(mLock) override; 258 void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) override; 259 260 void GetFontList(nsAtom* aLangGroup, const nsACString& aGenericFamily, 261 nsTArray<nsString>& aListOfFonts) override; 262 263 void ReadSystemFontList(mozilla::dom::SystemFontList*); 264 265 gfxFontEntry* CreateFontEntry( 266 mozilla::fontlist::Face* aFace, 267 const mozilla::fontlist::Family* aFamily) override; 268 269 gfxFontEntry* LookupLocalFont(FontVisibilityProvider* aFontVisibilityProvider, 270 const nsACString& aFontName, 271 WeightRange aWeightForEntry, 272 StretchRange aStretchForEntry, 273 SlantStyleRange aStyleForEntry) override; 274 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; 281 282 bool FindAndAddFamiliesLocked( 283 FontVisibilityProvider* aFontVisibilityProvider, 284 mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, 285 nsTArray<FamilyAndGeneric>* aOutput, FindFamiliesFlags aFlags, 286 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, 287 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) override; 288 289 bool GetStandardFamilyName(const nsCString& aFontName, 290 nsACString& aFamilyName) override; 291 292 FcConfig* GetLastConfig() const { return mLastConfig; } 293 294 // override to use fontconfig lookup for generics 295 void AddGenericFonts(FontVisibilityProvider* aFontVisibilityProvider, 296 mozilla::StyleGenericFontFamily, nsAtom* aLanguage, 297 nsTArray<FamilyAndGeneric>& aFamilyList) override; 298 299 void ClearLangGroupPrefFontsLocked() MOZ_REQUIRES(mLock) override; 300 301 // clear out cached generic-lang ==> family-list mappings 302 void ClearGenericMappings() { 303 AutoLock lock(mLock); 304 ClearGenericMappingsLocked(); 305 } 306 void ClearGenericMappingsLocked() MOZ_REQUIRES(mLock) { 307 mGenericMappings.Clear(); 308 } 309 310 // map lang group ==> lang string 311 void GetSampleLangForGroup(nsAtom* aLanguage, nsACString& aLangStr); 312 313 protected: 314 virtual ~gfxFcPlatformFontList(); 315 316 nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists() 317 override; 318 319 #if defined(MOZ_SANDBOX) && defined(XP_LINUX) 320 typedef mozilla::SandboxBroker::Policy SandboxPolicy; 321 #else 322 // Dummy type just so we can still have a SandboxPolicy* parameter. 323 struct SandboxPolicy {}; 324 #endif 325 326 // Add all the font families found in a font set. 327 // aAppFonts indicates whether this is the system or application fontset. 328 void AddFontSetFamilies(FcFontSet* aFontSet, const SandboxPolicy* aPolicy, 329 bool aAppFonts) MOZ_REQUIRES(mLock); 330 331 // Helper for above, to add a single font pattern. 332 void AddPatternToFontList(FcPattern* aFont, FcChar8*& aLastFamilyName, 333 nsACString& aFamilyName, 334 RefPtr<gfxFontconfigFontFamily>& aFontFamily, 335 bool aAppFonts) MOZ_REQUIRES(mLock); 336 337 // figure out which families fontconfig maps a generic to 338 // (aGeneric assumed already lowercase) 339 PrefFontList* FindGenericFamilies( 340 FontVisibilityProvider* aFontVisibilityProvider, 341 const nsCString& aGeneric, nsAtom* aLanguage) MOZ_REQUIRES(mLock); 342 343 // are all pref font settings set to use fontconfig generics? 344 bool PrefFontListsUseOnlyGenerics() MOZ_REQUIRES(mLock); 345 346 static void CheckFontUpdates(nsITimer* aTimer, void* aThis); 347 348 FontFamily GetDefaultFontForPlatform( 349 FontVisibilityProvider* aFontVisibilityProvider, 350 const gfxFontStyle* aStyle, nsAtom* aLanguage = nullptr) 351 MOZ_REQUIRES(mLock) override; 352 353 FontVisibility GetVisibilityForFamily(const nsACString& aName) const; 354 355 gfxFontFamily* CreateFontFamily(const nsACString& aName, 356 FontVisibility aVisibility) const override; 357 358 // helper method for finding an appropriate lang string 359 bool TryLangForGroup(const nsACString& aOSLang, nsAtom* aLangGroup, 360 nsACString& aLang); 361 362 #ifdef MOZ_BUNDLED_FONTS 363 void ActivateBundledFonts(); 364 nsCString mBundledFontsPath; 365 bool mBundledFontsInitialized; 366 #endif 367 368 // to avoid enumerating all fonts, maintain a mapping of local font 369 // names to family 370 nsTHashMap<nsCString, RefPtr<FcPattern>> mLocalNames; 371 372 // caching generic/lang ==> font family list 373 nsClassHashtable<nsCStringHashKey, PrefFontList> mGenericMappings; 374 375 // Caching family lookups as found by FindAndAddFamilies after resolving 376 // substitutions. The gfxFontFamily objects cached here are owned by the 377 // gfxFcPlatformFontList via its mFamilies table; note that if the main 378 // font list is rebuilt (e.g. due to a fontconfig configuration change), 379 // these pointers will be invalidated. InitFontList() flushes the cache 380 // in this case. 381 nsTHashMap<nsCStringHashKey, nsTArray<FamilyAndGeneric>> mFcSubstituteCache; 382 383 nsCOMPtr<nsITimer> mCheckFontUpdatesTimer; 384 RefPtr<FcConfig> mLastConfig; 385 386 // The current system font options in effect. 387 #ifdef MOZ_WIDGET_GTK 388 // NOTE(emilio): This is a *system cairo* cairo_font_options_t object. As 389 // such, it can't be used outside of the few functions defined here. 390 cairo_font_options_t* mSystemFontOptions = nullptr; 391 int32_t mFreetypeLcdSetting = -1; // -1 for not set 392 393 void ClearSystemFontOptions(); 394 395 // Returns whether options actually changed. 396 // TODO(emilio): We could call this when gsettings change or such, but 397 // historically we haven't reacted to these settings changes, so keeping it 398 // simple for now. 399 bool UpdateSystemFontOptions(); 400 401 void UpdateSystemFontOptionsFromIpc(const mozilla::dom::SystemFontOptions&); 402 void SystemFontOptionsToIpc(mozilla::dom::SystemFontOptions&); 403 404 public: 405 void SubstituteSystemFontOptions(FcPattern*); 406 407 private: 408 #endif 409 410 // Cache for most recently used language code in FindAndAddFamiliesLocked, 411 // and the result of checking whether to use lang-specific lookups. 412 RefPtr<nsAtom> mPrevLanguage; 413 nsCString mSampleLang; 414 bool mUseCustomLookups = false; 415 416 // By default, font prefs under Linux are set to simply lookup 417 // via fontconfig the appropriate font for serif/sans-serif/monospace. 418 // Rather than check each time a font pref is used, check them all at startup 419 // and set a boolean to flag the case that non-default user font prefs exist 420 // Note: langGroup == x-math is handled separately 421 bool mAlwaysUseFontconfigGenerics; 422 423 static FT_Library sFTLibrary; 424 }; 425 426 #endif /* GFXPLATFORMFONTLIST_H_ */