Bug 1744135 Part 2: Annotate macOS font loading with font name if a crash happens...
[gecko.git] / gfx / thebes / gfxDWriteFontList.h
blobec4c57457e44effc41d4db1a35ca83fb445ae1a2
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/. */
6 #ifndef GFX_DWRITEFONTLIST_H
7 #define GFX_DWRITEFONTLIST_H
9 #include "mozilla/FontPropertyTypes.h"
10 #include "mozilla/MathAlgorithms.h"
11 #include "mozilla/MemoryReporting.h"
12 #include "gfxDWriteCommon.h"
13 #include "dwrite_3.h"
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
27 #include "gfxFont.h"
28 #include "gfxUserFontSet.h"
29 #include "cairo-win32.h"
31 #include "gfxPlatformFontList.h"
32 #include "gfxPlatform.h"
33 #include <algorithm>
35 #include "mozilla/gfx/UnscaledFontDWrite.h"
37 /**
38 * \brief Class representing directwrite font family.
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.
44 class gfxDWriteFontFamily final : public gfxFontFamily {
45 public:
46 typedef mozilla::FontStretch FontStretch;
47 typedef mozilla::FontSlantStyle FontSlantStyle;
48 typedef mozilla::FontWeight FontWeight;
50 /**
51 * Constructs a new DWriteFont Family.
53 * \param aName Name identifying the family
54 * \param aFamily IDWriteFontFamily object representing the directwrite
55 * family object.
57 gfxDWriteFontFamily(const nsACString& aName, FontVisibility aVisibility,
58 IDWriteFontFamily* aFamily,
59 bool aIsSystemFontFamily = false)
60 : gfxFontFamily(aName, aVisibility),
61 mDWFamily(aFamily),
62 mIsSystemFontFamily(aIsSystemFontFamily),
63 mForceGDIClassic(false) {}
64 virtual ~gfxDWriteFontFamily();
66 void FindStyleVariations(FontInfoData* aFontInfoData = nullptr) final;
68 void LocalizedName(nsACString& aLocalizedName) final;
70 void ReadFaceNames(gfxPlatformFontList* aPlatformFontList,
71 bool aNeedFullnamePostscriptNames,
72 FontInfoData* aFontInfoData = nullptr) final;
74 void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
76 void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
77 FontListSizes* aSizes) const final;
78 void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
79 FontListSizes* aSizes) const final;
81 bool FilterForFontList(nsAtom* aLangGroup,
82 const nsACString& aGeneric) const final {
83 return !IsSymbolFontFamily();
86 protected:
87 // helper for FilterForFontList
88 bool IsSymbolFontFamily() const;
90 /** This font family's directwrite fontfamily object */
91 RefPtr<IDWriteFontFamily> mDWFamily;
92 bool mIsSystemFontFamily;
93 bool mForceGDIClassic;
96 /**
97 * \brief Class representing DirectWrite FontEntry (a unique font style/family)
99 class gfxDWriteFontEntry final : public gfxFontEntry {
100 public:
102 * Constructs a font entry.
104 * \param aFaceName The name of the corresponding font face.
105 * \param aFont DirectWrite font object
107 gfxDWriteFontEntry(const nsACString& aFaceName, IDWriteFont* aFont,
108 bool aIsSystemFont = false)
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);
124 mStretchRange =
125 StretchRange(FontStretchFromDWriteStretch(aFont->GetStretch()));
127 int weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100);
128 weight = mozilla::Clamp(weight, 100, 900);
129 mWeightRange = WeightRange(FontWeight(weight));
131 mIsCJK = UNINITIALIZED_VALUE;
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.
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
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;
163 * Constructs a font entry using a font file.
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
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;
191 gfxFontEntry* Clone() const override;
193 virtual ~gfxDWriteFontEntry();
195 hb_blob_t* GetFontTable(uint32_t aTableTag) override;
197 nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr);
199 bool IsCJKFont();
201 bool HasVariations() override;
202 void GetVariationAxes(nsTArray<gfxFontVariationAxis>& aAxes) override;
203 void GetVariationInstances(
204 nsTArray<gfxFontVariationInstance>& aInstances) override;
206 void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
207 bool GetForceGDIClassic() { return mForceGDIClassic; }
209 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
210 FontListSizes* aSizes) const;
211 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
212 FontListSizes* aSizes) const;
214 protected:
215 friend class gfxDWriteFont;
216 friend class gfxDWriteFontList;
217 friend class gfxDWriteFontFamily;
219 virtual nsresult CopyFontTable(uint32_t aTableTag,
220 nsTArray<uint8_t>& aBuffer) override;
222 virtual gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle);
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);
229 static bool InitLogFont(IDWriteFont* aFont, LOGFONTW* aLogFont);
232 * A fontentry only needs to have either of these. If it has both only
233 * the IDWriteFont will be used.
235 RefPtr<IDWriteFont> mFont;
236 RefPtr<IDWriteFontFile> mFontFile;
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;
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;
248 DWRITE_FONT_FACE_TYPE mFaceType;
250 int8_t mIsCJK;
251 bool mIsSystemFont;
252 bool mForceGDIClassic;
253 bool mHasVariations;
254 bool mHasVariationsInitialized;
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;
260 mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite> mUnscaledFont;
261 mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite>
262 mUnscaledFontBold;
265 // custom text renderer used to determine the fallback font for a given char
266 class DWriteFontFallbackRenderer final : public IDWriteTextRenderer {
267 public:
268 explicit DWriteFontFallbackRenderer(IDWriteFactory* aFactory) : mRefCount(0) {
269 HRESULT hr =
270 aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts));
271 NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!");
272 (void)hr;
275 ~DWriteFontFallbackRenderer() {}
277 // If we don't have an mSystemFonts pointer, this renderer is unusable.
278 bool IsValid() const { return mSystemFonts; }
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);
287 IFACEMETHOD(DrawUnderline)
288 (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,
289 DWRITE_UNDERLINE const* underline, IUnknown* clientDrawingEffect) {
290 return E_NOTIMPL;
293 IFACEMETHOD(DrawStrikethrough)
294 (void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY,
295 DWRITE_STRIKETHROUGH const* strikethrough, IUnknown* clientDrawingEffect) {
296 return E_NOTIMPL;
299 IFACEMETHOD(DrawInlineObject)
300 (void* clientDrawingContext, FLOAT originX, FLOAT originY,
301 IDWriteInlineObject* inlineObject, BOOL isSideways, BOOL isRightToLeft,
302 IUnknown* clientDrawingEffect) {
303 return E_NOTIMPL;
306 // IDWritePixelSnapping methods
308 IFACEMETHOD(IsPixelSnappingDisabled)
309 (void* clientDrawingContext, BOOL* isDisabled) {
310 *isDisabled = FALSE;
311 return S_OK;
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;
321 IFACEMETHOD(GetPixelsPerDip)
322 (void* clientDrawingContext, FLOAT* pixelsPerDip) {
323 *pixelsPerDip = 1.0f;
324 return S_OK;
327 // IUnknown methods
329 IFACEMETHOD_(unsigned long, AddRef)() {
330 return InterlockedIncrement(&mRefCount);
333 IFACEMETHOD_(unsigned long, Release)() {
334 unsigned long newCount = InterlockedDecrement(&mRefCount);
335 if (newCount == 0) {
336 delete this;
337 return 0;
340 return newCount;
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;
355 this->AddRef();
356 return S_OK;
359 const nsCString& FallbackFamilyName() { return mFamilyName; }
361 protected:
362 long mRefCount;
363 RefPtr<IDWriteFontCollection> mSystemFonts;
364 nsCString mFamilyName;
367 class gfxDWriteFontList final : public gfxPlatformFontList {
368 public:
369 gfxDWriteFontList();
371 static gfxDWriteFontList* PlatformFontList() {
372 return static_cast<gfxDWriteFontList*>(
373 gfxPlatformFontList::PlatformFontList());
376 // initialize font lists
377 nsresult InitFontListForPlatform() override;
378 void InitSharedFontListForPlatform() override;
380 FontVisibility GetVisibilityForFamily(const nsACString& aName) const;
382 gfxFontFamily* CreateFontFamily(const nsACString& aName,
383 FontVisibility aVisibility) const override;
385 gfxFontEntry* CreateFontEntry(
386 mozilla::fontlist::Face* aFace,
387 const mozilla::fontlist::Family* aFamily) override;
389 void ReadFaceNamesForFamily(mozilla::fontlist::Family* aFamily,
390 bool aNeedFullnamePostscriptNames) override;
392 bool ReadFaceNames(mozilla::fontlist::Family* aFamily,
393 mozilla::fontlist::Face* aFace, nsCString& aPSName,
394 nsCString& aFullName) override;
396 void GetFacesInitDataForFamily(
397 const mozilla::fontlist::Family* aFamily,
398 nsTArray<mozilla::fontlist::Face::InitData>& aFaces,
399 bool aLoadCmaps) const override;
401 gfxFontEntry* LookupLocalFont(nsPresContext* aPresContext,
402 const nsACString& aFontName,
403 WeightRange aWeightForEntry,
404 StretchRange aStretchForEntry,
405 SlantStyleRange aStyleForEntry) override;
407 gfxFontEntry* MakePlatformFont(const nsACString& aFontName,
408 WeightRange aWeightForEntry,
409 StretchRange aStretchForEntry,
410 SlantStyleRange aStyleForEntry,
411 const uint8_t* aFontData,
412 uint32_t aLength) override;
414 IDWriteGdiInterop* GetGDIInterop() { return mGDIInterop; }
415 bool UseGDIFontTableAccess() const;
417 bool FindAndAddFamilies(
418 nsPresContext* aPresContext, mozilla::StyleGenericFontFamily aGeneric,
419 const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
420 FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr,
421 nsAtom* aLanguage = nullptr, gfxFloat aDevToCssSize = 1.0) override;
423 gfxFloat GetForceGDIClassicMaxFontSize() {
424 return mForceGDIClassicMaxFontSize;
427 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
428 FontListSizes* aSizes) const;
429 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
430 FontListSizes* aSizes) const;
432 protected:
433 FontFamily GetDefaultFontForPlatform(nsPresContext* aPresContext,
434 const gfxFontStyle* aStyle,
435 nsAtom* aLanguage = nullptr) override;
437 // attempt to use platform-specific fallback for the given character,
438 // return null if no usable result found
439 gfxFontEntry* PlatformGlobalFontFallback(nsPresContext* aPresContext,
440 const uint32_t aCh,
441 Script aRunScript,
442 const gfxFontStyle* aMatchStyle,
443 FontFamily& aMatchedFamily) override;
445 private:
446 friend class gfxDWriteFontFamily;
448 nsresult GetFontSubstitutes();
450 void GetDirectWriteSubstitutes();
452 virtual bool UsesSystemFallback() { return true; }
454 void GetFontsFromCollection(IDWriteFontCollection* aCollection);
456 void AppendFamiliesFromCollection(
457 IDWriteFontCollection* aCollection,
458 nsTArray<mozilla::fontlist::Family::InitData>& aFamilies,
459 const nsTArray<nsCString>* aForceClassicFams = nullptr);
461 #ifdef MOZ_BUNDLED_FONTS
462 already_AddRefed<IDWriteFontCollection> CreateBundledFontsCollection(
463 IDWriteFactory* aFactory);
464 #endif
467 * Fonts listed in the registry as substitutes but for which no actual
468 * font family is found.
470 nsTArray<nsCString> mNonExistingFonts;
473 * Table of font substitutes, we grab this from the registry to get
474 * alternative font names.
476 FontFamilyTable mFontSubstitutes;
477 nsClassHashtable<nsCStringHashKey, nsCString> mSubstitutions;
479 virtual already_AddRefed<FontInfoData> CreateFontInfoData();
481 gfxFloat mForceGDIClassicMaxFontSize;
483 // whether to use GDI font table access routines
484 bool mGDIFontTableAccess;
485 RefPtr<IDWriteGdiInterop> mGDIInterop;
487 RefPtr<DWriteFontFallbackRenderer> mFallbackRenderer;
488 RefPtr<IDWriteTextFormat> mFallbackFormat;
490 RefPtr<IDWriteFontCollection> mSystemFonts;
491 #ifdef MOZ_BUNDLED_FONTS
492 RefPtr<IDWriteFontCollection> mBundledFonts;
493 #endif
496 #endif /* GFX_DWRITEFONTLIST_H */