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