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"
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
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"
28 #include "gfxUserFontSet.h"
29 #include "cairo-win32.h"
31 #include "gfxPlatformFontList.h"
32 #include "gfxPlatform.h"
35 #include "mozilla/gfx/UnscaledFontDWrite.h"
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
{
46 typedef mozilla::FontStretch FontStretch
;
47 typedef mozilla::FontSlantStyle FontSlantStyle
;
48 typedef mozilla::FontWeight FontWeight
;
51 * Constructs a new DWriteFont Family.
53 * \param aName Name identifying the family
54 * \param aFamily IDWriteFontFamily object representing the directwrite
57 gfxDWriteFontFamily(const nsACString
& aName
, FontVisibility aVisibility
,
58 IDWriteFontFamily
* aFamily
,
59 bool aIsSystemFontFamily
= false)
60 : gfxFontFamily(aName
, aVisibility
),
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();
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
;
97 * \brief Class representing DirectWrite FontEntry (a unique font style/family)
99 class gfxDWriteFontEntry final
: public gfxFontEntry
{
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
),
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
);
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
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
),
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
),
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);
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;
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
;
252 bool mForceGDIClassic
;
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
>
265 // custom text renderer used to determine the fallback font for a given char
266 class DWriteFontFallbackRenderer final
: public IDWriteTextRenderer
{
268 explicit DWriteFontFallbackRenderer(IDWriteFactory
* aFactory
) : mRefCount(0) {
270 aFactory
->GetSystemFontCollection(getter_AddRefs(mSystemFonts
));
271 NS_ASSERTION(SUCCEEDED(hr
), "GetSystemFontCollection failed!");
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
) {
293 IFACEMETHOD(DrawStrikethrough
)
294 (void* clientDrawingContext
, FLOAT baselineOriginX
, FLOAT baselineOriginY
,
295 DWRITE_STRIKETHROUGH
const* strikethrough
, IUnknown
* clientDrawingEffect
) {
299 IFACEMETHOD(DrawInlineObject
)
300 (void* clientDrawingContext
, FLOAT originX
, FLOAT originY
,
301 IDWriteInlineObject
* inlineObject
, BOOL isSideways
, BOOL isRightToLeft
,
302 IUnknown
* clientDrawingEffect
) {
306 // IDWritePixelSnapping methods
308 IFACEMETHOD(IsPixelSnappingDisabled
)
309 (void* clientDrawingContext
, BOOL
* isDisabled
) {
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};
321 IFACEMETHOD(GetPixelsPerDip
)
322 (void* clientDrawingContext
, FLOAT
* pixelsPerDip
) {
323 *pixelsPerDip
= 1.0f
;
329 IFACEMETHOD_(unsigned long, AddRef
)() {
330 return InterlockedIncrement(&mRefCount
);
333 IFACEMETHOD_(unsigned long, Release
)() {
334 unsigned long newCount
= InterlockedDecrement(&mRefCount
);
343 IFACEMETHOD(QueryInterface
)(IID
const& riid
, void** ppvObject
) {
344 if (__uuidof(IDWriteTextRenderer
) == riid
) {
346 } else if (__uuidof(IDWritePixelSnapping
) == riid
) {
348 } else if (__uuidof(IUnknown
) == riid
) {
351 *ppvObject
= nullptr;
359 const nsCString
& FallbackFamilyName() { return mFamilyName
; }
363 RefPtr
<IDWriteFontCollection
> mSystemFonts
;
364 nsCString mFamilyName
;
367 class gfxDWriteFontList final
: public gfxPlatformFontList
{
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;
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
,
442 const gfxFontStyle
* aMatchStyle
,
443 FontFamily
& aMatchedFamily
) override
;
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
);
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
;
496 #endif /* GFX_DWRITEFONTLIST_H */