1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 "gfxTypes.h"
10 #include "nsString.h"
11 #include "gfxFontConstants.h"
12 #include "gfxFontFeatures.h"
13 #include "gfxFontUtils.h"
14 #include "gfxFontVariations.h"
15 #include "nsTArray.h"
16 #include "nsTHashtable.h"
17 #include "mozilla/HashFunctions.h"
18 #include "mozilla/MemoryReporting.h"
19 #include "MainThreadUtils.h"
20 #include "nsUnicodeScriptCodes.h"
21 #include "nsDataHashtable.h"
22 #include "harfbuzz/hb.h"
23 #include "mozilla/gfx/2D.h"
24 #include "mozilla/UniquePtr.h"
25 #include "mozilla/WeakPtr.h"
26 
27 typedef struct gr_face gr_face;
28 
29 #ifdef DEBUG
30 #include <stdio.h>
31 #endif
32 
33 struct gfxFontStyle;
34 class gfxContext;
35 class gfxFont;
36 class gfxFontFamily;
37 class gfxUserFontData;
38 class gfxSVGGlyphs;
39 class FontInfoData;
40 struct FontListSizes;
41 class nsAtom;
42 
43 namespace mozilla {
44 class SVGContextPaint;
45 };
46 
47 class gfxCharacterMap : public gfxSparseBitSet {
48  public:
AddRef()49   nsrefcnt AddRef() {
50     NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
51     ++mRefCnt;
52     NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
53     return mRefCnt;
54   }
55 
Release()56   nsrefcnt Release() {
57     NS_PRECONDITION(0 != mRefCnt, "dup release");
58     --mRefCnt;
59     NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
60     if (mRefCnt == 0) {
61       NotifyReleased();
62       // |this| has been deleted.
63       return 0;
64     }
65     return mRefCnt;
66   }
67 
gfxCharacterMap()68   gfxCharacterMap() : mHash(0), mBuildOnTheFly(false), mShared(false) {}
69 
gfxCharacterMap(const gfxSparseBitSet & aOther)70   explicit gfxCharacterMap(const gfxSparseBitSet& aOther)
71       : gfxSparseBitSet(aOther),
72         mHash(0),
73         mBuildOnTheFly(false),
74         mShared(false) {}
75 
CalcHash()76   void CalcHash() { mHash = GetChecksum(); }
77 
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)78   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
79     return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
80   }
81 
82   // hash of the cmap bitvector
83   uint32_t mHash;
84 
85   // if cmap is built on the fly it's never shared
86   bool mBuildOnTheFly;
87 
88   // cmap is shared globally
89   bool mShared;
90 
91  protected:
92   void NotifyReleased();
93 
94   nsAutoRefCnt mRefCnt;
95 
96  private:
97   gfxCharacterMap(const gfxCharacterMap&);
98   gfxCharacterMap& operator=(const gfxCharacterMap&);
99 };
100 
101 // Info on an individual font feature, for reporting available features
102 // to DevTools via the GetFeatureInfo method.
103 struct gfxFontFeatureInfo {
104   uint32_t mTag;
105   uint32_t mScript;
106   uint32_t mLangSys;
107 };
108 
109 class gfxFontEntry {
110  public:
111   typedef mozilla::gfx::DrawTarget DrawTarget;
112   typedef mozilla::unicode::Script Script;
113 
114   // Used by stylo
115   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry)
116 
117   explicit gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false);
118 
119   // Create a new entry that refers to the same font as this, but without
120   // additional state that may have been set up (such as family name).
121   // (This is only to be used for system fonts in the platform font list,
122   // not user fonts.)
123   virtual gfxFontEntry* Clone() const = 0;
124 
125   // unique name for the face, *not* the family; not necessarily the
126   // "real" or user-friendly name, may be an internal identifier
Name()127   const nsString& Name() const { return mName; }
128 
129   // family name
FamilyName()130   const nsString& FamilyName() const { return mFamilyName; }
131 
132   // The following two methods may be relatively expensive, as they
133   // will (usually, except on Linux) load and parse the 'name' table;
134   // they are intended only for the font-inspection API, not for
135   // perf-critical layout/drawing work.
136 
137   // The "real" name of the face, if available from the font resource;
138   // returns Name() if nothing better is available.
139   virtual nsString RealFaceName();
140 
Weight()141   uint16_t Weight() const { return mWeight; }
Stretch()142   int16_t Stretch() const { return mStretch; }
143 
IsUserFont()144   bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
IsLocalUserFont()145   bool IsLocalUserFont() const { return mIsLocalUserFont; }
IsFixedPitch()146   bool IsFixedPitch() const { return mFixedPitch; }
IsItalic()147   bool IsItalic() const { return mStyle == NS_FONT_STYLE_ITALIC; }
IsOblique()148   bool IsOblique() const { return mStyle == NS_FONT_STYLE_OBLIQUE; }
IsUpright()149   bool IsUpright() const { return mStyle == NS_FONT_STYLE_NORMAL; }
IsBold()150   bool IsBold() const {
151     return mWeight >= 600;
152   }  // bold == weights 600 and above
IgnoreGDEF()153   bool IgnoreGDEF() const { return mIgnoreGDEF; }
IgnoreGSUB()154   bool IgnoreGSUB() const { return mIgnoreGSUB; }
155 
156   // Return whether the face corresponds to "normal" CSS style properties:
157   //    font-style: normal;
158   //    font-weight: normal;
159   //    font-stretch: normal;
160   // If this is false, we might want to fall back to a different face and
161   // possibly apply synthetic styling.
IsNormalStyle()162   bool IsNormalStyle() const {
163     return IsUpright() && Weight() == NS_FONT_WEIGHT_NORMAL &&
164            Stretch() == NS_FONT_STRETCH_NORMAL;
165   }
166 
167   // whether a feature is supported by the font (limited to a small set
168   // of features for which some form of fallback needs to be implemented)
169   virtual bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
170   bool SupportsGraphiteFeature(uint32_t aFeatureTag);
171 
172   // returns a set containing all input glyph ids for a given feature
173   const hb_set_t* InputsForOpenTypeFeature(Script aScript,
174                                            uint32_t aFeatureTag);
175 
176   virtual bool HasFontTable(uint32_t aTableTag);
177 
HasGraphiteTables()178   inline bool HasGraphiteTables() {
179     if (!mCheckedForGraphiteTables) {
180       CheckForGraphiteTables();
181       mCheckedForGraphiteTables = true;
182     }
183     return mHasGraphiteTables;
184   }
185 
HasCmapTable()186   inline bool HasCmapTable() {
187     if (!mCharacterMap) {
188       ReadCMAP();
189       NS_ASSERTION(mCharacterMap, "failed to initialize character map");
190     }
191     return mHasCmapTable;
192   }
193 
HasCharacter(uint32_t ch)194   inline bool HasCharacter(uint32_t ch) {
195     if (mCharacterMap && mCharacterMap->test(ch)) {
196       return true;
197     }
198     return TestCharacterMap(ch);
199   }
200 
SkipDuringSystemFallback()201   virtual bool SkipDuringSystemFallback() { return false; }
202   nsresult InitializeUVSMap();
203   uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS);
204 
205   // All concrete gfxFontEntry subclasses (except gfxUserFontEntry) need
206   // to override this, otherwise the font will never be used as it will
207   // be considered to support no characters.
208   // ReadCMAP() must *always* set the mCharacterMap pointer to a valid
209   // gfxCharacterMap, even if empty, as other code assumes this pointer
210   // can be safely dereferenced.
211   virtual nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr);
212 
213   bool TryGetSVGData(gfxFont* aFont);
214   bool HasSVGGlyph(uint32_t aGlyphId);
215   bool GetSVGGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphId,
216                           gfxFloat aSize, gfxRect* aResult);
217   void RenderSVGGlyph(gfxContext* aContext, uint32_t aGlyphId,
218                       mozilla::SVGContextPaint* aContextPaint);
219   // Call this when glyph geometry or rendering has changed
220   // (e.g. animated SVG glyphs)
221   void NotifyGlyphsChanged();
222 
223   bool TryGetColorGlyphs();
224   bool GetColorLayersInfo(uint32_t aGlyphId,
225                           const mozilla::gfx::Color& aDefaultColor,
226                           nsTArray<uint16_t>& layerGlyphs,
227                           nsTArray<mozilla::gfx::Color>& layerColors);
228 
229   // Access to raw font table data (needed for Harfbuzz):
230   // returns a pointer to data owned by the fontEntry or the OS,
231   // which will remain valid until the blob is destroyed.
232   // The data MUST be treated as read-only; we may be getting a
233   // reference to a shared system font cache.
234   //
235   // The default implementation uses CopyFontTable to get the data
236   // into a byte array, and maintains a cache of loaded tables.
237   //
238   // Subclasses should override this if they can provide more efficient
239   // access than copying table data into our own buffers.
240   //
241   // Get blob that encapsulates a specific font table, or nullptr if
242   // the table doesn't exist in the font.
243   //
244   // Caller is responsible to call hb_blob_destroy() on the returned blob
245   // (if non-nullptr) when no longer required. For transient access to a
246   // table, use of AutoTable (below) is generally preferred.
247   virtual hb_blob_t* GetFontTable(uint32_t aTag);
248 
249   // Stack-based utility to return a specified table, automatically releasing
250   // the blob when the AutoTable goes out of scope.
251   class AutoTable {
252    public:
AutoTable(gfxFontEntry * aFontEntry,uint32_t aTag)253     AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag) {
254       mBlob = aFontEntry->GetFontTable(aTag);
255     }
~AutoTable()256     ~AutoTable() {
257       if (mBlob) {
258         hb_blob_destroy(mBlob);
259       }
260     }
261     operator hb_blob_t*() const { return mBlob; }
262 
263    private:
264     hb_blob_t* mBlob;
265     // not implemented:
266     AutoTable(const AutoTable&) = delete;
267     AutoTable& operator=(const AutoTable&) = delete;
268   };
269 
270   // Return a font instance for a particular style. This may be a newly-
271   // created instance, or a font already in the global cache.
272   // We can't return a UniquePtr here, because we may be returning a shared
273   // cached instance; but we also don't return already_AddRefed, because
274   // the caller may only need to use the font temporarily and doesn't need
275   // a strong reference.
276   gfxFont* FindOrMakeFont(const gfxFontStyle* aStyle, bool aNeedsBold,
277                           gfxCharacterMap* aUnicodeRangeMap = nullptr);
278 
279   // Get an existing font table cache entry in aBlob if it has been
280   // registered, or return false if not.  Callers must call
281   // hb_blob_destroy on aBlob if true is returned.
282   //
283   // Note that some gfxFont implementations may not call this at all,
284   // if it is more efficient to get the table from the OS at that level.
285   bool GetExistingFontTable(uint32_t aTag, hb_blob_t** aBlob);
286 
287   // Elements of aTable are transferred (not copied) to and returned in a
288   // new hb_blob_t which is registered on the gfxFontEntry, but the initial
289   // reference is owned by the caller.  Removing the last reference
290   // unregisters the table from the font entry.
291   //
292   // Pass nullptr for aBuffer to indicate that the table is not present and
293   // nullptr will be returned.  Also returns nullptr on OOM.
294   hb_blob_t* ShareFontTableAndGetBlob(uint32_t aTag, nsTArray<uint8_t>* aTable);
295 
296   // Get the font's unitsPerEm from the 'head' table, in the case of an
297   // sfnt resource. Will return kInvalidUPEM for non-sfnt fonts,
298   // if present on the platform.
299   uint16_t UnitsPerEm();
300   enum {
301     kMinUPEM = 16,     // Limits on valid unitsPerEm range, from the
302     kMaxUPEM = 16384,  // OpenType spec
303     kInvalidUPEM = uint16_t(-1)
304   };
305 
306   // Shaper face accessors:
307   // NOTE that harfbuzz and graphite handle ownership/lifetime of the face
308   // object in completely different ways.
309 
310   // Get HarfBuzz face corresponding to this font file.
311   // Caller must release with hb_face_destroy() when finished with it,
312   // and the font entry will be notified via ForgetHBFace.
313   hb_face_t* GetHBFace();
314   virtual void ForgetHBFace();
315 
316   // Get Graphite face corresponding to this font file.
317   // Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
318   gr_face* GetGrFace();
319   virtual void ReleaseGrFace(gr_face* aFace);
320 
321   // Does the font have graphite contextuals that involve the space glyph
322   // (and therefore we should bypass the word cache)?
323   bool HasGraphiteSpaceContextuals();
324 
325   // Release any SVG-glyphs document this font may have loaded.
326   void DisconnectSVG();
327 
328   // Called to notify that aFont is being destroyed. Needed when we're tracking
329   // the fonts belonging to this font entry.
330   void NotifyFontDestroyed(gfxFont* aFont);
331 
332   // For memory reporting of the platform font list.
333   virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
334                                       FontListSizes* aSizes) const;
335   virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
336                                       FontListSizes* aSizes) const;
337 
338   // Used for reporting on individual font entries in the user font cache,
339   // which are not present in the platform font list.
340   size_t ComputedSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
341 
342   // Used when checking for complex script support, to mask off cmap ranges
343   struct ScriptRange {
344     uint32_t rangeStart;
345     uint32_t rangeEnd;
346     hb_tag_t tags[3];  // one or two OpenType script tags to check,
347                        // plus a NULL terminator
348   };
349 
350   bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags);
351 
352   // For variation font support, which is not yet implemented on all
353   // platforms; default implementations assume it is not present.
HasVariations()354   virtual bool HasVariations() { return false; }
GetVariationAxes(nsTArray<gfxFontVariationAxis> & aVariationAxes)355   virtual void GetVariationAxes(
356       nsTArray<gfxFontVariationAxis>& aVariationAxes) {}
GetVariationInstances(nsTArray<gfxFontVariationInstance> & aInstances)357   virtual void GetVariationInstances(
358       nsTArray<gfxFontVariationInstance>& aInstances) {}
359 
360   // Get the font's list of features (if any) for DevTools support.
361   void GetFeatureInfo(nsTArray<gfxFontFeatureInfo>& aFeatureInfo);
362 
363   nsString mName;
364   nsString mFamilyName;
365 
366   uint8_t mStyle : 2;  // italic/oblique
367   bool mFixedPitch : 1;
368   bool mIsBadUnderlineFont : 1;
369   bool mIsUserFontContainer : 1;  // userfont entry
370   bool mIsDataUserFont : 1;       // platform font entry (data)
371   bool mIsLocalUserFont : 1;      // platform font entry (local)
372   bool mStandardFace : 1;
373   bool mIgnoreGDEF : 1;
374   bool mIgnoreGSUB : 1;
375   bool mSVGInitialized : 1;
376   bool mHasSpaceFeaturesInitialized : 1;
377   bool mHasSpaceFeatures : 1;
378   bool mHasSpaceFeaturesKerning : 1;
379   bool mHasSpaceFeaturesNonKerning : 1;
380   bool mSkipDefaultFeatureSpaceCheck : 1;
381   bool mGraphiteSpaceContextualsInitialized : 1;
382   bool mHasGraphiteSpaceContextuals : 1;
383   bool mSpaceGlyphIsInvisible : 1;
384   bool mSpaceGlyphIsInvisibleInitialized : 1;
385   bool mHasGraphiteTables : 1;
386   bool mCheckedForGraphiteTables : 1;
387   bool mHasCmapTable : 1;
388   bool mGrFaceInitialized : 1;
389   bool mCheckedForColorGlyph : 1;
390 
391   // bitvector of substitution space features per script, one each
392   // for default and non-default features
393   uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
394   uint32_t
395       mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
396 
397   uint16_t mWeight;
398   int16_t mStretch;
399 
400   RefPtr<gfxCharacterMap> mCharacterMap;
401   uint32_t mUVSOffset;
402   mozilla::UniquePtr<uint8_t[]> mUVSData;
403   mozilla::UniquePtr<gfxUserFontData> mUserFontData;
404   mozilla::UniquePtr<gfxSVGGlyphs> mSVGGlyphs;
405   // list of gfxFonts that are using SVG glyphs
406   nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
407   nsTArray<gfxFontFeature> mFeatureSettings;
408   nsTArray<gfxFontVariation> mVariationSettings;
409   mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey, bool>> mSupportedFeatures;
410   mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey, hb_set_t*>>
411       mFeatureInputs;
412   uint32_t mLanguageOverride;
413 
414   // Color Layer font support
415   hb_blob_t* mCOLR;
416   hb_blob_t* mCPAL;
417 
418  protected:
419   friend class gfxPlatformFontList;
420   friend class gfxMacPlatformFontList;
421   friend class gfxUserFcFontEntry;
422   friend class gfxFontFamily;
423   friend class gfxSingleFaceMacFontFamily;
424   friend class gfxUserFontEntry;
425 
426   gfxFontEntry();
427 
428   // Protected destructor, to discourage deletion outside of Release():
429   virtual ~gfxFontEntry();
430 
431   virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle,
432                                       bool aNeedsBold) = 0;
433 
434   virtual void CheckForGraphiteTables();
435 
436   // Copy a font table into aBuffer.
437   // The caller will be responsible for ownership of the data.
CopyFontTable(uint32_t aTableTag,nsTArray<uint8_t> & aBuffer)438   virtual nsresult CopyFontTable(uint32_t aTableTag,
439                                  nsTArray<uint8_t>& aBuffer) {
440     NS_NOTREACHED("forgot to override either GetFontTable or CopyFontTable?");
441     return NS_ERROR_FAILURE;
442   }
443 
444   // lookup the cmap in cached font data
445   virtual already_AddRefed<gfxCharacterMap> GetCMAPFromFontInfo(
446       FontInfoData* aFontInfoData, uint32_t& aUVSOffset);
447 
448   // helper for HasCharacter(), which is what client code should call
449   virtual bool TestCharacterMap(uint32_t aCh);
450 
451   // Font's unitsPerEm from the 'head' table, if available (will be set to
452   // kInvalidUPEM for non-sfnt font formats)
453   uint16_t mUnitsPerEm;
454 
455   // Shaper-specific face objects, shared by all instantiations of the same
456   // physical font, regardless of size.
457   // Usually, only one of these will actually be created for any given font
458   // entry, depending on the font tables that are present.
459 
460   // hb_face_t is refcounted internally, so each shaper that's using it will
461   // bump the ref count when it acquires the face, and "destroy" (release) it
462   // in its destructor. The font entry has only this non-owning reference to
463   // the face; when the face is deleted, it will tell the font entry to forget
464   // it, so that a new face will be created next time it is needed.
465   hb_face_t* mHBFace;
466 
467   static hb_blob_t* HBGetTable(hb_face_t* face, uint32_t aTag, void* aUserData);
468 
469   // Callback that the hb_face will use to tell us when it is being deleted.
470   static void HBFaceDeletedCallback(void* aUserData);
471 
472   // gr_face is -not- refcounted, so it will be owned directly by the font
473   // entry, and we'll keep a count of how many references we've handed out;
474   // each shaper is responsible to call ReleaseGrFace on its entry when
475   // finished with it, so that we know when it can be deleted.
476   gr_face* mGrFace;
477 
478   // hashtable to map raw table data ptr back to its owning blob, for use by
479   // graphite table-release callback
480   nsDataHashtable<nsPtrHashKey<const void>, void*>* mGrTableMap;
481 
482   // number of current users of this entry's mGrFace
483   nsrefcnt mGrFaceRefCnt;
484 
485   static const void* GrGetTable(const void* aAppFaceHandle, unsigned int aName,
486                                 size_t* aLen);
487   static void GrReleaseTable(const void* aAppFaceHandle,
488                              const void* aTableBuffer);
489 
490   // For memory reporting: size of user-font data belonging to this entry.
491   // We record this in the font entry because the actual data block may be
492   // handed over to platform APIs, so that it would become difficult (and
493   // platform-specific) to measure it directly at report-gathering time.
494   uint32_t mComputedSizeOfUserFont;
495 
496  private:
497   /**
498    * Font table hashtable, to support GetFontTable for harfbuzz.
499    *
500    * The harfbuzz shaper (and potentially other clients) needs access to raw
501    * font table data. This needs to be cached so that it can be used
502    * repeatedly (each time we construct a text run; in some cases, for
503    * each character/glyph within the run) without re-fetching large tables
504    * every time.
505    *
506    * Because we may instantiate many gfxFonts for the same physical font
507    * file (at different sizes), we should ensure that they can share a
508    * single cached copy of the font tables. To do this, we implement table
509    * access and sharing on the fontEntry rather than the font itself.
510    *
511    * The default implementation uses GetFontTable() to read font table
512    * data into byte arrays, and wraps them in blobs which are registered in
513    * a hashtable.  The hashtable can then return pre-existing blobs to
514    * harfbuzz.
515    *
516    * Harfbuzz will "destroy" the blobs when it is finished with them.  When
517    * the last blob reference is removed, the FontTableBlobData user data
518    * will remove the blob from the hashtable if still registered.
519    */
520 
521   class FontTableBlobData;
522 
523   /**
524    * FontTableHashEntry manages the entries of hb_blob_t's containing font
525    * table data.
526    *
527    * This is used to share font tables across fonts with the same
528    * font entry (but different sizes) for use by HarfBuzz.  The hashtable
529    * does not own a strong reference to the blob, but keeps a weak pointer,
530    * managed by FontTableBlobData.  Similarly FontTableBlobData keeps only a
531    * weak pointer to the hashtable, managed by FontTableHashEntry.
532    */
533 
534   class FontTableHashEntry : public nsUint32HashKey {
535    public:
536     // Declarations for nsTHashtable
537 
538     typedef nsUint32HashKey KeyClass;
539     typedef KeyClass::KeyType KeyType;
540     typedef KeyClass::KeyTypePointer KeyTypePointer;
541 
FontTableHashEntry(KeyTypePointer aTag)542     explicit FontTableHashEntry(KeyTypePointer aTag)
543         : KeyClass(aTag), mSharedBlobData(nullptr), mBlob(nullptr) {}
544 
545     // NOTE: This assumes the new entry belongs to the same hashtable as
546     // the old, because the mHashtable pointer in mSharedBlobData (if
547     // present) will not be updated.
FontTableHashEntry(FontTableHashEntry && toMove)548     FontTableHashEntry(FontTableHashEntry&& toMove)
549         : KeyClass(mozilla::Move(toMove)),
550           mSharedBlobData(mozilla::Move(toMove.mSharedBlobData)),
551           mBlob(mozilla::Move(toMove.mBlob)) {
552       toMove.mSharedBlobData = nullptr;
553       toMove.mBlob = nullptr;
554     }
555 
~FontTableHashEntry()556     ~FontTableHashEntry() { Clear(); }
557 
558     // FontTable/Blob API
559 
560     // Transfer (not copy) elements of aTable to a new hb_blob_t and
561     // return ownership to the caller.  A weak reference to the blob is
562     // recorded in the hashtable entry so that others may use the same
563     // table.
564     hb_blob_t* ShareTableAndGetBlob(
565         nsTArray<uint8_t>&& aTable,
566         nsTHashtable<FontTableHashEntry>* aHashtable);
567 
568     // Return a strong reference to the blob.
569     // Callers must hb_blob_destroy the returned blob.
570     hb_blob_t* GetBlob() const;
571 
572     void Clear();
573 
574     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
575 
576    private:
577     static void DeleteFontTableBlobData(void* aBlobData);
578     // not implemented
579     FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
580 
581     FontTableBlobData* mSharedBlobData;
582     hb_blob_t* mBlob;
583   };
584 
585   mozilla::UniquePtr<nsTHashtable<FontTableHashEntry>> mFontTableCache;
586 
587   gfxFontEntry(const gfxFontEntry&);
588   gfxFontEntry& operator=(const gfxFontEntry&);
589 };
590 
591 // used when iterating over all fonts looking for a match for a given character
592 struct GlobalFontMatch {
GlobalFontMatchGlobalFontMatch593   GlobalFontMatch(const uint32_t aCharacter, const gfxFontStyle* aStyle)
594       : mCh(aCharacter),
595         mStyle(aStyle),
596         mMatchRank(0),
597         mCount(0),
598         mCmapsTested(0) {}
599 
600   const uint32_t mCh;                    // codepoint to be matched
601   const gfxFontStyle* mStyle;            // style to match
602   int32_t mMatchRank;                    // metric indicating closest match
603   RefPtr<gfxFontEntry> mBestMatch;       // current best match
604   RefPtr<gfxFontFamily> mMatchedFamily;  // the family it belongs to
605   uint32_t mCount;                       // number of fonts matched
606   uint32_t mCmapsTested;                 // number of cmaps tested
607 };
608 
609 class gfxFontFamily {
610  public:
611   // Used by stylo
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily)612   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily)
613 
614   explicit gfxFontFamily(const nsAString& aName)
615       : mName(aName),
616         mOtherFamilyNamesInitialized(false),
617         mHasOtherFamilyNames(false),
618         mFaceNamesInitialized(false),
619         mHasStyles(false),
620         mIsSimpleFamily(false),
621         mIsBadUnderlineFamily(false),
622         mFamilyCharacterMapInitialized(false),
623         mSkipDefaultFeatureSpaceCheck(false),
624         mCheckForFallbackFaces(false),
625         mCheckedForLegacyFamilyNames(false) {}
626 
Name()627   const nsString& Name() { return mName; }
628 
629   virtual void LocalizedName(nsAString& aLocalizedName);
630   virtual bool HasOtherFamilyNames();
631 
632   // See https://bugzilla.mozilla.org/show_bug.cgi?id=835204:
633   // check the font's 'name' table to see if it has a legacy family name
634   // that would have been used by GDI (e.g. to split extra-bold or light
635   // faces in a large family into separate "styled families" because of
636   // GDI's 4-faces-per-family limitation). If found, the styled family
637   // name will be added to the font list's "other family names" table.
638   bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList);
639 
GetFontList()640   nsTArray<RefPtr<gfxFontEntry>>& GetFontList() { return mAvailableFonts; }
641 
AddFontEntry(RefPtr<gfxFontEntry> aFontEntry)642   void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
643     // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
644     // of Times New Roman, because of buggy table in those fonts
645     if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
646         Name().EqualsLiteral("Times New Roman")) {
647       aFontEntry->mIgnoreGDEF = true;
648     }
649     if (aFontEntry->mFamilyName.IsEmpty()) {
650       aFontEntry->mFamilyName = Name();
651     } else {
652       MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name()));
653     }
654     aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
655     mAvailableFonts.AppendElement(aFontEntry);
656 
657     // If we're adding a face to a family that has been marked as "simple",
658     // we need to ensure any null entries are removed, as well as clearing
659     // the flag (which may be set again later).
660     if (mIsSimpleFamily) {
661       for (size_t i = mAvailableFonts.Length() - 1; i-- > 0;) {
662         if (!mAvailableFonts[i]) {
663           mAvailableFonts.RemoveElementAt(i);
664         }
665       }
666       mIsSimpleFamily = false;
667     }
668   }
669 
670   // note that the styles for this family have been added
HasStyles()671   bool HasStyles() { return mHasStyles; }
SetHasStyles(bool aHasStyles)672   void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
673 
674   // choose a specific face to match a style using CSS font matching
675   // rules (weight matching occurs here).  may return a face that doesn't
676   // precisely match (e.g. normal face when no italic face exists).
677   // aNeedsSyntheticBold is set to true when synthetic bolding is
678   // needed, false otherwise
679   gfxFontEntry* FindFontForStyle(const gfxFontStyle& aFontStyle,
680                                  bool& aNeedsSyntheticBold,
681                                  bool aIgnoreSizeTolerance = false);
682 
683   virtual void FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
684                                     nsTArray<gfxFontEntry*>& aFontEntryList,
685                                     bool& aNeedsSyntheticBold,
686                                     bool aIgnoreSizeTolerance = false);
687 
688   // checks for a matching font within the family
689   // used as part of the font fallback process
690   void FindFontForChar(GlobalFontMatch* aMatchData);
691 
692   // checks all fonts for a matching font within the family
693   void SearchAllFontsForChar(GlobalFontMatch* aMatchData);
694 
695   // read in other family names, if any, and use functor to add each into cache
696   virtual void ReadOtherFamilyNames(gfxPlatformFontList* aPlatformFontList);
697 
698   // helper method for reading localized family names from the name table
699   // of a single face
700   static void ReadOtherFamilyNamesForFace(const nsAString& aFamilyName,
701                                           const char* aNameData,
702                                           uint32_t aDataLength,
703                                           nsTArray<nsString>& aOtherFamilyNames,
704                                           bool useFullName);
705 
706   // set when other family names have been read in
SetOtherFamilyNamesInitialized()707   void SetOtherFamilyNamesInitialized() { mOtherFamilyNamesInitialized = true; }
708 
709   // read in other localized family names, fullnames and Postscript names
710   // for all faces and append to lookup tables
711   virtual void ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
712                              bool aNeedFullnamePostscriptNames,
713                              FontInfoData* aFontInfoData = nullptr);
714 
715   // find faces belonging to this family (platform implementations override
716   // this; should be made pure virtual once all subclasses have been updated)
717   virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) {}
718 
719   // search for a specific face using the Postscript name
720   gfxFontEntry* FindFont(const nsAString& aPostscriptName);
721 
722   // read in cmaps for all the faces
723   void ReadAllCMAPs(FontInfoData* aFontInfoData = nullptr);
724 
TestCharacterMap(uint32_t aCh)725   bool TestCharacterMap(uint32_t aCh) {
726     if (!mFamilyCharacterMapInitialized) {
727       ReadAllCMAPs();
728     }
729     return mFamilyCharacterMap.test(aCh);
730   }
731 
ResetCharacterMap()732   void ResetCharacterMap() {
733     mFamilyCharacterMap.reset();
734     mFamilyCharacterMapInitialized = false;
735   }
736 
737   // mark this family as being in the "bad" underline offset blacklist
SetBadUnderlineFamily()738   void SetBadUnderlineFamily() {
739     mIsBadUnderlineFamily = true;
740     if (mHasStyles) {
741       SetBadUnderlineFonts();
742     }
743   }
744 
IsBadUnderlineFamily()745   bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
CheckForFallbackFaces()746   bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
747 
748   // sort available fonts to put preferred (standard) faces towards the end
749   void SortAvailableFonts();
750 
751   // check whether the family fits into the simple 4-face model,
752   // so we can use simplified style-matching;
753   // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
754   void CheckForSimpleFamily();
755 
756   // For memory reporter
757   virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
758                                       FontListSizes* aSizes) const;
759   virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
760                                       FontListSizes* aSizes) const;
761 
762 #ifdef DEBUG
763   // Only used for debugging checks - does a linear search
764   bool ContainsFace(gfxFontEntry* aFontEntry);
765 #endif
766 
SetSkipSpaceFeatureCheck(bool aSkipCheck)767   void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
768     mSkipDefaultFeatureSpaceCheck = aSkipCheck;
769   }
770 
771   // Check whether this family is appropriate to include in the Preferences
772   // font list for the given langGroup and CSS generic, if the platform lets
773   // us determine this.
774   // Return true if the family should be included in the list, false to omit.
775   // Default implementation returns true for everything, so no filtering
776   // will occur; individual platforms may override.
FilterForFontList(nsAtom * aLangGroup,const nsACString & aGeneric)777   virtual bool FilterForFontList(nsAtom* aLangGroup,
778                                  const nsACString& aGeneric) const {
779     return true;
780   }
781 
782  protected:
783   // Protected destructor, to discourage deletion outside of Release():
784   virtual ~gfxFontFamily();
785 
786   bool ReadOtherFamilyNamesForFace(gfxPlatformFontList* aPlatformFontList,
787                                    hb_blob_t* aNameTable,
788                                    bool useFullName = false);
789 
790   // set whether this font family is in "bad" underline offset blacklist.
SetBadUnderlineFonts()791   void SetBadUnderlineFonts() {
792     uint32_t i, numFonts = mAvailableFonts.Length();
793     for (i = 0; i < numFonts; i++) {
794       if (mAvailableFonts[i]) {
795         mAvailableFonts[i]->mIsBadUnderlineFont = true;
796       }
797     }
798   }
799 
800   nsString mName;
801   nsTArray<RefPtr<gfxFontEntry>> mAvailableFonts;
802   gfxSparseBitSet mFamilyCharacterMap;
803   bool mOtherFamilyNamesInitialized : 1;
804   bool mHasOtherFamilyNames : 1;
805   bool mFaceNamesInitialized : 1;
806   bool mHasStyles : 1;
807   bool mIsSimpleFamily : 1;
808   bool mIsBadUnderlineFamily : 1;
809   bool mFamilyCharacterMapInitialized : 1;
810   bool mSkipDefaultFeatureSpaceCheck : 1;
811   bool mCheckForFallbackFaces : 1;  // check other faces for character
812   bool mCheckedForLegacyFamilyNames : 1;
813 
814   enum {
815     // for "simple" families, the faces are stored in mAvailableFonts
816     // with fixed positions:
817     kRegularFaceIndex = 0,
818     kBoldFaceIndex = 1,
819     kItalicFaceIndex = 2,
820     kBoldItalicFaceIndex = 3,
821     // mask values for selecting face with bold and/or italic attributes
822     kBoldMask = 0x01,
823     kItalicMask = 0x02
824   };
825 };
826 
827 #endif
828