tor-browser

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

gfxDWriteFontList.h (17328B)


      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 GFX_DWRITEFONTLIST_H
      7 #define GFX_DWRITEFONTLIST_H
      8 
      9 #include "mozilla/FontPropertyTypes.h"
     10 #include "mozilla/MemoryReporting.h"
     11 #include "gfxDWriteCommon.h"
     12 #include "dwrite_3.h"
     13 
     14 #include "gfxFont.h"
     15 #include "gfxUserFontSet.h"
     16 #include "cairo-win32.h"
     17 
     18 #include "gfxPlatformFontList.h"
     19 #include "gfxPlatform.h"
     20 #include <algorithm>
     21 
     22 #include "mozilla/gfx/UnscaledFontDWrite.h"
     23 
     24 /**
     25 * \brief Class representing directwrite font family.
     26 *
     27 * gfxDWriteFontFamily is a class that describes one of the font families on
     28 * the user's system.  It holds each gfxDWriteFontEntry (maps more directly to
     29 * a font face) which holds font type, charset info and character map info.
     30 */
     31 class gfxDWriteFontFamily final : public gfxFontFamily {
     32 public:
     33  typedef mozilla::FontStretch FontStretch;
     34  typedef mozilla::FontSlantStyle FontSlantStyle;
     35  typedef mozilla::FontWeight FontWeight;
     36 
     37  /**
     38   * Constructs a new DWriteFont Family.
     39   *
     40   * \param aName Name identifying the family
     41   * \param aFamily IDWriteFontFamily object representing the directwrite
     42   * family object.
     43   */
     44  gfxDWriteFontFamily(const nsACString& aName, FontVisibility aVisibility,
     45                      IDWriteFontFamily* aFamily,
     46                      bool aIsSystemFontFamily = false)
     47      : gfxFontFamily(aName, aVisibility),
     48        mDWFamily(aFamily),
     49        mIsSystemFontFamily(aIsSystemFontFamily),
     50        mForceGDIClassic(false) {}
     51  virtual ~gfxDWriteFontFamily();
     52 
     53  void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr)
     54      MOZ_REQUIRES(mLock) final;
     55 
     56  void LocalizedName(nsACString& aLocalizedName) final;
     57 
     58  void ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
     59                     bool aNeedFullnamePostscriptNames,
     60                     FontInfoData* aFontInfoData = nullptr) final;
     61 
     62  void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
     63 
     64  void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
     65                              FontListSizes* aSizes) const final;
     66  void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
     67                              FontListSizes* aSizes) const final;
     68 
     69  bool FilterForFontList(nsAtom* aLangGroup,
     70                         const nsACString& aGeneric) const final {
     71    return !IsSymbolFontFamily();
     72  }
     73 
     74 protected:
     75  // helper for FilterForFontList
     76  bool IsSymbolFontFamily() const;
     77 
     78  /** This font family's directwrite fontfamily object */
     79  RefPtr<IDWriteFontFamily> mDWFamily;
     80  bool mIsSystemFontFamily;
     81  bool mForceGDIClassic;
     82 };
     83 
     84 /**
     85 * \brief Class representing DirectWrite FontEntry (a unique font style/family)
     86 */
     87 class gfxDWriteFontEntry final : public gfxFontEntry {
     88 public:
     89  /**
     90   * Constructs a font entry.
     91   *
     92   * \param aFaceName The name of the corresponding font face.
     93   * \param aFont DirectWrite font object
     94   */
     95  gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFont* aFont,
     96                     bool aIsSystemFont = false)
     97      : gfxFontEntry(aFaceName),
     98        mFont(aFont),
     99        mFontFile(nullptr),
    100        mIsSystemFont(aIsSystemFont),
    101        mForceGDIClassic(false),
    102        mHasVariations(false),
    103        mHasVariationsInitialized(false) {
    104    DWRITE_FONT_STYLE dwriteStyle = aFont->GetStyle();
    105    FontSlantStyle style = (dwriteStyle == DWRITE_FONT_STYLE_ITALIC
    106                                ? FontSlantStyle::ITALIC
    107                                : (dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE
    108                                       ? FontSlantStyle::OBLIQUE
    109                                       : FontSlantStyle::NORMAL));
    110    mStyleRange = SlantStyleRange(style);
    111 
    112    mStretchRange =
    113        StretchRange(FontStretchFromDWriteStretch(aFont->GetStretch()));
    114 
    115    int weight = mozilla::RoundUpToMultiple(aFont->GetWeight() - 50, 100);
    116    weight = std::clamp(weight, 100, 900);
    117    mWeightRange = WeightRange(FontWeight::FromInt(weight));
    118 
    119    mIsCJK = UNINITIALIZED_VALUE;
    120  }
    121 
    122  /**
    123   * Constructs a font entry using a font. But with custom font values.
    124   * This is used for creating correct font entries for @font-face with local
    125   * font source.
    126   *
    127   * \param aFaceName The name of the corresponding font face.
    128   * \param aFont DirectWrite font object
    129   * \param aWeight Weight of the font
    130   * \param aStretch Stretch of the font
    131   * \param aStyle italic or oblique of font
    132   */
    133  gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFont* aFont,
    134                     WeightRange aWeight, StretchRange aStretch,
    135                     SlantStyleRange aStyle)
    136      : gfxFontEntry(aFaceName),
    137        mFont(aFont),
    138        mFontFile(nullptr),
    139        mIsSystemFont(false),
    140        mForceGDIClassic(false),
    141        mHasVariations(false),
    142        mHasVariationsInitialized(false) {
    143    mWeightRange = aWeight;
    144    mStretchRange = aStretch;
    145    mStyleRange = aStyle;
    146    mIsLocalUserFont = true;
    147    mIsCJK = UNINITIALIZED_VALUE;
    148  }
    149 
    150  /**
    151   * Constructs a font entry using a font file.
    152   *
    153   * \param aFaceName The name of the corresponding font face.
    154   * \param aFontFile DirectWrite fontfile object
    155   * \param aFontFileStream DirectWrite fontfile stream object
    156   * \param aWeight Weight of the font
    157   * \param aStretch Stretch of the font
    158   * \param aStyle italic or oblique of font
    159   */
    160  gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFontFile* aFontFile,
    161                     gfxDWriteFontFileStream* aFontFileStream,
    162                     WeightRange aWeight, StretchRange aStretch,
    163                     SlantStyleRange aStyle)
    164      : gfxFontEntry(aFaceName),
    165        mFont(nullptr),
    166        mFontFile(aFontFile),
    167        mFontFileStream(aFontFileStream),
    168        mIsSystemFont(false),
    169        mForceGDIClassic(false),
    170        mHasVariations(false),
    171        mHasVariationsInitialized(false) {
    172    mWeightRange = aWeight;
    173    mStretchRange = aStretch;
    174    mStyleRange = aStyle;
    175    mIsDataUserFont = true;
    176    mIsCJK = UNINITIALIZED_VALUE;
    177  }
    178 
    179  gfxFontEntry* Clone() const override;
    180 
    181  virtual ~gfxDWriteFontEntry();
    182 
    183  hb_blob_t* GetFontTable(uint32_t aTableTag) override;
    184 
    185  nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override;
    186 
    187  bool IsCJKFont();
    188 
    189  bool HasVariations() override;
    190  void GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes) override;
    191  void GetVariationInstances(
    192      nsTArray<gfxFontVariationInstance>& aInstances) override;
    193 
    194  void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
    195  bool GetForceGDIClassic() { return mForceGDIClassic; }
    196 
    197  void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    198                              FontListSizes* aSizes) const override;
    199  void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    200                              FontListSizes* aSizes) const override;
    201 
    202  size_t ComputedSizeOfExcludingThis(
    203      mozilla::MallocSizeOf aMallocSizeOf) override;
    204 
    205 protected:
    206  friend class gfxDWriteFont;
    207  friend class gfxDWriteFontList;
    208  friend class gfxDWriteFontFamily;
    209 
    210  virtual nsresult CopyFontTable(uint32_t aTableTag,
    211                                 nsTArray<uint8_t>& aBuffer) override;
    212 
    213  virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle);
    214 
    215  nsresult CreateFontFace(
    216      IDWriteFontFace** aFontFace, const gfxFontStyle* aFontStyle = nullptr,
    217      DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE,
    218      const nsTArray<gfxFontVariation>* aVariations = nullptr);
    219 
    220  static bool InitLogFont(IDWriteFont* aFont, LOGFONTW* aLogFont);
    221 
    222  /**
    223   * A fontentry only needs to have either of these. If it has both only
    224   * the IDWriteFont will be used.
    225   */
    226  RefPtr<IDWriteFont> mFont;
    227  RefPtr<IDWriteFontFile> mFontFile;
    228 
    229  // For custom fonts, we hold a reference to the IDWriteFontFileStream for
    230  // for the IDWriteFontFile, so that the data is available.
    231  RefPtr<gfxDWriteFontFileStream> mFontFileStream;
    232 
    233  // font face corresponding to the mFont/mFontFile *without* any DWrite
    234  // style simulations applied
    235  RefPtr<IDWriteFontFace> mFontFace;
    236  // Extended fontface interface if supported, else null
    237  RefPtr<IDWriteFontFace5> mFontFace5;
    238 
    239  DWRITE_FONT_FACE_TYPE mFaceType;
    240 
    241  int8_t mIsCJK;
    242  bool mIsSystemFont;
    243  bool mForceGDIClassic;
    244  bool mHasVariations;
    245  bool mHasVariationsInitialized;
    246 
    247  // Set to true only if the font belongs to a "simple" family where the
    248  // faces can be reliably identified via a GDI LOGFONT structure.
    249  bool mMayUseGDIAccess = false;
    250 
    251  mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite> mUnscaledFont;
    252  mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite>
    253      mUnscaledFontBold;
    254 };
    255 
    256 // custom text renderer used to determine the fallback font for a given char
    257 class DWriteFontFallbackRenderer final : public IDWriteTextRenderer {
    258 public:
    259  explicit DWriteFontFallbackRenderer(IDWriteFactory* aFactory) : mRefCount(0) {
    260    HRESULT hr =
    261        aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts));
    262    NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!");
    263    (void)hr;
    264  }
    265 
    266  ~DWriteFontFallbackRenderer() {}
    267 
    268  // If we don't have an mSystemFonts pointer, this renderer is unusable.
    269  bool IsValid() const { return mSystemFonts; }
    270 
    271  // IDWriteTextRenderer methods
    272  IFACEMETHOD(DrawGlyphRun)
    273  (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,
    274   DWRITE_MEASURING_MODE measuringMode, DWRITE_GLYPH_RUN const* glyphRun,
    275   DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
    276   IUnknown* clientDrawingEffect);
    277 
    278  IFACEMETHOD(DrawUnderline)
    279  (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,
    280   DWRITE_UNDERLINE const* underline, IUnknown* clientDrawingEffect) {
    281    return E_NOTIMPL;
    282  }
    283 
    284  IFACEMETHOD(DrawStrikethrough)
    285  (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,
    286   DWRITE_STRIKETHROUGH const* strikethrough, IUnknown* clientDrawingEffect) {
    287    return E_NOTIMPL;
    288  }
    289 
    290  IFACEMETHOD(DrawInlineObject)
    291  (void* clientDrawingContext, FLOAT originX, FLOAT originY,
    292   IDWriteInlineObject* inlineObject, BOOL isSideways, BOOL isRightToLeft,
    293   IUnknown* clientDrawingEffect) {
    294    return E_NOTIMPL;
    295  }
    296 
    297  // IDWritePixelSnapping methods
    298 
    299  IFACEMETHOD(IsPixelSnappingDisabled)
    300  (void* clientDrawingContext, BOOL* isDisabled) {
    301    *isDisabled = FALSE;
    302    return S_OK;
    303  }
    304 
    305  IFACEMETHOD(GetCurrentTransform)
    306  (void* clientDrawingContext, DWRITE_MATRIX* transform) {
    307    const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
    308    *transform = ident;
    309    return S_OK;
    310  }
    311 
    312  IFACEMETHOD(GetPixelsPerDip)
    313  (void* clientDrawingContext, FLOAT* pixelsPerDip) {
    314    *pixelsPerDip = 1.0f;
    315    return S_OK;
    316  }
    317 
    318  // IUnknown methods
    319 
    320  IFACEMETHOD_(unsigned long, AddRef)() {
    321    return InterlockedIncrement(&mRefCount);
    322  }
    323 
    324  IFACEMETHOD_(unsigned long, Release)() {
    325    unsigned long newCount = InterlockedDecrement(&mRefCount);
    326    if (newCount == 0) {
    327      delete this;
    328      return 0;
    329    }
    330 
    331    return newCount;
    332  }
    333 
    334  IFACEMETHOD(QueryInterface)(IID const& riid, void** ppvObject) {
    335    if (__uuidof(IDWriteTextRenderer) == riid) {
    336      *ppvObject = this;
    337    } else if (__uuidof(IDWritePixelSnapping) == riid) {
    338      *ppvObject = this;
    339    } else if (__uuidof(IUnknown) == riid) {
    340      *ppvObject = this;
    341    } else {
    342      *ppvObject = nullptr;
    343      return E_FAIL;
    344    }
    345 
    346    this->AddRef();
    347    return S_OK;
    348  }
    349 
    350  const nsCString& FallbackFamilyName() { return mFamilyName; }
    351 
    352 protected:
    353  long mRefCount;
    354  RefPtr<IDWriteFontCollection> mSystemFonts;
    355  nsCString mFamilyName;
    356 };
    357 
    358 class gfxDWriteFontList final : public gfxPlatformFontList {
    359 public:
    360  gfxDWriteFontList();
    361  virtual ~gfxDWriteFontList() { AutoLock lock(mLock); }
    362 
    363  static gfxDWriteFontList* PlatformFontList() {
    364    return static_cast<gfxDWriteFontList*>(
    365        gfxPlatformFontList::PlatformFontList());
    366  }
    367 
    368  // initialize font lists
    369  nsresult InitFontListForPlatform() MOZ_REQUIRES(mLock) override;
    370  void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) override;
    371 
    372  FontVisibility GetVisibilityForFamily(const nsACString& aName) const;
    373 
    374  gfxFontFamily* CreateFontFamily(const nsACString& aName,
    375                                  FontVisibility aVisibility) const override;
    376 
    377  gfxFontEntry* CreateFontEntry(
    378      mozilla::fontlist::Face* aFace,
    379      const mozilla::fontlist::Family* aFamily) override;
    380 
    381  void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
    382                              bool aNeedFullnamePostscriptNames)
    383      MOZ_REQUIRES(mLock) override;
    384 
    385  bool ReadFaceNames(const mozilla::fontlist::Family* aFamily,
    386                     const mozilla::fontlist::Face* aFace, nsCString& aPSName,
    387                     nsCString& aFullName) override;
    388 
    389  void GetFacesInitDataForFamily(
    390      const mozilla::fontlist::Family* aFamily,
    391      nsTArray<mozilla::fontlist::Face::InitData>& aFaces,
    392      bool aLoadCmaps) const override;
    393 
    394  gfxFontEntry* LookupLocalFont(FontVisibilityProvider* aFontVisibilityProvider,
    395                                const nsACString& aFontName,
    396                                WeightRange aWeightForEntry,
    397                                StretchRange aStretchForEntry,
    398                                SlantStyleRange aStyleForEntry) override;
    399 
    400  gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
    401                                 WeightRange aWeightForEntry,
    402                                 StretchRange aStretchForEntry,
    403                                 SlantStyleRange aStyleForEntry,
    404                                 const uint8_t* aFontData,
    405                                 uint32_t aLength) override;
    406 
    407  IDWriteGdiInterop* GetGDIInterop() { return mGDIInterop; }
    408  bool UseGDIFontTableAccess() const;
    409 
    410  bool FindAndAddFamiliesLocked(
    411      FontVisibilityProvider* aFontVisibilityProvider,
    412      mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily,
    413      nsTArray<FamilyAndGeneric>* aOutput, FindFamiliesFlags aFlags,
    414      gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr,
    415      gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) override;
    416 
    417  gfxFloat GetForceGDIClassicMaxFontSize() {
    418    return mForceGDIClassicMaxFontSize;
    419  }
    420 
    421  virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    422                                      FontListSizes* aSizes) const;
    423  virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    424                                      FontListSizes* aSizes) const;
    425 
    426 protected:
    427  FontFamily GetDefaultFontForPlatform(
    428      FontVisibilityProvider* aFontVisibilityProvider,
    429      const gfxFontStyle* aStyle, nsAtom* aLanguage = nullptr)
    430      MOZ_REQUIRES(mLock) override;
    431 
    432  // attempt to use platform-specific fallback for the given character,
    433  // return null if no usable result found
    434  gfxFontEntry* PlatformGlobalFontFallback(
    435      FontVisibilityProvider* aFontVisibilityProvider, const uint32_t aCh,
    436      Script aRunScript, const gfxFontStyle* aMatchStyle,
    437      FontFamily& aMatchedFamily) MOZ_REQUIRES(mLock) override;
    438 
    439  nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists()
    440      override;
    441 
    442 private:
    443  friend class gfxDWriteFontFamily;
    444 
    445  nsresult GetFontSubstitutes() MOZ_REQUIRES(mLock);
    446 
    447  void GetDirectWriteSubstitutes() MOZ_REQUIRES(mLock);
    448 
    449  virtual bool UsesSystemFallback() { return true; }
    450 
    451  void GetFontsFromCollection(IDWriteFontCollection* aCollection)
    452      MOZ_REQUIRES(mLock);
    453 
    454  void AppendFamiliesFromCollection(
    455      IDWriteFontCollection* aCollection,
    456      nsTArray<mozilla::fontlist::Family::InitData>& aFamilies,
    457      const nsTArray<nsCString>* aForceClassicFams = nullptr)
    458      MOZ_REQUIRES(mLock);
    459 
    460  void AddSubstitute(const nsCString& aSubstituteName,
    461                     const nsCString& aActualFontName, bool aIsHardcoded)
    462      MOZ_REQUIRES(mLock);
    463 
    464 #ifdef MOZ_BUNDLED_FONTS
    465  already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection(
    466      IDWriteFactory* aFactory);
    467 #endif
    468 
    469  /**
    470   * Fonts listed in the registry as substitutes but for which no actual
    471   * font family is found.
    472   */
    473  nsTArray<nsCString> mNonExistingFonts;
    474 
    475  /**
    476   * Table of font substitutes, we grab this from the registry to get
    477   * alternative font names.
    478   */
    479  FontFamilyTable mFontSubstitutes;
    480  nsClassHashtable<nsCStringHashKey, nsCString> mSubstitutions;
    481 
    482  /**
    483   * Table of hardcoded font substitutes. We use this instead of the one
    484   * generated from the registry when fingerprinting protections are enabled.
    485   */
    486  FontFamilyTable mHardcodedSubstitutes;
    487  nsClassHashtable<nsCStringHashKey, nsCString> mHardcodedSubstitutions;
    488 
    489  virtual already_AddRefed<FontInfoData> CreateFontInfoData();
    490 
    491  gfxFloat mForceGDIClassicMaxFontSize;
    492 
    493  // whether to use GDI font table access routines
    494  bool mGDIFontTableAccess;
    495  RefPtr<IDWriteGdiInterop> mGDIInterop;
    496 
    497  RefPtr<DWriteFontFallbackRenderer> mFallbackRenderer;
    498  RefPtr<IDWriteTextFormat> mFallbackFormat;
    499 
    500  RefPtr<IDWriteFontCollection> mSystemFonts;
    501 #ifdef MOZ_BUNDLED_FONTS
    502  RefPtr<IDWriteFontCollection> mBundledFonts;
    503 #endif
    504 };
    505 
    506 #endif /* GFX_DWRITEFONTLIST_H */