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