ddraw: Don't bother to unregister classes at process exit.
[wine.git] / dlls / dwrite / font.c
blobec18312c22809ad31b9b90f516973ca41485fb53
1 /*
2 * Font and collections
4 * Copyright 2012 Nikolay Sivov for CodeWeavers
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.
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.
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
21 #define COBJMACROS
23 #include "dwrite.h"
24 #include "dwrite_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
30 /* PANOSE is 10 bytes in size, need to pack the structure properly */
31 #include "pshpack2.h"
32 typedef struct
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;
53 typedef struct
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;
66 typedef struct
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.
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"
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
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))
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')
130 struct dwrite_fontcollection {
131 IDWriteFontCollection IDWriteFontCollection_iface;
133 WCHAR **families;
134 UINT32 count;
135 int alloc;
138 static IDWriteFontCollection *system_collection;
140 struct dwrite_fontfamily {
141 IDWriteFontFamily IDWriteFontFamily_iface;
142 LONG ref;
144 WCHAR *familyname;
147 struct dwrite_font {
148 IDWriteFont IDWriteFont_iface;
149 LONG ref;
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;
160 struct dwrite_fontface {
161 IDWriteFontFace IDWriteFontFace_iface;
162 LONG ref;
164 LOGFONTW logfont;
167 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family);
169 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
171 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
174 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
176 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
179 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
181 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
184 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
186 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
189 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
191 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
193 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
195 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
197 *obj = iface;
198 IDWriteFontFace_AddRef(iface);
199 return S_OK;
202 *obj = NULL;
203 return E_NOINTERFACE;
206 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
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;
214 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
216 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
217 ULONG ref = InterlockedDecrement(&This->ref);
219 TRACE("(%p)->(%d)\n", This, ref);
221 if (!ref)
222 heap_free(This);
224 return ref;
227 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
229 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
230 FIXME("(%p): stub\n", This);
231 return DWRITE_FONT_FACE_TYPE_UNKNOWN;
234 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
235 IDWriteFontFile **fontfiles)
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;
242 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
244 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
245 FIXME("(%p): stub\n", This);
246 return 0;
249 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
251 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
252 FIXME("(%p): stub\n", This);
253 return DWRITE_FONT_SIMULATIONS_NONE;
256 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
258 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
259 FIXME("(%p): stub\n", This);
260 return FALSE;
263 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
265 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
266 FIXME("(%p)->(%p): stub\n", This, metrics);
269 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
271 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
272 FIXME("(%p): stub\n", This);
273 return 0;
276 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
277 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
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;
284 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
285 UINT32 count, UINT16 *glyph_indices)
287 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
288 HFONT hfont;
289 WCHAR *str;
290 HDC hdc;
291 unsigned int i;
293 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
295 str = heap_alloc(count*sizeof(WCHAR));
296 if (!str) return E_OUTOFMEMORY;
298 for (i = 0; i < count; i++)
299 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
301 hdc = CreateCompatibleDC(0);
302 hfont = CreateFontIndirectW(&This->logfont);
303 SelectObject(hdc, hfont);
305 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
306 heap_free(str);
308 DeleteDC(hdc);
309 DeleteObject(hfont);
311 return S_OK;
314 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
315 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
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;
322 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
324 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
325 FIXME("(%p)->(%p): stub\n", This, table_context);
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)
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;
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)
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;
346 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
347 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
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;
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)
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;
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
385 static HRESULT create_fontface(struct dwrite_font *font, IDWriteFontFace **face)
387 struct dwrite_fontface *This;
389 *face = NULL;
391 This = heap_alloc(sizeof(struct dwrite_fontface));
392 if (!This) return E_OUTOFMEMORY;
394 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
395 This->ref = 1;
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);
401 *face = &This->IDWriteFontFace_iface;
403 return S_OK;
406 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
408 struct dwrite_font *This = impl_from_IDWriteFont(iface);
410 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
412 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
414 *obj = iface;
415 IDWriteFont_AddRef(iface);
416 return S_OK;
419 *obj = NULL;
420 return E_NOINTERFACE;
423 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
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;
431 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
433 struct dwrite_font *This = impl_from_IDWriteFont(iface);
434 ULONG ref = InterlockedDecrement(&This->ref);
436 TRACE("(%p)->(%d)\n", This, ref);
438 if (!ref)
440 if (This->face) IDWriteFontFace_Release(This->face);
441 IDWriteFontFamily_Release(This->family);
442 heap_free(This->facename);
443 heap_free(This);
446 return ref;
449 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
451 struct dwrite_font *This = impl_from_IDWriteFont(iface);
452 TRACE("(%p)->(%p)\n", This, family);
454 *family = This->family;
455 IDWriteFontFamily_AddRef(*family);
456 return S_OK;
459 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
461 struct dwrite_font *This = impl_from_IDWriteFont(iface);
462 TRACE("(%p)\n", This);
463 return This->weight;
466 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
468 struct dwrite_font *This = impl_from_IDWriteFont(iface);
469 TRACE("(%p)\n", This);
470 return This->stretch;
473 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
475 struct dwrite_font *This = impl_from_IDWriteFont(iface);
476 TRACE("(%p)\n", This);
477 return This->style;
480 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
482 struct dwrite_font *This = impl_from_IDWriteFont(iface);
483 FIXME("(%p): stub\n", This);
484 return FALSE;
487 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
489 struct dwrite_font *This = impl_from_IDWriteFont(iface);
490 FIXME("(%p)->(%p): stub\n", This, names);
491 return E_NOTIMPL;
494 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
495 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
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;
502 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
504 struct dwrite_font *This = impl_from_IDWriteFont(iface);
505 FIXME("(%p): stub\n", This);
506 return DWRITE_FONT_SIMULATIONS_NONE;
509 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
511 struct dwrite_font *This = impl_from_IDWriteFont(iface);
513 TRACE("(%p)->(%p)\n", This, metrics);
514 *metrics = This->metrics;
517 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
519 struct dwrite_font *This = impl_from_IDWriteFont(iface);
520 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
521 return E_NOTIMPL;
524 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
526 struct dwrite_font *This = impl_from_IDWriteFont(iface);
528 TRACE("(%p)->(%p)\n", This, face);
530 if (!This->face)
532 HRESULT hr = create_fontface(This, &This->face);
533 if (FAILED(hr)) return hr;
536 *face = This->face;
537 IDWriteFontFace_AddRef(*face);
539 return S_OK;
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
559 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
561 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
562 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
564 if (IsEqualIID(riid, &IID_IUnknown) ||
565 IsEqualIID(riid, &IID_IDWriteFontList) ||
566 IsEqualIID(riid, &IID_IDWriteFontFamily))
568 *obj = iface;
569 IDWriteFontFamily_AddRef(iface);
570 return S_OK;
573 *obj = NULL;
574 return E_NOINTERFACE;
577 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
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;
585 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
587 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
588 ULONG ref = InterlockedDecrement(&This->ref);
590 TRACE("(%p)->(%d)\n", This, ref);
592 if (!ref)
594 heap_free(This->familyname);
595 heap_free(This);
598 return ref;
601 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
603 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
604 FIXME("(%p)->(%p): stub\n", This, collection);
605 return E_NOTIMPL;
608 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
610 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
611 FIXME("(%p): stub\n", This);
612 return 0;
615 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
617 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
618 FIXME("(%p)->(%u %p): stub\n", This, index, font);
619 return E_NOTIMPL;
622 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
624 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
625 static const WCHAR enusW[] = {'e','n','-','u','s',0};
626 HRESULT hr;
628 TRACE("(%p)->(%p)\n", This, names);
630 hr = create_localizedstrings(names);
631 if (FAILED(hr)) return hr;
633 return add_localizedstring(*names, enusW, This->familyname);
636 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
637 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
639 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
640 LOGFONTW lf;
642 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
644 memset(&lf, 0, sizeof(lf));
645 lf.lfWeight = weight;
646 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
647 strcpyW(lf.lfFaceName, This->familyname);
649 return create_font_from_logfont(&lf, font);
652 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
653 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
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;
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
672 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
674 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
675 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
677 if (IsEqualIID(riid, &IID_IUnknown) ||
678 IsEqualIID(riid, &IID_IDWriteFontCollection))
680 *obj = iface;
681 IDWriteFontCollection_AddRef(iface);
682 return S_OK;
685 *obj = NULL;
686 return E_NOINTERFACE;
689 static ULONG WINAPI dwritesysfontcollection_AddRef(IDWriteFontCollection *iface)
691 return 2;
694 static ULONG WINAPI dwritesysfontcollection_Release(IDWriteFontCollection *iface)
696 return 1;
699 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
701 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
702 TRACE("(%p)\n", This);
703 return This->count;
706 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
708 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
710 TRACE("(%p)->(%u %p)\n", This, index, family);
712 if (index >= This->count)
714 *family = NULL;
715 return E_FAIL;
718 return create_fontfamily(This->families[index], family);
721 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
723 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
724 UINT32 i;
726 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
728 for (i = 0; i < This->count; i++)
729 if (!strcmpW(This->families[i], name))
731 *index = i;
732 *exists = TRUE;
733 return S_OK;
736 *index = (UINT32)-1;
737 *exists = FALSE;
739 return S_OK;
742 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
744 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
745 FIXME("(%p)->(%p %p): stub\n", This, face, font);
746 return E_NOTIMPL;
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
759 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
761 /* check for duplicate family name */
762 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
764 /* double array length */
765 if (collection->count == collection->alloc)
767 collection->alloc *= 2;
768 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
771 collection->families[collection->count++] = heap_strdupW(family);
772 TRACE("family name %s\n", debugstr_w(family));
774 return S_OK;
777 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
779 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
780 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
783 static void release_font_collection(IDWriteFontCollection *iface)
785 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
786 unsigned int i;
788 for (i = 0; i < This->count; i++)
789 heap_free(This->families[i]);
790 heap_free(This->families);
791 heap_free(This);
794 void release_system_fontcollection(void)
796 if (system_collection)
797 release_font_collection(system_collection);
800 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
802 if (!system_collection)
804 struct dwrite_fontcollection *This;
805 LOGFONTW lf;
806 HDC hdc;
808 *collection = NULL;
810 This = heap_alloc(sizeof(struct dwrite_fontcollection));
811 if (!This) return E_OUTOFMEMORY;
813 This->IDWriteFontCollection_iface.lpVtbl = &systemfontcollectionvtbl;
814 This->alloc = 50;
815 This->count = 0;
816 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
818 TRACE("building system font collection:\n");
820 hdc = CreateCompatibleDC(0);
821 memset(&lf, 0, sizeof(lf));
822 lf.lfCharSet = DEFAULT_CHARSET;
823 lf.lfPitchAndFamily = DEFAULT_PITCH;
824 lf.lfFaceName[0] = 0;
825 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
826 DeleteDC(hdc);
828 if (InterlockedCompareExchangePointer((void**)&system_collection, &This->IDWriteFontCollection_iface, NULL))
829 release_font_collection(&This->IDWriteFontCollection_iface);
832 *collection = system_collection;
834 return S_OK;
837 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
839 struct dwrite_fontfamily *This;
841 *family = NULL;
843 This = heap_alloc(sizeof(struct dwrite_fontfamily));
844 if (!This) return E_OUTOFMEMORY;
846 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
847 This->ref = 1;
848 This->familyname = heap_strdupW(familyname);
850 *family = &This->IDWriteFontFamily_iface;
852 return S_OK;
855 static void get_font_properties(struct dwrite_font *font, HDC hdc)
857 TT_OS2_V2 tt_os2;
858 TT_HEAD tt_head;
859 TT_POST tt_post;
860 LONG size;
862 /* default stretch and weight to normal */
863 font->stretch = DWRITE_FONT_STRETCH_NORMAL;
864 font->weight = DWRITE_FONT_WEIGHT_NORMAL;
866 memset(&font->metrics, 0, sizeof(font->metrics));
868 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
869 if (size != GDI_ERROR)
871 if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
873 memset(&tt_os2, 0, sizeof(tt_os2));
874 if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return;
876 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
877 if (GET_BE_WORD(tt_os2.usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
878 font->stretch = GET_BE_WORD(tt_os2.usWidthClass);
880 font->weight = GET_BE_WORD(tt_os2.usWeightClass);
881 TRACE("stretch=%d, weight=%d\n", font->stretch, font->weight);
883 font->metrics.ascent = GET_BE_WORD(tt_os2.sTypoAscender);
884 font->metrics.descent = GET_BE_WORD(tt_os2.sTypoDescender);
885 font->metrics.lineGap = GET_BE_WORD(tt_os2.sTypoLineGap);
886 font->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
887 font->metrics.xHeight = GET_BE_WORD(tt_os2.sxHeight);
888 font->metrics.strikethroughPosition = GET_BE_WORD(tt_os2.yStrikeoutPosition);
889 font->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
892 memset(&tt_head, 0, sizeof(tt_head));
893 if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
895 font->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
898 memset(&tt_post, 0, sizeof(tt_post));
899 if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
901 font->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
902 font->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
906 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
908 const WCHAR* facename, *familyname;
909 struct dwrite_font *This;
910 IDWriteFontFamily *family;
911 OUTLINETEXTMETRICW *otm;
912 HRESULT hr;
913 HFONT hfont;
914 HDC hdc;
915 int ret;
917 *font = NULL;
919 This = heap_alloc(sizeof(struct dwrite_font));
920 if (!This) return E_OUTOFMEMORY;
922 hfont = CreateFontIndirectW(logfont);
923 if (!hfont)
925 heap_free(This);
926 return DWRITE_E_NOFONT;
929 hdc = CreateCompatibleDC(0);
930 SelectObject(hdc, hfont);
932 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
933 otm = heap_alloc(ret);
934 if (!otm)
936 heap_free(This);
937 DeleteDC(hdc);
938 DeleteObject(hfont);
939 return E_OUTOFMEMORY;
941 otm->otmSize = ret;
942 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
944 get_font_properties(This, hdc);
946 DeleteDC(hdc);
947 DeleteObject(hfont);
949 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
950 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
951 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
953 hr = create_fontfamily(familyname, &family);
954 heap_free(otm);
955 if (hr != S_OK)
957 heap_free(This);
958 return hr;
961 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
962 This->ref = 1;
963 This->face = NULL;
964 This->family = family;
965 This->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
966 This->facename = heap_strdupW(logfont->lfFaceName);
968 *font = &This->IDWriteFont_iface;
970 return S_OK;