tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_ */