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