Bug 1492908 [wpt PR 13122] - Update wpt metadata, a=testonly
[gecko.git] / gfx / thebes / gfxFontEntry.h
blob55eaf328159b881f09071aaa8b19092b31f1a724
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/. */
6 #ifndef GFX_FONTENTRY_H
7 #define GFX_FONTENTRY_H
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/FontPropertyTypes.h"
24 #include "mozilla/gfx/2D.h"
25 #include "mozilla/UniquePtr.h"
26 #include "mozilla/WeakPtr.h"
27 #include <math.h>
29 typedef struct gr_face gr_face;
30 typedef struct FT_MM_Var_ FT_MM_Var;
32 #ifdef DEBUG
33 #include <stdio.h>
34 #endif
36 struct gfxFontStyle;
37 class gfxContext;
38 class gfxFont;
39 class gfxFontFamily;
40 class gfxUserFontData;
41 class gfxSVGGlyphs;
42 class FontInfoData;
43 struct FontListSizes;
44 class nsAtom;
46 namespace mozilla {
47 class SVGContextPaint;
50 #define NO_FONT_LANGUAGE_OVERRIDE 0
52 class gfxCharacterMap : public gfxSparseBitSet {
53 public:
54 nsrefcnt AddRef() {
55 MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
56 ++mRefCnt;
57 NS_LOG_ADDREF(this, mRefCnt, "gfxCharacterMap", sizeof(*this));
58 return mRefCnt;
61 nsrefcnt Release() {
62 MOZ_ASSERT(0 != mRefCnt, "dup release");
63 --mRefCnt;
64 NS_LOG_RELEASE(this, mRefCnt, "gfxCharacterMap");
65 if (mRefCnt == 0) {
66 NotifyReleased();
67 // |this| has been deleted.
68 return 0;
70 return mRefCnt;
73 gfxCharacterMap() :
74 mHash(0), mBuildOnTheFly(false), mShared(false)
75 { }
77 explicit gfxCharacterMap(const gfxSparseBitSet& aOther) :
78 gfxSparseBitSet(aOther),
79 mHash(0), mBuildOnTheFly(false), mShared(false)
80 { }
82 void CalcHash() { mHash = GetChecksum(); }
84 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
85 return gfxSparseBitSet::SizeOfExcludingThis(aMallocSizeOf);
88 // hash of the cmap bitvector
89 uint32_t mHash;
91 // if cmap is built on the fly it's never shared
92 bool mBuildOnTheFly;
94 // cmap is shared globally
95 bool mShared;
97 protected:
98 void NotifyReleased();
100 nsAutoRefCnt mRefCnt;
102 private:
103 gfxCharacterMap(const gfxCharacterMap&);
104 gfxCharacterMap& operator=(const gfxCharacterMap&);
107 // Info on an individual font feature, for reporting available features
108 // to DevTools via the GetFeatureInfo method.
109 struct gfxFontFeatureInfo {
110 uint32_t mTag;
111 uint32_t mScript;
112 uint32_t mLangSys;
115 class gfxFontEntry {
116 public:
117 typedef mozilla::gfx::DrawTarget DrawTarget;
118 typedef mozilla::unicode::Script Script;
119 typedef mozilla::FontWeight FontWeight;
120 typedef mozilla::FontSlantStyle FontSlantStyle;
121 typedef mozilla::FontStretch FontStretch;
122 typedef mozilla::WeightRange WeightRange;
123 typedef mozilla::SlantStyleRange SlantStyleRange;
124 typedef mozilla::StretchRange StretchRange;
126 // Used by stylo
127 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry)
129 explicit gfxFontEntry(const nsACString& aName, bool aIsStandardFace = false);
131 // Create a new entry that refers to the same font as this, but without
132 // additional state that may have been set up (such as family name).
133 // (This is only to be used for system fonts in the platform font list,
134 // not user fonts.)
135 virtual gfxFontEntry* Clone() const = 0;
137 // unique name for the face, *not* the family; not necessarily the
138 // "real" or user-friendly name, may be an internal identifier
139 const nsCString& Name() const { return mName; }
141 // family name
142 const nsCString& FamilyName() const { return mFamilyName; }
144 // The following two methods may be relatively expensive, as they
145 // will (usually, except on Linux) load and parse the 'name' table;
146 // they are intended only for the font-inspection API, not for
147 // perf-critical layout/drawing work.
149 // The "real" name of the face, if available from the font resource;
150 // returns Name() if nothing better is available.
151 virtual nsCString RealFaceName();
153 WeightRange Weight() const { return mWeightRange; }
154 StretchRange Stretch() const { return mStretchRange; }
155 SlantStyleRange SlantStyle() const { return mStyleRange; }
157 bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; }
158 bool IsLocalUserFont() const { return mIsLocalUserFont; }
159 bool IsFixedPitch() const { return mFixedPitch; }
160 bool IsItalic() const { return SlantStyle().Min().IsItalic(); }
161 bool IsOblique() const { return SlantStyle().Min().IsOblique(); }
162 bool IsUpright() const { return SlantStyle().Min().IsNormal(); }
163 inline bool SupportsItalic();
164 inline bool SupportsBold(); // defined below, because of RangeFlags use
165 bool IgnoreGDEF() const { return mIgnoreGDEF; }
166 bool IgnoreGSUB() const { return mIgnoreGSUB; }
168 // Return whether the face corresponds to "normal" CSS style properties:
169 // font-style: normal;
170 // font-weight: normal;
171 // font-stretch: normal;
172 // If this is false, we might want to fall back to a different face and
173 // possibly apply synthetic styling.
174 bool IsNormalStyle() const
176 return IsUpright() &&
177 Weight().Min() <= FontWeight::Normal() &&
178 Weight().Max() >= FontWeight::Normal() &&
179 Stretch().Min() <= FontStretch::Normal() &&
180 Stretch().Max() >= FontStretch::Normal();
183 // whether a feature is supported by the font (limited to a small set
184 // of features for which some form of fallback needs to be implemented)
185 virtual bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
186 bool SupportsGraphiteFeature(uint32_t aFeatureTag);
188 // returns a set containing all input glyph ids for a given feature
189 const hb_set_t*
190 InputsForOpenTypeFeature(Script aScript, uint32_t aFeatureTag);
192 virtual bool HasFontTable(uint32_t aTableTag);
194 inline bool HasGraphiteTables() {
195 if (!mCheckedForGraphiteTables) {
196 CheckForGraphiteTables();
197 mCheckedForGraphiteTables = true;
199 return mHasGraphiteTables;
202 inline bool HasCmapTable() {
203 if (!mCharacterMap) {
204 ReadCMAP();
205 NS_ASSERTION(mCharacterMap, "failed to initialize character map");
207 return mHasCmapTable;
210 inline bool HasCharacter(uint32_t ch) {
211 if (mCharacterMap && mCharacterMap->test(ch)) {
212 return true;
214 return TestCharacterMap(ch);
217 virtual bool SkipDuringSystemFallback() { return false; }
218 nsresult InitializeUVSMap();
219 uint16_t GetUVSGlyph(uint32_t aCh, uint32_t aVS);
221 // All concrete gfxFontEntry subclasses (except gfxUserFontEntry) need
222 // to override this, otherwise the font will never be used as it will
223 // be considered to support no characters.
224 // ReadCMAP() must *always* set the mCharacterMap pointer to a valid
225 // gfxCharacterMap, even if empty, as other code assumes this pointer
226 // can be safely dereferenced.
227 virtual nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
229 bool TryGetSVGData(gfxFont* aFont);
230 bool HasSVGGlyph(uint32_t aGlyphId);
231 bool GetSVGGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphId,
232 gfxFloat aSize, gfxRect* aResult);
233 void RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId,
234 mozilla::SVGContextPaint* aContextPaint);
235 // Call this when glyph geometry or rendering has changed
236 // (e.g. animated SVG glyphs)
237 void NotifyGlyphsChanged();
239 bool TryGetColorGlyphs();
240 bool GetColorLayersInfo(uint32_t aGlyphId,
241 const mozilla::gfx::Color& aDefaultColor,
242 nsTArray<uint16_t>& layerGlyphs,
243 nsTArray<mozilla::gfx::Color>& layerColors);
245 // Access to raw font table data (needed for Harfbuzz):
246 // returns a pointer to data owned by the fontEntry or the OS,
247 // which will remain valid until the blob is destroyed.
248 // The data MUST be treated as read-only; we may be getting a
249 // reference to a shared system font cache.
251 // The default implementation uses CopyFontTable to get the data
252 // into a byte array, and maintains a cache of loaded tables.
254 // Subclasses should override this if they can provide more efficient
255 // access than copying table data into our own buffers.
257 // Get blob that encapsulates a specific font table, or nullptr if
258 // the table doesn't exist in the font.
260 // Caller is responsible to call hb_blob_destroy() on the returned blob
261 // (if non-nullptr) when no longer required. For transient access to a
262 // table, use of AutoTable (below) is generally preferred.
263 virtual hb_blob_t *GetFontTable(uint32_t aTag);
265 // Stack-based utility to return a specified table, automatically releasing
266 // the blob when the AutoTable goes out of scope.
267 class AutoTable {
268 public:
269 AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag)
271 mBlob = aFontEntry->GetFontTable(aTag);
273 ~AutoTable() {
274 if (mBlob) {
275 hb_blob_destroy(mBlob);
278 operator hb_blob_t*() const { return mBlob; }
279 private:
280 hb_blob_t* mBlob;
281 // not implemented:
282 AutoTable(const AutoTable&) = delete;
283 AutoTable& operator=(const AutoTable&) = delete;
286 // Return a font instance for a particular style. This may be a newly-
287 // created instance, or a font already in the global cache.
288 // We can't return a UniquePtr here, because we may be returning a shared
289 // cached instance; but we also don't return already_AddRefed, because
290 // the caller may only need to use the font temporarily and doesn't need
291 // a strong reference.
292 gfxFont* FindOrMakeFont(const gfxFontStyle *aStyle,
293 gfxCharacterMap* aUnicodeRangeMap = nullptr);
295 // Get an existing font table cache entry in aBlob if it has been
296 // registered, or return false if not. Callers must call
297 // hb_blob_destroy on aBlob if true is returned.
299 // Note that some gfxFont implementations may not call this at all,
300 // if it is more efficient to get the table from the OS at that level.
301 bool GetExistingFontTable(uint32_t aTag, hb_blob_t** aBlob);
303 // Elements of aTable are transferred (not copied) to and returned in a
304 // new hb_blob_t which is registered on the gfxFontEntry, but the initial
305 // reference is owned by the caller. Removing the last reference
306 // unregisters the table from the font entry.
308 // Pass nullptr for aBuffer to indicate that the table is not present and
309 // nullptr will be returned. Also returns nullptr on OOM.
310 hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
311 nsTArray<uint8_t>* aTable);
313 // Get the font's unitsPerEm from the 'head' table, in the case of an
314 // sfnt resource. Will return kInvalidUPEM for non-sfnt fonts,
315 // if present on the platform.
316 uint16_t UnitsPerEm();
317 enum {
318 kMinUPEM = 16, // Limits on valid unitsPerEm range, from the
319 kMaxUPEM = 16384, // OpenType spec
320 kInvalidUPEM = uint16_t(-1)
323 // Shaper face accessors:
324 // NOTE that harfbuzz and graphite handle ownership/lifetime of the face
325 // object in completely different ways.
327 // Get HarfBuzz face corresponding to this font file.
328 // Caller must release with hb_face_destroy() when finished with it,
329 // and the font entry will be notified via ForgetHBFace.
330 hb_face_t* GetHBFace();
331 virtual void ForgetHBFace();
333 // Get Graphite face corresponding to this font file.
334 // Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
335 gr_face* GetGrFace();
336 virtual void ReleaseGrFace(gr_face* aFace);
338 // Does the font have graphite contextuals that involve the space glyph
339 // (and therefore we should bypass the word cache)?
340 bool HasGraphiteSpaceContextuals();
342 // Release any SVG-glyphs document this font may have loaded.
343 void DisconnectSVG();
345 // Called to notify that aFont is being destroyed. Needed when we're tracking
346 // the fonts belonging to this font entry.
347 void NotifyFontDestroyed(gfxFont* aFont);
349 // For memory reporting of the platform font list.
350 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
351 FontListSizes* aSizes) const;
352 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
353 FontListSizes* aSizes) const;
355 // Used for reporting on individual font entries in the user font cache,
356 // which are not present in the platform font list.
357 size_t
358 ComputedSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
360 // Used when checking for complex script support, to mask off cmap ranges
361 struct ScriptRange {
362 uint32_t rangeStart;
363 uint32_t rangeEnd;
364 hb_tag_t tags[3]; // one or two OpenType script tags to check,
365 // plus a NULL terminator
368 bool SupportsScriptInGSUB(const hb_tag_t* aScriptTags);
371 * Font-variation query methods.
373 * Font backends that don't support variations should provide empty
374 * implementations.
376 virtual bool HasVariations() = 0;
378 virtual void
379 GetVariationAxes(nsTArray<gfxFontVariationAxis>& aVariationAxes) = 0;
381 virtual void
382 GetVariationInstances(nsTArray<gfxFontVariationInstance>& aInstances) = 0;
384 bool HasBoldVariableWeight();
385 bool HasItalicVariation();
386 void CheckForVariationAxes();
388 // Set up the entry's weight/stretch/style ranges according to axes found
389 // by GetVariationAxes (for installed fonts; do NOT call this for user
390 // fonts, where the ranges are provided by @font-face descriptors).
391 void SetupVariationRanges();
393 // Get variation axis settings that should be used to implement a particular
394 // font style using this resource.
395 void GetVariationsForStyle(nsTArray<gfxFontVariation>& aResult,
396 const gfxFontStyle& aStyle);
398 // Get the font's list of features (if any) for DevTools support.
399 void GetFeatureInfo(nsTArray<gfxFontFeatureInfo>& aFeatureInfo);
401 // This is only called on platforms where we use FreeType.
402 virtual FT_MM_Var* GetMMVar() { return nullptr; }
404 nsCString mName;
405 nsCString mFamilyName;
407 RefPtr<gfxCharacterMap> mCharacterMap;
409 mozilla::UniquePtr<uint8_t[]> mUVSData;
410 mozilla::UniquePtr<gfxUserFontData> mUserFontData;
411 mozilla::UniquePtr<gfxSVGGlyphs> mSVGGlyphs;
412 // list of gfxFonts that are using SVG glyphs
413 nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
414 nsTArray<gfxFontFeature> mFeatureSettings;
415 nsTArray<gfxFontVariation> mVariationSettings;
416 mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,bool>> mSupportedFeatures;
417 mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,hb_set_t*>> mFeatureInputs;
419 // Color Layer font support
420 hb_blob_t* mCOLR = nullptr;
421 hb_blob_t* mCPAL = nullptr;
423 // bitvector of substitution space features per script, one each
424 // for default and non-default features
425 uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
426 uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32];
428 uint32_t mUVSOffset = 0;
430 uint32_t mLanguageOverride = NO_FONT_LANGUAGE_OVERRIDE;
432 WeightRange mWeightRange = WeightRange(FontWeight(500));
433 StretchRange mStretchRange = StretchRange(FontStretch::Normal());
434 SlantStyleRange mStyleRange = SlantStyleRange(FontSlantStyle::Normal());
436 // For user fonts (only), we need to record whether or not weight/stretch/
437 // slant variations should be clamped to the range specified in the entry
438 // properties. When the @font-face rule omitted one or more of these
439 // descriptors, it is treated as the initial value for font-matching (and
440 // so that is what we record in the font entry), but when rendering the
441 // range is NOT clamped.
442 enum class RangeFlags : uint8_t {
443 eNoFlags = 0,
444 eAutoWeight = (1 << 0),
445 eAutoStretch = (1 << 1),
446 eAutoSlantStyle = (1 << 2),
448 // Flag to record whether the face has a variable "wght" axis
449 // that supports "bold" values, used to disable the application
450 // of synthetic-bold effects.
451 eBoldVariableWeight = (1 << 3),
452 // Whether the face has an 'ital' axis.
453 eItalicVariation = (1 << 4),
455 // Flags to record if the face uses a non-CSS-compatible scale
456 // for weight and/or stretch, in which case we won't map the
457 // properties to the variation axes (though they can still be
458 // explicitly set using font-variation-settings).
459 eNonCSSWeight = (1 << 5),
460 eNonCSSStretch = (1 << 6)
462 RangeFlags mRangeFlags = RangeFlags::eNoFlags;
464 // NOTE that there are currently exactly 24 one-bit flags defined here,
465 // so together with the 8-bit RangeFlags above, this packs neatly to a
466 // 32-bit boundary. Worth considering if further flags are wanted.
467 bool mFixedPitch : 1;
468 bool mIsBadUnderlineFont : 1;
469 bool mIsUserFontContainer : 1; // userfont entry
470 bool mIsDataUserFont : 1; // platform font entry (data)
471 bool mIsLocalUserFont : 1; // platform font entry (local)
472 bool mStandardFace : 1;
473 bool mIgnoreGDEF : 1;
474 bool mIgnoreGSUB : 1;
475 bool mSVGInitialized : 1;
476 bool mHasSpaceFeaturesInitialized : 1;
477 bool mHasSpaceFeatures : 1;
478 bool mHasSpaceFeaturesKerning : 1;
479 bool mHasSpaceFeaturesNonKerning : 1;
480 bool mSkipDefaultFeatureSpaceCheck : 1;
481 bool mGraphiteSpaceContextualsInitialized : 1;
482 bool mHasGraphiteSpaceContextuals : 1;
483 bool mSpaceGlyphIsInvisible : 1;
484 bool mSpaceGlyphIsInvisibleInitialized : 1;
485 bool mHasGraphiteTables : 1;
486 bool mCheckedForGraphiteTables : 1;
487 bool mHasCmapTable : 1;
488 bool mGrFaceInitialized : 1;
489 bool mCheckedForColorGlyph : 1;
490 bool mCheckedForVariationAxes : 1;
492 protected:
493 friend class gfxPlatformFontList;
494 friend class gfxMacPlatformFontList;
495 friend class gfxUserFcFontEntry;
496 friend class gfxFontFamily;
497 friend class gfxSingleFaceMacFontFamily;
498 friend class gfxUserFontEntry;
500 gfxFontEntry();
502 // Protected destructor, to discourage deletion outside of Release():
503 virtual ~gfxFontEntry();
505 virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle) = 0;
507 virtual void CheckForGraphiteTables();
509 // Copy a font table into aBuffer.
510 // The caller will be responsible for ownership of the data.
511 virtual nsresult CopyFontTable(uint32_t aTableTag,
512 nsTArray<uint8_t>& aBuffer) {
513 MOZ_ASSERT_UNREACHABLE("forgot to override either GetFontTable or "
514 "CopyFontTable?");
515 return NS_ERROR_FAILURE;
518 // lookup the cmap in cached font data
519 virtual already_AddRefed<gfxCharacterMap>
520 GetCMAPFromFontInfo(FontInfoData *aFontInfoData,
521 uint32_t& aUVSOffset);
523 // helper for HasCharacter(), which is what client code should call
524 virtual bool TestCharacterMap(uint32_t aCh);
526 // Shaper-specific face objects, shared by all instantiations of the same
527 // physical font, regardless of size.
528 // Usually, only one of these will actually be created for any given font
529 // entry, depending on the font tables that are present.
531 // hb_face_t is refcounted internally, so each shaper that's using it will
532 // bump the ref count when it acquires the face, and "destroy" (release) it
533 // in its destructor. The font entry has only this non-owning reference to
534 // the face; when the face is deleted, it will tell the font entry to forget
535 // it, so that a new face will be created next time it is needed.
536 hb_face_t* mHBFace = nullptr;
538 static hb_blob_t* HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData);
540 // Callback that the hb_face will use to tell us when it is being deleted.
541 static void HBFaceDeletedCallback(void *aUserData);
543 // gr_face is -not- refcounted, so it will be owned directly by the font
544 // entry, and we'll keep a count of how many references we've handed out;
545 // each shaper is responsible to call ReleaseGrFace on its entry when
546 // finished with it, so that we know when it can be deleted.
547 gr_face* mGrFace = nullptr;
549 // hashtable to map raw table data ptr back to its owning blob, for use by
550 // graphite table-release callback
551 nsDataHashtable<nsPtrHashKey<const void>,void*>* mGrTableMap = nullptr;
553 // number of current users of this entry's mGrFace
554 nsrefcnt mGrFaceRefCnt = 0;
556 static const void* GrGetTable(const void *aAppFaceHandle,
557 unsigned int aName,
558 size_t *aLen);
559 static void GrReleaseTable(const void *aAppFaceHandle,
560 const void *aTableBuffer);
562 // For memory reporting: size of user-font data belonging to this entry.
563 // We record this in the font entry because the actual data block may be
564 // handed over to platform APIs, so that it would become difficult (and
565 // platform-specific) to measure it directly at report-gathering time.
566 uint32_t mComputedSizeOfUserFont = 0;
568 // Font's unitsPerEm from the 'head' table, if available (will be set to
569 // kInvalidUPEM for non-sfnt font formats)
570 uint16_t mUnitsPerEm = 0;
572 private:
574 * Font table hashtable, to support GetFontTable for harfbuzz.
576 * The harfbuzz shaper (and potentially other clients) needs access to raw
577 * font table data. This needs to be cached so that it can be used
578 * repeatedly (each time we construct a text run; in some cases, for
579 * each character/glyph within the run) without re-fetching large tables
580 * every time.
582 * Because we may instantiate many gfxFonts for the same physical font
583 * file (at different sizes), we should ensure that they can share a
584 * single cached copy of the font tables. To do this, we implement table
585 * access and sharing on the fontEntry rather than the font itself.
587 * The default implementation uses GetFontTable() to read font table
588 * data into byte arrays, and wraps them in blobs which are registered in
589 * a hashtable. The hashtable can then return pre-existing blobs to
590 * harfbuzz.
592 * Harfbuzz will "destroy" the blobs when it is finished with them. When
593 * the last blob reference is removed, the FontTableBlobData user data
594 * will remove the blob from the hashtable if still registered.
597 class FontTableBlobData;
600 * FontTableHashEntry manages the entries of hb_blob_t's containing font
601 * table data.
603 * This is used to share font tables across fonts with the same
604 * font entry (but different sizes) for use by HarfBuzz. The hashtable
605 * does not own a strong reference to the blob, but keeps a weak pointer,
606 * managed by FontTableBlobData. Similarly FontTableBlobData keeps only a
607 * weak pointer to the hashtable, managed by FontTableHashEntry.
610 class FontTableHashEntry : public nsUint32HashKey
612 public:
613 // Declarations for nsTHashtable
615 typedef nsUint32HashKey KeyClass;
616 typedef KeyClass::KeyType KeyType;
617 typedef KeyClass::KeyTypePointer KeyTypePointer;
619 explicit FontTableHashEntry(KeyTypePointer aTag)
620 : KeyClass(aTag)
621 , mSharedBlobData(nullptr)
622 , mBlob(nullptr)
625 // NOTE: This assumes the new entry belongs to the same hashtable as
626 // the old, because the mHashtable pointer in mSharedBlobData (if
627 // present) will not be updated.
628 FontTableHashEntry(FontTableHashEntry&& toMove)
629 : KeyClass(std::move(toMove))
630 , mSharedBlobData(std::move(toMove.mSharedBlobData))
631 , mBlob(std::move(toMove.mBlob))
633 toMove.mSharedBlobData = nullptr;
634 toMove.mBlob = nullptr;
637 ~FontTableHashEntry() { Clear(); }
639 // FontTable/Blob API
641 // Transfer (not copy) elements of aTable to a new hb_blob_t and
642 // return ownership to the caller. A weak reference to the blob is
643 // recorded in the hashtable entry so that others may use the same
644 // table.
645 hb_blob_t *
646 ShareTableAndGetBlob(nsTArray<uint8_t>&& aTable,
647 nsTHashtable<FontTableHashEntry> *aHashtable);
649 // Return a strong reference to the blob.
650 // Callers must hb_blob_destroy the returned blob.
651 hb_blob_t *GetBlob() const;
653 void Clear();
655 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
657 private:
658 static void DeleteFontTableBlobData(void *aBlobData);
659 // not implemented
660 FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
662 FontTableBlobData *mSharedBlobData;
663 hb_blob_t *mBlob;
666 mozilla::UniquePtr<nsTHashtable<FontTableHashEntry> > mFontTableCache;
668 gfxFontEntry(const gfxFontEntry&);
669 gfxFontEntry& operator=(const gfxFontEntry&);
672 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(gfxFontEntry::RangeFlags)
674 inline bool
675 gfxFontEntry::SupportsItalic()
677 return SlantStyle().Max().IsItalic() ||
678 ((mRangeFlags & RangeFlags::eAutoSlantStyle) ==
679 RangeFlags::eAutoSlantStyle &&
680 HasItalicVariation());
683 inline bool
684 gfxFontEntry::SupportsBold()
686 // bold == weights 600 and above
687 // We return true if the face has a max weight descriptor >= 600,
688 // OR if it's a user font with auto-weight (no descriptor) and has
689 // a weight axis that supports values >= 600
690 return Weight().Max().IsBold() ||
691 ((mRangeFlags & RangeFlags::eAutoWeight) ==
692 RangeFlags::eAutoWeight &&
693 HasBoldVariableWeight());
696 // used when iterating over all fonts looking for a match for a given character
697 struct GlobalFontMatch {
698 GlobalFontMatch(const uint32_t aCharacter,
699 const gfxFontStyle& aStyle) :
700 mStyle(aStyle), mCh(aCharacter),
701 mCount(0), mCmapsTested(0), mMatchDistance(INFINITY)
705 RefPtr<gfxFontEntry> mBestMatch; // current best match
706 RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
707 const gfxFontStyle& mStyle; // style to match
708 const uint32_t mCh; // codepoint to be matched
709 uint32_t mCount; // number of fonts matched
710 uint32_t mCmapsTested; // number of cmaps tested
711 float mMatchDistance; // metric indicating closest match
714 class gfxFontFamily {
715 public:
716 // Used by stylo
717 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily)
719 explicit gfxFontFamily(const nsACString& aName) :
720 mName(aName),
721 mOtherFamilyNamesInitialized(false),
722 mHasOtherFamilyNames(false),
723 mFaceNamesInitialized(false),
724 mHasStyles(false),
725 mIsSimpleFamily(false),
726 mIsBadUnderlineFamily(false),
727 mFamilyCharacterMapInitialized(false),
728 mSkipDefaultFeatureSpaceCheck(false),
729 mCheckForFallbackFaces(false),
730 mCheckedForLegacyFamilyNames(false)
733 const nsCString& Name() { return mName; }
735 virtual void LocalizedName(nsACString& aLocalizedName);
736 virtual bool HasOtherFamilyNames();
738 // See https://bugzilla.mozilla.org/show_bug.cgi?id=835204:
739 // check the font's 'name' table to see if it has a legacy family name
740 // that would have been used by GDI (e.g. to split extra-bold or light
741 // faces in a large family into separate "styled families" because of
742 // GDI's 4-faces-per-family limitation). If found, the styled family
743 // name will be added to the font list's "other family names" table.
744 bool CheckForLegacyFamilyNames(gfxPlatformFontList* aFontList);
746 nsTArray<RefPtr<gfxFontEntry> >& GetFontList() { return mAvailableFonts; }
748 void AddFontEntry(RefPtr<gfxFontEntry> aFontEntry) {
749 // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
750 // of Times New Roman, because of buggy table in those fonts
751 if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
752 Name().EqualsLiteral("Times New Roman"))
754 aFontEntry->mIgnoreGDEF = true;
756 if (aFontEntry->mFamilyName.IsEmpty()) {
757 aFontEntry->mFamilyName = Name();
758 } else {
759 MOZ_ASSERT(aFontEntry->mFamilyName.Equals(Name()));
761 aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
762 mAvailableFonts.AppendElement(aFontEntry);
764 // If we're adding a face to a family that has been marked as "simple",
765 // we need to ensure any null entries are removed, as well as clearing
766 // the flag (which may be set again later).
767 if (mIsSimpleFamily) {
768 for (size_t i = mAvailableFonts.Length() - 1; i-- > 0; ) {
769 if (!mAvailableFonts[i]) {
770 mAvailableFonts.RemoveElementAt(i);
773 mIsSimpleFamily = false;
777 // note that the styles for this family have been added
778 bool HasStyles() { return mHasStyles; }
779 void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
781 // choose a specific face to match a style using CSS font matching
782 // rules (weight matching occurs here). may return a face that doesn't
783 // precisely match (e.g. normal face when no italic face exists).
784 gfxFontEntry *FindFontForStyle(const gfxFontStyle& aFontStyle,
785 bool aIgnoreSizeTolerance = false);
787 virtual void
788 FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
789 nsTArray<gfxFontEntry*>& aFontEntryList,
790 bool aIgnoreSizeTolerance = false);
792 // checks for a matching font within the family
793 // used as part of the font fallback process
794 void FindFontForChar(GlobalFontMatch* aMatchData);
796 // checks all fonts for a matching font within the family
797 void SearchAllFontsForChar(GlobalFontMatch* aMatchData);
799 // read in other family names, if any, and use functor to add each into cache
800 virtual void ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList);
802 // helper method for reading localized family names from the name table
803 // of a single face
804 static void ReadOtherFamilyNamesForFace(const nsACString& aFamilyName,
805 const char *aNameData,
806 uint32_t aDataLength,
807 nsTArray<nsCString>& aOtherFamilyNames,
808 bool useFullName);
810 // set when other family names have been read in
811 void SetOtherFamilyNamesInitialized() {
812 mOtherFamilyNamesInitialized = true;
815 // read in other localized family names, fullnames and Postscript names
816 // for all faces and append to lookup tables
817 virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
818 bool aNeedFullnamePostscriptNames,
819 FontInfoData *aFontInfoData = nullptr);
821 // find faces belonging to this family (platform implementations override this;
822 // should be made pure virtual once all subclasses have been updated)
823 virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) { }
825 // search for a specific face using the Postscript name
826 gfxFontEntry* FindFont(const nsACString& aPostscriptName);
828 // read in cmaps for all the faces
829 void ReadAllCMAPs(FontInfoData *aFontInfoData = nullptr);
831 bool TestCharacterMap(uint32_t aCh) {
832 if (!mFamilyCharacterMapInitialized) {
833 ReadAllCMAPs();
835 return mFamilyCharacterMap.test(aCh);
838 void ResetCharacterMap() {
839 mFamilyCharacterMap.reset();
840 mFamilyCharacterMapInitialized = false;
843 // mark this family as being in the "bad" underline offset blacklist
844 void SetBadUnderlineFamily() {
845 mIsBadUnderlineFamily = true;
846 if (mHasStyles) {
847 SetBadUnderlineFonts();
851 bool IsBadUnderlineFamily() const { return mIsBadUnderlineFamily; }
852 bool CheckForFallbackFaces() const { return mCheckForFallbackFaces; }
854 // sort available fonts to put preferred (standard) faces towards the end
855 void SortAvailableFonts();
857 // check whether the family fits into the simple 4-face model,
858 // so we can use simplified style-matching;
859 // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
860 void CheckForSimpleFamily();
862 // For memory reporter
863 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
864 FontListSizes* aSizes) const;
865 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
866 FontListSizes* aSizes) const;
868 #ifdef DEBUG
869 // Only used for debugging checks - does a linear search
870 bool ContainsFace(gfxFontEntry* aFontEntry);
871 #endif
873 void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
874 mSkipDefaultFeatureSpaceCheck = aSkipCheck;
877 // Check whether this family is appropriate to include in the Preferences
878 // font list for the given langGroup and CSS generic, if the platform lets
879 // us determine this.
880 // Return true if the family should be included in the list, false to omit.
881 // Default implementation returns true for everything, so no filtering
882 // will occur; individual platforms may override.
883 virtual bool FilterForFontList(nsAtom* aLangGroup,
884 const nsACString& aGeneric) const {
885 return true;
888 protected:
889 // Protected destructor, to discourage deletion outside of Release():
890 virtual ~gfxFontFamily();
892 bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
893 hb_blob_t *aNameTable,
894 bool useFullName = false);
896 // set whether this font family is in "bad" underline offset blacklist.
897 void SetBadUnderlineFonts() {
898 uint32_t i, numFonts = mAvailableFonts.Length();
899 for (i = 0; i < numFonts; i++) {
900 if (mAvailableFonts[i]) {
901 mAvailableFonts[i]->mIsBadUnderlineFont = true;
906 nsCString mName;
907 nsTArray<RefPtr<gfxFontEntry> > mAvailableFonts;
908 gfxSparseBitSet mFamilyCharacterMap;
909 bool mOtherFamilyNamesInitialized : 1;
910 bool mHasOtherFamilyNames : 1;
911 bool mFaceNamesInitialized : 1;
912 bool mHasStyles : 1;
913 bool mIsSimpleFamily : 1;
914 bool mIsBadUnderlineFamily : 1;
915 bool mFamilyCharacterMapInitialized : 1;
916 bool mSkipDefaultFeatureSpaceCheck : 1;
917 bool mCheckForFallbackFaces : 1; // check other faces for character
918 bool mCheckedForLegacyFamilyNames : 1;
920 enum {
921 // for "simple" families, the faces are stored in mAvailableFonts
922 // with fixed positions:
923 kRegularFaceIndex = 0,
924 kBoldFaceIndex = 1,
925 kItalicFaceIndex = 2,
926 kBoldItalicFaceIndex = 3,
927 // mask values for selecting face with bold and/or italic attributes
928 kBoldMask = 0x01,
929 kItalicMask = 0x02
933 // Struct used in the gfxFontGroup font list to keep track of a font family
934 // together with the CSS generic (if any) that was mapped to it in this
935 // particular case (so it can be reported to the DevTools font inspector).
936 struct FamilyAndGeneric final {
937 FamilyAndGeneric()
938 : mFamily(nullptr)
939 , mGeneric(mozilla::FontFamilyType::eFamily_none)
942 FamilyAndGeneric(const FamilyAndGeneric& aOther)
943 : mFamily(aOther.mFamily)
944 , mGeneric(aOther.mGeneric)
947 explicit FamilyAndGeneric(gfxFontFamily* aFamily,
948 mozilla::FontFamilyType aGeneric =
949 mozilla::FontFamilyType::eFamily_none)
950 : mFamily(aFamily)
951 , mGeneric(aGeneric)
954 gfxFontFamily* mFamily;
955 mozilla::FontFamilyType mGeneric;
958 #endif