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_DWRITEFONTLIST_H 7 #define GFX_DWRITEFONTLIST_H 8 9 #include "mozilla/MemoryReporting.h" 10 #include "gfxDWriteCommon.h" 11 12 #include "gfxFont.h" 13 #include "gfxUserFontSet.h" 14 #include "cairo-win32.h" 15 16 #include "gfxPlatformFontList.h" 17 #include "gfxPlatform.h" 18 #include <algorithm> 19 20 21 /** 22 * gfxDWriteFontFamily is a class that describes one of the fonts on the 23 * users system. It holds each gfxDWriteFontEntry (maps more directly to 24 * a font face) which holds font type, charset info and character map info. 25 */ 26 class gfxDWriteFontEntry; 27 28 /** 29 * \brief Class representing directwrite font family. 30 */ 31 class gfxDWriteFontFamily : public gfxFontFamily 32 { 33 public: 34 /** 35 * Constructs a new DWriteFont Family. 36 * 37 * \param aName Name identifying the family 38 * \param aFamily IDWriteFontFamily object representing the directwrite 39 * family object. 40 */ gfxDWriteFontFamily(const nsAString & aName,IDWriteFontFamily * aFamily)41 gfxDWriteFontFamily(const nsAString& aName, 42 IDWriteFontFamily *aFamily) 43 : gfxFontFamily(aName), mDWFamily(aFamily), mForceGDIClassic(false) {} 44 virtual ~gfxDWriteFontFamily(); 45 46 void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) final; 47 48 void LocalizedName(nsAString& aLocalizedName) final; 49 50 void ReadFaceNames(gfxPlatformFontList *aPlatformFontList, 51 bool aNeedFullnamePostscriptNames, 52 FontInfoData *aFontInfoData = nullptr) final; 53 SetForceGDIClassic(bool aForce)54 void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } 55 56 void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 57 FontListSizes* aSizes) const final; 58 void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 59 FontListSizes* aSizes) const final; 60 61 protected: 62 /** This font family's directwrite fontfamily object */ 63 RefPtr<IDWriteFontFamily> mDWFamily; 64 bool mForceGDIClassic; 65 }; 66 67 /** 68 * \brief Class representing DirectWrite FontEntry (a unique font style/family) 69 */ 70 class gfxDWriteFontEntry : public gfxFontEntry 71 { 72 public: 73 /** 74 * Constructs a font entry. 75 * 76 * \param aFaceName The name of the corresponding font face. 77 * \param aFont DirectWrite font object 78 */ gfxDWriteFontEntry(const nsAString & aFaceName,IDWriteFont * aFont)79 gfxDWriteFontEntry(const nsAString& aFaceName, 80 IDWriteFont *aFont) 81 : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), 82 mForceGDIClassic(false) 83 { 84 DWRITE_FONT_STYLE dwriteStyle = aFont->GetStyle(); 85 mStyle = (dwriteStyle == DWRITE_FONT_STYLE_ITALIC ? 86 NS_FONT_STYLE_ITALIC : 87 (dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE ? 88 NS_FONT_STYLE_OBLIQUE : NS_FONT_STYLE_NORMAL)); 89 mStretch = FontStretchFromDWriteStretch(aFont->GetStretch()); 90 uint16_t weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100); 91 92 weight = std::max<uint16_t>(100, weight); 93 weight = std::min<uint16_t>(900, weight); 94 mWeight = weight; 95 96 mIsCJK = UNINITIALIZED_VALUE; 97 } 98 99 /** 100 * Constructs a font entry using a font. But with custom font values. 101 * This is used for creating correct font entries for @font-face with local 102 * font source. 103 * 104 * \param aFaceName The name of the corresponding font face. 105 * \param aFont DirectWrite font object 106 * \param aWeight Weight of the font 107 * \param aStretch Stretch of the font 108 * \param aStyle italic or oblique of font 109 */ gfxDWriteFontEntry(const nsAString & aFaceName,IDWriteFont * aFont,uint16_t aWeight,int16_t aStretch,uint8_t aStyle)110 gfxDWriteFontEntry(const nsAString& aFaceName, 111 IDWriteFont *aFont, 112 uint16_t aWeight, 113 int16_t aStretch, 114 uint8_t aStyle) 115 : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), 116 mForceGDIClassic(false) 117 { 118 mWeight = aWeight; 119 mStretch = aStretch; 120 mStyle = aStyle; 121 mIsLocalUserFont = true; 122 mIsCJK = UNINITIALIZED_VALUE; 123 } 124 125 /** 126 * Constructs a font entry using a font file. 127 * 128 * \param aFaceName The name of the corresponding font face. 129 * \param aFontFile DirectWrite fontfile object 130 * \param aFontFileStream DirectWrite fontfile stream object 131 * \param aWeight Weight of the font 132 * \param aStretch Stretch of the font 133 * \param aStyle italic or oblique of font 134 */ gfxDWriteFontEntry(const nsAString & aFaceName,IDWriteFontFile * aFontFile,IDWriteFontFileStream * aFontFileStream,uint16_t aWeight,int16_t aStretch,uint8_t aStyle)135 gfxDWriteFontEntry(const nsAString& aFaceName, 136 IDWriteFontFile *aFontFile, 137 IDWriteFontFileStream *aFontFileStream, 138 uint16_t aWeight, 139 int16_t aStretch, 140 uint8_t aStyle) 141 : gfxFontEntry(aFaceName), mFont(nullptr), mFontFile(aFontFile), 142 mFontFileStream(aFontFileStream), mForceGDIClassic(false) 143 { 144 mWeight = aWeight; 145 mStretch = aStretch; 146 mStyle = aStyle; 147 mIsDataUserFont = true; 148 mIsCJK = UNINITIALIZED_VALUE; 149 } 150 151 virtual ~gfxDWriteFontEntry(); 152 153 virtual bool IsSymbolFont(); 154 155 virtual hb_blob_t* GetFontTable(uint32_t aTableTag) override; 156 157 nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); 158 159 bool IsCJKFont(); 160 SetForceGDIClassic(bool aForce)161 void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } GetForceGDIClassic()162 bool GetForceGDIClassic() { return mForceGDIClassic; } 163 164 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 165 FontListSizes* aSizes) const; 166 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 167 FontListSizes* aSizes) const; 168 169 protected: 170 friend class gfxDWriteFont; 171 friend class gfxDWriteFontList; 172 173 virtual nsresult CopyFontTable(uint32_t aTableTag, 174 nsTArray<uint8_t>& aBuffer) override; 175 176 virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, 177 bool aNeedsBold); 178 179 nsresult CreateFontFace( 180 IDWriteFontFace **aFontFace, 181 DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE); 182 183 static bool InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont); 184 185 /** 186 * A fontentry only needs to have either of these. If it has both only 187 * the IDWriteFont will be used. 188 */ 189 RefPtr<IDWriteFont> mFont; 190 RefPtr<IDWriteFontFile> mFontFile; 191 192 // For custom fonts, we hold a reference to the IDWriteFontFileStream for 193 // for the IDWriteFontFile, so that the data is available. 194 RefPtr<IDWriteFontFileStream> mFontFileStream; 195 196 // font face corresponding to the mFont/mFontFile *without* any DWrite 197 // style simulations applied 198 RefPtr<IDWriteFontFace> mFontFace; 199 200 DWRITE_FONT_FACE_TYPE mFaceType; 201 202 int8_t mIsCJK; 203 bool mForceGDIClassic; 204 }; 205 206 // custom text renderer used to determine the fallback font for a given char 207 class DWriteFontFallbackRenderer final : public IDWriteTextRenderer 208 { 209 public: DWriteFontFallbackRenderer(IDWriteFactory * aFactory)210 DWriteFontFallbackRenderer(IDWriteFactory *aFactory) 211 : mRefCount(0) 212 { 213 HRESULT hr = S_OK; 214 215 hr = aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts)); 216 NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); 217 } 218 ~DWriteFontFallbackRenderer()219 ~DWriteFontFallbackRenderer() 220 {} 221 222 // IDWriteTextRenderer methods 223 IFACEMETHOD(DrawGlyphRun)( 224 void* clientDrawingContext, 225 FLOAT baselineOriginX, 226 FLOAT baselineOriginY, 227 DWRITE_MEASURING_MODE measuringMode, 228 DWRITE_GLYPH_RUN const* glyphRun, 229 DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, 230 IUnknown* clientDrawingEffect 231 ); 232 IFACEMETHOD(DrawUnderline)233 IFACEMETHOD(DrawUnderline)( 234 void* clientDrawingContext, 235 FLOAT baselineOriginX, 236 FLOAT baselineOriginY, 237 DWRITE_UNDERLINE const* underline, 238 IUnknown* clientDrawingEffect 239 ) 240 { 241 return E_NOTIMPL; 242 } 243 244 IFACEMETHOD(DrawStrikethrough)245 IFACEMETHOD(DrawStrikethrough)( 246 void* clientDrawingContext, 247 FLOAT baselineOriginX, 248 FLOAT baselineOriginY, 249 DWRITE_STRIKETHROUGH const* strikethrough, 250 IUnknown* clientDrawingEffect 251 ) 252 { 253 return E_NOTIMPL; 254 } 255 256 IFACEMETHOD(DrawInlineObject)257 IFACEMETHOD(DrawInlineObject)( 258 void* clientDrawingContext, 259 FLOAT originX, 260 FLOAT originY, 261 IDWriteInlineObject* inlineObject, 262 BOOL isSideways, 263 BOOL isRightToLeft, 264 IUnknown* clientDrawingEffect 265 ) 266 { 267 return E_NOTIMPL; 268 } 269 270 // IDWritePixelSnapping methods 271 IFACEMETHOD(IsPixelSnappingDisabled)272 IFACEMETHOD(IsPixelSnappingDisabled)( 273 void* clientDrawingContext, 274 BOOL* isDisabled 275 ) 276 { 277 *isDisabled = FALSE; 278 return S_OK; 279 } 280 IFACEMETHOD(GetCurrentTransform)281 IFACEMETHOD(GetCurrentTransform)( 282 void* clientDrawingContext, 283 DWRITE_MATRIX* transform 284 ) 285 { 286 const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; 287 *transform = ident; 288 return S_OK; 289 } 290 IFACEMETHOD(GetPixelsPerDip)291 IFACEMETHOD(GetPixelsPerDip)( 292 void* clientDrawingContext, 293 FLOAT* pixelsPerDip 294 ) 295 { 296 *pixelsPerDip = 1.0f; 297 return S_OK; 298 } 299 300 // IUnknown methods 301 IFACEMETHOD_(unsigned long,AddRef)302 IFACEMETHOD_(unsigned long, AddRef) () 303 { 304 return InterlockedIncrement(&mRefCount); 305 } 306 IFACEMETHOD_(unsigned long,Release)307 IFACEMETHOD_(unsigned long, Release) () 308 { 309 unsigned long newCount = InterlockedDecrement(&mRefCount); 310 if (newCount == 0) 311 { 312 delete this; 313 return 0; 314 } 315 316 return newCount; 317 } 318 IFACEMETHOD(QueryInterface)319 IFACEMETHOD(QueryInterface) (IID const& riid, void** ppvObject) 320 { 321 if (__uuidof(IDWriteTextRenderer) == riid) { 322 *ppvObject = this; 323 } else if (__uuidof(IDWritePixelSnapping) == riid) { 324 *ppvObject = this; 325 } else if (__uuidof(IUnknown) == riid) { 326 *ppvObject = this; 327 } else { 328 *ppvObject = nullptr; 329 return E_FAIL; 330 } 331 332 this->AddRef(); 333 return S_OK; 334 } 335 FallbackFamilyName()336 const nsString& FallbackFamilyName() { return mFamilyName; } 337 338 protected: 339 long mRefCount; 340 RefPtr<IDWriteFontCollection> mSystemFonts; 341 nsString mFamilyName; 342 }; 343 344 345 346 class gfxDWriteFontList : public gfxPlatformFontList { 347 public: 348 gfxDWriteFontList(); 349 PlatformFontList()350 static gfxDWriteFontList* PlatformFontList() { 351 return static_cast<gfxDWriteFontList*>(sPlatformFontList); 352 } 353 354 // initialize font lists 355 virtual nsresult InitFontListForPlatform() override; 356 357 virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, 358 uint16_t aWeight, 359 int16_t aStretch, 360 uint8_t aStyle); 361 362 virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, 363 uint16_t aWeight, 364 int16_t aStretch, 365 uint8_t aStyle, 366 const uint8_t* aFontData, 367 uint32_t aLength); 368 369 bool GetStandardFamilyName(const nsAString& aFontName, 370 nsAString& aFamilyName); 371 GetGDIInterop()372 IDWriteGdiInterop *GetGDIInterop() { return mGDIInterop; } UseGDIFontTableAccess()373 bool UseGDIFontTableAccess() { return mGDIFontTableAccess; } 374 375 bool FindAndAddFamilies(const nsAString& aFamily, 376 nsTArray<gfxFontFamily*>* aOutput, 377 gfxFontStyle* aStyle = nullptr, 378 gfxFloat aDevToCssSize = 1.0) override; 379 GetForceGDIClassicMaxFontSize()380 gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; } 381 382 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 383 FontListSizes* aSizes) const; 384 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 385 FontListSizes* aSizes) const; 386 387 protected: 388 virtual gfxFontFamily* 389 GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; 390 391 // attempt to use platform-specific fallback for the given character, 392 // return null if no usable result found 393 gfxFontEntry* 394 PlatformGlobalFontFallback(const uint32_t aCh, 395 Script aRunScript, 396 const gfxFontStyle* aMatchStyle, 397 gfxFontFamily** aMatchedFamily) override; 398 399 private: 400 friend class gfxDWriteFontFamily; 401 402 nsresult GetFontSubstitutes(); 403 404 void GetDirectWriteSubstitutes(); 405 UsesSystemFallback()406 virtual bool UsesSystemFallback() { return true; } 407 408 void GetFontsFromCollection(IDWriteFontCollection* aCollection); 409 410 #ifdef MOZ_BUNDLED_FONTS 411 already_AddRefed<IDWriteFontCollection> 412 CreateBundledFontsCollection(IDWriteFactory* aFactory); 413 #endif 414 415 /** 416 * Fonts listed in the registry as substitutes but for which no actual 417 * font family is found. 418 */ 419 nsTArray<nsString> mNonExistingFonts; 420 421 /** 422 * Table of font substitutes, we grab this from the registry to get 423 * alternative font names. 424 */ 425 FontFamilyTable mFontSubstitutes; 426 427 virtual already_AddRefed<FontInfoData> CreateFontInfoData(); 428 429 gfxFloat mForceGDIClassicMaxFontSize; 430 431 // whether to use GDI font table access routines 432 bool mGDIFontTableAccess; 433 RefPtr<IDWriteGdiInterop> mGDIInterop; 434 435 RefPtr<DWriteFontFallbackRenderer> mFallbackRenderer; 436 RefPtr<IDWriteTextFormat> mFallbackFormat; 437 438 RefPtr<IDWriteFontCollection> mSystemFonts; 439 #ifdef MOZ_BUNDLED_FONTS 440 RefPtr<IDWriteFontCollection> mBundledFonts; 441 #endif 442 }; 443 444 445 #endif /* GFX_DWRITEFONTLIST_H */ 446