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