|
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_GDIFONTLIST_H |
|
7 #define GFX_GDIFONTLIST_H |
|
8 |
|
9 #include "mozilla/MemoryReporting.h" |
|
10 #include "gfxWindowsPlatform.h" |
|
11 #include "gfxPlatformFontList.h" |
|
12 #include "nsGkAtoms.h" |
|
13 |
|
14 #include <windows.h> |
|
15 |
|
16 class AutoDC // get the global device context, and auto-release it on destruction |
|
17 { |
|
18 public: |
|
19 AutoDC() { |
|
20 mDC = ::GetDC(nullptr); |
|
21 } |
|
22 |
|
23 ~AutoDC() { |
|
24 ::ReleaseDC(nullptr, mDC); |
|
25 } |
|
26 |
|
27 HDC GetDC() { |
|
28 return mDC; |
|
29 } |
|
30 |
|
31 private: |
|
32 HDC mDC; |
|
33 }; |
|
34 |
|
35 class AutoSelectFont // select a font into the given DC, and auto-restore |
|
36 { |
|
37 public: |
|
38 AutoSelectFont(HDC aDC, LOGFONTW *aLogFont) |
|
39 : mOwnsFont(false) |
|
40 { |
|
41 mFont = ::CreateFontIndirectW(aLogFont); |
|
42 if (mFont) { |
|
43 mOwnsFont = true; |
|
44 mDC = aDC; |
|
45 mOldFont = (HFONT)::SelectObject(aDC, mFont); |
|
46 } else { |
|
47 mOldFont = nullptr; |
|
48 } |
|
49 } |
|
50 |
|
51 AutoSelectFont(HDC aDC, HFONT aFont) |
|
52 : mOwnsFont(false) |
|
53 { |
|
54 mDC = aDC; |
|
55 mFont = aFont; |
|
56 mOldFont = (HFONT)::SelectObject(aDC, aFont); |
|
57 } |
|
58 |
|
59 ~AutoSelectFont() { |
|
60 if (mOldFont) { |
|
61 ::SelectObject(mDC, mOldFont); |
|
62 if (mOwnsFont) { |
|
63 ::DeleteObject(mFont); |
|
64 } |
|
65 } |
|
66 } |
|
67 |
|
68 bool IsValid() const { |
|
69 return mFont != nullptr; |
|
70 } |
|
71 |
|
72 HFONT GetFont() const { |
|
73 return mFont; |
|
74 } |
|
75 |
|
76 private: |
|
77 HDC mDC; |
|
78 HFONT mFont; |
|
79 HFONT mOldFont; |
|
80 bool mOwnsFont; |
|
81 }; |
|
82 |
|
83 /** |
|
84 * List of different types of fonts we support on Windows. |
|
85 * These can generally be lumped in to 3 categories where we have to |
|
86 * do special things: Really old fonts bitmap and vector fonts (device |
|
87 * and raster), Type 1 fonts, and TrueType/OpenType fonts. |
|
88 * |
|
89 * This list is sorted in order from least prefered to most prefered. |
|
90 * We prefer Type1 fonts over OpenType fonts to avoid falling back to |
|
91 * things like Arial (opentype) when you ask for Helvetica (type1) |
|
92 **/ |
|
93 enum gfxWindowsFontType { |
|
94 GFX_FONT_TYPE_UNKNOWN = 0, |
|
95 GFX_FONT_TYPE_DEVICE, |
|
96 GFX_FONT_TYPE_RASTER, |
|
97 GFX_FONT_TYPE_TRUETYPE, |
|
98 GFX_FONT_TYPE_PS_OPENTYPE, |
|
99 GFX_FONT_TYPE_TT_OPENTYPE, |
|
100 GFX_FONT_TYPE_TYPE1 |
|
101 }; |
|
102 |
|
103 // A single member of a font family (i.e. a single face, such as Times Italic) |
|
104 // represented as a LOGFONT that will resolve to the correct face. |
|
105 // This replaces FontEntry from gfxWindowsFonts.h/cpp. |
|
106 class GDIFontEntry : public gfxFontEntry |
|
107 { |
|
108 public: |
|
109 LPLOGFONTW GetLogFont() { return &mLogFont; } |
|
110 |
|
111 nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); |
|
112 |
|
113 virtual bool IsSymbolFont(); |
|
114 |
|
115 void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize, |
|
116 bool aUseCleartype); |
|
117 |
|
118 static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, |
|
119 DWORD fontType) |
|
120 { |
|
121 gfxWindowsFontType feType; |
|
122 if (metrics.ntmFlags & NTM_TYPE1) |
|
123 feType = GFX_FONT_TYPE_TYPE1; |
|
124 else if (metrics.ntmFlags & NTM_PS_OPENTYPE) |
|
125 feType = GFX_FONT_TYPE_PS_OPENTYPE; |
|
126 else if (metrics.ntmFlags & NTM_TT_OPENTYPE) |
|
127 feType = GFX_FONT_TYPE_TT_OPENTYPE; |
|
128 else if (fontType == TRUETYPE_FONTTYPE) |
|
129 feType = GFX_FONT_TYPE_TRUETYPE; |
|
130 else if (fontType == RASTER_FONTTYPE) |
|
131 feType = GFX_FONT_TYPE_RASTER; |
|
132 else if (fontType == DEVICE_FONTTYPE) |
|
133 feType = GFX_FONT_TYPE_DEVICE; |
|
134 else |
|
135 feType = GFX_FONT_TYPE_UNKNOWN; |
|
136 |
|
137 return feType; |
|
138 } |
|
139 |
|
140 bool IsType1() const { |
|
141 return (mFontType == GFX_FONT_TYPE_TYPE1); |
|
142 } |
|
143 |
|
144 bool IsTrueType() const { |
|
145 return (mFontType == GFX_FONT_TYPE_TRUETYPE || |
|
146 mFontType == GFX_FONT_TYPE_PS_OPENTYPE || |
|
147 mFontType == GFX_FONT_TYPE_TT_OPENTYPE); |
|
148 } |
|
149 |
|
150 virtual bool MatchesGenericFamily(const nsACString& aGeneric) const { |
|
151 if (aGeneric.IsEmpty()) { |
|
152 return true; |
|
153 } |
|
154 |
|
155 // Japanese 'Mincho' fonts do not belong to FF_MODERN even if |
|
156 // they are fixed pitch because they have variable stroke width. |
|
157 if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) { |
|
158 return aGeneric.EqualsLiteral("monospace"); |
|
159 } |
|
160 |
|
161 // Japanese 'Gothic' fonts do not belong to FF_SWISS even if |
|
162 // they are variable pitch because they have constant stroke width. |
|
163 if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) { |
|
164 return aGeneric.EqualsLiteral("sans-serif"); |
|
165 } |
|
166 |
|
167 // All other fonts will be grouped correctly using family... |
|
168 switch (mWindowsFamily) { |
|
169 case FF_DONTCARE: |
|
170 return false; |
|
171 case FF_ROMAN: |
|
172 return aGeneric.EqualsLiteral("serif"); |
|
173 case FF_SWISS: |
|
174 return aGeneric.EqualsLiteral("sans-serif"); |
|
175 case FF_MODERN: |
|
176 return aGeneric.EqualsLiteral("monospace"); |
|
177 case FF_SCRIPT: |
|
178 return aGeneric.EqualsLiteral("cursive"); |
|
179 case FF_DECORATIVE: |
|
180 return aGeneric.EqualsLiteral("fantasy"); |
|
181 } |
|
182 |
|
183 return false; |
|
184 } |
|
185 |
|
186 virtual bool SupportsLangGroup(nsIAtom* aLangGroup) const { |
|
187 if (!aLangGroup || aLangGroup == nsGkAtoms::Unicode) { |
|
188 return true; |
|
189 } |
|
190 |
|
191 int16_t bit = -1; |
|
192 |
|
193 /* map our langgroup names in to Windows charset bits */ |
|
194 if (aLangGroup == nsGkAtoms::x_western) { |
|
195 bit = ANSI_CHARSET; |
|
196 } else if (aLangGroup == nsGkAtoms::Japanese) { |
|
197 bit = SHIFTJIS_CHARSET; |
|
198 } else if (aLangGroup == nsGkAtoms::ko) { |
|
199 bit = HANGEUL_CHARSET; |
|
200 } else if (aLangGroup == nsGkAtoms::ko_xxx) { |
|
201 bit = JOHAB_CHARSET; |
|
202 } else if (aLangGroup == nsGkAtoms::zh_cn) { |
|
203 bit = GB2312_CHARSET; |
|
204 } else if (aLangGroup == nsGkAtoms::zh_tw) { |
|
205 bit = CHINESEBIG5_CHARSET; |
|
206 } else if (aLangGroup == nsGkAtoms::el_) { |
|
207 bit = GREEK_CHARSET; |
|
208 } else if (aLangGroup == nsGkAtoms::tr) { |
|
209 bit = TURKISH_CHARSET; |
|
210 } else if (aLangGroup == nsGkAtoms::he) { |
|
211 bit = HEBREW_CHARSET; |
|
212 } else if (aLangGroup == nsGkAtoms::ar) { |
|
213 bit = ARABIC_CHARSET; |
|
214 } else if (aLangGroup == nsGkAtoms::x_baltic) { |
|
215 bit = BALTIC_CHARSET; |
|
216 } else if (aLangGroup == nsGkAtoms::x_cyrillic) { |
|
217 bit = RUSSIAN_CHARSET; |
|
218 } else if (aLangGroup == nsGkAtoms::th) { |
|
219 bit = THAI_CHARSET; |
|
220 } else if (aLangGroup == nsGkAtoms::x_central_euro) { |
|
221 bit = EASTEUROPE_CHARSET; |
|
222 } else if (aLangGroup == nsGkAtoms::x_symbol) { |
|
223 bit = SYMBOL_CHARSET; |
|
224 } |
|
225 |
|
226 if (bit != -1) { |
|
227 return mCharset.test(bit); |
|
228 } |
|
229 |
|
230 return false; |
|
231 } |
|
232 |
|
233 virtual bool SupportsRange(uint8_t range) { |
|
234 return mUnicodeRanges.test(range); |
|
235 } |
|
236 |
|
237 virtual bool SkipDuringSystemFallback() { |
|
238 return !HasCmapTable(); // explicitly skip non-SFNT fonts |
|
239 } |
|
240 |
|
241 virtual bool TestCharacterMap(uint32_t aCh); |
|
242 |
|
243 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
|
244 FontListSizes* aSizes) const; |
|
245 |
|
246 // create a font entry for a font with a given name |
|
247 static GDIFontEntry* CreateFontEntry(const nsAString& aName, |
|
248 gfxWindowsFontType aFontType, |
|
249 bool aItalic, |
|
250 uint16_t aWeight, int16_t aStretch, |
|
251 gfxUserFontData* aUserFontData, |
|
252 bool aFamilyHasItalicFace); |
|
253 |
|
254 // create a font entry for a font referenced by its fullname |
|
255 static GDIFontEntry* LoadLocalFont(const gfxProxyFontEntry &aProxyEntry, |
|
256 const nsAString& aFullname); |
|
257 |
|
258 uint8_t mWindowsFamily; |
|
259 uint8_t mWindowsPitch; |
|
260 |
|
261 gfxWindowsFontType mFontType; |
|
262 bool mForceGDI : 1; |
|
263 |
|
264 // For src:local user-fonts, we keep track of whether the platform family |
|
265 // contains an italic face, because in this case we can't safely ask GDI |
|
266 // to create synthetic italics (oblique) via the LOGFONT. |
|
267 // (For other types of font, this is just set to false.) |
|
268 bool mFamilyHasItalicFace : 1; |
|
269 |
|
270 gfxSparseBitSet mCharset; |
|
271 gfxSparseBitSet mUnicodeRanges; |
|
272 |
|
273 protected: |
|
274 friend class gfxWindowsFont; |
|
275 |
|
276 GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType, |
|
277 bool aItalic, uint16_t aWeight, int16_t aStretch, |
|
278 gfxUserFontData *aUserFontData, bool aFamilyHasItalicFace); |
|
279 |
|
280 void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType); |
|
281 |
|
282 virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold); |
|
283 |
|
284 virtual nsresult CopyFontTable(uint32_t aTableTag, |
|
285 FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE; |
|
286 |
|
287 LOGFONTW mLogFont; |
|
288 }; |
|
289 |
|
290 // a single font family, referencing one or more faces |
|
291 class GDIFontFamily : public gfxFontFamily |
|
292 { |
|
293 public: |
|
294 GDIFontFamily(nsAString &aName) : |
|
295 gfxFontFamily(aName) {} |
|
296 |
|
297 virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr); |
|
298 |
|
299 private: |
|
300 static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe, |
|
301 const NEWTEXTMETRICEXW *nmetrics, |
|
302 DWORD fontType, LPARAM data); |
|
303 }; |
|
304 |
|
305 class gfxGDIFontList : public gfxPlatformFontList { |
|
306 public: |
|
307 static gfxGDIFontList* PlatformFontList() { |
|
308 return static_cast<gfxGDIFontList*>(sPlatformFontList); |
|
309 } |
|
310 |
|
311 // initialize font lists |
|
312 virtual nsresult InitFontList(); |
|
313 |
|
314 virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); |
|
315 |
|
316 virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, |
|
317 const nsAString& aFontName); |
|
318 |
|
319 virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, |
|
320 const uint8_t *aFontData, uint32_t aLength); |
|
321 |
|
322 virtual bool ResolveFontName(const nsAString& aFontName, |
|
323 nsAString& aResolvedFontName); |
|
324 |
|
325 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
|
326 FontListSizes* aSizes) const; |
|
327 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, |
|
328 FontListSizes* aSizes) const; |
|
329 |
|
330 private: |
|
331 friend class gfxWindowsPlatform; |
|
332 |
|
333 gfxGDIFontList(); |
|
334 |
|
335 nsresult GetFontSubstitutes(); |
|
336 |
|
337 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, |
|
338 NEWTEXTMETRICEXW *lpntme, |
|
339 DWORD fontType, |
|
340 LPARAM lParam); |
|
341 |
|
342 virtual already_AddRefed<FontInfoData> CreateFontInfoData(); |
|
343 |
|
344 typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable; |
|
345 |
|
346 FontTable mFontSubstitutes; |
|
347 nsTArray<nsString> mNonExistingFonts; |
|
348 }; |
|
349 |
|
350 #endif /* GFX_GDIFONTLIST_H */ |