gfxDWriteFontList.h (17328B)
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_DWRITEFONTLIST_H 7 #define GFX_DWRITEFONTLIST_H 8 9 #include "mozilla/FontPropertyTypes.h" 10 #include "mozilla/MemoryReporting.h" 11 #include "gfxDWriteCommon.h" 12 #include "dwrite_3.h" 13 14 #include "gfxFont.h" 15 #include "gfxUserFontSet.h" 16 #include "cairo-win32.h" 17 18 #include "gfxPlatformFontList.h" 19 #include "gfxPlatform.h" 20 #include <algorithm> 21 22 #include "mozilla/gfx/UnscaledFontDWrite.h" 23 24 /** 25 * \brief Class representing directwrite font family. 26 * 27 * gfxDWriteFontFamily is a class that describes one of the font families on 28 * the user's system. It holds each gfxDWriteFontEntry (maps more directly to 29 * a font face) which holds font type, charset info and character map info. 30 */ 31 class gfxDWriteFontFamily final : public gfxFontFamily { 32 public: 33 typedef mozilla::FontStretch FontStretch; 34 typedef mozilla::FontSlantStyle FontSlantStyle; 35 typedef mozilla::FontWeight FontWeight; 36 37 /** 38 * Constructs a new DWriteFont Family. 39 * 40 * \param aName Name identifying the family 41 * \param aFamily IDWriteFontFamily object representing the directwrite 42 * family object. 43 */ 44 gfxDWriteFontFamily(const nsACString& aName, FontVisibility aVisibility, 45 IDWriteFontFamily* aFamily, 46 bool aIsSystemFontFamily = false) 47 : gfxFontFamily(aName, aVisibility), 48 mDWFamily(aFamily), 49 mIsSystemFontFamily(aIsSystemFontFamily), 50 mForceGDIClassic(false) {} 51 virtual ~gfxDWriteFontFamily(); 52 53 void FindStyleVariationsLocked(FontInfoData* aFontInfoData = nullptr) 54 MOZ_REQUIRES(mLock) final; 55 56 void LocalizedName(nsACString& aLocalizedName) final; 57 58 void ReadFaceNames(gfxPlatformFontList* aPlatformFontList, 59 bool aNeedFullnamePostscriptNames, 60 FontInfoData* aFontInfoData = nullptr) final; 61 62 void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } 63 64 void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 65 FontListSizes* aSizes) const final; 66 void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 67 FontListSizes* aSizes) const final; 68 69 bool FilterForFontList(nsAtom* aLangGroup, 70 const nsACString& aGeneric) const final { 71 return !IsSymbolFontFamily(); 72 } 73 74 protected: 75 // helper for FilterForFontList 76 bool IsSymbolFontFamily() const; 77 78 /** This font family's directwrite fontfamily object */ 79 RefPtr<IDWriteFontFamily> mDWFamily; 80 bool mIsSystemFontFamily; 81 bool mForceGDIClassic; 82 }; 83 84 /** 85 * \brief Class representing DirectWrite FontEntry (a unique font style/family) 86 */ 87 class gfxDWriteFontEntry final : public gfxFontEntry { 88 public: 89 /** 90 * Constructs a font entry. 91 * 92 * \param aFaceName The name of the corresponding font face. 93 * \param aFont DirectWrite font object 94 */ 95 gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFont* aFont, 96 bool aIsSystemFont = false) 97 : gfxFontEntry(aFaceName), 98 mFont(aFont), 99 mFontFile(nullptr), 100 mIsSystemFont(aIsSystemFont), 101 mForceGDIClassic(false), 102 mHasVariations(false), 103 mHasVariationsInitialized(false) { 104 DWRITE_FONT_STYLE dwriteStyle = aFont->GetStyle(); 105 FontSlantStyle style = (dwriteStyle == DWRITE_FONT_STYLE_ITALIC 106 ? FontSlantStyle::ITALIC 107 : (dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE 108 ? FontSlantStyle::OBLIQUE 109 : FontSlantStyle::NORMAL)); 110 mStyleRange = SlantStyleRange(style); 111 112 mStretchRange = 113 StretchRange(FontStretchFromDWriteStretch(aFont->GetStretch())); 114 115 int weight = mozilla::RoundUpToMultiple(aFont->GetWeight() - 50, 100); 116 weight = std::clamp(weight, 100, 900); 117 mWeightRange = WeightRange(FontWeight::FromInt(weight)); 118 119 mIsCJK = UNINITIALIZED_VALUE; 120 } 121 122 /** 123 * Constructs a font entry using a font. But with custom font values. 124 * This is used for creating correct font entries for @font-face with local 125 * font source. 126 * 127 * \param aFaceName The name of the corresponding font face. 128 * \param aFont DirectWrite font object 129 * \param aWeight Weight of the font 130 * \param aStretch Stretch of the font 131 * \param aStyle italic or oblique of font 132 */ 133 gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFont* aFont, 134 WeightRange aWeight, StretchRange aStretch, 135 SlantStyleRange aStyle) 136 : gfxFontEntry(aFaceName), 137 mFont(aFont), 138 mFontFile(nullptr), 139 mIsSystemFont(false), 140 mForceGDIClassic(false), 141 mHasVariations(false), 142 mHasVariationsInitialized(false) { 143 mWeightRange = aWeight; 144 mStretchRange = aStretch; 145 mStyleRange = aStyle; 146 mIsLocalUserFont = true; 147 mIsCJK = UNINITIALIZED_VALUE; 148 } 149 150 /** 151 * Constructs a font entry using a font file. 152 * 153 * \param aFaceName The name of the corresponding font face. 154 * \param aFontFile DirectWrite fontfile object 155 * \param aFontFileStream DirectWrite fontfile stream object 156 * \param aWeight Weight of the font 157 * \param aStretch Stretch of the font 158 * \param aStyle italic or oblique of font 159 */ 160 gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFontFile* aFontFile, 161 gfxDWriteFontFileStream* aFontFileStream, 162 WeightRange aWeight, StretchRange aStretch, 163 SlantStyleRange aStyle) 164 : gfxFontEntry(aFaceName), 165 mFont(nullptr), 166 mFontFile(aFontFile), 167 mFontFileStream(aFontFileStream), 168 mIsSystemFont(false), 169 mForceGDIClassic(false), 170 mHasVariations(false), 171 mHasVariationsInitialized(false) { 172 mWeightRange = aWeight; 173 mStretchRange = aStretch; 174 mStyleRange = aStyle; 175 mIsDataUserFont = true; 176 mIsCJK = UNINITIALIZED_VALUE; 177 } 178 179 gfxFontEntry* Clone() const override; 180 181 virtual ~gfxDWriteFontEntry(); 182 183 hb_blob_t* GetFontTable(uint32_t aTableTag) override; 184 185 nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override; 186 187 bool IsCJKFont(); 188 189 bool HasVariations() override; 190 void GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes) override; 191 void GetVariationInstances( 192 nsTArray<gfxFontVariationInstance>& aInstances) override; 193 194 void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } 195 bool GetForceGDIClassic() { return mForceGDIClassic; } 196 197 void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 198 FontListSizes* aSizes) const override; 199 void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 200 FontListSizes* aSizes) const override; 201 202 size_t ComputedSizeOfExcludingThis( 203 mozilla::MallocSizeOf aMallocSizeOf) override; 204 205 protected: 206 friend class gfxDWriteFont; 207 friend class gfxDWriteFontList; 208 friend class gfxDWriteFontFamily; 209 210 virtual nsresult CopyFontTable(uint32_t aTableTag, 211 nsTArray<uint8_t>& aBuffer) override; 212 213 virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle); 214 215 nsresult CreateFontFace( 216 IDWriteFontFace** aFontFace, const gfxFontStyle* aFontStyle = nullptr, 217 DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE, 218 const nsTArray<gfxFontVariation>* aVariations = nullptr); 219 220 static bool InitLogFont(IDWriteFont* aFont, LOGFONTW* aLogFont); 221 222 /** 223 * A fontentry only needs to have either of these. If it has both only 224 * the IDWriteFont will be used. 225 */ 226 RefPtr<IDWriteFont> mFont; 227 RefPtr<IDWriteFontFile> mFontFile; 228 229 // For custom fonts, we hold a reference to the IDWriteFontFileStream for 230 // for the IDWriteFontFile, so that the data is available. 231 RefPtr<gfxDWriteFontFileStream> mFontFileStream; 232 233 // font face corresponding to the mFont/mFontFile *without* any DWrite 234 // style simulations applied 235 RefPtr<IDWriteFontFace> mFontFace; 236 // Extended fontface interface if supported, else null 237 RefPtr<IDWriteFontFace5> mFontFace5; 238 239 DWRITE_FONT_FACE_TYPE mFaceType; 240 241 int8_t mIsCJK; 242 bool mIsSystemFont; 243 bool mForceGDIClassic; 244 bool mHasVariations; 245 bool mHasVariationsInitialized; 246 247 // Set to true only if the font belongs to a "simple" family where the 248 // faces can be reliably identified via a GDI LOGFONT structure. 249 bool mMayUseGDIAccess = false; 250 251 mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite> mUnscaledFont; 252 mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite> 253 mUnscaledFontBold; 254 }; 255 256 // custom text renderer used to determine the fallback font for a given char 257 class DWriteFontFallbackRenderer final : public IDWriteTextRenderer { 258 public: 259 explicit DWriteFontFallbackRenderer(IDWriteFactory* aFactory) : mRefCount(0) { 260 HRESULT hr = 261 aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts)); 262 NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); 263 (void)hr; 264 } 265 266 ~DWriteFontFallbackRenderer() {} 267 268 // If we don't have an mSystemFonts pointer, this renderer is unusable. 269 bool IsValid() const { return mSystemFonts; } 270 271 // IDWriteTextRenderer methods 272 IFACEMETHOD(DrawGlyphRun) 273 (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, 274 DWRITE_MEASURING_MODE measuringMode, DWRITE_GLYPH_RUN const* glyphRun, 275 DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, 276 IUnknown* clientDrawingEffect); 277 278 IFACEMETHOD(DrawUnderline) 279 (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, 280 DWRITE_UNDERLINE const* underline, IUnknown* clientDrawingEffect) { 281 return E_NOTIMPL; 282 } 283 284 IFACEMETHOD(DrawStrikethrough) 285 (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, 286 DWRITE_STRIKETHROUGH const* strikethrough, IUnknown* clientDrawingEffect) { 287 return E_NOTIMPL; 288 } 289 290 IFACEMETHOD(DrawInlineObject) 291 (void* clientDrawingContext, FLOAT originX, FLOAT originY, 292 IDWriteInlineObject* inlineObject, BOOL isSideways, BOOL isRightToLeft, 293 IUnknown* clientDrawingEffect) { 294 return E_NOTIMPL; 295 } 296 297 // IDWritePixelSnapping methods 298 299 IFACEMETHOD(IsPixelSnappingDisabled) 300 (void* clientDrawingContext, BOOL* isDisabled) { 301 *isDisabled = FALSE; 302 return S_OK; 303 } 304 305 IFACEMETHOD(GetCurrentTransform) 306 (void* clientDrawingContext, DWRITE_MATRIX* transform) { 307 const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; 308 *transform = ident; 309 return S_OK; 310 } 311 312 IFACEMETHOD(GetPixelsPerDip) 313 (void* clientDrawingContext, FLOAT* pixelsPerDip) { 314 *pixelsPerDip = 1.0f; 315 return S_OK; 316 } 317 318 // IUnknown methods 319 320 IFACEMETHOD_(unsigned long, AddRef)() { 321 return InterlockedIncrement(&mRefCount); 322 } 323 324 IFACEMETHOD_(unsigned long, Release)() { 325 unsigned long newCount = InterlockedDecrement(&mRefCount); 326 if (newCount == 0) { 327 delete this; 328 return 0; 329 } 330 331 return newCount; 332 } 333 334 IFACEMETHOD(QueryInterface)(IID const& riid, void** ppvObject) { 335 if (__uuidof(IDWriteTextRenderer) == riid) { 336 *ppvObject = this; 337 } else if (__uuidof(IDWritePixelSnapping) == riid) { 338 *ppvObject = this; 339 } else if (__uuidof(IUnknown) == riid) { 340 *ppvObject = this; 341 } else { 342 *ppvObject = nullptr; 343 return E_FAIL; 344 } 345 346 this->AddRef(); 347 return S_OK; 348 } 349 350 const nsCString& FallbackFamilyName() { return mFamilyName; } 351 352 protected: 353 long mRefCount; 354 RefPtr<IDWriteFontCollection> mSystemFonts; 355 nsCString mFamilyName; 356 }; 357 358 class gfxDWriteFontList final : public gfxPlatformFontList { 359 public: 360 gfxDWriteFontList(); 361 virtual ~gfxDWriteFontList() { AutoLock lock(mLock); } 362 363 static gfxDWriteFontList* PlatformFontList() { 364 return static_cast<gfxDWriteFontList*>( 365 gfxPlatformFontList::PlatformFontList()); 366 } 367 368 // initialize font lists 369 nsresult InitFontListForPlatform() MOZ_REQUIRES(mLock) override; 370 void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock) override; 371 372 FontVisibility GetVisibilityForFamily(const nsACString& aName) const; 373 374 gfxFontFamily* CreateFontFamily(const nsACString& aName, 375 FontVisibility aVisibility) const override; 376 377 gfxFontEntry* CreateFontEntry( 378 mozilla::fontlist::Face* aFace, 379 const mozilla::fontlist::Family* aFamily) override; 380 381 void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily, 382 bool aNeedFullnamePostscriptNames) 383 MOZ_REQUIRES(mLock) override; 384 385 bool ReadFaceNames(const mozilla::fontlist::Family* aFamily, 386 const mozilla::fontlist::Face* aFace, nsCString& aPSName, 387 nsCString& aFullName) override; 388 389 void GetFacesInitDataForFamily( 390 const mozilla::fontlist::Family* aFamily, 391 nsTArray<mozilla::fontlist::Face::InitData>& aFaces, 392 bool aLoadCmaps) const override; 393 394 gfxFontEntry* LookupLocalFont(FontVisibilityProvider* aFontVisibilityProvider, 395 const nsACString& aFontName, 396 WeightRange aWeightForEntry, 397 StretchRange aStretchForEntry, 398 SlantStyleRange aStyleForEntry) override; 399 400 gfxFontEntry* MakePlatformFont(const nsACString& aFontName, 401 WeightRange aWeightForEntry, 402 StretchRange aStretchForEntry, 403 SlantStyleRange aStyleForEntry, 404 const uint8_t* aFontData, 405 uint32_t aLength) override; 406 407 IDWriteGdiInterop* GetGDIInterop() { return mGDIInterop; } 408 bool UseGDIFontTableAccess() const; 409 410 bool FindAndAddFamiliesLocked( 411 FontVisibilityProvider* aFontVisibilityProvider, 412 mozilla::StyleGenericFontFamily aGeneric, const nsACString& aFamily, 413 nsTArray<FamilyAndGeneric>* aOutput, FindFamiliesFlags aFlags, 414 gfxFontStyle* aStyle = nullptr, nsAtom* aLanguage = nullptr, 415 gfxFloat aDevToCssSize = 1.0) MOZ_REQUIRES(mLock) override; 416 417 gfxFloat GetForceGDIClassicMaxFontSize() { 418 return mForceGDIClassicMaxFontSize; 419 } 420 421 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 422 FontListSizes* aSizes) const; 423 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 424 FontListSizes* aSizes) const; 425 426 protected: 427 FontFamily GetDefaultFontForPlatform( 428 FontVisibilityProvider* aFontVisibilityProvider, 429 const gfxFontStyle* aStyle, nsAtom* aLanguage = nullptr) 430 MOZ_REQUIRES(mLock) override; 431 432 // attempt to use platform-specific fallback for the given character, 433 // return null if no usable result found 434 gfxFontEntry* PlatformGlobalFontFallback( 435 FontVisibilityProvider* aFontVisibilityProvider, const uint32_t aCh, 436 Script aRunScript, const gfxFontStyle* aMatchStyle, 437 FontFamily& aMatchedFamily) MOZ_REQUIRES(mLock) override; 438 439 nsTArray<std::pair<const char**, uint32_t>> GetFilteredPlatformFontLists() 440 override; 441 442 private: 443 friend class gfxDWriteFontFamily; 444 445 nsresult GetFontSubstitutes() MOZ_REQUIRES(mLock); 446 447 void GetDirectWriteSubstitutes() MOZ_REQUIRES(mLock); 448 449 virtual bool UsesSystemFallback() { return true; } 450 451 void GetFontsFromCollection(IDWriteFontCollection* aCollection) 452 MOZ_REQUIRES(mLock); 453 454 void AppendFamiliesFromCollection( 455 IDWriteFontCollection* aCollection, 456 nsTArray<mozilla::fontlist::Family::InitData>& aFamilies, 457 const nsTArray<nsCString>* aForceClassicFams = nullptr) 458 MOZ_REQUIRES(mLock); 459 460 void AddSubstitute(const nsCString& aSubstituteName, 461 const nsCString& aActualFontName, bool aIsHardcoded) 462 MOZ_REQUIRES(mLock); 463 464 #ifdef MOZ_BUNDLED_FONTS 465 already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection( 466 IDWriteFactory* aFactory); 467 #endif 468 469 /** 470 * Fonts listed in the registry as substitutes but for which no actual 471 * font family is found. 472 */ 473 nsTArray<nsCString> mNonExistingFonts; 474 475 /** 476 * Table of font substitutes, we grab this from the registry to get 477 * alternative font names. 478 */ 479 FontFamilyTable mFontSubstitutes; 480 nsClassHashtable<nsCStringHashKey, nsCString> mSubstitutions; 481 482 /** 483 * Table of hardcoded font substitutes. We use this instead of the one 484 * generated from the registry when fingerprinting protections are enabled. 485 */ 486 FontFamilyTable mHardcodedSubstitutes; 487 nsClassHashtable<nsCStringHashKey, nsCString> mHardcodedSubstitutions; 488 489 virtual already_AddRefed<FontInfoData> CreateFontInfoData(); 490 491 gfxFloat mForceGDIClassicMaxFontSize; 492 493 // whether to use GDI font table access routines 494 bool mGDIFontTableAccess; 495 RefPtr<IDWriteGdiInterop> mGDIInterop; 496 497 RefPtr<DWriteFontFallbackRenderer> mFallbackRenderer; 498 RefPtr<IDWriteTextFormat> mFallbackFormat; 499 500 RefPtr<IDWriteFontCollection> mSystemFonts; 501 #ifdef MOZ_BUNDLED_FONTS 502 RefPtr<IDWriteFontCollection> mBundledFonts; 503 #endif 504 }; 505 506 #endif /* GFX_DWRITEFONTLIST_H */