wbemprox: Support overriding the CIM to VARIANT type mapping for method parameters.
[wine] / dlls / dwrite / font.c
1 /*
2  *    Font and collections
3  *
4  * Copyright 2012 Nikolay Sivov for CodeWeavers
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include "dwrite.h"
24 #include "dwrite_private.h"
25
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
29
30 /* PANOSE is 10 bytes in size, need to pack the structure properly */
31 #include "pshpack2.h"
32 typedef struct
33 {
34     USHORT version;
35     SHORT xAvgCharWidth;
36     USHORT usWeightClass;
37     USHORT usWidthClass;
38     SHORT fsType;
39     SHORT ySubscriptXSize;
40     SHORT ySubscriptYSize;
41     SHORT ySubscriptXOffset;
42     SHORT ySubscriptYOffset;
43     SHORT ySuperscriptXSize;
44     SHORT ySuperscriptYSize;
45     SHORT ySuperscriptXOffset;
46     SHORT ySuperscriptYOffset;
47     SHORT yStrikeoutSize;
48     SHORT yStrikeoutPosition;
49     SHORT sFamilyClass;
50     PANOSE panose;
51     ULONG ulUnicodeRange1;
52     ULONG ulUnicodeRange2;
53     ULONG ulUnicodeRange3;
54     ULONG ulUnicodeRange4;
55     CHAR achVendID[4];
56     USHORT fsSelection;
57     USHORT usFirstCharIndex;
58     USHORT usLastCharIndex;
59     /* According to the Apple spec, original version didn't have the below fields,
60      * version numbers were taken from the OpenType spec.
61      */
62     /* version 0 (TrueType 1.5) */
63     USHORT sTypoAscender;
64     USHORT sTypoDescender;
65     USHORT sTypoLineGap;
66     USHORT usWinAscent;
67     USHORT usWinDescent;
68     /* version 1 (TrueType 1.66) */
69     ULONG ulCodePageRange1;
70     ULONG ulCodePageRange2;
71     /* version 2 (OpenType 1.2) */
72     SHORT sxHeight;
73     SHORT sCapHeight;
74     USHORT usDefaultChar;
75     USHORT usBreakChar;
76     USHORT usMaxContext;
77 } TT_OS2_V2;
78 #include "poppack.h"
79
80 #ifdef WORDS_BIGENDIAN
81 #define GET_BE_WORD(x) (x)
82 #define GET_BE_DWORD(x) (x)
83 #else
84 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
85 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
86 #endif
87
88 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
89                     ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
90                     ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
91 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
92
93 struct dwrite_fontfamily {
94     IDWriteFontFamily IDWriteFontFamily_iface;
95     LONG ref;
96
97     WCHAR *familyname;
98 };
99
100 struct dwrite_font {
101     IDWriteFont IDWriteFont_iface;
102     LONG ref;
103
104     IDWriteFontFamily *family;
105     IDWriteFontFace *face;
106     DWRITE_FONT_STYLE style;
107     DWRITE_FONT_STRETCH stretch;
108     DWRITE_FONT_WEIGHT weight;
109 };
110
111 struct dwrite_fontface {
112     IDWriteFontFace IDWriteFontFace_iface;
113     LONG ref;
114 };
115
116 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
117 {
118     return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
119 }
120
121 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
122 {
123     return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
124 }
125
126 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
127 {
128     return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
129 }
130
131 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
132 {
133     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
134
135     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
136
137     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
138     {
139         *obj = iface;
140         IDWriteFontFace_AddRef(iface);
141         return S_OK;
142     }
143
144     *obj = NULL;
145     return E_NOINTERFACE;
146 }
147
148 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
149 {
150     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
151     ULONG ref = InterlockedIncrement(&This->ref);
152     TRACE("(%p)->(%d)\n", This, ref);
153     return ref;
154 }
155
156 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
157 {
158     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
159     ULONG ref = InterlockedDecrement(&This->ref);
160
161     TRACE("(%p)->(%d)\n", This, ref);
162
163     if (!ref)
164         heap_free(This);
165
166     return S_OK;
167 }
168
169 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
170 {
171     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
172     FIXME("(%p): stub\n", This);
173     return DWRITE_FONT_FACE_TYPE_UNKNOWN;
174 }
175
176 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
177     IDWriteFontFile **fontfiles)
178 {
179     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
180     FIXME("(%p)->(%p %p): stub\n", This, number_of_files, fontfiles);
181     return E_NOTIMPL;
182 }
183
184 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
185 {
186     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
187     FIXME("(%p): stub\n", This);
188     return 0;
189 }
190
191 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
192 {
193     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
194     FIXME("(%p): stub\n", This);
195     return DWRITE_FONT_SIMULATIONS_NONE;
196 }
197
198 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
199 {
200     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
201     FIXME("(%p): stub\n", This);
202     return FALSE;
203 }
204
205 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
206 {
207     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
208     FIXME("(%p)->(%p): stub\n", This, metrics);
209 }
210
211 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
212 {
213     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
214     FIXME("(%p): stub\n", This);
215     return 0;
216 }
217
218 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
219     UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
220 {
221     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
222     FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
223     return E_NOTIMPL;
224 }
225
226 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
227     UINT32 count, UINT16 *glyph_indices)
228 {
229     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
230     FIXME("(%p)->(%p %u %p): stub\n", This, codepoints, count, glyph_indices);
231     return E_NOTIMPL;
232 }
233
234 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
235     const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
236 {
237     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
238     FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
239     return E_NOTIMPL;
240 }
241
242 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
243 {
244     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
245     FIXME("(%p)->(%p): stub\n", This, table_context);
246 }
247
248 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
249     UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
250     UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
251 {
252     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
253     FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
254         glyph_count, is_sideways, is_rtl, geometrysink);
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
259     FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
260 {
261     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
262     FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
263     return E_NOTIMPL;
264 }
265
266 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
267     DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
268 {
269     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
270     FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
271     return E_NOTIMPL;
272 }
273
274 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
275     DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
276     DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
277 {
278     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
279     FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
280         glyph_count, metrics, is_sideways);
281     return E_NOTIMPL;
282 }
283
284 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
285     dwritefontface_QueryInterface,
286     dwritefontface_AddRef,
287     dwritefontface_Release,
288     dwritefontface_GetType,
289     dwritefontface_GetFiles,
290     dwritefontface_GetIndex,
291     dwritefontface_GetSimulations,
292     dwritefontface_IsSymbolFont,
293     dwritefontface_GetMetrics,
294     dwritefontface_GetGlyphCount,
295     dwritefontface_GetDesignGlyphMetrics,
296     dwritefontface_GetGlyphIndices,
297     dwritefontface_TryGetFontTable,
298     dwritefontface_ReleaseFontTable,
299     dwritefontface_GetGlyphRunOutline,
300     dwritefontface_GetRecommendedRenderingMode,
301     dwritefontface_GetGdiCompatibleMetrics,
302     dwritefontface_GetGdiCompatibleGlyphMetrics
303 };
304
305 static HRESULT create_fontface(IDWriteFontFace **face)
306 {
307     struct dwrite_fontface *This;
308
309     *face = NULL;
310
311     This = heap_alloc(sizeof(struct dwrite_fontface));
312     if (!This) return E_OUTOFMEMORY;
313
314     This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
315     This->ref = 1;
316     *face = &This->IDWriteFontFace_iface;
317
318     return S_OK;
319 }
320
321 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
322 {
323     struct dwrite_font *This = impl_from_IDWriteFont(iface);
324
325     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
326
327     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
328     {
329         *obj = iface;
330         IDWriteFont_AddRef(iface);
331         return S_OK;
332     }
333
334     *obj = NULL;
335     return E_NOINTERFACE;
336 }
337
338 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
339 {
340     struct dwrite_font *This = impl_from_IDWriteFont(iface);
341     ULONG ref = InterlockedIncrement(&This->ref);
342     TRACE("(%p)->(%d)\n", This, ref);
343     return ref;
344 }
345
346 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
347 {
348     struct dwrite_font *This = impl_from_IDWriteFont(iface);
349     ULONG ref = InterlockedDecrement(&This->ref);
350
351     TRACE("(%p)->(%d)\n", This, ref);
352
353     if (!ref)
354     {
355         IDWriteFontFamily_Release(This->family);
356         heap_free(This);
357     }
358
359     return S_OK;
360 }
361
362 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
363 {
364     struct dwrite_font *This = impl_from_IDWriteFont(iface);
365     TRACE("(%p)->(%p)\n", This, family);
366
367     *family = This->family;
368     IDWriteFontFamily_AddRef(*family);
369     return S_OK;
370 }
371
372 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
373 {
374     struct dwrite_font *This = impl_from_IDWriteFont(iface);
375     TRACE("(%p)\n", This);
376     return This->weight;
377 }
378
379 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
380 {
381     struct dwrite_font *This = impl_from_IDWriteFont(iface);
382     TRACE("(%p)\n", This);
383     return This->stretch;
384 }
385
386 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
387 {
388     struct dwrite_font *This = impl_from_IDWriteFont(iface);
389     TRACE("(%p)\n", This);
390     return This->style;
391 }
392
393 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
394 {
395     struct dwrite_font *This = impl_from_IDWriteFont(iface);
396     FIXME("(%p): stub\n", This);
397     return FALSE;
398 }
399
400 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
401 {
402     struct dwrite_font *This = impl_from_IDWriteFont(iface);
403     FIXME("(%p)->(%p): stub\n", This, names);
404     return E_NOTIMPL;
405 }
406
407 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
408     DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
409 {
410     struct dwrite_font *This = impl_from_IDWriteFont(iface);
411     FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
412     return E_NOTIMPL;
413 }
414
415 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
416 {
417     struct dwrite_font *This = impl_from_IDWriteFont(iface);
418     FIXME("(%p): stub\n", This);
419     return DWRITE_FONT_SIMULATIONS_NONE;
420 }
421
422 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
423 {
424     struct dwrite_font *This = impl_from_IDWriteFont(iface);
425     FIXME("(%p)->(%p): stub\n", This, metrics);
426 }
427
428 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
429 {
430     struct dwrite_font *This = impl_from_IDWriteFont(iface);
431     FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
432     return E_NOTIMPL;
433 }
434
435 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
436 {
437     struct dwrite_font *This = impl_from_IDWriteFont(iface);
438
439     TRACE("(%p)->(%p)\n", This, face);
440
441     if (!This->face)
442     {
443         HRESULT hr = create_fontface(&This->face);
444         if (FAILED(hr)) return hr;
445         *face = This->face;
446         return hr;
447     }
448
449     *face = This->face;
450     IDWriteFontFace_AddRef(*face);
451
452     return S_OK;
453 }
454
455 static const IDWriteFontVtbl dwritefontvtbl = {
456     dwritefont_QueryInterface,
457     dwritefont_AddRef,
458     dwritefont_Release,
459     dwritefont_GetFontFamily,
460     dwritefont_GetWeight,
461     dwritefont_GetStretch,
462     dwritefont_GetStyle,
463     dwritefont_IsSymbolFont,
464     dwritefont_GetFaceNames,
465     dwritefont_GetInformationalStrings,
466     dwritefont_GetSimulations,
467     dwritefont_GetMetrics,
468     dwritefont_HasCharacter,
469     dwritefont_CreateFontFace
470 };
471
472
473 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
474 {
475     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
476     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
477
478     if (IsEqualIID(riid, &IID_IUnknown) ||
479         IsEqualIID(riid, &IID_IDWriteFontList) ||
480         IsEqualIID(riid, &IID_IDWriteFontFamily))
481     {
482         *obj = iface;
483         IDWriteFontFamily_AddRef(iface);
484         return S_OK;
485     }
486
487     *obj = NULL;
488     return E_NOINTERFACE;
489 }
490
491 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
492 {
493     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
494     ULONG ref = InterlockedIncrement(&This->ref);
495     TRACE("(%p)->(%d)\n", This, ref);
496     return ref;
497 }
498
499 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
500 {
501     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
502     ULONG ref = InterlockedDecrement(&This->ref);
503
504     TRACE("(%p)->(%d)\n", This, ref);
505
506     if (!ref)
507     {
508         heap_free(This->familyname);
509         heap_free(This);
510     }
511
512     return S_OK;
513 }
514
515 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
516 {
517     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
518     FIXME("(%p)->(%p): stub\n", This, collection);
519     return E_NOTIMPL;
520 }
521
522 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
523 {
524     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
525     FIXME("(%p): stub\n", This);
526     return 0;
527 }
528
529 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
530 {
531     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
532     FIXME("(%p)->(%u %p): stub\n", This, index, font);
533     return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
537 {
538     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
539     static const WCHAR enusW[] = {'e','n','-','u','s',0};
540     HRESULT hr;
541
542     TRACE("(%p)->(%p)\n", This, names);
543
544     hr = create_localizedstrings(names);
545     if (FAILED(hr)) return hr;
546
547     return add_localizedstring(*names, enusW, This->familyname);
548 }
549
550 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
551     DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
552 {
553     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
554     FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, font);
555     return E_NOTIMPL;
556 }
557
558 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
559     DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
560 {
561     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
562     FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
563     return E_NOTIMPL;
564 }
565
566 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
567     dwritefontfamily_QueryInterface,
568     dwritefontfamily_AddRef,
569     dwritefontfamily_Release,
570     dwritefontfamily_GetFontCollection,
571     dwritefontfamily_GetFontCount,
572     dwritefontfamily_GetFont,
573     dwritefontfamily_GetFamilyNames,
574     dwritefontfamily_GetFirstMatchingFont,
575     dwritefontfamily_GetMatchingFonts
576 };
577
578 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
579 {
580     struct dwrite_fontfamily *This;
581
582     *family = NULL;
583
584     This = heap_alloc(sizeof(struct dwrite_fontfamily));
585     if (!This) return E_OUTOFMEMORY;
586
587     This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
588     This->ref = 1;
589     This->familyname = heap_strdupW(familyname);
590
591     *family = &This->IDWriteFontFamily_iface;
592
593     return S_OK;
594 }
595
596 static void get_font_properties(struct dwrite_font *font, HDC hdc)
597 {
598     TT_OS2_V2 tt_os2;
599     LONG size;
600
601     /* default stretch and weight to normal */
602     font->stretch = DWRITE_FONT_STRETCH_NORMAL;
603     font->weight = DWRITE_FONT_WEIGHT_NORMAL;
604
605     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
606     if (size != GDI_ERROR)
607     {
608         if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
609
610         memset(&tt_os2, 0, sizeof(tt_os2));
611         if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return;
612
613         /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
614         if (GET_BE_WORD(tt_os2.usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
615             font->stretch = GET_BE_WORD(tt_os2.usWidthClass);
616
617         font->weight = GET_BE_WORD(tt_os2.usWeightClass);
618         TRACE("stretch=%d, weight=%d\n", font->stretch, font->weight);
619     }
620 }
621
622 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
623 {
624     const WCHAR* facename, *familyname;
625     struct dwrite_font *This;
626     IDWriteFontFamily *family;
627     OUTLINETEXTMETRICW *otm;
628     HRESULT hr;
629     HFONT hfont;
630     HDC hdc;
631     int ret;
632
633     *font = NULL;
634
635     This = heap_alloc(sizeof(struct dwrite_font));
636     if (!This) return E_OUTOFMEMORY;
637
638     hfont = CreateFontIndirectW(logfont);
639     if (!hfont)
640     {
641         heap_free(This);
642         return DWRITE_E_NOFONT;
643     }
644
645     hdc = CreateCompatibleDC(0);
646     SelectObject(hdc, hfont);
647
648     ret = GetOutlineTextMetricsW(hdc, 0, NULL);
649     otm = heap_alloc(ret);
650     otm->otmSize = ret;
651     ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
652
653     get_font_properties(This, hdc);
654
655     DeleteDC(hdc);
656     DeleteObject(hfont);
657
658     facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
659     familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
660     TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
661
662     hr = create_fontfamily(familyname, &family);
663     heap_free(otm);
664     if (hr != S_OK)
665     {
666         heap_free(This);
667         return hr;
668     }
669
670     This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
671     This->ref = 1;
672     This->face = NULL;
673     This->family = family;
674     This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
675
676     *font = &This->IDWriteFont_iface;
677
678     return S_OK;
679 }