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