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"
16 #include "gfxUserFontSet.h"
17 #include "cairo-win32.h"
19 #include "gfxPlatformFontList.h"
20 #include "gfxPlatform.h"
23 #include "mozilla/gfx/UnscaledFontDWrite.h"
26 * \brief Class representing directwrite font family.
28 * gfxDWriteFontFamily is a class that describes one of the font families on
29 * the user's system. It holds each gfxDWriteFontEntry (maps more directly to
30 * a font face) which holds font type, charset info and character map info.
32 class gfxDWriteFontFamily final
: public gfxFontFamily
{
34 typedef mozilla::FontStretch FontStretch
;
35 typedef mozilla::FontSlantStyle FontSlantStyle
;
36 typedef mozilla::FontWeight FontWeight
;
39 * Constructs a new DWriteFont Family.
41 * \param aName Name identifying the family
42 * \param aFamily IDWriteFontFamily object representing the directwrite
45 gfxDWriteFontFamily(const nsACString
& aName
, FontVisibility aVisibility
,
46 IDWriteFontFamily
* aFamily
,
47 bool aIsSystemFontFamily
= false)
48 : gfxFontFamily(aName
, aVisibility
),
50 mIsSystemFontFamily(aIsSystemFontFamily
),
51 mForceGDIClassic(false) {}
52 virtual ~gfxDWriteFontFamily();
54 void FindStyleVariationsLocked(FontInfoData
* aFontInfoData
= nullptr)
55 MOZ_REQUIRES(mLock
) final
;
57 void LocalizedName(nsACString
& aLocalizedName
) final
;
59 void ReadFaceNames(gfxPlatformFontList
* aPlatformFontList
,
60 bool aNeedFullnamePostscriptNames
,
61 FontInfoData
* aFontInfoData
= nullptr) final
;
63 void SetForceGDIClassic(bool aForce
) { mForceGDIClassic
= aForce
; }
65 void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
66 FontListSizes
* aSizes
) const final
;
67 void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
68 FontListSizes
* aSizes
) const final
;
70 bool FilterForFontList(nsAtom
* aLangGroup
,
71 const nsACString
& aGeneric
) const final
{
72 return !IsSymbolFontFamily();
76 // helper for FilterForFontList
77 bool IsSymbolFontFamily() const;
79 /** This font family's directwrite fontfamily object */
80 RefPtr
<IDWriteFontFamily
> mDWFamily
;
81 bool mIsSystemFontFamily
;
82 bool mForceGDIClassic
;
86 * \brief Class representing DirectWrite FontEntry (a unique font style/family)
88 class gfxDWriteFontEntry final
: public gfxFontEntry
{
91 * Constructs a font entry.
93 * \param aFaceName The name of the corresponding font face.
94 * \param aFont DirectWrite font object
96 gfxDWriteFontEntry(const nsACString
& aFaceName
, IDWriteFont
* aFont
,
97 bool aIsSystemFont
= false)
98 : gfxFontEntry(aFaceName
),
101 mIsSystemFont(aIsSystemFont
),
102 mForceGDIClassic(false),
103 mHasVariations(false),
104 mHasVariationsInitialized(false) {
105 DWRITE_FONT_STYLE dwriteStyle
= aFont
->GetStyle();
106 FontSlantStyle style
= (dwriteStyle
== DWRITE_FONT_STYLE_ITALIC
107 ? FontSlantStyle::ITALIC
108 : (dwriteStyle
== DWRITE_FONT_STYLE_OBLIQUE
109 ? FontSlantStyle::OBLIQUE
110 : FontSlantStyle::NORMAL
));
111 mStyleRange
= SlantStyleRange(style
);
114 StretchRange(FontStretchFromDWriteStretch(aFont
->GetStretch()));
116 int weight
= NS_ROUNDUP(aFont
->GetWeight() - 50, 100);
117 weight
= mozilla::Clamp(weight
, 100, 900);
118 mWeightRange
= WeightRange(FontWeight::FromInt(weight
));
120 mIsCJK
= UNINITIALIZED_VALUE
;
124 * Constructs a font entry using a font. But with custom font values.
125 * This is used for creating correct font entries for @font-face with local
128 * \param aFaceName The name of the corresponding font face.
129 * \param aFont DirectWrite font object
130 * \param aWeight Weight of the font
131 * \param aStretch Stretch of the font
132 * \param aStyle italic or oblique of font
134 gfxDWriteFontEntry(const nsACString
& aFaceName
, IDWriteFont
* aFont
,
135 WeightRange aWeight
, StretchRange aStretch
,
136 SlantStyleRange aStyle
)
137 : gfxFontEntry(aFaceName
),
140 mIsSystemFont(false),
141 mForceGDIClassic(false),
142 mHasVariations(false),
143 mHasVariationsInitialized(false) {
144 mWeightRange
= aWeight
;
145 mStretchRange
= aStretch
;
146 mStyleRange
= aStyle
;
147 mIsLocalUserFont
= true;
148 mIsCJK
= UNINITIALIZED_VALUE
;
152 * Constructs a font entry using a font file.
154 * \param aFaceName The name of the corresponding font face.
155 * \param aFontFile DirectWrite fontfile object
156 * \param aFontFileStream DirectWrite fontfile stream object
157 * \param aWeight Weight of the font
158 * \param aStretch Stretch of the font
159 * \param aStyle italic or oblique of font
161 gfxDWriteFontEntry(const nsACString
& aFaceName
, IDWriteFontFile
* aFontFile
,
162 IDWriteFontFileStream
* aFontFileStream
,
163 WeightRange aWeight
, StretchRange aStretch
,
164 SlantStyleRange aStyle
)
165 : gfxFontEntry(aFaceName
),
167 mFontFile(aFontFile
),
168 mFontFileStream(aFontFileStream
),
169 mIsSystemFont(false),
170 mForceGDIClassic(false),
171 mHasVariations(false),
172 mHasVariationsInitialized(false) {
173 mWeightRange
= aWeight
;
174 mStretchRange
= aStretch
;
175 mStyleRange
= aStyle
;
176 mIsDataUserFont
= true;
177 mIsCJK
= UNINITIALIZED_VALUE
;
180 gfxFontEntry
* Clone() const override
;
182 virtual ~gfxDWriteFontEntry();
184 hb_blob_t
* GetFontTable(uint32_t aTableTag
) override
;
186 nsresult
ReadCMAP(FontInfoData
* aFontInfoData
= nullptr) override
;
190 bool HasVariations() override
;
191 void GetVariationAxes(nsTArray
<gfxFontVariationAxis
>& aAxes
) override
;
192 void GetVariationInstances(
193 nsTArray
<gfxFontVariationInstance
>& aInstances
) override
;
195 void SetForceGDIClassic(bool aForce
) { mForceGDIClassic
= aForce
; }
196 bool GetForceGDIClassic() { return mForceGDIClassic
; }
198 void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
199 FontListSizes
* aSizes
) const override
;
200 void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
201 FontListSizes
* aSizes
) const override
;
204 friend class gfxDWriteFont
;
205 friend class gfxDWriteFontList
;
206 friend class gfxDWriteFontFamily
;
208 virtual nsresult
CopyFontTable(uint32_t aTableTag
,
209 nsTArray
<uint8_t>& aBuffer
) override
;
211 virtual gfxFont
* CreateFontInstance(const gfxFontStyle
* aFontStyle
);
213 nsresult
CreateFontFace(
214 IDWriteFontFace
** aFontFace
, const gfxFontStyle
* aFontStyle
= nullptr,
215 DWRITE_FONT_SIMULATIONS aSimulations
= DWRITE_FONT_SIMULATIONS_NONE
,
216 const nsTArray
<gfxFontVariation
>* aVariations
= nullptr);
218 static bool InitLogFont(IDWriteFont
* aFont
, LOGFONTW
* aLogFont
);
221 * A fontentry only needs to have either of these. If it has both only
222 * the IDWriteFont will be used.
224 RefPtr
<IDWriteFont
> mFont
;
225 RefPtr
<IDWriteFontFile
> mFontFile
;
227 // For custom fonts, we hold a reference to the IDWriteFontFileStream for
228 // for the IDWriteFontFile, so that the data is available.
229 RefPtr
<IDWriteFontFileStream
> mFontFileStream
;
231 // font face corresponding to the mFont/mFontFile *without* any DWrite
232 // style simulations applied
233 RefPtr
<IDWriteFontFace
> mFontFace
;
234 // Extended fontface interface if supported, else null
235 RefPtr
<IDWriteFontFace5
> mFontFace5
;
237 DWRITE_FONT_FACE_TYPE mFaceType
;
241 bool mForceGDIClassic
;
243 bool mHasVariationsInitialized
;
245 // Set to true only if the font belongs to a "simple" family where the
246 // faces can be reliably identified via a GDI LOGFONT structure.
247 bool mMayUseGDIAccess
= false;
249 mozilla::ThreadSafeWeakPtr
<mozilla::gfx::UnscaledFontDWrite
> mUnscaledFont
;
250 mozilla::ThreadSafeWeakPtr
<mozilla::gfx::UnscaledFontDWrite
>
254 // custom text renderer used to determine the fallback font for a given char
255 class DWriteFontFallbackRenderer final
: public IDWriteTextRenderer
{
257 explicit DWriteFontFallbackRenderer(IDWriteFactory
* aFactory
) : mRefCount(0) {
259 aFactory
->GetSystemFontCollection(getter_AddRefs(mSystemFonts
));
260 NS_ASSERTION(SUCCEEDED(hr
), "GetSystemFontCollection failed!");
264 ~DWriteFontFallbackRenderer() {}
266 // If we don't have an mSystemFonts pointer, this renderer is unusable.
267 bool IsValid() const { return mSystemFonts
; }
269 // IDWriteTextRenderer methods
270 IFACEMETHOD(DrawGlyphRun
)
271 (void* clientDrawingContext
, FLOAT baselineOriginX
, FLOAT baselineOriginY
,
272 DWRITE_MEASURING_MODE measuringMode
, DWRITE_GLYPH_RUN
const* glyphRun
,
273 DWRITE_GLYPH_RUN_DESCRIPTION
const* glyphRunDescription
,
274 IUnknown
* clientDrawingEffect
);
276 IFACEMETHOD(DrawUnderline
)
277 (void* clientDrawingContext
, FLOAT baselineOriginX
, FLOAT baselineOriginY
,
278 DWRITE_UNDERLINE
const* underline
, IUnknown
* clientDrawingEffect
) {
282 IFACEMETHOD(DrawStrikethrough
)
283 (void* clientDrawingContext
, FLOAT baselineOriginX
, FLOAT baselineOriginY
,
284 DWRITE_STRIKETHROUGH
const* strikethrough
, IUnknown
* clientDrawingEffect
) {
288 IFACEMETHOD(DrawInlineObject
)
289 (void* clientDrawingContext
, FLOAT originX
, FLOAT originY
,
290 IDWriteInlineObject
* inlineObject
, BOOL isSideways
, BOOL isRightToLeft
,
291 IUnknown
* clientDrawingEffect
) {
295 // IDWritePixelSnapping methods
297 IFACEMETHOD(IsPixelSnappingDisabled
)
298 (void* clientDrawingContext
, BOOL
* isDisabled
) {
303 IFACEMETHOD(GetCurrentTransform
)
304 (void* clientDrawingContext
, DWRITE_MATRIX
* transform
) {
305 const DWRITE_MATRIX ident
= {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
310 IFACEMETHOD(GetPixelsPerDip
)
311 (void* clientDrawingContext
, FLOAT
* pixelsPerDip
) {
312 *pixelsPerDip
= 1.0f
;
318 IFACEMETHOD_(unsigned long, AddRef
)() {
319 return InterlockedIncrement(&mRefCount
);
322 IFACEMETHOD_(unsigned long, Release
)() {
323 unsigned long newCount
= InterlockedDecrement(&mRefCount
);
332 IFACEMETHOD(QueryInterface
)(IID
const& riid
, void** ppvObject
) {
333 if (__uuidof(IDWriteTextRenderer
) == riid
) {
335 } else if (__uuidof(IDWritePixelSnapping
) == riid
) {
337 } else if (__uuidof(IUnknown
) == riid
) {
340 *ppvObject
= nullptr;
348 const nsCString
& FallbackFamilyName() { return mFamilyName
; }
352 RefPtr
<IDWriteFontCollection
> mSystemFonts
;
353 nsCString mFamilyName
;
356 class gfxDWriteFontList final
: public gfxPlatformFontList
{
359 virtual ~gfxDWriteFontList() { AutoLock
lock(mLock
); }
361 static gfxDWriteFontList
* PlatformFontList() {
362 return static_cast<gfxDWriteFontList
*>(
363 gfxPlatformFontList::PlatformFontList());
366 // initialize font lists
367 nsresult
InitFontListForPlatform() MOZ_REQUIRES(mLock
) override
;
368 void InitSharedFontListForPlatform() MOZ_REQUIRES(mLock
) override
;
370 FontVisibility
GetVisibilityForFamily(const nsACString
& aName
) const;
372 gfxFontFamily
* CreateFontFamily(const nsACString
& aName
,
373 FontVisibility aVisibility
) const override
;
375 gfxFontEntry
* CreateFontEntry(
376 mozilla::fontlist::Face
* aFace
,
377 const mozilla::fontlist::Family
* aFamily
) override
;
379 void ReadFaceNamesForFamily(mozilla::fontlist::Family
* aFamily
,
380 bool aNeedFullnamePostscriptNames
)
381 MOZ_REQUIRES(mLock
) override
;
383 bool ReadFaceNames(const mozilla::fontlist::Family
* aFamily
,
384 const mozilla::fontlist::Face
* aFace
, nsCString
& aPSName
,
385 nsCString
& aFullName
) override
;
387 void GetFacesInitDataForFamily(
388 const mozilla::fontlist::Family
* aFamily
,
389 nsTArray
<mozilla::fontlist::Face::InitData
>& aFaces
,
390 bool aLoadCmaps
) const override
;
392 gfxFontEntry
* LookupLocalFont(nsPresContext
* aPresContext
,
393 const nsACString
& aFontName
,
394 WeightRange aWeightForEntry
,
395 StretchRange aStretchForEntry
,
396 SlantStyleRange aStyleForEntry
) override
;
398 gfxFontEntry
* MakePlatformFont(const nsACString
& aFontName
,
399 WeightRange aWeightForEntry
,
400 StretchRange aStretchForEntry
,
401 SlantStyleRange aStyleForEntry
,
402 const uint8_t* aFontData
,
403 uint32_t aLength
) override
;
405 IDWriteGdiInterop
* GetGDIInterop() { return mGDIInterop
; }
406 bool UseGDIFontTableAccess() const;
408 bool FindAndAddFamiliesLocked(
409 nsPresContext
* aPresContext
, mozilla::StyleGenericFontFamily aGeneric
,
410 const nsACString
& aFamily
, nsTArray
<FamilyAndGeneric
>* aOutput
,
411 FindFamiliesFlags aFlags
, gfxFontStyle
* aStyle
= nullptr,
412 nsAtom
* aLanguage
= nullptr, gfxFloat aDevToCssSize
= 1.0)
413 MOZ_REQUIRES(mLock
) override
;
415 gfxFloat
GetForceGDIClassicMaxFontSize() {
416 return mForceGDIClassicMaxFontSize
;
419 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
420 FontListSizes
* aSizes
) const;
421 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf
,
422 FontListSizes
* aSizes
) const;
425 FontFamily
GetDefaultFontForPlatform(nsPresContext
* aPresContext
,
426 const gfxFontStyle
* aStyle
,
427 nsAtom
* aLanguage
= nullptr)
428 MOZ_REQUIRES(mLock
) override
;
430 // attempt to use platform-specific fallback for the given character,
431 // return null if no usable result found
432 gfxFontEntry
* PlatformGlobalFontFallback(nsPresContext
* aPresContext
,
435 const gfxFontStyle
* aMatchStyle
,
436 FontFamily
& aMatchedFamily
)
437 MOZ_REQUIRES(mLock
) override
;
439 nsTArray
<std::pair
<const char**, uint32_t>> GetFilteredPlatformFontLists()
443 friend class gfxDWriteFontFamily
;
445 nsresult
GetFontSubstitutes() MOZ_REQUIRES(mLock
);
447 void GetDirectWriteSubstitutes() MOZ_REQUIRES(mLock
);
449 virtual bool UsesSystemFallback() { return true; }
451 void GetFontsFromCollection(IDWriteFontCollection
* aCollection
)
454 void AppendFamiliesFromCollection(
455 IDWriteFontCollection
* aCollection
,
456 nsTArray
<mozilla::fontlist::Family::InitData
>& aFamilies
,
457 const nsTArray
<nsCString
>* aForceClassicFams
= nullptr)
460 #ifdef MOZ_BUNDLED_FONTS
461 already_AddRefed
<IDWriteFontCollection
> CreateBundledFontsCollection(
462 IDWriteFactory
* aFactory
);
466 * Fonts listed in the registry as substitutes but for which no actual
467 * font family is found.
469 nsTArray
<nsCString
> mNonExistingFonts
;
472 * Table of font substitutes, we grab this from the registry to get
473 * alternative font names.
475 FontFamilyTable mFontSubstitutes
;
476 nsClassHashtable
<nsCStringHashKey
, nsCString
> mSubstitutions
;
478 virtual already_AddRefed
<FontInfoData
> CreateFontInfoData();
480 gfxFloat mForceGDIClassicMaxFontSize
;
482 // whether to use GDI font table access routines
483 bool mGDIFontTableAccess
;
484 RefPtr
<IDWriteGdiInterop
> mGDIInterop
;
486 RefPtr
<DWriteFontFallbackRenderer
> mFallbackRenderer
;
487 RefPtr
<IDWriteTextFormat
> mFallbackFormat
;
489 RefPtr
<IDWriteFontCollection
> mSystemFonts
;
490 #ifdef MOZ_BUNDLED_FONTS
491 RefPtr
<IDWriteFontCollection
> mBundledFonts
;
495 #endif /* GFX_DWRITEFONTLIST_H */