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