dwrite: Implement a list of font data for IDWriteFontFamily.
[wine.git] / dlls / dwrite / font.c
blob546dab8fddfba4c5f214fc70e6430a22d3964d6f
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 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
28 /* PANOSE is 10 bytes in size, need to pack the structure properly */
29 #include "pshpack2.h"
30 typedef struct
32 ULONG version;
33 ULONG revision;
34 ULONG checksumadj;
35 ULONG magic;
36 USHORT flags;
37 USHORT unitsPerEm;
38 ULONGLONG created;
39 ULONGLONG modified;
40 SHORT xMin;
41 SHORT yMin;
42 SHORT xMax;
43 SHORT yMax;
44 USHORT macStyle;
45 USHORT lowestRecPPEM;
46 SHORT direction_hint;
47 SHORT index_format;
48 SHORT glyphdata_format;
49 } TT_HEAD;
51 typedef struct
53 ULONG Version;
54 ULONG italicAngle;
55 SHORT underlinePosition;
56 SHORT underlineThickness;
57 ULONG fixed_pitch;
58 ULONG minmemType42;
59 ULONG maxmemType42;
60 ULONG minmemType1;
61 ULONG maxmemType1;
62 } TT_POST;
64 typedef struct
66 USHORT version;
67 SHORT xAvgCharWidth;
68 USHORT usWeightClass;
69 USHORT usWidthClass;
70 SHORT fsType;
71 SHORT ySubscriptXSize;
72 SHORT ySubscriptYSize;
73 SHORT ySubscriptXOffset;
74 SHORT ySubscriptYOffset;
75 SHORT ySuperscriptXSize;
76 SHORT ySuperscriptYSize;
77 SHORT ySuperscriptXOffset;
78 SHORT ySuperscriptYOffset;
79 SHORT yStrikeoutSize;
80 SHORT yStrikeoutPosition;
81 SHORT sFamilyClass;
82 PANOSE panose;
83 ULONG ulUnicodeRange1;
84 ULONG ulUnicodeRange2;
85 ULONG ulUnicodeRange3;
86 ULONG ulUnicodeRange4;
87 CHAR achVendID[4];
88 USHORT fsSelection;
89 USHORT usFirstCharIndex;
90 USHORT usLastCharIndex;
91 /* According to the Apple spec, original version didn't have the below fields,
92 * version numbers were taken from the OpenType spec.
94 /* version 0 (TrueType 1.5) */
95 USHORT sTypoAscender;
96 USHORT sTypoDescender;
97 USHORT sTypoLineGap;
98 USHORT usWinAscent;
99 USHORT usWinDescent;
100 /* version 1 (TrueType 1.66) */
101 ULONG ulCodePageRange1;
102 ULONG ulCodePageRange2;
103 /* version 2 (OpenType 1.2) */
104 SHORT sxHeight;
105 SHORT sCapHeight;
106 USHORT usDefaultChar;
107 USHORT usBreakChar;
108 USHORT usMaxContext;
109 } TT_OS2_V2;
110 #include "poppack.h"
112 #ifdef WORDS_BIGENDIAN
113 #define GET_BE_WORD(x) (x)
114 #define GET_BE_DWORD(x) (x)
115 #else
116 #define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
117 #define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
118 #endif
120 #define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
121 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
122 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
124 #define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
125 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
126 #define MS_POST_TAG MS_MAKE_TAG('p','o','s','t')
127 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
129 struct dwrite_fontface_data {
130 LONG ref;
132 DWRITE_FONT_FACE_TYPE type;
133 UINT32 file_count;
134 IDWriteFontFile ** files;
135 DWRITE_FONT_SIMULATIONS simulations;
136 UINT32 index;
139 struct dwrite_font_data {
140 LONG ref;
142 DWRITE_FONT_STYLE style;
143 DWRITE_FONT_STRETCH stretch;
144 DWRITE_FONT_WEIGHT weight;
145 DWRITE_FONT_SIMULATIONS simulations;
146 DWRITE_FONT_METRICS metrics;
148 struct dwrite_fontface_data *face_data;
150 WCHAR *facename;
153 struct dwrite_fontcollection {
154 IDWriteFontCollection IDWriteFontCollection_iface;
155 LONG ref;
157 WCHAR **families;
158 UINT32 count;
159 int alloc;
162 struct dwrite_fontfamily {
163 IDWriteFontFamily IDWriteFontFamily_iface;
164 LONG ref;
166 struct dwrite_font_data **fonts;
167 UINT32 font_count;
168 UINT32 alloc;
170 WCHAR *familyname;
173 struct dwrite_font {
174 IDWriteFont IDWriteFont_iface;
175 LONG ref;
177 BOOL is_system;
178 IDWriteFontFamily *family;
179 IDWriteFontFace *face;
181 struct dwrite_font_data *data;
184 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
186 struct dwrite_fonttable {
187 UINT32 magic;
188 LPVOID context;
189 UINT32 file_index;
192 struct dwrite_fontface {
193 IDWriteFontFace IDWriteFontFace_iface;
194 LONG ref;
196 struct dwrite_fontface_data *data;
198 LPVOID CMAP_table;
199 LPVOID CMAP_context;
200 DWORD CMAP_size;
202 BOOL is_system;
203 LOGFONTW logfont;
206 struct dwrite_fontfile {
207 IDWriteFontFile IDWriteFontFile_iface;
208 LONG ref;
210 IDWriteFontFileLoader *loader;
211 void *reference_key;
212 UINT32 key_size;
213 IDWriteFontFileStream *stream;
216 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family);
217 static HRESULT create_font_base(IDWriteFont **font);
218 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font);
220 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
222 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
225 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
227 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
230 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
232 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
235 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
237 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
240 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
242 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
245 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
247 HRESULT hr;
248 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
249 if (!This->stream)
251 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
252 if (FAILED(hr))
253 return hr;
255 if (This->stream)
257 IDWriteFontFileStream_AddRef(This->stream);
258 *stream = This->stream;
259 return S_OK;
261 return E_FAIL;
264 static VOID _free_fontface_data(struct dwrite_fontface_data *data)
266 int i;
267 if (!data)
268 return;
269 i = InterlockedDecrement(&data->ref);
270 if (i > 0)
271 return;
272 for (i = 0; i < data->file_count; i++)
273 IDWriteFontFile_Release(data->files[i]);
274 heap_free(data->files);
275 heap_free(data);
278 static VOID _free_font_data(struct dwrite_font_data *data)
280 int i;
281 if (!data)
282 return;
283 i = InterlockedDecrement(&data->ref);
284 if (i > 0)
285 return;
286 _free_fontface_data(data->face_data);
287 heap_free(data->facename);
288 heap_free(data);
291 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
293 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
295 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
297 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
299 *obj = iface;
300 IDWriteFontFace_AddRef(iface);
301 return S_OK;
304 *obj = NULL;
305 return E_NOINTERFACE;
308 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
310 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
311 ULONG ref = InterlockedIncrement(&This->ref);
312 TRACE("(%p)->(%d)\n", This, ref);
313 return ref;
316 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
318 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
319 ULONG ref = InterlockedDecrement(&This->ref);
321 TRACE("(%p)->(%d)\n", This, ref);
323 if (!ref)
325 if (This->CMAP_context)
326 IDWriteFontFace_ReleaseFontTable(iface, This->CMAP_context);
327 _free_fontface_data(This->data);
328 heap_free(This);
331 return ref;
334 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
336 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
337 TRACE("(%p)\n", This);
338 return This->data->type;
341 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
342 IDWriteFontFile **fontfiles)
344 int i;
345 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
346 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
347 if (fontfiles == NULL)
349 *number_of_files = This->data->file_count;
350 return S_OK;
352 if (*number_of_files < This->data->file_count)
353 return E_INVALIDARG;
355 for (i = 0; i < This->data->file_count; i++)
357 IDWriteFontFile_AddRef(This->data->files[i]);
358 fontfiles[i] = This->data->files[i];
361 return S_OK;
364 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
366 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
367 TRACE("(%p)\n", This);
368 return This->data->index;
371 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
373 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
374 TRACE("(%p)\n", This);
375 return This->data->simulations;
378 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
380 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
381 FIXME("(%p): stub\n", This);
382 return FALSE;
385 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
387 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
388 FIXME("(%p)->(%p): stub\n", This, metrics);
391 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
393 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
394 FIXME("(%p): stub\n", This);
395 return 0;
398 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
399 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
401 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
402 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
403 return E_NOTIMPL;
406 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
407 UINT32 count, UINT16 *glyph_indices)
409 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
410 unsigned int i;
412 if (This->is_system)
414 HFONT hfont;
415 WCHAR *str;
416 HDC hdc;
418 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
420 str = heap_alloc(count*sizeof(WCHAR));
421 if (!str) return E_OUTOFMEMORY;
423 for (i = 0; i < count; i++)
424 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
426 hdc = CreateCompatibleDC(0);
427 hfont = CreateFontIndirectW(&This->logfont);
428 SelectObject(hdc, hfont);
430 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
431 heap_free(str);
433 DeleteDC(hdc);
434 DeleteObject(hfont);
436 return S_OK;
438 else
440 HRESULT hr;
441 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
442 if (!This->CMAP_table)
444 BOOL exists = FALSE;
445 hr = IDWriteFontFace_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->CMAP_table, &This->CMAP_size, &This->CMAP_context, &exists);
446 if (FAILED(hr) || !exists)
448 ERR("Font does not have a CMAP table\n");
449 return E_FAIL;
453 for (i = 0; i < count; i++)
455 OpenType_CMAP_GetGlyphIndex(This->CMAP_table, codepoints[i], &glyph_indices[i], 0);
457 return S_OK;
461 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
462 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
464 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
465 if (This->is_system)
467 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
468 return E_NOTIMPL;
470 else
472 HRESULT hr = S_OK;
473 int i;
474 struct dwrite_fonttable *table;
476 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
478 table = heap_alloc(sizeof(struct dwrite_fonttable));
479 table->magic = DWRITE_FONTTABLE_MAGIC;
480 if (!table)
481 return E_OUTOFMEMORY;
483 *exists = FALSE;
484 for (i = 0; i < This->data->file_count && !(*exists); i++)
486 IDWriteFontFileStream *stream;
487 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
488 if (FAILED(hr))
489 continue;
490 table->file_index = i;
492 hr = find_font_table(stream, This->data->index, table_tag, table_data, &table->context, table_size, exists);
494 IDWriteFontFileStream_Release(stream);
496 if (FAILED(hr) && !*exists)
497 heap_free(table);
498 else
499 *context = (LPVOID)table;
500 return hr;
504 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
506 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
507 struct dwrite_fonttable *table = (struct dwrite_fonttable *)table_context;
508 IDWriteFontFileStream *stream;
509 HRESULT hr;
510 TRACE("(%p)->(%p)\n", This, table_context);
512 if (table->magic != DWRITE_FONTTABLE_MAGIC)
514 TRACE("Invalid table magic\n");
515 return;
518 hr = _dwritefontfile_GetFontFileStream(This->data->files[table->file_index], &stream);
519 if (FAILED(hr))
520 return;
521 IDWriteFontFileStream_ReleaseFileFragment(stream, table->context);
522 IDWriteFontFileStream_Release(stream);
523 heap_free(table);
526 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
527 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
528 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
530 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
531 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
532 glyph_count, is_sideways, is_rtl, geometrysink);
533 return E_NOTIMPL;
536 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
537 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
539 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
540 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
541 return E_NOTIMPL;
544 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
545 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
547 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
548 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
549 return E_NOTIMPL;
552 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
553 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
554 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
556 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
557 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
558 glyph_count, metrics, is_sideways);
559 return E_NOTIMPL;
562 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
563 dwritefontface_QueryInterface,
564 dwritefontface_AddRef,
565 dwritefontface_Release,
566 dwritefontface_GetType,
567 dwritefontface_GetFiles,
568 dwritefontface_GetIndex,
569 dwritefontface_GetSimulations,
570 dwritefontface_IsSymbolFont,
571 dwritefontface_GetMetrics,
572 dwritefontface_GetGlyphCount,
573 dwritefontface_GetDesignGlyphMetrics,
574 dwritefontface_GetGlyphIndices,
575 dwritefontface_TryGetFontTable,
576 dwritefontface_ReleaseFontTable,
577 dwritefontface_GetGlyphRunOutline,
578 dwritefontface_GetRecommendedRenderingMode,
579 dwritefontface_GetGdiCompatibleMetrics,
580 dwritefontface_GetGdiCompatibleGlyphMetrics
583 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
585 struct dwrite_fontface *This;
587 *face = NULL;
589 This = heap_alloc(sizeof(struct dwrite_fontface));
590 if (!This) return E_OUTOFMEMORY;
591 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
592 if (!This->data)
594 heap_free(This);
595 return E_OUTOFMEMORY;
598 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
599 This->ref = 1;
600 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
601 This->data->file_count = 0;
602 This->data->files = NULL;
603 This->data->index = 0;
604 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
605 This->CMAP_table = NULL;
606 This->CMAP_context = NULL;
607 This->CMAP_size = 0;
609 This->is_system = TRUE;
610 memset(&This->logfont, 0, sizeof(This->logfont));
611 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
612 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
613 This->logfont.lfWeight = font->data->weight;
614 strcpyW(This->logfont.lfFaceName, font->data->facename);
616 *face = &This->IDWriteFontFace_iface;
618 return S_OK;
621 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
623 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace(face);
625 *logfont = fontface->logfont;
627 return S_OK;
630 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
632 struct dwrite_font *This = impl_from_IDWriteFont(iface);
634 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
636 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
638 *obj = iface;
639 IDWriteFont_AddRef(iface);
640 return S_OK;
643 *obj = NULL;
644 return E_NOINTERFACE;
647 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
649 struct dwrite_font *This = impl_from_IDWriteFont(iface);
650 ULONG ref = InterlockedIncrement(&This->ref);
651 TRACE("(%p)->(%d)\n", This, ref);
652 return ref;
655 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
657 struct dwrite_font *This = impl_from_IDWriteFont(iface);
658 ULONG ref = InterlockedDecrement(&This->ref);
660 TRACE("(%p)->(%d)\n", This, ref);
662 if (!ref)
664 if (This->face) IDWriteFontFace_Release(This->face);
665 if (This->family) IDWriteFontFamily_Release(This->family);
666 _free_font_data(This->data);
667 heap_free(This);
670 return ref;
673 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
675 struct dwrite_font *This = impl_from_IDWriteFont(iface);
676 TRACE("(%p)->(%p)\n", This, family);
678 *family = This->family;
679 IDWriteFontFamily_AddRef(*family);
680 return S_OK;
683 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
685 struct dwrite_font *This = impl_from_IDWriteFont(iface);
686 TRACE("(%p)\n", This);
687 return This->data->weight;
690 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
692 struct dwrite_font *This = impl_from_IDWriteFont(iface);
693 TRACE("(%p)\n", This);
694 return This->data->stretch;
697 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
699 struct dwrite_font *This = impl_from_IDWriteFont(iface);
700 TRACE("(%p)\n", This);
701 return This->data->style;
704 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
706 struct dwrite_font *This = impl_from_IDWriteFont(iface);
707 FIXME("(%p): stub\n", This);
708 return FALSE;
711 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
713 struct dwrite_font *This = impl_from_IDWriteFont(iface);
714 FIXME("(%p)->(%p): stub\n", This, names);
715 return E_NOTIMPL;
718 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
719 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
721 struct dwrite_font *This = impl_from_IDWriteFont(iface);
722 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
723 return E_NOTIMPL;
726 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
728 struct dwrite_font *This = impl_from_IDWriteFont(iface);
729 TRACE("(%p)\n", This);
730 return This->data->simulations;
733 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
735 struct dwrite_font *This = impl_from_IDWriteFont(iface);
737 TRACE("(%p)->(%p)\n", This, metrics);
738 *metrics = This->data->metrics;
741 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
743 struct dwrite_font *This = impl_from_IDWriteFont(iface);
744 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
745 return E_NOTIMPL;
748 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
750 struct dwrite_font *This = impl_from_IDWriteFont(iface);
752 if (This->is_system)
754 TRACE("(%p)->(%p)\n", This, face);
756 if (!This->face)
758 HRESULT hr = create_system_fontface(This, &This->face);
759 if (FAILED(hr)) return hr;
762 *face = This->face;
763 IDWriteFontFace_AddRef(*face);
765 return S_OK;
767 else
769 TRACE("(%p)->(%p)\n", This, face);
771 if (!This->face)
773 HRESULT hr = font_create_fontface(NULL, This->data->face_data->type, This->data->face_data->file_count, This->data->face_data->files, This->data->face_data->index, This->data->face_data->simulations, &This->face);
774 if (FAILED(hr)) return hr;
777 *face = This->face;
778 IDWriteFontFace_AddRef(*face);
780 return S_OK;
784 static const IDWriteFontVtbl dwritefontvtbl = {
785 dwritefont_QueryInterface,
786 dwritefont_AddRef,
787 dwritefont_Release,
788 dwritefont_GetFontFamily,
789 dwritefont_GetWeight,
790 dwritefont_GetStretch,
791 dwritefont_GetStyle,
792 dwritefont_IsSymbolFont,
793 dwritefont_GetFaceNames,
794 dwritefont_GetInformationalStrings,
795 dwritefont_GetSimulations,
796 dwritefont_GetMetrics,
797 dwritefont_HasCharacter,
798 dwritefont_CreateFontFace
801 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
803 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
804 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
806 if (IsEqualIID(riid, &IID_IUnknown) ||
807 IsEqualIID(riid, &IID_IDWriteFontList) ||
808 IsEqualIID(riid, &IID_IDWriteFontFamily))
810 *obj = iface;
811 IDWriteFontFamily_AddRef(iface);
812 return S_OK;
815 *obj = NULL;
816 return E_NOINTERFACE;
819 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
821 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
822 ULONG ref = InterlockedIncrement(&This->ref);
823 TRACE("(%p)->(%d)\n", This, ref);
824 return ref;
827 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
829 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
830 ULONG ref = InterlockedDecrement(&This->ref);
832 TRACE("(%p)->(%d)\n", This, ref);
834 if (!ref)
836 int i;
837 heap_free(This->familyname);
839 for (i = 0; i < This->font_count; i++)
840 _free_font_data(This->fonts[i]);
841 heap_free(This->fonts);
842 heap_free(This);
845 return ref;
848 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
850 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
851 FIXME("(%p)->(%p): stub\n", This, collection);
852 return E_NOTIMPL;
855 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
857 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
858 TRACE("(%p)\n", This);
859 return This->font_count;
862 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
864 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
865 TRACE("(%p)->(%u %p)\n", This, index, font);
866 if (This->font_count > 0)
868 HRESULT hr;
869 if (index >= This->font_count)
870 return E_INVALIDARG;
871 hr = create_font_from_data(This->fonts[index], font);
872 if (SUCCEEDED(hr))
874 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
875 font_data->family = iface;
876 IDWriteFontFamily_AddRef(iface);
878 return hr;
880 else
881 return E_NOTIMPL;
884 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
886 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
887 static const WCHAR enusW[] = {'e','n','-','u','s',0};
888 HRESULT hr;
890 TRACE("(%p)->(%p)\n", This, names);
892 hr = create_localizedstrings(names);
893 if (FAILED(hr)) return hr;
895 return add_localizedstring(*names, enusW, This->familyname);
898 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
899 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
901 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
902 LOGFONTW lf;
904 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
906 /* fallback for system font collections */
907 if (This->font_count == 0)
909 memset(&lf, 0, sizeof(lf));
910 lf.lfWeight = weight;
911 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
912 strcpyW(lf.lfFaceName, This->familyname);
914 return create_font_from_logfont(&lf, font);
916 else
918 int i;
919 for (i = 0; i < This->font_count; i++)
921 if (style == This->fonts[i]->style &&
922 weight == This->fonts[i]->weight &&
923 stretch == This->fonts[i]->stretch)
925 HRESULT hr;
926 hr = create_font_from_data(This->fonts[i], font);
927 if (SUCCEEDED(hr))
929 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
930 font_data->family = iface;
931 IDWriteFontFamily_AddRef(iface);
933 return hr;
936 return DWRITE_E_NOFONT;
940 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
941 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
943 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
944 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
945 return E_NOTIMPL;
948 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
949 dwritefontfamily_QueryInterface,
950 dwritefontfamily_AddRef,
951 dwritefontfamily_Release,
952 dwritefontfamily_GetFontCollection,
953 dwritefontfamily_GetFontCount,
954 dwritefontfamily_GetFont,
955 dwritefontfamily_GetFamilyNames,
956 dwritefontfamily_GetFirstMatchingFont,
957 dwritefontfamily_GetMatchingFonts
960 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
962 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
963 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
965 if (IsEqualIID(riid, &IID_IUnknown) ||
966 IsEqualIID(riid, &IID_IDWriteFontCollection))
968 *obj = iface;
969 IDWriteFontCollection_AddRef(iface);
970 return S_OK;
973 *obj = NULL;
974 return E_NOINTERFACE;
977 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
979 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
980 ULONG ref = InterlockedIncrement(&This->ref);
981 TRACE("(%p)->(%d)\n", This, ref);
982 return ref;
985 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
987 unsigned int i;
988 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
989 ULONG ref = InterlockedDecrement(&This->ref);
990 TRACE("(%p)->(%d)\n", This, ref);
992 if (!ref)
994 for (i = 0; i < This->count; i++)
995 heap_free(This->families[i]);
996 heap_free(This->families);
997 heap_free(This);
1000 return ref;
1003 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
1005 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1006 TRACE("(%p)\n", This);
1007 return This->count;
1010 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
1012 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1014 TRACE("(%p)->(%u %p)\n", This, index, family);
1016 if (index >= This->count)
1018 *family = NULL;
1019 return E_FAIL;
1022 return create_fontfamily(This->families[index], family);
1025 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
1027 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1028 UINT32 i;
1030 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
1032 for (i = 0; i < This->count; i++)
1033 if (!strcmpW(This->families[i], name))
1035 *index = i;
1036 *exists = TRUE;
1037 return S_OK;
1040 *index = (UINT32)-1;
1041 *exists = FALSE;
1043 return S_OK;
1046 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
1048 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1049 FIXME("(%p)->(%p %p): stub\n", This, face, font);
1050 return E_NOTIMPL;
1053 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
1054 dwritefontcollection_QueryInterface,
1055 dwritefontcollection_AddRef,
1056 dwritefontcollection_Release,
1057 dwritefontcollection_GetFontFamilyCount,
1058 dwritefontcollection_GetFontFamily,
1059 dwritefontcollection_FindFamilyName,
1060 dwritefontcollection_GetFontFromFontFace
1063 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
1065 /* check for duplicate family name */
1066 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
1068 /* double array length */
1069 if (collection->count == collection->alloc)
1071 collection->alloc *= 2;
1072 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
1075 collection->families[collection->count++] = heap_strdupW(family);
1076 TRACE("family name %s\n", debugstr_w(family));
1078 return S_OK;
1081 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1083 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1084 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1087 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1089 struct dwrite_fontcollection *This;
1090 LOGFONTW lf;
1091 HDC hdc;
1093 *collection = NULL;
1095 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1096 if (!This) return E_OUTOFMEMORY;
1098 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1099 This->ref = 1;
1100 This->alloc = 50;
1101 This->count = 0;
1102 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1104 TRACE("building system font collection:\n");
1106 hdc = CreateCompatibleDC(0);
1107 memset(&lf, 0, sizeof(lf));
1108 lf.lfCharSet = DEFAULT_CHARSET;
1109 lf.lfPitchAndFamily = DEFAULT_PITCH;
1110 lf.lfFaceName[0] = 0;
1111 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1112 DeleteDC(hdc);
1114 *collection = &This->IDWriteFontCollection_iface;
1116 return S_OK;
1119 static HRESULT create_fontfamily(const WCHAR *familyname, IDWriteFontFamily **family)
1121 struct dwrite_fontfamily *This;
1123 *family = NULL;
1125 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1126 if (!This) return E_OUTOFMEMORY;
1128 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1129 This->ref = 1;
1130 This->font_count = 0;
1131 This->alloc = 2;
1132 This->fonts = heap_alloc(sizeof(*This->fonts) * 2);
1133 This->familyname = heap_strdupW(familyname);
1135 *family = &This->IDWriteFontFamily_iface;
1137 return S_OK;
1140 static void get_font_properties(struct dwrite_font *font, HDC hdc)
1142 TT_OS2_V2 tt_os2;
1143 TT_HEAD tt_head;
1144 TT_POST tt_post;
1145 LONG size;
1147 /* default stretch and weight to normal */
1148 font->data->stretch = DWRITE_FONT_STRETCH_NORMAL;
1149 font->data->weight = DWRITE_FONT_WEIGHT_NORMAL;
1151 memset(&font->data->metrics, 0, sizeof(font->data->metrics));
1153 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1154 if (size != GDI_ERROR)
1156 if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
1158 memset(&tt_os2, 0, sizeof(tt_os2));
1159 if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return;
1161 /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
1162 if (GET_BE_WORD(tt_os2.usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
1163 font->data->stretch = GET_BE_WORD(tt_os2.usWidthClass);
1165 font->data->weight = GET_BE_WORD(tt_os2.usWeightClass);
1166 TRACE("stretch=%d, weight=%d\n", font->data->stretch, font->data->weight);
1168 font->data->metrics.ascent = GET_BE_WORD(tt_os2.sTypoAscender);
1169 font->data->metrics.descent = GET_BE_WORD(tt_os2.sTypoDescender);
1170 font->data->metrics.lineGap = GET_BE_WORD(tt_os2.sTypoLineGap);
1171 font->data->metrics.capHeight = GET_BE_WORD(tt_os2.sCapHeight);
1172 font->data->metrics.xHeight = GET_BE_WORD(tt_os2.sxHeight);
1173 font->data->metrics.strikethroughPosition = GET_BE_WORD(tt_os2.yStrikeoutPosition);
1174 font->data->metrics.strikethroughThickness = GET_BE_WORD(tt_os2.yStrikeoutSize);
1177 memset(&tt_head, 0, sizeof(tt_head));
1178 if (GetFontData(hdc, MS_HEAD_TAG, 0, &tt_head, sizeof(tt_head)) != GDI_ERROR)
1180 font->data->metrics.designUnitsPerEm = GET_BE_WORD(tt_head.unitsPerEm);
1183 memset(&tt_post, 0, sizeof(tt_post));
1184 if (GetFontData(hdc, MS_POST_TAG, 0, &tt_post, sizeof(tt_post)) != GDI_ERROR)
1186 font->data->metrics.underlinePosition = GET_BE_WORD(tt_post.underlinePosition);
1187 font->data->metrics.underlineThickness = GET_BE_WORD(tt_post.underlineThickness);
1191 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font)
1193 struct dwrite_font *This;
1194 *font = NULL;
1196 This = heap_alloc(sizeof(struct dwrite_font));
1197 if (!This) return E_OUTOFMEMORY;
1199 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
1200 This->ref = 1;
1201 This->face = NULL;
1202 This->family = NULL;
1203 This->is_system = FALSE;
1204 This->data = data;
1205 InterlockedIncrement(&This->data->ref);
1207 *font = &This->IDWriteFont_iface;
1209 return S_OK;
1212 static HRESULT create_font_base(IDWriteFont **font)
1214 struct dwrite_font_data *data;
1215 HRESULT ret;
1217 *font = NULL;
1218 data = heap_alloc(sizeof(*data));
1219 if (!data) return E_OUTOFMEMORY;
1221 data->ref = 0;
1222 data->face_data = NULL;
1224 ret = create_font_from_data( data, font );
1225 if (FAILED(ret)) heap_free( data );
1226 return ret;
1229 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1231 const WCHAR* facename, *familyname;
1232 struct dwrite_font *This;
1233 IDWriteFontFamily *family;
1234 OUTLINETEXTMETRICW *otm;
1235 HRESULT hr;
1236 HFONT hfont;
1237 HDC hdc;
1238 int ret;
1240 hr = create_font_base(font);
1241 if (FAILED(hr))
1242 return hr;
1244 This = impl_from_IDWriteFont(*font);
1246 hfont = CreateFontIndirectW(logfont);
1247 if (!hfont)
1249 heap_free(This->data);
1250 heap_free(This);
1251 return DWRITE_E_NOFONT;
1254 hdc = CreateCompatibleDC(0);
1255 SelectObject(hdc, hfont);
1257 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1258 otm = heap_alloc(ret);
1259 if (!otm)
1261 heap_free(This->data);
1262 heap_free(This);
1263 DeleteDC(hdc);
1264 DeleteObject(hfont);
1265 return E_OUTOFMEMORY;
1267 otm->otmSize = ret;
1268 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1270 get_font_properties(This, hdc);
1272 DeleteDC(hdc);
1273 DeleteObject(hfont);
1275 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1276 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1277 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1279 hr = create_fontfamily(familyname, &family);
1280 heap_free(otm);
1281 if (hr != S_OK)
1283 heap_free(This->data);
1284 heap_free(This);
1285 return hr;
1288 This->is_system = TRUE;
1289 This->family = family;
1290 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1291 This->data->style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
1292 This->data->facename = heap_strdupW(logfont->lfFaceName);
1294 return S_OK;
1297 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1299 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1301 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1303 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1305 *obj = iface;
1306 IDWriteFontFile_AddRef(iface);
1307 return S_OK;
1310 *obj = NULL;
1311 return E_NOINTERFACE;
1314 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1316 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1317 ULONG ref = InterlockedIncrement(&This->ref);
1318 TRACE("(%p)->(%d)\n", This, ref);
1319 return ref;
1322 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1324 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1325 ULONG ref = InterlockedDecrement(&This->ref);
1327 TRACE("(%p)->(%d)\n", This, ref);
1329 if (!ref)
1331 IDWriteFontFileLoader_Release(This->loader);
1332 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1333 heap_free(This->reference_key);
1334 heap_free(This);
1337 return ref;
1340 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1342 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1343 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1344 *fontFileReferenceKey = This->reference_key;
1345 *fontFileReferenceKeySize = This->key_size;
1347 return S_OK;
1350 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1352 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1353 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1354 *fontFileLoader = This->loader;
1355 IDWriteFontFileLoader_AddRef(This->loader);
1357 return S_OK;
1360 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1362 HRESULT hr;
1363 const void *font_data;
1364 void *context;
1365 IDWriteFontFileStream *stream;
1367 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1368 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1370 *isSupportedFontType = FALSE;
1371 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1372 if (fontFaceType)
1373 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1374 *numberOfFaces = 0;
1376 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1377 if (FAILED(hr))
1378 return S_OK;
1379 hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, 28, &context);
1380 if (SUCCEEDED(hr))
1382 hr = analyze_opentype_font(font_data, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1383 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1385 /* TODO: Further Analysis */
1386 IDWriteFontFileStream_Release(stream);
1387 return S_OK;
1390 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1391 dwritefontfile_QueryInterface,
1392 dwritefontfile_AddRef,
1393 dwritefontfile_Release,
1394 dwritefontfile_GetReferenceKey,
1395 dwritefontfile_GetLoader,
1396 dwritefontfile_Analyze,
1399 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1401 struct dwrite_fontfile *This;
1403 This = heap_alloc(sizeof(struct dwrite_fontfile));
1404 if (!This) return E_OUTOFMEMORY;
1406 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1407 This->ref = 1;
1408 IDWriteFontFileLoader_AddRef(loader);
1409 This->loader = loader;
1410 This->stream = NULL;
1411 This->reference_key = heap_alloc(key_size);
1412 memcpy(This->reference_key, reference_key, key_size);
1413 This->key_size = key_size;
1415 *font_file = &This->IDWriteFontFile_iface;
1417 return S_OK;
1420 HRESULT font_create_fontface(IDWriteFactory *iface, DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS sim_flags, IDWriteFontFace **font_face)
1422 int i;
1423 struct dwrite_fontface *This;
1424 HRESULT hr = S_OK;
1426 *font_face = NULL;
1428 This = heap_alloc(sizeof(struct dwrite_fontface));
1429 if (!This) return E_OUTOFMEMORY;
1430 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1431 if (!This)
1433 heap_free(This);
1434 return E_OUTOFMEMORY;
1437 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
1438 This->ref = 1;
1439 This->data->ref = 1;
1440 This->data->type = facetype;
1441 This->data->file_count = files_number;
1442 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1443 This->CMAP_table = NULL;
1444 This->CMAP_context = NULL;
1445 This->CMAP_size = 0;
1446 /* Verify font file streams */
1447 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1449 IDWriteFontFileStream *stream;
1450 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1451 if (SUCCEEDED(hr))
1452 IDWriteFontFileStream_Release(stream);
1454 if (FAILED(hr))
1456 heap_free(This->data->files);
1457 heap_free(This->data);
1458 heap_free(This);
1459 return hr;
1461 for (i = 0; i < This->data->file_count; i++)
1463 This->data->files[i] = font_files[i];
1464 IDWriteFontFile_AddRef(font_files[i]);
1467 This->data->index = index;
1468 This->data->simulations = sim_flags;
1469 This->is_system = FALSE;
1471 *font_face = &This->IDWriteFontFace_iface;
1473 return S_OK;
1476 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1478 struct dwrite_localfontfilestream
1480 IDWriteFontFileStream IDWriteFontFileStream_iface;
1481 LONG ref;
1483 HANDLE handle;
1486 struct dwrite_localfontfileloader {
1487 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1488 LONG ref;
1491 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1493 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1496 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1498 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1501 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1503 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1504 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1505 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1507 *obj = iface;
1508 IDWriteFontFileStream_AddRef(iface);
1509 return S_OK;
1512 *obj = NULL;
1513 return E_NOINTERFACE;
1516 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1518 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1519 ULONG ref = InterlockedIncrement(&This->ref);
1520 TRACE("(%p)->(%d)\n", This, ref);
1521 return ref;
1524 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1526 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1527 ULONG ref = InterlockedDecrement(&This->ref);
1529 TRACE("(%p)->(%d)\n", This, ref);
1531 if (!ref)
1533 if (This->handle != INVALID_HANDLE_VALUE)
1534 CloseHandle(This->handle);
1535 heap_free(This);
1538 return ref;
1541 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1543 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1544 LARGE_INTEGER distance;
1545 DWORD bytes = fragment_size;
1546 DWORD read;
1548 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1549 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1551 *fragment_context = NULL;
1552 distance.QuadPart = offset;
1553 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1554 return E_FAIL;
1555 *fragment_start = *fragment_context = heap_alloc(bytes);
1556 if (!*fragment_context)
1557 return E_FAIL;
1558 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1560 heap_free(*fragment_context);
1561 return E_FAIL;
1564 return S_OK;
1567 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1569 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1570 TRACE("(%p)->(%p)\n", This, fragment_context);
1571 heap_free(fragment_context);
1574 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1576 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1577 LARGE_INTEGER li;
1578 TRACE("(%p)->(%p)\n",This, size);
1579 GetFileSizeEx(This->handle, &li);
1580 *size = li.QuadPart;
1581 return S_OK;
1584 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1586 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1587 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1588 *last_writetime = 0;
1589 return E_NOTIMPL;
1592 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1594 localfontfilestream_QueryInterface,
1595 localfontfilestream_AddRef,
1596 localfontfilestream_Release,
1597 localfontfilestream_ReadFileFragment,
1598 localfontfilestream_ReleaseFileFragment,
1599 localfontfilestream_GetFileSize,
1600 localfontfilestream_GetLastWriteTime
1603 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1605 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1606 if (!This)
1607 return E_OUTOFMEMORY;
1609 This->ref = 1;
1610 This->handle = handle;
1611 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1613 *iface = &This->IDWriteFontFileStream_iface;
1614 return S_OK;
1617 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1619 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1621 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1623 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1625 *obj = iface;
1626 IDWriteLocalFontFileLoader_AddRef(iface);
1627 return S_OK;
1630 *obj = NULL;
1631 return E_NOINTERFACE;
1634 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1636 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1637 ULONG ref = InterlockedIncrement(&This->ref);
1638 TRACE("(%p)->(%d)\n", This, ref);
1639 return ref;
1642 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1644 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1645 ULONG ref = InterlockedDecrement(&This->ref);
1647 TRACE("(%p)->(%d)\n", This, ref);
1649 if (!ref)
1650 heap_free(This);
1652 return ref;
1655 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1657 HANDLE handle;
1658 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1659 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1661 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1663 TRACE("name: %s\n",debugstr_w(name));
1664 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1665 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1667 if (handle == INVALID_HANDLE_VALUE)
1668 return E_FAIL;
1670 return create_localfontfilestream(handle, fontFileStream);
1673 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1675 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1676 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1677 *length = key_size;
1678 return S_OK;
1681 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1683 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1684 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1685 if (length < key_size)
1686 return E_INVALIDARG;
1687 lstrcpynW((WCHAR*)key, path, key_size);
1688 return S_OK;
1691 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1693 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1694 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1695 return E_NOTIMPL;
1698 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1699 localfontfileloader_QueryInterface,
1700 localfontfileloader_AddRef,
1701 localfontfileloader_Release,
1702 localfontfileloader_CreateStreamFromKey,
1703 localfontfileloader_GetFilePathLengthFromKey,
1704 localfontfileloader_GetFilePathFromKey,
1705 localfontfileloader_GetLastWriteTimeFromKey
1708 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1710 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1711 if (!This)
1712 return E_OUTOFMEMORY;
1714 This->ref = 1;
1715 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1717 *iface = &This->IDWriteLocalFontFileLoader_iface;
1718 return S_OK;