msvcrt: NULL terminate program arguments list in __getmainargs.
[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_fontcollection {
131     IDWriteFontCollection IDWriteFontCollection_iface;
132
133     WCHAR **families;
134     UINT32 count;
135     int alloc;
136 };
137
138 static IDWriteFontCollection *system_collection;
139
140 struct dwrite_fontfamily {
141     IDWriteFontFamily IDWriteFontFamily_iface;
142     LONG ref;
143
144     WCHAR *familyname;
145 };
146
147 struct dwrite_font {
148     IDWriteFont IDWriteFont_iface;
149     LONG ref;
150
151     IDWriteFontFamily *family;
152     IDWriteFontFace *face;
153     DWRITE_FONT_STYLE style;
154     DWRITE_FONT_STRETCH stretch;
155     DWRITE_FONT_WEIGHT weight;
156     DWRITE_FONT_METRICS metrics;
157     WCHAR *facename;
158 };
159
160 struct dwrite_fontface {
161     IDWriteFontFace IDWriteFontFace_iface;
162     LONG ref;
163
164     LOGFONTW logfont;
165 };
166
167 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family);
168
169 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
170 {
171     return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
172 }
173
174 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
175 {
176     return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
177 }
178
179 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
180 {
181     return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
182 }
183
184 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
185 {
186     return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
187 }
188
189 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
190 {
191     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
192
193     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
194
195     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
196     {
197         *obj = iface;
198         IDWriteFontFace_AddRef(iface);
199         return S_OK;
200     }
201
202     *obj = NULL;
203     return E_NOINTERFACE;
204 }
205
206 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
207 {
208     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
209     ULONG ref = InterlockedIncrement(&This->ref);
210     TRACE("(%p)->(%d)\n", This, ref);
211     return ref;
212 }
213
214 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
215 {
216     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
217     ULONG ref = InterlockedDecrement(&This->ref);
218
219     TRACE("(%p)->(%d)\n", This, ref);
220
221     if (!ref)
222         heap_free(This);
223
224     return ref;
225 }
226
227 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
228 {
229     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
230     FIXME("(%p): stub\n", This);
231     return DWRITE_FONT_FACE_TYPE_UNKNOWN;
232 }
233
234 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
235     IDWriteFontFile **fontfiles)
236 {
237     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
238     FIXME("(%p)->(%p %p): stub\n", This, number_of_files, fontfiles);
239     return E_NOTIMPL;
240 }
241
242 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
243 {
244     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
245     FIXME("(%p): stub\n", This);
246     return 0;
247 }
248
249 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
250 {
251     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
252     FIXME("(%p): stub\n", This);
253     return DWRITE_FONT_SIMULATIONS_NONE;
254 }
255
256 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
257 {
258     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
259     FIXME("(%p): stub\n", This);
260     return FALSE;
261 }
262
263 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
264 {
265     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
266     FIXME("(%p)->(%p): stub\n", This, metrics);
267 }
268
269 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
270 {
271     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
272     FIXME("(%p): stub\n", This);
273     return 0;
274 }
275
276 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
277     UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
278 {
279     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
280     FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
281     return E_NOTIMPL;
282 }
283
284 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
285     UINT32 count, UINT16 *glyph_indices)
286 {
287     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
288     HFONT hfont;
289     WCHAR *str;
290     HDC hdc;
291     int i;
292
293     TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
294
295     str = heap_alloc(count*sizeof(WCHAR));
296     if (!str) return E_OUTOFMEMORY;
297
298     for (i = 0; i < count; i++)
299         str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
300
301     hdc = CreateCompatibleDC(0);
302     hfont = CreateFontIndirectW(&This->logfont);
303     SelectObject(hdc, hfont);
304
305     GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
306     heap_free(str);
307
308     DeleteDC(hdc);
309     DeleteObject(hfont);
310
311     return S_OK;
312 }
313
314 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
315     const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
316 {
317     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
318     FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
319     return E_NOTIMPL;
320 }
321
322 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
323 {
324     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
325     FIXME("(%p)->(%p): stub\n", This, table_context);
326 }
327
328 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
329     UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
330     UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
331 {
332     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
333     FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
334         glyph_count, is_sideways, is_rtl, geometrysink);
335     return E_NOTIMPL;
336 }
337
338 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
339     FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
340 {
341     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
342     FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
343     return E_NOTIMPL;
344 }
345
346 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
347     DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
348 {
349     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
350     FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
351     return E_NOTIMPL;
352 }
353
354 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
355     DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
356     DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
357 {
358     struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
359     FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
360         glyph_count, metrics, is_sideways);
361     return E_NOTIMPL;
362 }
363
364 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
365     dwritefontface_QueryInterface,
366     dwritefontface_AddRef,
367     dwritefontface_Release,
368     dwritefontface_GetType,
369     dwritefontface_GetFiles,
370     dwritefontface_GetIndex,
371     dwritefontface_GetSimulations,
372     dwritefontface_IsSymbolFont,
373     dwritefontface_GetMetrics,
374     dwritefontface_GetGlyphCount,
375     dwritefontface_GetDesignGlyphMetrics,
376     dwritefontface_GetGlyphIndices,
377     dwritefontface_TryGetFontTable,
378     dwritefontface_ReleaseFontTable,
379     dwritefontface_GetGlyphRunOutline,
380     dwritefontface_GetRecommendedRenderingMode,
381     dwritefontface_GetGdiCompatibleMetrics,
382     dwritefontface_GetGdiCompatibleGlyphMetrics
383 };
384
385 static HRESULT create_fontface(struct dwrite_font *font, IDWriteFontFace **face)
386 {
387     struct dwrite_fontface *This;
388
389     *face = NULL;
390
391     This = heap_alloc(sizeof(struct dwrite_fontface));
392     if (!This) return E_OUTOFMEMORY;
393
394     This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
395     This->ref = 1;
396
397     memset(&This->logfont, 0, sizeof(This->logfont));
398     This->logfont.lfItalic = font->style == DWRITE_FONT_STYLE_ITALIC;
399     strcpyW(This->logfont.lfFaceName, font->facename);
400
401     *face = &This->IDWriteFontFace_iface;
402
403     return S_OK;
404 }
405
406 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
407 {
408     struct dwrite_font *This = impl_from_IDWriteFont(iface);
409
410     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
411
412     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
413     {
414         *obj = iface;
415         IDWriteFont_AddRef(iface);
416         return S_OK;
417     }
418
419     *obj = NULL;
420     return E_NOINTERFACE;
421 }
422
423 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
424 {
425     struct dwrite_font *This = impl_from_IDWriteFont(iface);
426     ULONG ref = InterlockedIncrement(&This->ref);
427     TRACE("(%p)->(%d)\n", This, ref);
428     return ref;
429 }
430
431 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
432 {
433     struct dwrite_font *This = impl_from_IDWriteFont(iface);
434     ULONG ref = InterlockedDecrement(&This->ref);
435
436     TRACE("(%p)->(%d)\n", This, ref);
437
438     if (!ref)
439     {
440         if (This->face) IDWriteFontFace_Release(This->face);
441         IDWriteFontFamily_Release(This->family);
442         heap_free(This->facename);
443         heap_free(This);
444     }
445
446     return ref;
447 }
448
449 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
450 {
451     struct dwrite_font *This = impl_from_IDWriteFont(iface);
452     TRACE("(%p)->(%p)\n", This, family);
453
454     *family = This->family;
455     IDWriteFontFamily_AddRef(*family);
456     return S_OK;
457 }
458
459 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
460 {
461     struct dwrite_font *This = impl_from_IDWriteFont(iface);
462     TRACE("(%p)\n", This);
463     return This->weight;
464 }
465
466 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
467 {
468     struct dwrite_font *This = impl_from_IDWriteFont(iface);
469     TRACE("(%p)\n", This);
470     return This->stretch;
471 }
472
473 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
474 {
475     struct dwrite_font *This = impl_from_IDWriteFont(iface);
476     TRACE("(%p)\n", This);
477     return This->style;
478 }
479
480 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
481 {
482     struct dwrite_font *This = impl_from_IDWriteFont(iface);
483     FIXME("(%p): stub\n", This);
484     return FALSE;
485 }
486
487 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
488 {
489     struct dwrite_font *This = impl_from_IDWriteFont(iface);
490     FIXME("(%p)->(%p): stub\n", This, names);
491     return E_NOTIMPL;
492 }
493
494 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
495     DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
496 {
497     struct dwrite_font *This = impl_from_IDWriteFont(iface);
498     FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
499     return E_NOTIMPL;
500 }
501
502 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
503 {
504     struct dwrite_font *This = impl_from_IDWriteFont(iface);
505     FIXME("(%p): stub\n", This);
506     return DWRITE_FONT_SIMULATIONS_NONE;
507 }
508
509 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
510 {
511     struct dwrite_font *This = impl_from_IDWriteFont(iface);
512
513     TRACE("(%p)->(%p)\n", This, metrics);
514     *metrics = This->metrics;
515 }
516
517 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
518 {
519     struct dwrite_font *This = impl_from_IDWriteFont(iface);
520     FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
521     return E_NOTIMPL;
522 }
523
524 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
525 {
526     struct dwrite_font *This = impl_from_IDWriteFont(iface);
527
528     TRACE("(%p)->(%p)\n", This, face);
529
530     if (!This->face)
531     {
532         HRESULT hr = create_fontface(This, &This->face);
533         if (FAILED(hr)) return hr;
534     }
535
536     *face = This->face;
537     IDWriteFontFace_AddRef(*face);
538
539     return S_OK;
540 }
541
542 static const IDWriteFontVtbl dwritefontvtbl = {
543     dwritefont_QueryInterface,
544     dwritefont_AddRef,
545     dwritefont_Release,
546     dwritefont_GetFontFamily,
547     dwritefont_GetWeight,
548     dwritefont_GetStretch,
549     dwritefont_GetStyle,
550     dwritefont_IsSymbolFont,
551     dwritefont_GetFaceNames,
552     dwritefont_GetInformationalStrings,
553     dwritefont_GetSimulations,
554     dwritefont_GetMetrics,
555     dwritefont_HasCharacter,
556     dwritefont_CreateFontFace
557 };
558
559 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
560 {
561     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
562     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
563
564     if (IsEqualIID(riid, &IID_IUnknown) ||
565         IsEqualIID(riid, &IID_IDWriteFontList) ||
566         IsEqualIID(riid, &IID_IDWriteFontFamily))
567     {
568         *obj = iface;
569         IDWriteFontFamily_AddRef(iface);
570         return S_OK;
571     }
572
573     *obj = NULL;
574     return E_NOINTERFACE;
575 }
576
577 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
578 {
579     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
580     ULONG ref = InterlockedIncrement(&This->ref);
581     TRACE("(%p)->(%d)\n", This, ref);
582     return ref;
583 }
584
585 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
586 {
587     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
588     ULONG ref = InterlockedDecrement(&This->ref);
589
590     TRACE("(%p)->(%d)\n", This, ref);
591
592     if (!ref)
593     {
594         heap_free(This->familyname);
595         heap_free(This);
596     }
597
598     return ref;
599 }
600
601 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
602 {
603     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
604     FIXME("(%p)->(%p): stub\n", This, collection);
605     return E_NOTIMPL;
606 }
607
608 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
609 {
610     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
611     FIXME("(%p): stub\n", This);
612     return 0;
613 }
614
615 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
616 {
617     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
618     FIXME("(%p)->(%u %p): stub\n", This, index, font);
619     return E_NOTIMPL;
620 }
621
622 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
623 {
624     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
625     static const WCHAR enusW[] = {'e','n','-','u','s',0};
626     HRESULT hr;
627
628     TRACE("(%p)->(%p)\n", This, names);
629
630     hr = create_localizedstrings(names);
631     if (FAILED(hr)) return hr;
632
633     return add_localizedstring(*names, enusW, This->familyname);
634 }
635
636 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
637     DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
638 {
639     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
640     LOGFONTW lf;
641
642     TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
643
644     memset(&lf, 0, sizeof(lf));
645     lf.lfWeight = weight;
646     lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
647     strcpyW(lf.lfFaceName, This->familyname);
648
649     return create_font_from_logfont(&lf, font);
650 }
651
652 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
653     DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
654 {
655     struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
656     FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
657     return E_NOTIMPL;
658 }
659
660 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
661     dwritefontfamily_QueryInterface,
662     dwritefontfamily_AddRef,
663     dwritefontfamily_Release,
664     dwritefontfamily_GetFontCollection,
665     dwritefontfamily_GetFontCount,
666     dwritefontfamily_GetFont,
667     dwritefontfamily_GetFamilyNames,
668     dwritefontfamily_GetFirstMatchingFont,
669     dwritefontfamily_GetMatchingFonts
670 };
671
672 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
673 {
674     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
675     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
676
677     if (IsEqualIID(riid, &IID_IUnknown) ||
678         IsEqualIID(riid, &IID_IDWriteFontCollection))
679     {
680         *obj = iface;
681         IDWriteFontCollection_AddRef(iface);
682         return S_OK;
683     }
684
685     *obj = NULL;
686     return E_NOINTERFACE;
687 }
688
689 static ULONG WINAPI dwritesysfontcollection_AddRef(IDWriteFontCollection *iface)
690 {
691     return 2;
692 }
693
694 static ULONG WINAPI dwritesysfontcollection_Release(IDWriteFontCollection *iface)
695 {
696     return 1;
697 }
698
699 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
700 {
701     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
702     TRACE("(%p)\n", This);
703     return This->count;
704 }
705
706 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
707 {
708     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
709
710     TRACE("(%p)->(%u %p)\n", This, index, family);
711
712     if (index >= This->count)
713     {
714         *family = NULL;
715         return E_FAIL;
716     }
717
718     return create_fontfamily(This->families[index], family);
719 }
720
721 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
722 {
723     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
724     UINT32 i;
725
726     TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
727
728     for (i = 0; i < This->count; i++)
729         if (!strcmpW(This->families[i], name))
730         {
731             *index = i;
732             *exists = TRUE;
733             return S_OK;
734         }
735
736     *index = (UINT32)-1;
737     *exists = FALSE;
738
739     return S_OK;
740 }
741
742 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
743 {
744     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
745     FIXME("(%p)->(%p %p): stub\n", This, face, font);
746     return E_NOTIMPL;
747 }
748
749 static const IDWriteFontCollectionVtbl systemfontcollectionvtbl = {
750     dwritefontcollection_QueryInterface,
751     dwritesysfontcollection_AddRef,
752     dwritesysfontcollection_Release,
753     dwritefontcollection_GetFontFamilyCount,
754     dwritefontcollection_GetFontFamily,
755     dwritefontcollection_FindFamilyName,
756     dwritefontcollection_GetFontFromFontFace
757 };
758
759 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
760 {
761     /* check for duplicate family name */
762     if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
763
764     /* double array length */
765     if (collection->count == collection->alloc)
766     {
767         collection->alloc *= 2;
768         collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
769     }
770
771     collection->families[collection->count++] = heap_strdupW(family);
772     TRACE("family name %s\n", debugstr_w(family));
773
774     return S_OK;
775 }
776
777 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
778 {
779     struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
780     return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
781 }
782
783 static void release_font_collection(IDWriteFontCollection *iface)
784 {
785     struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
786     int i;
787
788     for (i = 0; i < This->count; i++)
789         heap_free(This->families[i]);
790     heap_free(This->families);
791     heap_free(This);
792 }
793
794 void release_system_fontcollection(void)
795 {
796     release_font_collection(system_collection);
797 }
798
799 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
800 {
801     if (!system_collection)
802     {
803         struct dwrite_fontcollection *This;
804         LOGFONTW lf;
805         HDC hdc;
806
807         *collection = NULL;
808
809         This = heap_alloc(sizeof(struct dwrite_fontcollection));
810         if (!This) return E_OUTOFMEMORY;
811
812         This->IDWriteFontCollection_iface.lpVtbl = &systemfontcollectionvtbl;
813         This->alloc = 50;
814         This->count = 0;
815         This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
816
817         TRACE("building system font collection:\n");
818
819         hdc = CreateCompatibleDC(0);
820         memset(&lf, 0, sizeof(lf));
821         lf.lfCharSet = DEFAULT_CHARSET;
822         lf.lfPitchAndFamily = DEFAULT_PITCH;
823         lf.lfFaceName[0] = 0;
824         EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
825         DeleteDC(hdc);
826
827         if (InterlockedCompareExchangePointer((void**)&system_collection, &This->IDWriteFontCollection_iface, NULL))
828             release_font_collection(&This->IDWriteFontCollection_iface);
829     }
830
831     *collection = system_collection;
832
833     return S_OK;
834 }
835
836 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
837 {
838     struct dwrite_fontfamily *This;
839
840     *family = NULL;
841
842     This = heap_alloc(sizeof(struct dwrite_fontfamily));
843     if (!This) return E_OUTOFMEMORY;
844
845     This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
846     This->ref = 1;
847     This->familyname = heap_strdupW(familyname);
848
849     *family = &This->IDWriteFontFamily_iface;
850
851     return S_OK;
852 }
853
854 static void get_font_properties(struct dwrite_font *font, HDC hdc)
855 {
856     TT_OS2_V2 tt_os2;
857     TT_HEAD tt_head;
858     TT_POST tt_post;
859     LONG size;
860
861     /* default stretch and weight to normal */
862     font->stretch = DWRITE_FONT_STRETCH_NORMAL;
863     font->weight = DWRITE_FONT_WEIGHT_NORMAL;
864
865     memset(&font->metrics, 0, sizeof(font->metrics));
866
867     size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
868     if (size != GDI_ERROR)
869     {
870         if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
871
872         memset(&tt_os2, 0, sizeof(tt_os2));
873         if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return;
874
875         /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
876         if (GET_BE_WORD(tt_os2.usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
877             font->stretch = GET_BE_WORD(tt_os2.usWidthClass);
878
879         font->weight = GET_BE_WORD(tt_os2.usWeightClass);
880         TRACE("stretch=%d, weight=%d\n", font->stretch, font->weight);
881
882         font->metrics.ascent    = GET_BE_WORD(tt_os2.sTypoAscender);
883         font->metrics.descent   = GET_BE_WORD(tt_os2.sTypoDescender);
884         font->metrics.lineGap   = GET_BE_WORD(tt_os2.sTypoLineGap);
885         font->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
886         font->metrics.xHeight   = GET_BE_WORD(tt_os2.sxHeight);
887         font->metrics.strikethroughPosition  = GET_BE_WORD(tt_os2.yStrikeoutPosition);
888         font->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
889     }
890
891     memset(&tt_head, 0, sizeof(tt_head));
892     if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
893     {
894         font->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
895     }
896
897     memset(&tt_post, 0, sizeof(tt_post));
898     if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
899     {
900         font->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
901         font->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
902     }
903 }
904
905 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
906 {
907     const WCHAR* facename, *familyname;
908     struct dwrite_font *This;
909     IDWriteFontFamily *family;
910     OUTLINETEXTMETRICW *otm;
911     HRESULT hr;
912     HFONT hfont;
913     HDC hdc;
914     int ret;
915
916     *font = NULL;
917
918     This = heap_alloc(sizeof(struct dwrite_font));
919     if (!This) return E_OUTOFMEMORY;
920
921     hfont = CreateFontIndirectW(logfont);
922     if (!hfont)
923     {
924         heap_free(This);
925         return DWRITE_E_NOFONT;
926     }
927
928     hdc = CreateCompatibleDC(0);
929     SelectObject(hdc, hfont);
930
931     ret = GetOutlineTextMetricsW(hdc, 0, NULL);
932     otm = heap_alloc(ret);
933     if (!otm)
934     {
935         heap_free(This);
936         DeleteDC(hdc);
937         DeleteObject(hfont);
938         return E_OUTOFMEMORY;
939     }
940     otm->otmSize = ret;
941     ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
942
943     get_font_properties(This, hdc);
944
945     DeleteDC(hdc);
946     DeleteObject(hfont);
947
948     facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
949     familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
950     TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
951
952     hr = create_fontfamily(familyname, &family);
953     heap_free(otm);
954     if (hr != S_OK)
955     {
956         heap_free(This);
957         return hr;
958     }
959
960     This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
961     This->ref = 1;
962     This->face = NULL;
963     This->family = family;
964     This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
965     This->facename = heap_strdupW(logfont->lfFaceName);
966
967     *font = &This->IDWriteFont_iface;
968
969     return S_OK;
970 }