dwrite: Refuse to create IDWriteFontFace with invalid collection index.
[wine.git] / dlls / dwrite / font.c
bloba220501db9f248004d3ec13812621880d41dbc83
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_2.h"
25 #include "dwrite_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
29 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
30 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
31 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
32 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
34 struct dwrite_fontface_data {
35 LONG ref;
37 DWRITE_FONT_FACE_TYPE type;
38 UINT32 file_count;
39 IDWriteFontFile ** files;
40 DWRITE_FONT_SIMULATIONS simulations;
41 UINT32 index;
44 struct dwrite_font_data {
45 LONG ref;
47 DWRITE_FONT_STYLE style;
48 DWRITE_FONT_STRETCH stretch;
49 DWRITE_FONT_WEIGHT weight;
50 DWRITE_FONT_SIMULATIONS simulations;
51 DWRITE_FONT_METRICS metrics;
53 struct dwrite_fontface_data *face_data;
55 WCHAR *facename;
58 struct dwrite_fontfamily_data {
59 LONG ref;
61 IDWriteLocalizedStrings *familyname;
63 struct dwrite_font_data **fonts;
64 UINT32 font_count;
65 UINT32 alloc;
68 struct dwrite_fontcollection {
69 IDWriteFontCollection IDWriteFontCollection_iface;
70 LONG ref;
72 WCHAR **families;
73 UINT32 count;
74 int alloc;
76 struct dwrite_fontfamily_data **family_data;
77 DWORD data_count;
78 int data_alloc;
81 struct dwrite_fontfamily {
82 IDWriteFontFamily IDWriteFontFamily_iface;
83 LONG ref;
85 struct dwrite_fontfamily_data *data;
87 IDWriteFontCollection* collection;
90 struct dwrite_font {
91 IDWriteFont2 IDWriteFont2_iface;
92 LONG ref;
94 BOOL is_system;
95 IDWriteFontFamily *family;
96 IDWriteFontFace *face;
98 struct dwrite_font_data *data;
101 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
103 struct dwrite_fonttablecontext {
104 UINT32 magic;
105 void *context;
106 UINT32 file_index;
109 struct dwrite_fonttable {
110 void *data;
111 void *context;
112 UINT32 size;
115 struct dwrite_fontface {
116 IDWriteFontFace2 IDWriteFontFace2_iface;
117 LONG ref;
119 struct dwrite_fontface_data *data;
120 struct dwrite_fonttable cmap;
122 BOOL is_system;
123 LOGFONTW logfont;
126 struct dwrite_fontfile {
127 IDWriteFontFile IDWriteFontFile_iface;
128 LONG ref;
130 IDWriteFontFileLoader *loader;
131 void *reference_key;
132 UINT32 key_size;
133 IDWriteFontFileStream *stream;
136 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family);
137 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family);
138 static HRESULT create_font_base(IDWriteFont **font);
139 static HRESULT create_font_from_data(struct dwrite_font_data*,IDWriteFontFamily*,IDWriteFont**);
141 static inline struct dwrite_fontface *impl_from_IDWriteFontFace2(IDWriteFontFace2 *iface)
143 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace2_iface);
146 static inline struct dwrite_font *impl_from_IDWriteFont2(IDWriteFont2 *iface)
148 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont2_iface);
151 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
153 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
156 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
158 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
161 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
163 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
166 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
168 HRESULT hr;
169 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
170 if (!This->stream)
172 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
173 if (FAILED(hr))
174 return hr;
176 if (This->stream)
178 IDWriteFontFileStream_AddRef(This->stream);
179 *stream = This->stream;
180 return S_OK;
182 return E_FAIL;
185 static VOID _free_fontface_data(struct dwrite_fontface_data *data)
187 int i;
188 if (!data)
189 return;
190 i = InterlockedDecrement(&data->ref);
191 if (i > 0)
192 return;
193 for (i = 0; i < data->file_count; i++)
194 IDWriteFontFile_Release(data->files[i]);
195 heap_free(data->files);
196 heap_free(data);
199 static VOID _free_font_data(struct dwrite_font_data *data)
201 int i;
202 if (!data)
203 return;
204 i = InterlockedDecrement(&data->ref);
205 if (i > 0)
206 return;
207 _free_fontface_data(data->face_data);
208 heap_free(data->facename);
209 heap_free(data);
212 static VOID _free_fontfamily_data(struct dwrite_fontfamily_data *data)
214 int i;
215 if (!data)
216 return;
217 i = InterlockedDecrement(&data->ref);
218 if (i > 0)
219 return;
220 for (i = 0; i < data->font_count; i++)
221 _free_font_data(data->fonts[i]);
222 heap_free(data->fonts);
223 IDWriteLocalizedStrings_Release(data->familyname);
224 heap_free(data);
227 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace2 *iface, REFIID riid, void **obj)
229 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
231 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
233 if (IsEqualIID(riid, &IID_IDWriteFontFace2) ||
234 IsEqualIID(riid, &IID_IDWriteFontFace1) ||
235 IsEqualIID(riid, &IID_IDWriteFontFace) ||
236 IsEqualIID(riid, &IID_IUnknown))
238 *obj = iface;
239 IDWriteFontFace2_AddRef(iface);
240 return S_OK;
243 *obj = NULL;
244 return E_NOINTERFACE;
247 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace2 *iface)
249 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
250 ULONG ref = InterlockedIncrement(&This->ref);
251 TRACE("(%p)->(%d)\n", This, ref);
252 return ref;
255 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace2 *iface)
257 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
258 ULONG ref = InterlockedDecrement(&This->ref);
260 TRACE("(%p)->(%d)\n", This, ref);
262 if (!ref)
264 if (This->cmap.context)
265 IDWriteFontFace2_ReleaseFontTable(iface, This->cmap.context);
266 _free_fontface_data(This->data);
267 heap_free(This);
270 return ref;
273 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace2 *iface)
275 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
276 TRACE("(%p)\n", This);
277 return This->data->type;
280 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace2 *iface, UINT32 *number_of_files,
281 IDWriteFontFile **fontfiles)
283 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
284 int i;
286 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
287 if (fontfiles == NULL)
289 *number_of_files = This->data->file_count;
290 return S_OK;
292 if (*number_of_files < This->data->file_count)
293 return E_INVALIDARG;
295 for (i = 0; i < This->data->file_count; i++)
297 IDWriteFontFile_AddRef(This->data->files[i]);
298 fontfiles[i] = This->data->files[i];
301 return S_OK;
304 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace2 *iface)
306 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
307 TRACE("(%p)\n", This);
308 return This->data->index;
311 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace2 *iface)
313 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
314 TRACE("(%p)\n", This);
315 return This->data->simulations;
318 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace2 *iface)
320 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
321 FIXME("(%p): stub\n", This);
322 return FALSE;
325 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS *metrics)
327 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
328 FIXME("(%p)->(%p): stub\n", This, metrics);
331 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace2 *iface)
333 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
334 FIXME("(%p): stub\n", This);
335 return 0;
338 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2 *iface,
339 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
341 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
342 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
343 return E_NOTIMPL;
346 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UINT32 const *codepoints,
347 UINT32 count, UINT16 *glyph_indices)
349 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
350 unsigned int i;
352 if (This->is_system)
354 HFONT hfont;
355 WCHAR *str;
356 HDC hdc;
358 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
360 str = heap_alloc(count*sizeof(WCHAR));
361 if (!str) return E_OUTOFMEMORY;
363 for (i = 0; i < count; i++)
364 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
366 hdc = CreateCompatibleDC(0);
367 hfont = CreateFontIndirectW(&This->logfont);
368 SelectObject(hdc, hfont);
370 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
371 heap_free(str);
373 DeleteDC(hdc);
374 DeleteObject(hfont);
376 return S_OK;
378 else
380 HRESULT hr;
381 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
382 if (!This->cmap.data)
384 BOOL exists = FALSE;
385 hr = IDWriteFontFace2_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->cmap.data, &This->cmap.size, &This->cmap.context, &exists);
386 if (FAILED(hr) || !exists)
388 ERR("Font does not have a CMAP table\n");
389 return E_FAIL;
393 for (i = 0; i < count; i++)
395 OpenType_CMAP_GetGlyphIndex(This->cmap.data, codepoints[i], &glyph_indices[i], 0);
397 return S_OK;
401 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace2 *iface, UINT32 table_tag,
402 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
404 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
405 if (This->is_system)
407 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
408 return E_NOTIMPL;
410 else
412 HRESULT hr = S_OK;
413 int i;
414 struct dwrite_fonttablecontext *tablecontext;
416 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
418 tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext));
419 if (!tablecontext)
420 return E_OUTOFMEMORY;
421 tablecontext->magic = DWRITE_FONTTABLE_MAGIC;
423 *exists = FALSE;
424 for (i = 0; i < This->data->file_count && !(*exists); i++)
426 IDWriteFontFileStream *stream;
427 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
428 if (FAILED(hr))
429 continue;
430 tablecontext->file_index = i;
432 hr = opentype_get_font_table(stream, This->data->type, This->data->index, table_tag, table_data, &tablecontext->context, table_size, exists);
434 IDWriteFontFileStream_Release(stream);
436 if (FAILED(hr) && !*exists)
437 heap_free(tablecontext);
438 else
439 *context = (void*)tablecontext;
440 return hr;
444 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace2 *iface, void *table_context)
446 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
447 struct dwrite_fonttablecontext *tablecontext = (struct dwrite_fonttablecontext*)table_context;
448 IDWriteFontFileStream *stream;
449 HRESULT hr;
450 TRACE("(%p)->(%p)\n", This, table_context);
452 if (tablecontext->magic != DWRITE_FONTTABLE_MAGIC)
454 TRACE("Invalid table magic\n");
455 return;
458 hr = _dwritefontfile_GetFontFileStream(This->data->files[tablecontext->file_index], &stream);
459 if (FAILED(hr))
460 return;
461 IDWriteFontFileStream_ReleaseFileFragment(stream, tablecontext->context);
462 IDWriteFontFileStream_Release(stream);
463 heap_free(tablecontext);
466 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace2 *iface, FLOAT emSize,
467 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
468 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
470 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
471 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
472 glyph_count, is_sideways, is_rtl, geometrysink);
473 return E_NOTIMPL;
476 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
477 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
479 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
480 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
481 return E_NOTIMPL;
484 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
485 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
487 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
488 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
489 return E_NOTIMPL;
492 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
493 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
494 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
496 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
497 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
498 glyph_count, metrics, is_sideways);
499 return E_NOTIMPL;
502 static HRESULT WINAPI dwritefontface1_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS1 *metrics)
504 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
505 FIXME("(%p)->(%p): stub\n", This, metrics);
506 return E_NOTIMPL;
509 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT em_size, FLOAT pixels_per_dip,
510 const DWRITE_MATRIX *transform, DWRITE_FONT_METRICS1 *metrics)
512 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
513 FIXME("(%p)->(%f %f %p %p): stub\n", This, em_size, pixels_per_dip, transform, metrics);
514 return E_NOTIMPL;
517 static void WINAPI dwritefontface1_GetCaretMetrics(IDWriteFontFace2 *iface, DWRITE_CARET_METRICS *metrics)
519 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
520 FIXME("(%p)->(%p): stub\n", This, metrics);
523 static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace2 *iface, UINT32 max_count,
524 DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
526 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
527 FIXME("(%p)->(%u %p %p): stub\n", This, max_count, ranges, count);
528 return E_NOTIMPL;
531 static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace2 *iface)
533 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
534 FIXME("(%p): stub\n", This);
535 return FALSE;
538 static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2 *iface,
539 UINT32 glyph_count, UINT16 const *indices, INT32 *advances, BOOL is_sideways)
541 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
542 FIXME("(%p)->(%u %p %p %d): stub\n", This, glyph_count, indices, advances, is_sideways);
543 return E_NOTIMPL;
546 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2 *iface,
547 FLOAT em_size, FLOAT pixels_per_dip, const DWRITE_MATRIX *transform, BOOL use_gdi_natural,
548 BOOL is_sideways, UINT32 glyph_count, UINT16 const *indices, INT32 *advances)
550 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
551 FIXME("(%p)->(%f %f %p %d %d %u %p %p): stub\n", This, em_size, pixels_per_dip, transform,
552 use_gdi_natural, is_sideways, glyph_count, indices, advances);
553 return E_NOTIMPL;
556 static HRESULT WINAPI dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2 *iface, UINT32 glyph_count,
557 const UINT16 *indices, INT32 *adjustments)
559 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
560 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, indices, adjustments);
561 return E_NOTIMPL;
564 static BOOL WINAPI dwritefontface1_HasKerningPairs(IDWriteFontFace2 *iface)
566 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
567 FIXME("(%p): stub\n", This);
568 return FALSE;
571 static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2 *iface,
572 FLOAT font_emsize, FLOAT dpiX, FLOAT dpiY, const DWRITE_MATRIX *transform, BOOL is_sideways,
573 DWRITE_OUTLINE_THRESHOLD threshold, DWRITE_MEASURING_MODE measuring_mode, DWRITE_RENDERING_MODE *rendering_mode)
575 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
576 FIXME("(%p)->(%f %f %f %p %d %d %d %p): stub\n", This, font_emsize, dpiX, dpiY, transform, is_sideways,
577 threshold, measuring_mode, rendering_mode);
578 return E_NOTIMPL;
581 static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2 *iface, UINT32 glyph_count,
582 const UINT16 *nominal_indices, UINT16 *vertical_indices)
584 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
585 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, nominal_indices, vertical_indices);
586 return E_NOTIMPL;
589 static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2 *iface)
591 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
592 FIXME("(%p): stub\n", This);
593 return FALSE;
596 static BOOL WINAPI dwritefontface2_IsColorFont(IDWriteFontFace2 *iface)
598 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
599 FIXME("(%p): stub\n", This);
600 return FALSE;
603 static UINT32 WINAPI dwritefontface2_GetColorPaletteCount(IDWriteFontFace2 *iface)
605 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
606 FIXME("(%p): stub\n", This);
607 return 0;
610 static UINT32 WINAPI dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2 *iface)
612 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
613 FIXME("(%p): stub\n", This);
614 return 0;
617 static HRESULT WINAPI dwritefontface2_GetPaletteEntries(IDWriteFontFace2 *iface, UINT32 palette_index,
618 UINT32 first_entry_index, UINT32 entry_count, DWRITE_COLOR_F *entries)
620 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
621 FIXME("(%p)->(%u %u %u %p): stub\n", This, palette_index, first_entry_index, entry_count, entries);
622 return E_NOTIMPL;
625 static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT fontEmSize,
626 FLOAT dpiX, FLOAT dpiY, DWRITE_MATRIX const *transform, BOOL is_sideways, DWRITE_OUTLINE_THRESHOLD threshold,
627 DWRITE_MEASURING_MODE measuringmode, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *renderingmode,
628 DWRITE_GRID_FIT_MODE *gridfitmode)
630 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
631 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This, fontEmSize, dpiX, dpiY, transform, is_sideways, threshold,
632 measuringmode, params, renderingmode, gridfitmode);
633 return E_NOTIMPL;
636 static const IDWriteFontFace2Vtbl dwritefontfacevtbl = {
637 dwritefontface_QueryInterface,
638 dwritefontface_AddRef,
639 dwritefontface_Release,
640 dwritefontface_GetType,
641 dwritefontface_GetFiles,
642 dwritefontface_GetIndex,
643 dwritefontface_GetSimulations,
644 dwritefontface_IsSymbolFont,
645 dwritefontface_GetMetrics,
646 dwritefontface_GetGlyphCount,
647 dwritefontface_GetDesignGlyphMetrics,
648 dwritefontface_GetGlyphIndices,
649 dwritefontface_TryGetFontTable,
650 dwritefontface_ReleaseFontTable,
651 dwritefontface_GetGlyphRunOutline,
652 dwritefontface_GetRecommendedRenderingMode,
653 dwritefontface_GetGdiCompatibleMetrics,
654 dwritefontface_GetGdiCompatibleGlyphMetrics,
655 dwritefontface1_GetMetrics,
656 dwritefontface1_GetGdiCompatibleMetrics,
657 dwritefontface1_GetCaretMetrics,
658 dwritefontface1_GetUnicodeRanges,
659 dwritefontface1_IsMonospacedFont,
660 dwritefontface1_GetDesignGlyphAdvances,
661 dwritefontface1_GetGdiCompatibleGlyphAdvances,
662 dwritefontface1_GetKerningPairAdjustments,
663 dwritefontface1_HasKerningPairs,
664 dwritefontface1_GetRecommendedRenderingMode,
665 dwritefontface1_GetVerticalGlyphVariants,
666 dwritefontface1_HasVerticalGlyphVariants,
667 dwritefontface2_IsColorFont,
668 dwritefontface2_GetColorPaletteCount,
669 dwritefontface2_GetPaletteEntryCount,
670 dwritefontface2_GetPaletteEntries,
671 dwritefontface2_GetRecommendedRenderingMode
674 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
676 struct dwrite_fontface *This;
678 *face = NULL;
680 This = heap_alloc(sizeof(struct dwrite_fontface));
681 if (!This) return E_OUTOFMEMORY;
682 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
683 if (!This->data)
685 heap_free(This);
686 return E_OUTOFMEMORY;
689 This->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
690 This->ref = 1;
691 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
692 This->data->file_count = 0;
693 This->data->files = NULL;
694 This->data->index = 0;
695 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
696 This->cmap.data = NULL;
697 This->cmap.context = NULL;
698 This->cmap.size = 0;
700 This->is_system = TRUE;
701 memset(&This->logfont, 0, sizeof(This->logfont));
702 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
703 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
704 This->logfont.lfWeight = font->data->weight;
705 strcpyW(This->logfont.lfFaceName, font->data->facename);
707 *face = (IDWriteFontFace*)&This->IDWriteFontFace2_iface;
709 return S_OK;
712 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
714 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace2((IDWriteFontFace2*)face);
716 *logfont = fontface->logfont;
718 return S_OK;
721 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont2 *iface, REFIID riid, void **obj)
723 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
725 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
727 if (IsEqualIID(riid, &IID_IDWriteFont2) ||
728 IsEqualIID(riid, &IID_IDWriteFont1) ||
729 IsEqualIID(riid, &IID_IDWriteFont) ||
730 IsEqualIID(riid, &IID_IUnknown))
732 *obj = iface;
733 IDWriteFont2_AddRef(iface);
734 return S_OK;
737 *obj = NULL;
738 return E_NOINTERFACE;
741 static ULONG WINAPI dwritefont_AddRef(IDWriteFont2 *iface)
743 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
744 ULONG ref = InterlockedIncrement(&This->ref);
745 TRACE("(%p)->(%d)\n", This, ref);
746 return ref;
749 static ULONG WINAPI dwritefont_Release(IDWriteFont2 *iface)
751 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
752 ULONG ref = InterlockedDecrement(&This->ref);
754 TRACE("(%p)->(%d)\n", This, ref);
756 if (!ref)
758 if (This->face) IDWriteFontFace_Release(This->face);
759 if (This->family) IDWriteFontFamily_Release(This->family);
760 _free_font_data(This->data);
761 heap_free(This);
764 return ref;
767 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont2 *iface, IDWriteFontFamily **family)
769 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
770 TRACE("(%p)->(%p)\n", This, family);
772 *family = This->family;
773 IDWriteFontFamily_AddRef(*family);
774 return S_OK;
777 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont2 *iface)
779 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
780 TRACE("(%p)\n", This);
781 return This->data->weight;
784 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont2 *iface)
786 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
787 TRACE("(%p)\n", This);
788 return This->data->stretch;
791 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont2 *iface)
793 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
794 TRACE("(%p)\n", This);
795 return This->data->style;
798 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont2 *iface)
800 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
801 FIXME("(%p): stub\n", This);
802 return FALSE;
805 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont2 *iface, IDWriteLocalizedStrings **names)
807 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
808 FIXME("(%p)->(%p): stub\n", This, names);
809 return E_NOTIMPL;
812 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont2 *iface,
813 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
815 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
816 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
817 return E_NOTIMPL;
820 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont2 *iface)
822 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
823 TRACE("(%p)\n", This);
824 return This->data->simulations;
827 static void WINAPI dwritefont_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS *metrics)
829 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
831 TRACE("(%p)->(%p)\n", This, metrics);
832 *metrics = This->data->metrics;
835 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont2 *iface, UINT32 value, BOOL *exists)
837 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
838 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
839 return E_NOTIMPL;
842 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont2 *iface, IDWriteFontFace **face)
844 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
846 if (This->is_system)
848 TRACE("(%p)->(%p)\n", This, face);
850 if (!This->face)
852 HRESULT hr = create_system_fontface(This, &This->face);
853 if (FAILED(hr)) return hr;
856 *face = This->face;
857 IDWriteFontFace_AddRef(*face);
859 return S_OK;
861 else
863 TRACE("(%p)->(%p)\n", This, face);
865 if (!This->face)
867 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);
868 if (FAILED(hr)) return hr;
871 *face = This->face;
872 IDWriteFontFace_AddRef(*face);
874 return S_OK;
878 static void WINAPI dwritefont1_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS1 *metrics)
880 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
881 FIXME("(%p)->(%p): stub\n", This, metrics);
884 static void WINAPI dwritefont1_GetPanose(IDWriteFont2 *iface, DWRITE_PANOSE *panose)
886 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
887 FIXME("(%p)->(%p): stub\n", This, panose);
890 static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont2 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
892 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
893 FIXME("(%p)->(%u %p %p): stub\n", This, max_count, ranges, count);
894 return E_NOTIMPL;
897 static HRESULT WINAPI dwritefont1_IsMonospacedFont(IDWriteFont2 *iface)
899 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
900 FIXME("(%p): stub\n", This);
901 return FALSE;
904 static HRESULT WINAPI dwritefont2_IsColorFont(IDWriteFont2 *iface)
906 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
907 FIXME("(%p): stub\n", This);
908 return FALSE;
911 static const IDWriteFont2Vtbl dwritefontvtbl = {
912 dwritefont_QueryInterface,
913 dwritefont_AddRef,
914 dwritefont_Release,
915 dwritefont_GetFontFamily,
916 dwritefont_GetWeight,
917 dwritefont_GetStretch,
918 dwritefont_GetStyle,
919 dwritefont_IsSymbolFont,
920 dwritefont_GetFaceNames,
921 dwritefont_GetInformationalStrings,
922 dwritefont_GetSimulations,
923 dwritefont_GetMetrics,
924 dwritefont_HasCharacter,
925 dwritefont_CreateFontFace,
926 dwritefont1_GetMetrics,
927 dwritefont1_GetPanose,
928 dwritefont1_GetUnicodeRanges,
929 dwritefont1_IsMonospacedFont,
930 dwritefont2_IsColorFont
933 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
935 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
936 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
938 if (IsEqualIID(riid, &IID_IUnknown) ||
939 IsEqualIID(riid, &IID_IDWriteFontList) ||
940 IsEqualIID(riid, &IID_IDWriteFontFamily))
942 *obj = iface;
943 IDWriteFontFamily_AddRef(iface);
944 return S_OK;
947 *obj = NULL;
948 return E_NOINTERFACE;
951 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
953 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
954 ULONG ref = InterlockedIncrement(&This->ref);
955 TRACE("(%p)->(%d)\n", This, ref);
956 return ref;
959 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
961 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
962 ULONG ref = InterlockedDecrement(&This->ref);
964 TRACE("(%p)->(%d)\n", This, ref);
966 if (!ref)
968 if (This->collection)
969 IDWriteFontCollection_Release(This->collection);
970 _free_fontfamily_data(This->data);
971 heap_free(This);
974 return ref;
977 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
979 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
980 TRACE("(%p)->(%p)\n", This, collection);
981 if (This->collection)
983 IDWriteFontCollection_AddRef(This->collection);
984 *collection = This->collection;
985 return S_OK;
987 else
988 return E_NOTIMPL;
991 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
993 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
994 TRACE("(%p)\n", This);
995 return This->data->font_count;
998 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
1000 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1001 TRACE("(%p)->(%u %p)\n", This, index, font);
1002 if (This->data->font_count > 0)
1004 if (index >= This->data->font_count)
1005 return E_INVALIDARG;
1006 return create_font_from_data(This->data->fonts[index], iface, font);
1008 else
1009 return E_NOTIMPL;
1012 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
1014 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1015 return clone_localizedstring(This->data->familyname, names);
1018 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1019 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
1021 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1022 LOGFONTW lf;
1024 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
1026 /* fallback for system font collections */
1027 if (This->data->font_count == 0)
1029 memset(&lf, 0, sizeof(lf));
1030 lf.lfWeight = weight;
1031 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
1032 IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE);
1034 return create_font_from_logfont(&lf, font);
1036 else
1038 int i;
1039 for (i = 0; i < This->data->font_count; i++)
1041 if (style == This->data->fonts[i]->style &&
1042 weight == This->data->fonts[i]->weight &&
1043 stretch == This->data->fonts[i]->stretch)
1045 return create_font_from_data(This->data->fonts[i], iface, font);
1048 return DWRITE_E_NOFONT;
1052 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1053 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
1055 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1056 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
1057 return E_NOTIMPL;
1060 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
1061 dwritefontfamily_QueryInterface,
1062 dwritefontfamily_AddRef,
1063 dwritefontfamily_Release,
1064 dwritefontfamily_GetFontCollection,
1065 dwritefontfamily_GetFontCount,
1066 dwritefontfamily_GetFont,
1067 dwritefontfamily_GetFamilyNames,
1068 dwritefontfamily_GetFirstMatchingFont,
1069 dwritefontfamily_GetMatchingFonts
1072 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
1074 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1075 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1077 if (IsEqualIID(riid, &IID_IUnknown) ||
1078 IsEqualIID(riid, &IID_IDWriteFontCollection))
1080 *obj = iface;
1081 IDWriteFontCollection_AddRef(iface);
1082 return S_OK;
1085 *obj = NULL;
1086 return E_NOINTERFACE;
1089 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
1091 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1092 ULONG ref = InterlockedIncrement(&This->ref);
1093 TRACE("(%p)->(%d)\n", This, ref);
1094 return ref;
1097 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
1099 unsigned int i;
1100 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1101 ULONG ref = InterlockedDecrement(&This->ref);
1102 TRACE("(%p)->(%d)\n", This, ref);
1104 if (!ref)
1106 for (i = 0; i < This->count; i++)
1107 heap_free(This->families[i]);
1108 heap_free(This->families);
1109 for (i = 0; i < This->data_count; i++)
1110 _free_fontfamily_data(This->family_data[i]);
1111 heap_free(This->family_data);
1112 heap_free(This);
1115 return ref;
1118 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
1120 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1121 TRACE("(%p)\n", This);
1122 if (This->data_count)
1123 return This->data_count;
1124 return This->count;
1127 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
1129 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1130 HRESULT hr;
1131 IDWriteLocalizedStrings *familyname;
1132 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1134 TRACE("(%p)->(%u %p)\n", This, index, family);
1136 if (This->data_count)
1138 if (index >= This->data_count)
1140 *family = NULL;
1141 return E_FAIL;
1143 else
1144 return create_fontfamily_from_data(This->family_data[index], iface, family);
1146 else
1148 if (index >= This->count)
1150 *family = NULL;
1151 return E_FAIL;
1154 hr = create_localizedstrings(&familyname);
1155 if (FAILED(hr))
1156 return hr;
1157 add_localizedstring(familyname, enusW, This->families[index]);
1159 return create_fontfamily(familyname, family);
1163 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
1165 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1166 UINT32 i;
1168 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
1170 if (This->data_count)
1172 for (i = 0; i < This->data_count; i++)
1174 HRESULT hr;
1175 IDWriteLocalizedStrings *family_name = This->family_data[i]->familyname;
1176 int j;
1177 for (j = 0; j < IDWriteLocalizedStrings_GetCount(family_name); j ++)
1179 WCHAR buffer[255];
1180 hr = IDWriteLocalizedStrings_GetString(family_name, j, buffer, 255);
1181 if (SUCCEEDED(hr))
1183 if (!strcmpW(buffer, name))
1185 *index = i;
1186 *exists = TRUE;
1187 return S_OK;
1192 *index = (UINT32)-1;
1193 *exists = FALSE;
1195 else
1197 for (i = 0; i < This->count; i++)
1198 if (!strcmpW(This->families[i], name))
1200 *index = i;
1201 *exists = TRUE;
1202 return S_OK;
1205 *index = (UINT32)-1;
1206 *exists = FALSE;
1209 return S_OK;
1212 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
1214 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1215 FIXME("(%p)->(%p %p): stub\n", This, face, font);
1216 return E_NOTIMPL;
1219 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
1220 dwritefontcollection_QueryInterface,
1221 dwritefontcollection_AddRef,
1222 dwritefontcollection_Release,
1223 dwritefontcollection_GetFontFamilyCount,
1224 dwritefontcollection_GetFontFamily,
1225 dwritefontcollection_FindFamilyName,
1226 dwritefontcollection_GetFontFromFontFace
1229 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
1231 /* check for duplicate family name */
1232 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
1234 /* double array length */
1235 if (collection->count == collection->alloc)
1237 collection->alloc *= 2;
1238 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
1241 collection->families[collection->count++] = heap_strdupW(family);
1242 TRACE("family name %s\n", debugstr_w(family));
1244 return S_OK;
1247 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1249 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1250 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1253 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1255 struct dwrite_fontcollection *This;
1256 LOGFONTW lf;
1257 HDC hdc;
1259 *collection = NULL;
1261 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1262 if (!This) return E_OUTOFMEMORY;
1264 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1265 This->ref = 1;
1266 This->alloc = 50;
1267 This->count = 0;
1268 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1269 if (!This->families)
1271 heap_free(This);
1272 return E_OUTOFMEMORY;
1274 This->data_count = 0;
1275 This->data_alloc = 2;
1276 This->family_data = heap_alloc(sizeof(*This->family_data)*2);
1277 if (!This->family_data)
1279 heap_free(This->families);
1280 heap_free(This);
1281 return E_OUTOFMEMORY;
1284 TRACE("building system font collection:\n");
1286 hdc = CreateCompatibleDC(0);
1287 memset(&lf, 0, sizeof(lf));
1288 lf.lfCharSet = DEFAULT_CHARSET;
1289 lf.lfPitchAndFamily = DEFAULT_PITCH;
1290 lf.lfFaceName[0] = 0;
1291 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1292 DeleteDC(hdc);
1294 *collection = &This->IDWriteFontCollection_iface;
1296 return S_OK;
1299 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family)
1301 struct dwrite_fontfamily *This;
1303 *family = NULL;
1305 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1306 if (!This) return E_OUTOFMEMORY;
1308 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1309 This->ref = 1;
1310 This->collection = collection;
1311 if (collection)
1312 IDWriteFontCollection_AddRef(collection);
1313 This->data = data;
1314 InterlockedIncrement(&This->data->ref);
1316 *family = &This->IDWriteFontFamily_iface;
1318 return S_OK;
1321 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family)
1323 struct dwrite_fontfamily_data *data;
1324 HRESULT ret;
1326 data = heap_alloc(sizeof(struct dwrite_fontfamily_data));
1327 if (!data) return E_OUTOFMEMORY;
1329 data->ref = 0;
1330 data->font_count = 0;
1331 data->alloc = 2;
1332 data->fonts = heap_alloc(sizeof(*data->fonts) * 2);
1333 if (!data->fonts)
1335 heap_free(data);
1336 return E_OUTOFMEMORY;
1338 data->familyname = familyname;
1340 ret = create_fontfamily_from_data(data, NULL, family);
1341 if (FAILED(ret))
1343 heap_free(data->fonts);
1344 heap_free(data);
1347 return ret;
1350 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFontFamily *family, IDWriteFont **font)
1352 struct dwrite_font *This;
1353 *font = NULL;
1355 This = heap_alloc(sizeof(struct dwrite_font));
1356 if (!This) return E_OUTOFMEMORY;
1358 This->IDWriteFont2_iface.lpVtbl = &dwritefontvtbl;
1359 This->ref = 1;
1360 This->face = NULL;
1361 This->family = family;
1362 if (family)
1363 IDWriteFontFamily_AddRef(family);
1364 This->is_system = FALSE;
1365 This->data = data;
1366 InterlockedIncrement(&This->data->ref);
1368 *font = (IDWriteFont*)&This->IDWriteFont2_iface;
1370 return S_OK;
1373 static HRESULT create_font_base(IDWriteFont **font)
1375 struct dwrite_font_data *data;
1376 HRESULT ret;
1378 *font = NULL;
1379 data = heap_alloc(sizeof(*data));
1380 if (!data) return E_OUTOFMEMORY;
1382 data->ref = 0;
1383 data->face_data = NULL;
1385 ret = create_font_from_data( data, NULL, font );
1386 if (FAILED(ret)) heap_free( data );
1387 return ret;
1390 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1392 const WCHAR* facename, *familyname;
1393 IDWriteLocalizedStrings *name;
1394 struct dwrite_font *This;
1395 IDWriteFontFamily *family;
1396 OUTLINETEXTMETRICW *otm;
1397 HRESULT hr;
1398 HFONT hfont;
1399 HDC hdc;
1400 int ret;
1401 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1402 LPVOID tt_os2 = NULL;
1403 LPVOID tt_head = NULL;
1404 LPVOID tt_post = NULL;
1405 LONG size;
1407 hr = create_font_base(font);
1408 if (FAILED(hr))
1409 return hr;
1411 This = impl_from_IDWriteFont2((IDWriteFont2*)*font);
1413 hfont = CreateFontIndirectW(logfont);
1414 if (!hfont)
1416 heap_free(This->data);
1417 heap_free(This);
1418 return DWRITE_E_NOFONT;
1421 hdc = CreateCompatibleDC(0);
1422 SelectObject(hdc, hfont);
1424 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1425 otm = heap_alloc(ret);
1426 if (!otm)
1428 heap_free(This->data);
1429 heap_free(This);
1430 DeleteDC(hdc);
1431 DeleteObject(hfont);
1432 return E_OUTOFMEMORY;
1434 otm->otmSize = ret;
1435 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1437 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1438 if (size != GDI_ERROR)
1440 tt_os2 = heap_alloc(size);
1441 GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size);
1443 size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0);
1444 if (size != GDI_ERROR)
1446 tt_head = heap_alloc(size);
1447 GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size);
1449 size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0);
1450 if (size != GDI_ERROR)
1452 tt_post = heap_alloc(size);
1453 GetFontData(hdc, MS_POST_TAG, 0, tt_post, size);
1456 get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style);
1457 heap_free(tt_os2);
1458 heap_free(tt_head);
1459 heap_free(tt_post);
1461 if (logfont->lfItalic)
1462 This->data->style = DWRITE_FONT_STYLE_ITALIC;
1464 DeleteDC(hdc);
1465 DeleteObject(hfont);
1467 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1468 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1469 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1471 hr = create_localizedstrings(&name);
1472 if (FAILED(hr))
1474 heap_free(This);
1475 return hr;
1477 add_localizedstring(name, enusW, familyname);
1478 hr = create_fontfamily(name, &family);
1480 heap_free(otm);
1481 if (hr != S_OK)
1483 heap_free(This->data);
1484 heap_free(This);
1485 return hr;
1488 This->is_system = TRUE;
1489 This->family = family;
1490 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1491 This->data->facename = heap_strdupW(logfont->lfFaceName);
1493 return S_OK;
1496 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1498 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1500 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1502 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1504 *obj = iface;
1505 IDWriteFontFile_AddRef(iface);
1506 return S_OK;
1509 *obj = NULL;
1510 return E_NOINTERFACE;
1513 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1515 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1516 ULONG ref = InterlockedIncrement(&This->ref);
1517 TRACE("(%p)->(%d)\n", This, ref);
1518 return ref;
1521 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1523 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1524 ULONG ref = InterlockedDecrement(&This->ref);
1526 TRACE("(%p)->(%d)\n", This, ref);
1528 if (!ref)
1530 IDWriteFontFileLoader_Release(This->loader);
1531 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1532 heap_free(This->reference_key);
1533 heap_free(This);
1536 return ref;
1539 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1541 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1542 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1543 *fontFileReferenceKey = This->reference_key;
1544 *fontFileReferenceKeySize = This->key_size;
1546 return S_OK;
1549 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1551 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1552 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1553 *fontFileLoader = This->loader;
1554 IDWriteFontFileLoader_AddRef(This->loader);
1556 return S_OK;
1559 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1561 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1562 IDWriteFontFileStream *stream;
1563 HRESULT hr;
1565 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1567 *isSupportedFontType = FALSE;
1568 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1569 if (fontFaceType)
1570 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1571 *numberOfFaces = 0;
1573 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1574 if (FAILED(hr))
1575 return S_OK;
1577 hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1579 /* TODO: Further Analysis */
1580 IDWriteFontFileStream_Release(stream);
1581 return S_OK;
1584 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1585 dwritefontfile_QueryInterface,
1586 dwritefontfile_AddRef,
1587 dwritefontfile_Release,
1588 dwritefontfile_GetReferenceKey,
1589 dwritefontfile_GetLoader,
1590 dwritefontfile_Analyze,
1593 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1595 struct dwrite_fontfile *This;
1597 This = heap_alloc(sizeof(struct dwrite_fontfile));
1598 if (!This) return E_OUTOFMEMORY;
1600 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1601 This->ref = 1;
1602 IDWriteFontFileLoader_AddRef(loader);
1603 This->loader = loader;
1604 This->stream = NULL;
1605 This->reference_key = heap_alloc(key_size);
1606 memcpy(This->reference_key, reference_key, key_size);
1607 This->key_size = key_size;
1609 *font_file = &This->IDWriteFontFile_iface;
1611 return S_OK;
1614 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)
1616 int i;
1617 struct dwrite_fontface *This;
1618 HRESULT hr = S_OK;
1620 *font_face = NULL;
1622 if (facetype != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION && index)
1623 return E_INVALIDARG;
1625 This = heap_alloc(sizeof(struct dwrite_fontface));
1626 if (!This) return E_OUTOFMEMORY;
1627 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1628 if (!This->data)
1630 heap_free(This);
1631 return E_OUTOFMEMORY;
1634 This->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
1635 This->ref = 1;
1636 This->data->ref = 1;
1637 This->data->type = facetype;
1638 This->data->file_count = files_number;
1639 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1640 This->cmap.data = NULL;
1641 This->cmap.context = NULL;
1642 This->cmap.size = 0;
1643 /* Verify font file streams */
1644 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1646 IDWriteFontFileStream *stream;
1647 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1648 if (SUCCEEDED(hr))
1649 IDWriteFontFileStream_Release(stream);
1651 if (FAILED(hr))
1653 heap_free(This->data->files);
1654 heap_free(This->data);
1655 heap_free(This);
1656 return hr;
1658 for (i = 0; i < This->data->file_count; i++)
1660 This->data->files[i] = font_files[i];
1661 IDWriteFontFile_AddRef(font_files[i]);
1664 This->data->index = index;
1665 This->data->simulations = sim_flags;
1666 This->is_system = FALSE;
1668 *font_face = (IDWriteFontFace*)&This->IDWriteFontFace2_iface;
1670 return S_OK;
1673 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1675 struct dwrite_localfontfilestream
1677 IDWriteFontFileStream IDWriteFontFileStream_iface;
1678 LONG ref;
1680 HANDLE handle;
1683 struct dwrite_localfontfileloader {
1684 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1685 LONG ref;
1688 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1690 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1693 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1695 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1698 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1700 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1701 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1702 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1704 *obj = iface;
1705 IDWriteFontFileStream_AddRef(iface);
1706 return S_OK;
1709 *obj = NULL;
1710 return E_NOINTERFACE;
1713 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1715 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1716 ULONG ref = InterlockedIncrement(&This->ref);
1717 TRACE("(%p)->(%d)\n", This, ref);
1718 return ref;
1721 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1723 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1724 ULONG ref = InterlockedDecrement(&This->ref);
1726 TRACE("(%p)->(%d)\n", This, ref);
1728 if (!ref)
1730 if (This->handle != INVALID_HANDLE_VALUE)
1731 CloseHandle(This->handle);
1732 heap_free(This);
1735 return ref;
1738 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1740 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1741 LARGE_INTEGER distance;
1742 DWORD bytes = fragment_size;
1743 DWORD read;
1745 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1746 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1748 *fragment_context = NULL;
1749 distance.QuadPart = offset;
1750 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1751 return E_FAIL;
1752 *fragment_start = *fragment_context = heap_alloc(bytes);
1753 if (!*fragment_context)
1754 return E_FAIL;
1755 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1757 heap_free(*fragment_context);
1758 return E_FAIL;
1761 return S_OK;
1764 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1766 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1767 TRACE("(%p)->(%p)\n", This, fragment_context);
1768 heap_free(fragment_context);
1771 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1773 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1774 LARGE_INTEGER li;
1775 TRACE("(%p)->(%p)\n",This, size);
1776 GetFileSizeEx(This->handle, &li);
1777 *size = li.QuadPart;
1778 return S_OK;
1781 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1783 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1784 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1785 *last_writetime = 0;
1786 return E_NOTIMPL;
1789 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1791 localfontfilestream_QueryInterface,
1792 localfontfilestream_AddRef,
1793 localfontfilestream_Release,
1794 localfontfilestream_ReadFileFragment,
1795 localfontfilestream_ReleaseFileFragment,
1796 localfontfilestream_GetFileSize,
1797 localfontfilestream_GetLastWriteTime
1800 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1802 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1803 if (!This)
1804 return E_OUTOFMEMORY;
1806 This->ref = 1;
1807 This->handle = handle;
1808 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1810 *iface = &This->IDWriteFontFileStream_iface;
1811 return S_OK;
1814 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1816 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1818 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1820 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1822 *obj = iface;
1823 IDWriteLocalFontFileLoader_AddRef(iface);
1824 return S_OK;
1827 *obj = NULL;
1828 return E_NOINTERFACE;
1831 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1833 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1834 ULONG ref = InterlockedIncrement(&This->ref);
1835 TRACE("(%p)->(%d)\n", This, ref);
1836 return ref;
1839 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1841 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1842 ULONG ref = InterlockedDecrement(&This->ref);
1844 TRACE("(%p)->(%d)\n", This, ref);
1846 if (!ref)
1847 heap_free(This);
1849 return ref;
1852 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1854 HANDLE handle;
1855 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1856 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1858 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1860 TRACE("name: %s\n",debugstr_w(name));
1861 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1862 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1864 if (handle == INVALID_HANDLE_VALUE)
1865 return E_FAIL;
1867 return create_localfontfilestream(handle, fontFileStream);
1870 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1872 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1873 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1874 *length = key_size;
1875 return S_OK;
1878 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1880 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1881 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1882 if (length < key_size)
1883 return E_INVALIDARG;
1884 lstrcpynW((WCHAR*)key, path, key_size);
1885 return S_OK;
1888 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1890 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1891 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1892 return E_NOTIMPL;
1895 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1896 localfontfileloader_QueryInterface,
1897 localfontfileloader_AddRef,
1898 localfontfileloader_Release,
1899 localfontfileloader_CreateStreamFromKey,
1900 localfontfileloader_GetFilePathLengthFromKey,
1901 localfontfileloader_GetFilePathFromKey,
1902 localfontfileloader_GetLastWriteTimeFromKey
1905 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1907 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1908 if (!This)
1909 return E_OUTOFMEMORY;
1911 This->ref = 1;
1912 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1914 *iface = &This->IDWriteLocalFontFileLoader_iface;
1915 return S_OK;