tor-browser

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

gfxFontEntry.h (49097B)


      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_FONTENTRY_H
      7 #define GFX_FONTENTRY_H
      8 
      9 #include <limits>
     10 #include <math.h>
     11 #include <new>
     12 #include <utility>
     13 #include "COLRFonts.h"
     14 #include "ThebesRLBoxTypes.h"
     15 #include "gfxFontUtils.h"
     16 #include "gfxFontVariations.h"
     17 #include "gfxRect.h"
     18 #include "gfxTypes.h"
     19 #include "gfxFontFeatures.h"
     20 #include "harfbuzz/hb.h"
     21 #include "mozilla/AlreadyAddRefed.h"
     22 #include "mozilla/Assertions.h"
     23 #include "mozilla/FontPropertyTypes.h"
     24 #include "mozilla/MemoryReporting.h"
     25 #include "mozilla/Mutex.h"
     26 #include "mozilla/RefPtr.h"
     27 #include "mozilla/RWLock.h"
     28 #include "mozilla/TypedEnumBits.h"
     29 #include "mozilla/UniquePtr.h"
     30 #include "mozilla/intl/UnicodeScriptCodes.h"
     31 #include "nsTHashMap.h"
     32 #include "nsDebug.h"
     33 #include "nsHashKeys.h"
     34 #include "nsISupports.h"
     35 #include "nsStringFwd.h"
     36 #include "nsTArray.h"
     37 #include "nscore.h"
     38 
     39 class FontInfoData;
     40 class gfxContext;
     41 class gfxFont;
     42 class gfxFontFamily;
     43 class gfxPlatformFontList;
     44 class gfxSVGGlyphs;
     45 class gfxUserFontData;
     46 class nsAtom;
     47 struct FontListSizes;
     48 struct gfxFontStyle;
     49 enum class FontPresentation : uint8_t;
     50 
     51 namespace IPC {
     52 template <class P>
     53 struct ParamTraits;
     54 }
     55 
     56 namespace mozilla {
     57 class SVGContextPaint;
     58 namespace fontlist {
     59 struct Face;
     60 struct Family;
     61 }  // namespace fontlist
     62 }  // namespace mozilla
     63 
     64 typedef struct gr_face gr_face;
     65 typedef struct FT_MM_Var_ FT_MM_Var;
     66 
     67 #define NO_FONT_LANGUAGE_OVERRIDE 0
     68 
     69 class gfxCharacterMap : public gfxSparseBitSet {
     70 public:
     71  // gfxCharacterMap instances may be shared across multiple threads via a
     72  // global table managed by gfxPlatformFontList. Once a gfxCharacterMap is
     73  // inserted in the global table, its mShared flag will be TRUE, and we
     74  // cannot safely delete it except from gfxPlatformFontList (which will
     75  // use a lock to ensure entries are removed from its table and deleted
     76  // safely).
     77 
     78  // AddRef() is pretty much standard. We don't return the refcount as our
     79  // users don't care about it.
     80  void AddRef() {
     81    MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(gfxCharacterMap);
     82    MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
     83    [[maybe_unused]] nsrefcnt count = ++mRefCnt;
     84    NS_LOG_ADDREF(this, count, "gfxCharacterMap", sizeof(*this));
     85  }
     86 
     87  // Custom Release(): if the object is referenced from the global shared
     88  // table, and we're releasing the last *other* reference to it, then we
     89  // notify the global table to consider also releasing its ref. (That may
     90  // not actually happen, if another thread is racing with us and takes a
     91  // new reference, or completes the release first!)
     92  void Release() {
     93    MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
     94    // We can't safely read this after we've decremented mRefCnt, so save it
     95    // in a local variable here. Note that the value is never reset to false
     96    // once it has been set to true (when recording the cmap in the shared
     97    // table), so there's no risk of this resulting in a "false positive" when
     98    // tested later. A "false negative" is possible but harmless; it would
     99    // just mean we miss an opportunity to release a reference from the shared
    100    // cmap table.
    101    bool isShared = mShared;
    102 
    103    // Ensure we only access mRefCnt once, for consistency if the object is
    104    // being used by multiple threads.
    105    nsrefcnt count = --mRefCnt;
    106    NS_LOG_RELEASE(this, count, "gfxCharacterMap");
    107 
    108    // If isShared was true, this object has been shared across threads. In
    109    // that case, if the refcount went to 1, we notify the shared table so
    110    // it can drop its reference and delete the object.
    111    if (isShared) {
    112      MOZ_ASSERT(count > 0);
    113      if (count == 1) {
    114        NotifyMaybeReleased(this);
    115      }
    116      return;
    117    }
    118 
    119    // Otherwise, this object hasn't been shared and we can safely delete it
    120    // as we must have been holding the only reference. (Note that if we were
    121    // holding the only reference, there's no other owner who can have set
    122    // mShared to true since we read it above.)
    123    if (count == 0) {
    124      delete this;
    125    }
    126  }
    127 
    128  explicit gfxCharacterMap(uint32_t aReserveBlocks)
    129      : gfxSparseBitSet(aReserveBlocks) {}
    130 
    131  explicit gfxCharacterMap(const gfxSparseBitSet& aOther)
    132      : gfxSparseBitSet(aOther) {}
    133 
    134  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
    135    return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
    136  }
    137 
    138  // hash of the cmap bitvector
    139  uint32_t mHash = 0;
    140 
    141  // if cmap is built on the fly it's never shared
    142  bool mBuildOnTheFly = false;
    143 
    144  // Character map is shared globally. This can only be set by the thread that
    145  // originally created the map, as no other thread can get a reference until
    146  // it has been shared via the global table.
    147  bool mShared = false;
    148 
    149 protected:
    150  friend class gfxPlatformFontList;
    151 
    152  // Destructor should not be called except via Release().
    153  // (Note that our "friend" gfxPlatformFontList also accesses this from its
    154  // MaybeRemoveCmap method.)
    155  ~gfxCharacterMap() = default;
    156 
    157  nsrefcnt RefCount() const { return mRefCnt; }
    158 
    159  void CalcHash() { mHash = GetChecksum(); }
    160 
    161  static void NotifyMaybeReleased(gfxCharacterMap* aCmap);
    162 
    163  // Only used when clearing the shared-cmap hashtable during shutdown.
    164  void ClearSharedFlag() {
    165    MOZ_ASSERT(NS_IsMainThread());
    166    mShared = false;
    167  }
    168 
    169  mozilla::ThreadSafeAutoRefCnt mRefCnt;
    170 
    171 private:
    172  gfxCharacterMap(const gfxCharacterMap&) = delete;
    173  gfxCharacterMap& operator=(const gfxCharacterMap&) = delete;
    174 };
    175 
    176 // Info on an individual font feature, for reporting available features
    177 // to DevTools via the GetFeatureInfo method.
    178 struct gfxFontFeatureInfo {
    179  uint32_t mTag;
    180  uint32_t mScript;
    181  uint32_t mLangSys;
    182 };
    183 
    184 class gfxFontEntryCallbacks;
    185 
    186 class gfxFontEntry {
    187 public:
    188  typedef mozilla::gfx::DrawTarget DrawTarget;
    189  typedef mozilla::intl::Script Script;
    190  typedef mozilla::FontWeight FontWeight;
    191  typedef mozilla::FontSlantStyle FontSlantStyle;
    192  typedef mozilla::FontStretch FontStretch;
    193  typedef mozilla::WeightRange WeightRange;
    194  typedef mozilla::SlantStyleRange SlantStyleRange;
    195  typedef mozilla::StretchRange StretchRange;
    196 
    197  // Used by stylo
    198  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry)
    199 
    200  explicit gfxFontEntry(const nsACString& aName, bool aIsStandardFace = false);
    201 
    202  gfxFontEntry() = delete;
    203  gfxFontEntry(const gfxFontEntry&) = delete;
    204  gfxFontEntry& operator=(const gfxFontEntry&) = delete;
    205 
    206  // Create a new entry that refers to the same font as this, but without
    207  // additional state that may have been set up (such as family name).
    208  // (This is only to be used for system fonts in the platform font list,
    209  // not user fonts.)
    210  virtual gfxFontEntry* Clone() const = 0;
    211 
    212  // unique name for the face, *not* the family; not necessarily the
    213  // "real" or user-friendly name, may be an internal identifier
    214  const nsCString& Name() const { return mName; }
    215 
    216  // family name
    217  const nsCString& FamilyName() const { return mFamilyName; }
    218 
    219  // The following two methods may be relatively expensive, as they
    220  // will (usually, except on Linux) load and parse the 'name' table;
    221  // they are intended only for the font-inspection API, not for
    222  // perf-critical layout/drawing work.
    223 
    224  // The "real" name of the face, if available from the font resource;
    225  // returns Name() if nothing better is available.
    226  virtual nsCString RealFaceName();
    227 
    228  WeightRange Weight() const { return mWeightRange; }
    229  StretchRange Stretch() const { return mStretchRange; }
    230  SlantStyleRange SlantStyle() const { return mStyleRange; }
    231 
    232  bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
    233  bool IsLocalUserFont() const { return mIsLocalUserFont; }
    234  bool IsFixedPitch() const { return mFixedPitch; }
    235  bool IsItalic() const { return SlantStyle().Min().IsItalic(); }
    236  // IsOblique returns true if the oblique angle is non-zero; 'oblique 0deg'
    237  // is synonymous with 'normal' and will return false here.
    238  bool IsOblique() const { return !IsUpright() && !IsItalic(); }
    239  bool IsUpright() const { return SlantStyle().Min().IsNormal(); }
    240  inline bool SupportsItalic();  // defined below, because of RangeFlags use
    241  inline bool SupportsBold();
    242  inline bool MayUseSyntheticSlant();
    243  bool IgnoreGDEF() const { return mIgnoreGDEF; }
    244  bool IgnoreGSUB() const { return mIgnoreGSUB; }
    245 
    246  // Return whether the face corresponds to "normal" CSS style properties:
    247  //    font-style: normal;
    248  //    font-weight: normal;
    249  //    font-stretch: normal;
    250  // If this is false, we might want to fall back to a different face and
    251  // possibly apply synthetic styling.
    252  bool IsNormalStyle() const {
    253    return IsUpright() && Weight().Min() <= FontWeight::NORMAL &&
    254           Weight().Max() >= FontWeight::NORMAL &&
    255           Stretch().Min() <= FontStretch::NORMAL &&
    256           Stretch().Max() >= FontStretch::NORMAL;
    257  }
    258 
    259  // whether a feature is supported by the font (limited to a small set
    260  // of features for which some form of fallback needs to be implemented)
    261  virtual bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
    262  bool SupportsGraphiteFeature(uint32_t aFeatureTag);
    263 
    264  // returns a set containing all input glyph ids for a given feature
    265  const hb_set_t* InputsForOpenTypeFeature(Script aScript,
    266                                           uint32_t aFeatureTag);
    267 
    268  virtual bool HasFontTable(uint32_t aTableTag);
    269 
    270  inline bool HasGraphiteTables() {
    271    LazyFlag flag = mHasGraphiteTables;
    272    if (flag == LazyFlag::Uninitialized) {
    273      flag = CheckForGraphiteTables() ? LazyFlag::Yes : LazyFlag::No;
    274      mHasGraphiteTables = flag;
    275    }
    276    return flag == LazyFlag::Yes;
    277  }
    278 
    279  inline bool AlwaysNeedsMaskForShadow() {
    280    LazyFlag flag = mNeedsMaskForShadow;
    281    if (flag == LazyFlag::Uninitialized) {
    282      flag =
    283          TryGetColorGlyphs() || TryGetSVGData(nullptr) || HasColorBitmapTable()
    284              ? LazyFlag::Yes
    285              : LazyFlag::No;
    286      mNeedsMaskForShadow = flag;
    287    }
    288    return flag == LazyFlag::Yes;
    289  }
    290 
    291  inline bool HasCmapTable() {
    292    if (!mCharacterMap && !mShmemCharacterMap) {
    293      ReadCMAP();
    294      NS_ASSERTION(mCharacterMap || mShmemCharacterMap,
    295                   "failed to initialize character map");
    296    }
    297    return mHasCmapTable;
    298  }
    299 
    300  inline bool HasCharacter(uint32_t ch) {
    301    if (mShmemCharacterMap) {
    302      return GetShmemCharacterMap()->test(ch);
    303    }
    304    if (mCharacterMap) {
    305      if (mShmemFace && TrySetShmemCharacterMap()) {
    306        // Forget our temporary local copy, now we can use the shared cmap
    307        auto* oldCmap = mCharacterMap.exchange(nullptr);
    308        NS_IF_RELEASE(oldCmap);
    309        return GetShmemCharacterMap()->test(ch);
    310      }
    311      if (GetCharacterMap()->test(ch)) {
    312        return true;
    313      }
    314    }
    315    return TestCharacterMap(ch);
    316  }
    317 
    318  virtual bool SkipDuringSystemFallback() { return false; }
    319  void EnsureUVSMapInitialized();
    320  uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS);
    321 
    322  // All concrete gfxFontEntry subclasses (except gfxUserFontEntry) need
    323  // to override this, otherwise the font will never be used as it will
    324  // be considered to support no characters.
    325  // ReadCMAP() must *always* set the mCharacterMap pointer to a valid
    326  // gfxCharacterMap, even if empty, as other code assumes this pointer
    327  // can be safely dereferenced.
    328  virtual nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr);
    329 
    330  bool TryGetSVGData(const gfxFont* aFont);
    331  bool HasSVGGlyph(uint32_t aGlyphId);
    332  bool GetSVGGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphId,
    333                          gfxFloat aSize, gfxRect* aResult);
    334  void RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
    335                      mozilla::SVGContextPaint* aContextPaint);
    336  // Call this when glyph geometry or rendering has changed
    337  // (e.g. animated SVG glyphs)
    338  void NotifyGlyphsChanged();
    339 
    340  bool TryGetColorGlyphs();
    341 
    342  bool HasColorBitmapTable() {
    343    LazyFlag flag = mHasColorBitmapTable;
    344    if (flag == LazyFlag::Uninitialized) {
    345      flag = HasFontTable(TRUETYPE_TAG('C', 'B', 'D', 'T')) ||
    346                     HasFontTable(TRUETYPE_TAG('s', 'b', 'i', 'x'))
    347                 ? LazyFlag::Yes
    348                 : LazyFlag::No;
    349      mHasColorBitmapTable = flag;
    350    }
    351    return flag == LazyFlag::Yes;
    352  }
    353 
    354  // Access to raw font table data (needed for Harfbuzz):
    355  // returns a pointer to data owned by the fontEntry or the OS,
    356  // which will remain valid until the blob is destroyed.
    357  // The data MUST be treated as read-only; we may be getting a
    358  // reference to a shared system font cache.
    359  //
    360  // The default implementation uses CopyFontTable to get the data
    361  // into a byte array, and maintains a cache of loaded tables.
    362  //
    363  // Subclasses should override this if they can provide more efficient
    364  // access than copying table data into our own buffers.
    365  //
    366  // Get blob that encapsulates a specific font table, or nullptr if
    367  // the table doesn't exist in the font.
    368  //
    369  // Caller is responsible to call hb_blob_destroy() on the returned blob
    370  // (if non-nullptr) when no longer required. For transient access to a
    371  // table, use of AutoTable (below) is generally preferred.
    372  virtual hb_blob_t* GetFontTable(uint32_t aTag);
    373 
    374  // Stack-based utility to return a specified table, automatically releasing
    375  // the blob when the AutoTable goes out of scope.
    376  class AutoTable {
    377   public:
    378    AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag) {
    379      mBlob = aFontEntry->GetFontTable(aTag);
    380    }
    381    ~AutoTable() { hb_blob_destroy(mBlob); }
    382    operator hb_blob_t*() const { return mBlob; }
    383 
    384   private:
    385    hb_blob_t* mBlob;
    386    // not implemented:
    387    AutoTable(const AutoTable&) = delete;
    388    AutoTable& operator=(const AutoTable&) = delete;
    389  };
    390 
    391  // Return a font instance for a particular style. This may be a newly-
    392  // created instance, or a font already in the global cache.
    393  // We can't return a UniquePtr here, because we may be returning a shared
    394  // cached instance; but we also don't return already_AddRefed, because
    395  // the caller may only need to use the font temporarily and doesn't need
    396  // a strong reference.
    397  already_AddRefed<gfxFont> FindOrMakeFont(
    398      const gfxFontStyle* aStyle, gfxCharacterMap* aUnicodeRangeMap = nullptr);
    399 
    400  // Get an existing font table cache entry in aBlob if it has been
    401  // registered, or return false if not.  Callers must call
    402  // hb_blob_destroy on aBlob if true is returned.
    403  //
    404  // Note that some gfxFont implementations may not call this at all,
    405  // if it is more efficient to get the table from the OS at that level.
    406  bool GetExistingFontTable(uint32_t aTag, hb_blob_t** aBlob);
    407 
    408  // Elements of aTable are transferred (not copied) to and returned in a
    409  // new hb_blob_t which is registered on the gfxFontEntry, but the initial
    410  // reference is owned by the caller.  Removing the last reference
    411  // unregisters the table from the font entry.
    412  //
    413  // Pass nullptr for aBuffer to indicate that the table is not present and
    414  // nullptr will be returned.
    415  hb_blob_t* ShareFontTableAndGetBlob(uint32_t aTag, nsTArray<uint8_t>* aTable);
    416 
    417  // Get the font's unitsPerEm from the 'head' table, in the case of an
    418  // sfnt resource. Will return kInvalidUPEM for non-sfnt fonts,
    419  // if present on the platform.
    420  uint16_t UnitsPerEm();
    421  enum {
    422    kMinUPEM = 16,     // Limits on valid unitsPerEm range, from the
    423    kMaxUPEM = 16384,  // OpenType spec
    424    kInvalidUPEM = uint16_t(-1)
    425  };
    426 
    427  // Shaper face accessors:
    428  // NOTE that harfbuzz and graphite handle ownership/lifetime of the face
    429  // object in completely different ways.
    430 
    431  // Create a HarfBuzz face corresponding to this font file.
    432  // Our reference to the underlying hb_face_t will be released when the
    433  // returned AutoHBFace goes out of scope, but the hb_face_t itself may
    434  // be kept alive by other references (e.g. if an hb_font_t has been
    435  // instantiated for it).
    436  class MOZ_STACK_CLASS AutoHBFace {
    437   public:
    438    explicit AutoHBFace(hb_face_t* aFace) : mFace(aFace) {}
    439    ~AutoHBFace() { hb_face_destroy(mFace); }
    440 
    441    operator hb_face_t*() const { return mFace; }
    442 
    443    // Not default-constructible, not copyable.
    444    AutoHBFace() = delete;
    445    AutoHBFace(const AutoHBFace&) = delete;
    446    AutoHBFace& operator=(const AutoHBFace&) = delete;
    447 
    448   private:
    449    hb_face_t* mFace;
    450  };
    451 
    452  AutoHBFace GetHBFace() {
    453    return AutoHBFace(hb_face_create_for_tables(HBGetTable, this, nullptr));
    454  }
    455 
    456  // Get the sandbox instance that graphite is running in.
    457  rlbox_sandbox_gr* GetGrSandbox();
    458 
    459  // Register and get the callback handle for the glyph advance firefox callback
    460  // Since the sandbox instance is shared with multiple test shapers, callback
    461  // registration must be handled centrally to ensure multiple instances don't
    462  // register the same callback.
    463  sandbox_callback_gr<float (*)(const void*, uint16_t)>*
    464  GetGrSandboxAdvanceCallbackHandle();
    465 
    466  // Get Graphite face corresponding to this font file.
    467  // Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
    468  // Graphite is run in a sandbox
    469  tainted_opaque_gr<gr_face*> GetGrFace();
    470  void ReleaseGrFace(tainted_opaque_gr<gr_face*> aFace);
    471 
    472  // Does the font have graphite contextuals that involve the space glyph
    473  // (and therefore we should bypass the word cache)?
    474  // Since this function inspects data from libGraphite stored in sandbox memory
    475  // it can only return a "hint" to the correct return value. This is because
    476  // a compromised libGraphite could change the sandbox memory maliciously at
    477  // any moment. The caller must ensure the calling code performs safe actions
    478  // independent of the value returned, to unwrap this return.
    479  tainted_boolean_hint HasGraphiteSpaceContextuals();
    480 
    481  // Release any SVG-glyphs document this font may have loaded.
    482  void DisconnectSVG();
    483 
    484  // Called to notify that aFont is being destroyed. Needed when we're tracking
    485  // the fonts belonging to this font entry.
    486  void NotifyFontDestroyed(gfxFont* aFont);
    487 
    488  // For memory reporting of the platform font list.
    489  virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    490                                      FontListSizes* aSizes) const;
    491  virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
    492                                      FontListSizes* aSizes) const;
    493 
    494  // Used for reporting on individual font entries in the user font cache,
    495  // which are not present in the platform font list.
    496  virtual size_t ComputedSizeOfExcludingThis(
    497      mozilla::MallocSizeOf aMallocSizeOf);
    498 
    499  // Used when checking for complex script support, to mask off cmap ranges
    500  struct ScriptRange {
    501    uint32_t rangeStart;
    502    uint32_t rangeEnd;
    503    uint32_t numTags;  // number of entries in the tags[] array
    504    hb_tag_t tags[3];  // up to three OpenType script tags to check
    505  };
    506 
    507  bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags, uint32_t aNumTags);
    508 
    509  /**
    510   * Font-variation query methods.
    511   *
    512   * Font backends that don't support variations should provide empty
    513   * implementations.
    514   */
    515  virtual bool HasVariations() = 0;
    516 
    517  virtual void GetVariationAxes(
    518      nsTArray<gfxFontVariationAxis>& aVariationAxes) = 0;
    519 
    520  virtual void GetVariationInstances(
    521      nsTArray<gfxFontVariationInstance>& aInstances) = 0;
    522 
    523  bool HasBoldVariableWeight();
    524  bool HasItalicVariation();
    525  bool HasSlantVariation();
    526  bool HasOpticalSize();
    527 
    528  void CheckForVariationAxes();
    529 
    530  // Set up the entry's weight/stretch/style ranges according to axes found
    531  // by GetVariationAxes (for installed fonts; do NOT call this for user
    532  // fonts, where the ranges are provided by @font-face descriptors).
    533  void SetupVariationRanges();
    534 
    535  // Get variation axis settings that should be used to implement a particular
    536  // font style using this resource.
    537  void GetVariationsForStyle(nsTArray<gfxFontVariation>& aResult,
    538                             const gfxFontStyle& aStyle);
    539 
    540  // Get the font's list of features (if any) for DevTools support.
    541  void GetFeatureInfo(nsTArray<gfxFontFeatureInfo>& aFeatureInfo);
    542 
    543  // This is only called on platforms where we use FreeType.
    544  virtual FT_MM_Var* GetMMVar() { return nullptr; }
    545 
    546  // Return true if the font has a 'trak' table (and we can successfully
    547  // interpret it), otherwise false. This will load and cache the table
    548  // the first time it is called.
    549  bool HasTrackingTable();
    550 
    551  // Return the tracking (in font units) to be applied for the given size.
    552  // (This is a floating-point number because of possible interpolation.)
    553  gfxFloat TrackingForCSSPx(gfxFloat aSize) const;
    554 
    555  mozilla::gfx::Rect GetFontExtents(float aFUnitScaleFactor) const {
    556    // Flip the y-axis here to match the orientation of Gecko's coordinates.
    557    // We don't need to take a lock here because the min/max fields are inert
    558    // after initialization, and we make sure to initialize them at gfxFont-
    559    // creation time.
    560    return mozilla::gfx::Rect(float(mXMin) * aFUnitScaleFactor,
    561                              float(-mYMax) * aFUnitScaleFactor,
    562                              float(mXMax - mXMin) * aFUnitScaleFactor,
    563                              float(mYMax - mYMin) * aFUnitScaleFactor);
    564  }
    565 
    566  nsCString mName;
    567  nsCString mFamilyName;
    568 
    569  // These are mutable so that we can take a read lock within a const method.
    570  mutable mozilla::RWLock mLock;
    571  mutable mozilla::Mutex mFeatureInfoLock;
    572 
    573  mozilla::Atomic<gfxCharacterMap*> mCharacterMap;  // strong ref
    574  gfxCharacterMap* GetCharacterMap() const { return mCharacterMap; }
    575 
    576  mozilla::fontlist::Face* mShmemFace = nullptr;
    577  const mozilla::fontlist::Family* mShmemFamily = nullptr;
    578 
    579  mozilla::Atomic<const SharedBitSet*> mShmemCharacterMap;
    580  const SharedBitSet* GetShmemCharacterMap() const {
    581    return mShmemCharacterMap;
    582  }
    583 
    584  mozilla::Atomic<const uint8_t*> mUVSData;
    585  const uint8_t* GetUVSData() const { return mUVSData; }
    586 
    587  mozilla::UniquePtr<gfxUserFontData> mUserFontData;
    588 
    589  mozilla::Atomic<gfxSVGGlyphs*> mSVGGlyphs;
    590  gfxSVGGlyphs* GetSVGGlyphs() const { return mSVGGlyphs; }
    591 
    592  // list of gfxFonts that are using SVG glyphs
    593  nsTArray<const gfxFont*> mFontsUsingSVGGlyphs MOZ_GUARDED_BY(mLock);
    594  nsTArray<gfxFontFeature> mFeatureSettings;
    595  nsTArray<gfxFontVariation> mVariationSettings;
    596 
    597  mozilla::UniquePtr<nsTHashMap<nsUint32HashKey, bool>> mSupportedFeatures
    598      MOZ_GUARDED_BY(mFeatureInfoLock);
    599  mozilla::UniquePtr<nsTHashMap<nsUint32HashKey, hb_set_t*>> mFeatureInputs
    600      MOZ_GUARDED_BY(mFeatureInfoLock);
    601 
    602  // Color Layer font support. These tables are inert once loaded, so we don't
    603  // need to hold a lock when reading them.
    604  mozilla::Atomic<hb_blob_t*> mCOLR;
    605  mozilla::Atomic<hb_blob_t*> mCPAL;
    606  hb_blob_t* GetCOLR() const { return mCOLR; }
    607  hb_blob_t* GetCPAL() const { return mCPAL; }
    608 
    609  // bitvector of substitution space features per script, one each
    610  // for default and non-default features
    611  uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) /
    612                                    32] MOZ_GUARDED_BY(mFeatureInfoLock);
    613  uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) /
    614                                       32] MOZ_GUARDED_BY(mFeatureInfoLock);
    615 
    616  mozilla::Atomic<uint32_t> mUVSOffset;
    617 
    618  uint32_t mLanguageOverride = NO_FONT_LANGUAGE_OVERRIDE;
    619 
    620  WeightRange mWeightRange = WeightRange(FontWeight::FromInt(500));
    621  StretchRange mStretchRange = StretchRange(FontStretch::NORMAL);
    622  SlantStyleRange mStyleRange = SlantStyleRange(FontSlantStyle::NORMAL);
    623 
    624  // Font metrics overrides (as multiples of used font size); negative values
    625  // indicate no override to be applied.
    626  float mAscentOverride = -1.0;
    627  float mDescentOverride = -1.0;
    628  float mLineGapOverride = -1.0;
    629 
    630  // Scaling factor to be applied to the font size.
    631  float mSizeAdjust = 1.0;
    632 
    633  // For user fonts (only), we need to record whether or not weight/stretch/
    634  // slant variations should be clamped to the range specified in the entry
    635  // properties. When the @font-face rule omitted one or more of these
    636  // descriptors, it is treated as the initial value for font-matching (and
    637  // so that is what we record in the font entry), but when rendering the
    638  // range is NOT clamped.
    639  enum class RangeFlags : uint16_t {
    640    eNoFlags = 0,
    641    eAutoWeight = (1 << 0),
    642    eAutoStretch = (1 << 1),
    643    eAutoSlantStyle = (1 << 2),
    644 
    645    // Flag to record whether the face has a variable "wght" axis
    646    // that supports "bold" values, used to disable the application
    647    // of synthetic-bold effects.
    648    eBoldVariableWeight = (1 << 3),
    649    // Whether the face has an 'ital' axis.
    650    eItalicVariation = (1 << 4),
    651    // Whether the face has a 'slnt' axis.
    652    eSlantVariation = (1 << 5),
    653 
    654    // Flags to record if the face uses a non-CSS-compatible scale
    655    // for weight and/or stretch, in which case we won't map the
    656    // properties to the variation axes (though they can still be
    657    // explicitly set using font-variation-settings).
    658    eNonCSSWeight = (1 << 6),
    659    eNonCSSStretch = (1 << 7),
    660 
    661    // Whether the font has an 'opsz' axis.
    662    eOpticalSize = (1 << 8)
    663  };
    664  RangeFlags mRangeFlags = RangeFlags::eNoFlags;
    665 
    666  inline RangeFlags AutoRangeFlags() const;
    667 
    668  bool mFixedPitch : 1;
    669  bool mIsBadUnderlineFont : 1;
    670  bool mIsUserFontContainer : 1;  // userfont entry
    671  bool mIsDataUserFont : 1;       // platform font entry (data)
    672  bool mIsLocalUserFont : 1;      // platform font entry (local)
    673  bool mStandardFace : 1;
    674  bool mIgnoreGDEF : 1;
    675  bool mIgnoreGSUB : 1;
    676  bool mSkipDefaultFeatureSpaceCheck : 1;
    677 
    678  mozilla::Atomic<bool> mSVGInitialized;
    679  mozilla::Atomic<bool> mHasCmapTable;
    680  mozilla::Atomic<bool> mGrFaceInitialized;
    681  mozilla::Atomic<bool> mCheckedForColorGlyph;
    682  mozilla::Atomic<bool> mCheckedForVariationAxes;
    683 
    684  // Atomic flags that are lazily evaluated - initially set to UNINITIALIZED,
    685  // changed to NO or YES once we determine the actual value.
    686  enum class LazyFlag : uint8_t { Uninitialized = 0xff, No = 0, Yes = 1 };
    687 
    688  std::atomic<LazyFlag> mSpaceGlyphIsInvisible;
    689  std::atomic<LazyFlag> mHasGraphiteTables;
    690  std::atomic<LazyFlag> mHasGraphiteSpaceContextuals;
    691  std::atomic<LazyFlag> mHasColorBitmapTable;
    692  std::atomic<LazyFlag> mNeedsMaskForShadow;
    693 
    694  enum class SpaceFeatures : uint8_t {
    695    Uninitialized = 0xff,
    696    None = 0,
    697    HasFeatures = 1 << 0,
    698    Kerning = 1 << 1,
    699    NonKerning = 1 << 2
    700  };
    701 
    702  std::atomic<SpaceFeatures> mHasSpaceFeatures;
    703 
    704 protected:
    705  friend class gfxPlatformFontList;
    706  friend class gfxFontFamily;
    707  friend class gfxUserFontEntry;
    708 
    709  // Protected destructor, to discourage deletion outside of Release():
    710  virtual ~gfxFontEntry();
    711 
    712  virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) = 0;
    713 
    714  inline bool CheckForGraphiteTables() {
    715    return HasFontTable(TRUETYPE_TAG('S', 'i', 'l', 'f'));
    716  }
    717 
    718  // Copy a font table into aBuffer.
    719  // The caller will be responsible for ownership of the data.
    720  virtual nsresult CopyFontTable(uint32_t aTableTag,
    721                                 nsTArray<uint8_t>& aBuffer) {
    722    MOZ_ASSERT_UNREACHABLE(
    723        "forgot to override either GetFontTable or "
    724        "CopyFontTable?");
    725    return NS_ERROR_FAILURE;
    726  }
    727 
    728  // Helper for HasTrackingTable; check/parse the table and cache pointers
    729  // to the subtables we need. Returns false on failure, in which case the
    730  // table is unusable.
    731  bool ParseTrakTable() MOZ_REQUIRES(mLock);
    732 
    733  // lookup the cmap in cached font data
    734  virtual already_AddRefed<gfxCharacterMap> GetCMAPFromFontInfo(
    735      FontInfoData* aFontInfoData, uint32_t& aUVSOffset);
    736 
    737  // helper for HasCharacter(), which is what client code should call
    738  virtual bool TestCharacterMap(uint32_t aCh);
    739 
    740  // Try to set mShmemCharacterMap, based on the char map in mShmemFace;
    741  // return true if successful, false if it remains null (maybe the parent
    742  // hasn't handled our SetCharacterMap message yet).
    743  bool TrySetShmemCharacterMap();
    744 
    745  // Helper for gfxPlatformFontList::CreateFontEntry methods: set properties
    746  // of the gfxFontEntry based on shared Face and Family records.
    747  void InitializeFrom(mozilla::fontlist::Face* aFace,
    748                      const mozilla::fontlist::Family* aFamily);
    749 
    750  // Shaper-specific face objects, shared by all instantiations of the same
    751  // physical font, regardless of size.
    752  // Usually, only one of these will actually be created for any given font
    753  // entry, depending on the font tables that are present.
    754 
    755  // hb_face_t is refcounted internally, so each shaper that's using it will
    756  // bump the ref count when it acquires the face, and "destroy" (release) it
    757  // in its destructor. The font entry has only this non-owning reference to
    758  // the face; when the face is deleted, it will tell the font entry to forget
    759  // it, so that a new face will be created next time it is needed.
    760  mozilla::Atomic<hb_face_t*> mHBFace;
    761 
    762  static hb_blob_t* HBGetTable(hb_face_t* face, uint32_t aTag, void* aUserData);
    763 
    764  // Callback that the hb_face will use to tell us when it is being deleted.
    765  static void HBFaceDeletedCallback(void* aUserData);
    766 
    767  // All libGraphite functionality is sandboxed in an rlbox sandbox. This
    768  // contains data for the sandbox instance.
    769  // Currently graphite shaping is only supported on the main thread.
    770  struct GrSandboxData;
    771  GrSandboxData* mSandboxData = nullptr;
    772 
    773  // gr_face is -not- refcounted, so it will be owned directly by the font
    774  // entry, and we'll keep a count of how many references we've handed out;
    775  // each shaper is responsible to call ReleaseGrFace on its entry when
    776  // finished with it, so that we know when it can be deleted.
    777  tainted_opaque_gr<gr_face*> mGrFace;
    778 
    779  // For AAT font, a strong reference to the 'trak' table (if present).
    780  hb_blob_t* const kTrakTableUninitialized = (hb_blob_t*)(intptr_t(-1));
    781  mozilla::Atomic<hb_blob_t*> mTrakTable;
    782  hb_blob_t* GetTrakTable() const { return mTrakTable; }
    783  bool TrakTableInitialized() const {
    784    return mTrakTable != kTrakTableUninitialized;
    785  }
    786 
    787  // Cached pointers to tables within 'trak', initialized by ParseTrakTable.
    788  // This data is inert once loaded, so locking is not required to read it.
    789  const mozilla::AutoSwap_PRInt16* mTrakValues = nullptr;
    790  const mozilla::AutoSwap_PRInt32* mTrakSizeTable = nullptr;
    791 
    792  // number of current users of this entry's mGrFace
    793  nsrefcnt mGrFaceRefCnt = 0;
    794 
    795  friend class gfxFontEntryCallbacks;
    796 
    797  // Font's unitsPerEm from the 'head' table, if available (will be set to
    798  // kInvalidUPEM for non-sfnt font formats)
    799  uint16_t mUnitsPerEm = 0;
    800 
    801  uint16_t mNumTrakSizes = 0;
    802 
    803  // Font extents in FUnits. (To be set from the 'head' table; default to
    804  // "huge" to avoid any clipping if real extents not available.)
    805  int16_t mXMin = std::numeric_limits<int16_t>::min();
    806  int16_t mYMin = std::numeric_limits<int16_t>::min();
    807  int16_t mXMax = std::numeric_limits<int16_t>::max();
    808  int16_t mYMax = std::numeric_limits<int16_t>::max();
    809 
    810 private:
    811  /**
    812   * Font table hashtable, to support GetFontTable for harfbuzz.
    813   *
    814   * The harfbuzz shaper (and potentially other clients) needs access to raw
    815   * font table data. This needs to be cached so that it can be used
    816   * repeatedly (each time we construct a text run; in some cases, for
    817   * each character/glyph within the run) without re-fetching large tables
    818   * every time.
    819   *
    820   * Because we may instantiate many gfxFonts for the same physical font
    821   * file (at different sizes), we should ensure that they can share a
    822   * single cached copy of the font tables. To do this, we implement table
    823   * access and sharing on the fontEntry rather than the font itself.
    824   *
    825   * The default implementation uses GetFontTable() to read font table
    826   * data into byte arrays, and wraps them in blobs which are registered in
    827   * a hashtable.  The hashtable can then return pre-existing blobs to
    828   * harfbuzz.
    829   *
    830   * Harfbuzz will "destroy" the blobs when it is finished with them.  When
    831   * the last blob reference is removed, the FontTableBlobData user data
    832   * will remove the blob from the hashtable if still registered.
    833   */
    834 
    835  class FontTableBlobData;
    836 
    837  /**
    838   * FontTableHashEntry manages the entries of hb_blob_t's containing font
    839   * table data.
    840   *
    841   * This is used to share font tables across fonts with the same
    842   * font entry (but different sizes) for use by HarfBuzz.  The hashtable
    843   * does not own a strong reference to the blob, but keeps a weak pointer,
    844   * managed by FontTableBlobData.  Similarly FontTableBlobData keeps only a
    845   * weak pointer to the hashtable, managed by FontTableHashEntry.
    846   */
    847 
    848  class FontTableHashEntry : public nsUint32HashKey {
    849   public:
    850    // Declarations for nsTHashtable
    851 
    852    typedef nsUint32HashKey KeyClass;
    853    typedef KeyClass::KeyType KeyType;
    854    typedef KeyClass::KeyTypePointer KeyTypePointer;
    855 
    856    explicit FontTableHashEntry(KeyTypePointer aTag)
    857        : KeyClass(aTag), mSharedBlobData(nullptr), mBlob(nullptr) {}
    858 
    859    // NOTE: This assumes the new entry belongs to the same hashtable as
    860    // the old, because the mHashtable pointer in mSharedBlobData (if
    861    // present) will not be updated.
    862    FontTableHashEntry(FontTableHashEntry&& toMove)
    863        : KeyClass(std::move(toMove)),
    864          mSharedBlobData(std::move(toMove.mSharedBlobData)),
    865          mBlob(std::move(toMove.mBlob)) {
    866      toMove.mSharedBlobData = nullptr;
    867      toMove.mBlob = nullptr;
    868    }
    869 
    870    ~FontTableHashEntry() { Clear(); }
    871 
    872    // FontTable/Blob API
    873 
    874    // Transfer (not copy) elements of aTable to a new hb_blob_t and
    875    // return ownership to the caller.  A weak reference to the blob is
    876    // recorded in the font entry's table cache so that others may use
    877    // the same table.
    878    hb_blob_t* ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
    879                                    gfxFontEntry* aFontEntry);
    880 
    881    // Return a strong reference to the blob.
    882    // Callers must hb_blob_destroy the returned blob.
    883    hb_blob_t* GetBlob() const;
    884 
    885    void Clear();
    886 
    887    size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
    888 
    889   private:
    890    static void DeleteFontTableBlobData(void* aBlobData);
    891    // not implemented
    892    FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
    893 
    894    FontTableBlobData* mSharedBlobData;
    895    hb_blob_t* mBlob;
    896  };
    897 
    898  using FontTableCache = nsTHashtable<FontTableHashEntry>;
    899  mozilla::UniquePtr<FontTableCache> mFontTableCache MOZ_GUARDED_BY(mLock);
    900 };
    901 
    902 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontEntry::RangeFlags)
    903 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontEntry::SpaceFeatures)
    904 
    905 inline gfxFontEntry::RangeFlags gfxFontEntry::AutoRangeFlags() const {
    906  return mRangeFlags & (RangeFlags::eAutoWeight | RangeFlags::eAutoStretch |
    907                        RangeFlags::eAutoSlantStyle);
    908 }
    909 
    910 inline bool gfxFontEntry::SupportsItalic() {
    911  return SlantStyle().Max().IsItalic() ||
    912         ((mRangeFlags & RangeFlags::eAutoSlantStyle) ==
    913              RangeFlags::eAutoSlantStyle &&
    914          HasItalicVariation());
    915 }
    916 
    917 inline bool gfxFontEntry::SupportsBold() {
    918  // bold == weights 600 and above
    919  // We return true if the face has a max weight descriptor >= 600,
    920  // OR if it's a user font with auto-weight (no descriptor) and has
    921  // a weight axis that supports values >= 600
    922  return Weight().Max().IsBold() ||
    923         ((mRangeFlags & RangeFlags::eAutoWeight) == RangeFlags::eAutoWeight &&
    924          HasBoldVariableWeight());
    925 }
    926 
    927 inline bool gfxFontEntry::MayUseSyntheticSlant() {
    928  if (!IsUpright()) {
    929    return false;  // The resource is already non-upright.
    930  }
    931  if (HasSlantVariation()) {
    932    if (mRangeFlags & RangeFlags::eAutoSlantStyle) {
    933      return false;
    934    }
    935    if (!SlantStyle().IsSingle()) {
    936      return false;  // The resource has a 'slnt' axis, and has not been
    937                     // clamped to just its upright setting.
    938    }
    939  }
    940  return true;
    941 }
    942 
    943 // used when iterating over all fonts looking for a match for a given character
    944 struct GlobalFontMatch {
    945  GlobalFontMatch(uint32_t aCharacter, uint32_t aNextCh,
    946                  const gfxFontStyle& aStyle, FontPresentation aPresentation)
    947      : mStyle(aStyle),
    948        mCh(aCharacter),
    949        mNextCh(aNextCh),
    950        mPresentation(aPresentation) {}
    951 
    952  RefPtr<gfxFontEntry> mBestMatch;       // current best match
    953  RefPtr<gfxFontFamily> mMatchedFamily;  // the family it belongs to
    954  mozilla::fontlist::Family* mMatchedSharedFamily = nullptr;
    955  const gfxFontStyle& mStyle;  // style to match
    956  const uint32_t mCh;          // codepoint to be matched
    957  const uint32_t mNextCh;      // following codepoint (or zero)
    958  FontPresentation mPresentation;
    959  uint32_t mCount = 0;               // number of fonts matched
    960  uint32_t mCmapsTested = 0;         // number of cmaps tested
    961  double mMatchDistance = INFINITY;  // metric indicating closest match
    962 };
    963 
    964 class gfxFontFamily {
    965 public:
    966  // Used by stylo
    967  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily)
    968 
    969  gfxFontFamily(const nsACString& aName, FontVisibility aVisibility)
    970      : mName(aName),
    971        mLock("gfxFontFamily lock"),
    972        mVisibility(aVisibility),
    973        mIsSimpleFamily(false),
    974        mIsBadUnderlineFamily(false),
    975        mSkipDefaultFeatureSpaceCheck(false),
    976        mCheckForFallbackFaces(false) {}
    977 
    978  const nsCString& Name() const { return mName; }
    979 
    980  virtual void LocalizedName(nsACString& aLocalizedName);
    981  virtual bool HasOtherFamilyNames();
    982 
    983  // See https://bugzilla.mozilla.org/show_bug.cgi?id=835204:
    984  // check the font's 'name' table to see if it has a legacy family name
    985  // that would have been used by GDI (e.g. to split extra-bold or light
    986  // faces in a large family into separate "styled families" because of
    987  // GDI's 4-faces-per-family limitation). If found, the styled family
    988  // name will be added to the font list's "other family names" table.
    989  // Note that the caller must already hold the gfxPlatformFontList lock.
    990  bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList);
    991 
    992  // Callers must hold a read-lock for as long as they're using the list.
    993  const nsTArray<RefPtr<gfxFontEntry>>& GetFontList()
    994      MOZ_REQUIRES_SHARED(mLock) {
    995    return mAvailableFonts;
    996  }
    997  void ReadLock() MOZ_ACQUIRE_SHARED(mLock) { mLock.ReadLock(); }
    998  void ReadUnlock() MOZ_RELEASE_SHARED(mLock) { mLock.ReadUnlock(); }
    999 
   1000  uint32_t FontListLength() const {
   1001    mozilla::AutoReadLock lock(mLock);
   1002    return mAvailableFonts.Length();
   1003  }
   1004 
   1005  void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
   1006    mozilla::AutoWriteLock lock(mLock);
   1007    AddFontEntryLocked(aFontEntry);
   1008  }
   1009 
   1010  void AddFontEntryLocked(RefPtr<gfxFontEntry> aFontEntry) MOZ_REQUIRES(mLock) {
   1011    // Avoid potentially duplicating entries.
   1012    if (mAvailableFonts.Contains(aFontEntry)) {
   1013      return;
   1014    }
   1015    // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
   1016    // of Times New Roman, because of buggy table in those fonts
   1017    if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
   1018        Name().EqualsLiteral("Times New Roman")) {
   1019      aFontEntry->mIgnoreGDEF = true;
   1020    }
   1021    if (aFontEntry->mFamilyName.IsEmpty()) {
   1022      aFontEntry->mFamilyName = Name();
   1023    } else {
   1024      MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name()));
   1025    }
   1026    aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
   1027    mAvailableFonts.AppendElement(aFontEntry);
   1028 
   1029    // If we're adding a face to a family that has been marked as "simple",
   1030    // we need to ensure any null entries are removed, as well as clearing
   1031    // the flag (which may be set again later).
   1032    if (mIsSimpleFamily) {
   1033      mAvailableFonts.RemoveElementsBy([](const auto& font) { return !font; });
   1034      mIsSimpleFamily = false;
   1035    }
   1036  }
   1037 
   1038  // note that the styles for this family have been added
   1039  bool HasStyles() const { return mHasStyles; }
   1040  void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
   1041 
   1042  void SetCheckedForLegacyFamilyNames(bool aChecked) {
   1043    mCheckedForLegacyFamilyNames = aChecked;
   1044  }
   1045 
   1046  // choose a specific face to match a style using CSS font matching
   1047  // rules (weight matching occurs here).  may return a face that doesn't
   1048  // precisely match (e.g. normal face when no italic face exists).
   1049  gfxFontEntry* FindFontForStyle(const gfxFontStyle& aFontStyle,
   1050                                 bool aIgnoreSizeTolerance = false);
   1051 
   1052  virtual void FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
   1053                                    nsTArray<gfxFontEntry*>& aFontEntryList,
   1054                                    bool aIgnoreSizeTolerance = false);
   1055 
   1056  // Checks for a matching font within the family; used as part of the font
   1057  // fallback process.
   1058  // Note that when this is called, the caller must already be holding the
   1059  // gfxPlatformFontList lock.
   1060  void FindFontForChar(GlobalFontMatch* aMatchData);
   1061 
   1062  // checks all fonts for a matching font within the family
   1063  void SearchAllFontsForChar(GlobalFontMatch* aMatchData);
   1064 
   1065  // read in other family names, if any, and use functor to add each into cache
   1066  virtual void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList);
   1067 
   1068  // set when other family names have been read in
   1069  void SetOtherFamilyNamesInitialized() { mOtherFamilyNamesInitialized = true; }
   1070 
   1071  // Read in other localized family names, fullnames and Postscript names
   1072  // for all faces and append to lookup tables.
   1073  // Note that when this is called, the caller must already be holding the
   1074  // gfxPlatformFontList lock.
   1075  virtual void ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
   1076                             bool aNeedFullnamePostscriptNames,
   1077                             FontInfoData* aFontInfoData = nullptr);
   1078 
   1079  // Find faces belonging to this family (platform implementations override).
   1080  // This is a no-op in cases where the family is explicitly populated by other
   1081  // means, rather than being asked to find its faces via system API.
   1082  virtual void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr)
   1083      MOZ_REQUIRES(mLock) {};
   1084  void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) {
   1085    if (mHasStyles) {
   1086      return;
   1087    }
   1088    mozilla::AutoWriteLock lock(mLock);
   1089    FindStyleVariationsLocked(aFontInfoData);
   1090  }
   1091 
   1092  // search for a specific face using the Postscript name
   1093  gfxFontEntry* FindFont(const nsACString& aFontName,
   1094                         const nsCStringComparator& aCmp) const;
   1095 
   1096  // Read in cmaps for all the faces.
   1097  // Note that when this is called, the caller must already be holding the
   1098  // gfxPlatformFontList lock.
   1099  void ReadAllCMAPs(FontInfoData* aFontInfoData = nullptr);
   1100 
   1101  bool TestCharacterMap(uint32_t aCh) {
   1102    if (!mFamilyCharacterMapInitialized) {
   1103      ReadAllCMAPs();
   1104    }
   1105    mozilla::AutoReadLock lock(mLock);
   1106    return mFamilyCharacterMap.test(aCh);
   1107  }
   1108 
   1109  void ResetCharacterMap() MOZ_REQUIRES(mLock) {
   1110    mFamilyCharacterMap.reset();
   1111    mFamilyCharacterMapInitialized = false;
   1112  }
   1113 
   1114  // mark this family as being in the "bad" underline offset blocklist
   1115  void SetBadUnderlineFamily() {
   1116    mozilla::AutoWriteLock lock(mLock);
   1117    mIsBadUnderlineFamily = true;
   1118    if (mHasStyles) {
   1119      SetBadUnderlineFonts();
   1120    }
   1121  }
   1122 
   1123  virtual bool IsSingleFaceFamily() const { return false; }
   1124 
   1125  bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
   1126  bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
   1127 
   1128  // sort available fonts to put preferred (standard) faces towards the end
   1129  void SortAvailableFonts() MOZ_REQUIRES(mLock);
   1130 
   1131  // check whether the family fits into the simple 4-face model,
   1132  // so we can use simplified style-matching;
   1133  // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
   1134  void CheckForSimpleFamily() MOZ_REQUIRES(mLock);
   1135 
   1136  // For memory reporter
   1137  virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   1138                                      FontListSizes* aSizes) const;
   1139  virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
   1140                                      FontListSizes* aSizes) const;
   1141 
   1142 #ifdef DEBUG
   1143  // Only used for debugging checks - does a linear search
   1144  bool ContainsFace(gfxFontEntry* aFontEntry);
   1145 #endif
   1146 
   1147  void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
   1148    mSkipDefaultFeatureSpaceCheck = aSkipCheck;
   1149  }
   1150 
   1151  // Check whether this family is appropriate to include in the Preferences
   1152  // font list for the given langGroup and CSS generic, if the platform lets
   1153  // us determine this.
   1154  // Return true if the family should be included in the list, false to omit.
   1155  // Default implementation returns true for everything, so no filtering
   1156  // will occur; individual platforms may override.
   1157  virtual bool FilterForFontList(nsAtom* aLangGroup,
   1158                                 const nsACString& aGeneric) const {
   1159    return true;
   1160  }
   1161 
   1162  FontVisibility Visibility() const { return mVisibility; }
   1163  bool IsHidden() const { return Visibility() == FontVisibility::Hidden; }
   1164  bool IsWebFontFamily() const {
   1165    return Visibility() == FontVisibility::Webfont;
   1166  }
   1167 
   1168 protected:
   1169  // Protected destructor, to discourage deletion outside of Release():
   1170  virtual ~gfxFontFamily();
   1171 
   1172  bool ReadOtherFamilyNamesForFace(gfxPlatformFontList* aPlatformFontList,
   1173                                   hb_blob_t* aNameTable,
   1174                                   bool useFullName = false);
   1175 
   1176  // set whether this font family is in "bad" underline offset blocklist.
   1177  void SetBadUnderlineFonts() MOZ_REQUIRES(mLock) {
   1178    for (auto& f : mAvailableFonts) {
   1179      if (f) {
   1180        f->mIsBadUnderlineFont = true;
   1181      }
   1182    }
   1183  }
   1184 
   1185  nsCString mName;
   1186  nsTArray<RefPtr<gfxFontEntry>> mAvailableFonts MOZ_GUARDED_BY(mLock);
   1187  gfxSparseBitSet mFamilyCharacterMap MOZ_GUARDED_BY(mLock);
   1188 
   1189  mutable mozilla::RWLock mLock;
   1190 
   1191  FontVisibility mVisibility;
   1192 
   1193  mozilla::Atomic<bool> mOtherFamilyNamesInitialized;
   1194  mozilla::Atomic<bool> mFaceNamesInitialized;
   1195  mozilla::Atomic<bool> mHasStyles;
   1196  mozilla::Atomic<bool> mFamilyCharacterMapInitialized;
   1197  mozilla::Atomic<bool> mCheckedForLegacyFamilyNames;
   1198  mozilla::Atomic<bool> mHasOtherFamilyNames;
   1199 
   1200  bool mIsSimpleFamily : 1 MOZ_GUARDED_BY(mLock);
   1201  bool mIsBadUnderlineFamily : 1;
   1202  bool mSkipDefaultFeatureSpaceCheck : 1;
   1203  bool mCheckForFallbackFaces : 1;  // check other faces for character
   1204 
   1205  enum {
   1206    // for "simple" families, the faces are stored in mAvailableFonts
   1207    // with fixed positions:
   1208    kRegularFaceIndex = 0,
   1209    kBoldFaceIndex = 1,
   1210    kItalicFaceIndex = 2,
   1211    kBoldItalicFaceIndex = 3,
   1212    // mask values for selecting face with bold and/or italic attributes
   1213    kBoldMask = 0x01,
   1214    kItalicMask = 0x02
   1215  };
   1216 };
   1217 
   1218 // Wrapper for either a raw pointer to a mozilla::fontlist::Family in the shared
   1219 // font list or a strong pointer to an unshared gfxFontFamily that belongs just
   1220 // to the current process.
   1221 struct FontFamily {
   1222  FontFamily() = default;
   1223  FontFamily(const FontFamily& aOther) = default;
   1224 
   1225  explicit FontFamily(RefPtr<gfxFontFamily>&& aFamily)
   1226      : mUnshared(std::move(aFamily)) {}
   1227 
   1228  explicit FontFamily(gfxFontFamily* aFamily) : mUnshared(aFamily) {}
   1229 
   1230  explicit FontFamily(mozilla::fontlist::Family* aFamily) : mShared(aFamily) {}
   1231 
   1232  bool operator==(const FontFamily& aOther) const {
   1233    return mShared == aOther.mShared && mUnshared == aOther.mUnshared;
   1234  }
   1235 
   1236  bool IsNull() const { return !mShared && !mUnshared; }
   1237 
   1238  RefPtr<gfxFontFamily> mUnshared;
   1239  mozilla::fontlist::Family* mShared = nullptr;
   1240 };
   1241 
   1242 // Struct used in the gfxFontGroup font list to keep track of a font family
   1243 // together with the CSS generic (if any) that was mapped to it in this
   1244 // particular case (so it can be reported to the DevTools font inspector).
   1245 struct FamilyAndGeneric final {
   1246  FamilyAndGeneric() : mGeneric(mozilla::StyleGenericFontFamily(0)) {}
   1247  FamilyAndGeneric(const FamilyAndGeneric& aOther) = default;
   1248  explicit FamilyAndGeneric(gfxFontFamily* aFamily,
   1249                            mozilla::StyleGenericFontFamily aGeneric =
   1250                                mozilla::StyleGenericFontFamily(0))
   1251      : mFamily(aFamily), mGeneric(aGeneric) {}
   1252  explicit FamilyAndGeneric(RefPtr<gfxFontFamily>&& aFamily,
   1253                            mozilla::StyleGenericFontFamily aGeneric =
   1254                                mozilla::StyleGenericFontFamily(0))
   1255      : mFamily(std::move(aFamily)), mGeneric(aGeneric) {}
   1256  explicit FamilyAndGeneric(mozilla::fontlist::Family* aFamily,
   1257                            mozilla::StyleGenericFontFamily aGeneric =
   1258                                mozilla::StyleGenericFontFamily(0))
   1259      : mFamily(aFamily), mGeneric(aGeneric) {}
   1260  explicit FamilyAndGeneric(const FontFamily& aFamily,
   1261                            mozilla::StyleGenericFontFamily aGeneric =
   1262                                mozilla::StyleGenericFontFamily(0))
   1263      : mFamily(aFamily), mGeneric(aGeneric) {}
   1264 
   1265  bool operator==(const FamilyAndGeneric& aOther) const {
   1266    return mFamily == aOther.mFamily && mGeneric == aOther.mGeneric;
   1267  }
   1268 
   1269  FontFamily mFamily;
   1270  mozilla::StyleGenericFontFamily mGeneric;
   1271 };
   1272 
   1273 #endif