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