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