jscript: Get rid of BSTR in date.c.
[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 };
109
110 struct dwrite_fontface {
111     IDWriteFontFace IDWriteFontFace_iface;
112     LONG ref;
113 };
114
115 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
116 {
117     return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
118 }
119
120 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
121 {
122     return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
123 }
124
125 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
126 {
127     return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
128 }
129
130 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
131 {
132     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
133
134     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
135
136     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
137     {
138         *obj = iface;
139         IDWriteFontFace_AddRef(iface);
140         return S_OK;
141     }
142
143     *obj = NULL;
144     return E_NOINTERFACE;
145 }
146
147 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
148 {
149     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
150     ULONG ref = InterlockedIncrement(&This->ref);
151     TRACE("(%p)->(%d)\n", This, ref);
152     return ref;
153 }
154
155 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
156 {
157     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
158     ULONG ref = InterlockedDecrement(&This->ref);
159
160     TRACE("(%p)->(%d)\n", This, ref);
161
162     if (!ref)
163         heap_free(This);
164
165     return S_OK;
166 }
167
168 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
169 {
170     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
171     FIXME("(%p): stub\n", This);
172     return DWRITE_FONT_FACE_TYPE_UNKNOWN;
173 }
174
175 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
176     IDWriteFontFile **fontfiles)
177 {
178     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
179     FIXME("(%p)->(%p %p): stub\n", This, number_of_files, fontfiles);
180     return E_NOTIMPL;
181 }
182
183 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
184 {
185     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
186     FIXME("(%p): stub\n", This);
187     return 0;
188 }
189
190 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
191 {
192     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
193     FIXME("(%p): stub\n", This);
194     return DWRITE_FONT_SIMULATIONS_NONE;
195 }
196
197 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
198 {
199     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
200     FIXME("(%p): stub\n", This);
201     return FALSE;
202 }
203
204 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
205 {
206     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
207     FIXME("(%p)->(%p): stub\n", This, metrics);
208 }
209
210 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
211 {
212     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
213     FIXME("(%p): stub\n", This);
214     return 0;
215 }
216
217 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
218     UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
219 {
220     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
221     FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
222     return E_NOTIMPL;
223 }
224
225 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
226     UINT32 count, UINT16 *glyph_indices)
227 {
228     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
229     FIXME("(%p)->(%p %u %p): stub\n", This, codepoints, count, glyph_indices);
230     return E_NOTIMPL;
231 }
232
233 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
234     const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
235 {
236     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
237     FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
238     return E_NOTIMPL;
239 }
240
241 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
242 {
243     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
244     FIXME("(%p)->(%p): stub\n", This, table_context);
245 }
246
247 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
248     UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
249     UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
250 {
251     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
252     FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
253         glyph_count, is_sideways, is_rtl, geometrysink);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
258     FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
259 {
260     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
261     FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
266     DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
267 {
268     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
269     FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
270     return E_NOTIMPL;
271 }
272
273 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
274     DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
275     DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
276 {
277     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
278     FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
279         glyph_count, metrics, is_sideways);
280     return E_NOTIMPL;
281 }
282
283 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
284     dwritefontface_QueryInterface,
285     dwritefontface_AddRef,
286     dwritefontface_Release,
287     dwritefontface_GetType,
288     dwritefontface_GetFiles,
289     dwritefontface_GetIndex,
290     dwritefontface_GetSimulations,
291     dwritefontface_IsSymbolFont,
292     dwritefontface_GetMetrics,
293     dwritefontface_GetGlyphCount,
294     dwritefontface_GetDesignGlyphMetrics,
295     dwritefontface_GetGlyphIndices,
296     dwritefontface_TryGetFontTable,
297     dwritefontface_ReleaseFontTable,
298     dwritefontface_GetGlyphRunOutline,
299     dwritefontface_GetRecommendedRenderingMode,
300     dwritefontface_GetGdiCompatibleMetrics,
301     dwritefontface_GetGdiCompatibleGlyphMetrics
302 };
303
304 static HRESULT create_fontface(IDWriteFontFace **face)
305 {
306     struct dwrite_fontface *This;
307
308     *face = NULL;
309
310     This = heap_alloc(sizeof(struct dwrite_fontface));
311     if (!This) return E_OUTOFMEMORY;
312
313     This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
314     This->ref = 1;
315     *face = &This->IDWriteFontFace_iface;
316
317     return S_OK;
318 }
319
320 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
321 {
322     struct dwrite_font *This = impl_from_IDWriteFont(iface);
323
324     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
325
326     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
327     {
328         *obj = iface;
329         IDWriteFont_AddRef(iface);
330         return S_OK;
331     }
332
333     *obj = NULL;
334     return E_NOINTERFACE;
335 }
336
337 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
338 {
339     struct dwrite_font *This = impl_from_IDWriteFont(iface);
340     ULONG ref = InterlockedIncrement(&This->ref);
341     TRACE("(%p)->(%d)\n", This, ref);
342     return ref;
343 }
344
345 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
346 {
347     struct dwrite_font *This = impl_from_IDWriteFont(iface);
348     ULONG ref = InterlockedDecrement(&This->ref);
349
350     TRACE("(%p)->(%d)\n", This, ref);
351
352     if (!ref)
353     {
354         IDWriteFontFamily_Release(This->family);
355         heap_free(This);
356     }
357
358     return S_OK;
359 }
360
361 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
362 {
363     struct dwrite_font *This = impl_from_IDWriteFont(iface);
364     TRACE("(%p)->(%p)\n", This, family);
365
366     *family = This->family;
367     IDWriteFontFamily_AddRef(*family);
368     return S_OK;
369 }
370
371 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
372 {
373     struct dwrite_font *This = impl_from_IDWriteFont(iface);
374     FIXME("(%p): stub\n", This);
375     return 0;
376 }
377
378 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
379 {
380     struct dwrite_font *This = impl_from_IDWriteFont(iface);
381     TRACE("(%p)\n", This);
382     return This->stretch;
383 }
384
385 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
386 {
387     struct dwrite_font *This = impl_from_IDWriteFont(iface);
388     TRACE("(%p)\n", This);
389     return This->style;
390 }
391
392 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
393 {
394     struct dwrite_font *This = impl_from_IDWriteFont(iface);
395     FIXME("(%p): stub\n", This);
396     return FALSE;
397 }
398
399 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
400 {
401     struct dwrite_font *This = impl_from_IDWriteFont(iface);
402     FIXME("(%p)->(%p): stub\n", This, names);
403     return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
407     DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
408 {
409     struct dwrite_font *This = impl_from_IDWriteFont(iface);
410     FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
411     return E_NOTIMPL;
412 }
413
414 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
415 {
416     struct dwrite_font *This = impl_from_IDWriteFont(iface);
417     FIXME("(%p): stub\n", This);
418     return DWRITE_FONT_SIMULATIONS_NONE;
419 }
420
421 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
422 {
423     struct dwrite_font *This = impl_from_IDWriteFont(iface);
424     FIXME("(%p)->(%p): stub\n", This, metrics);
425 }
426
427 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
428 {
429     struct dwrite_font *This = impl_from_IDWriteFont(iface);
430     FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
431     return E_NOTIMPL;
432 }
433
434 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
435 {
436     struct dwrite_font *This = impl_from_IDWriteFont(iface);
437
438     TRACE("(%p)->(%p)\n", This, face);
439
440     if (!This->face)
441     {
442         HRESULT hr = create_fontface(&This->face);
443         if (FAILED(hr)) return hr;
444         *face = This->face;
445         return hr;
446     }
447
448     *face = This->face;
449     IDWriteFontFace_AddRef(*face);
450
451     return S_OK;
452 }
453
454 static const IDWriteFontVtbl dwritefontvtbl = {
455     dwritefont_QueryInterface,
456     dwritefont_AddRef,
457     dwritefont_Release,
458     dwritefont_GetFontFamily,
459     dwritefont_GetWeight,
460     dwritefont_GetStretch,
461     dwritefont_GetStyle,
462     dwritefont_IsSymbolFont,
463     dwritefont_GetFaceNames,
464     dwritefont_GetInformationalStrings,
465     dwritefont_GetSimulations,
466     dwritefont_GetMetrics,
467     dwritefont_HasCharacter,
468     dwritefont_CreateFontFace
469 };
470
471
472 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
473 {
474     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
475     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
476
477     if (IsEqualIID(riid, &IID_IUnknown) ||
478         IsEqualIID(riid, &IID_IDWriteFontList) ||
479         IsEqualIID(riid, &IID_IDWriteFontFamily))
480     {
481         *obj = iface;
482         IDWriteFontFamily_AddRef(iface);
483         return S_OK;
484     }
485
486     *obj = NULL;
487     return E_NOINTERFACE;
488 }
489
490 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
491 {
492     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
493     ULONG ref = InterlockedIncrement(&This->ref);
494     TRACE("(%p)->(%d)\n", This, ref);
495     return ref;
496 }
497
498 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
499 {
500     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
501     ULONG ref = InterlockedDecrement(&This->ref);
502
503     TRACE("(%p)->(%d)\n", This, ref);
504
505     if (!ref)
506     {
507         heap_free(This->familyname);
508         heap_free(This);
509     }
510
511     return S_OK;
512 }
513
514 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
515 {
516     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
517     FIXME("(%p)->(%p): stub\n", This, collection);
518     return E_NOTIMPL;
519 }
520
521 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
522 {
523     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
524     FIXME("(%p): stub\n", This);
525     return 0;
526 }
527
528 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
529 {
530     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
531     FIXME("(%p)->(%u %p): stub\n", This, index, font);
532     return E_NOTIMPL;
533 }
534
535 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
536 {
537     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
538     static const WCHAR enusW[] = {'e','n','-','u','s',0};
539     HRESULT hr;
540
541     TRACE("(%p)->(%p)\n", This, names);
542
543     hr = create_localizedstrings(names);
544     if (FAILED(hr)) return hr;
545
546     return add_localizedstring(*names, enusW, This->familyname);
547 }
548
549 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
550     DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
551 {
552     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
553     FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, font);
554     return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
558     DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
559 {
560     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
561     FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
562     return E_NOTIMPL;
563 }
564
565 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
566     dwritefontfamily_QueryInterface,
567     dwritefontfamily_AddRef,
568     dwritefontfamily_Release,
569     dwritefontfamily_GetFontCollection,
570     dwritefontfamily_GetFontCount,
571     dwritefontfamily_GetFont,
572     dwritefontfamily_GetFamilyNames,
573     dwritefontfamily_GetFirstMatchingFont,
574     dwritefontfamily_GetMatchingFonts
575 };
576
577 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
578 {
579     struct dwrite_fontfamily *This;
580
581     *family = NULL;
582
583     This = heap_alloc(sizeof(struct dwrite_fontfamily));
584     if (!This) return E_OUTOFMEMORY;
585
586     This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
587     This->ref = 1;
588     This->familyname = heap_strdupW(familyname);
589
590     *family = &This->IDWriteFontFamily_iface;
591
592     return S_OK;
593 }
594
595 static DWRITE_FONT_STRETCH get_font_stretch(HDC hdc)
596 {
597     DWRITE_FONT_STRETCH stretch;
598     TT_OS2_V2 tt_os2;
599     LONG size;
600
601     /* default stretch to normal */
602     stretch = DWRITE_FONT_STRETCH_NORMAL;
603
604     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
605     if (size == GDI_ERROR) return stretch;
606
607     if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
608
609     memset(&tt_os2, 0, sizeof(tt_os2));
610     if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return stretch;
611
612     /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
613     if (GET_BE_WORD(tt_os2.usWeightClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
614         stretch = GET_BE_WORD(tt_os2.usWeightClass);
615
616     return stretch;
617 }
618
619 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
620 {
621     const WCHAR* facename, *familyname;
622     struct dwrite_font *This;
623     IDWriteFontFamily *family;
624     OUTLINETEXTMETRICW *otm;
625     DWRITE_FONT_STRETCH stretch;
626     HRESULT hr;
627     HFONT hfont;
628     HDC hdc;
629     int ret;
630
631     *font = NULL;
632
633     hfont = CreateFontIndirectW(logfont);
634     if (!hfont) return DWRITE_E_NOFONT;
635
636     hdc = CreateCompatibleDC(0);
637     SelectObject(hdc, hfont);
638
639     ret = GetOutlineTextMetricsW(hdc, 0, NULL);
640     otm = heap_alloc(ret);
641     otm->otmSize = ret;
642     ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
643
644     stretch = get_font_stretch(hdc);
645
646     DeleteDC(hdc);
647     DeleteObject(hfont);
648
649     facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
650     familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
651     TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
652
653     hr = create_fontfamily(familyname, &family);
654     heap_free(otm);
655     if (hr != S_OK) return hr;
656
657     This = heap_alloc(sizeof(struct dwrite_font));
658     if (!This)
659     {
660         IDWriteFontFamily_Release(family);
661         return E_OUTOFMEMORY;
662     }
663
664     This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
665     This->ref = 1;
666     This->face = NULL;
667     This->family = family;
668     This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
669     This->stretch = stretch;
670
671     *font = &This->IDWriteFont_iface;
672
673     return S_OK;
674 }