dwrite: Use better integer types for cmap helpers.
[wine.git] / dlls / dwrite / font.c
blobe3edbaa2d4928c8a5821aea207022c7553fdb1d2
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++)
394 opentype_cmap_get_glyphindex(This->cmap.data, codepoints[i], &glyph_indices[i]);
396 return S_OK;
400 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace2 *iface, UINT32 table_tag,
401 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
403 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
404 if (This->is_system)
406 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
407 return E_NOTIMPL;
409 else
411 HRESULT hr = S_OK;
412 int i;
413 struct dwrite_fonttablecontext *tablecontext;
415 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
417 tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext));
418 if (!tablecontext)
419 return E_OUTOFMEMORY;
420 tablecontext->magic = DWRITE_FONTTABLE_MAGIC;
422 *exists = FALSE;
423 for (i = 0; i < This->data->file_count && !(*exists); i++)
425 IDWriteFontFileStream *stream;
426 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
427 if (FAILED(hr))
428 continue;
429 tablecontext->file_index = i;
431 hr = opentype_get_font_table(stream, This->data->type, This->data->index, table_tag, table_data, &tablecontext->context, table_size, exists);
433 IDWriteFontFileStream_Release(stream);
435 if (FAILED(hr) && !*exists)
436 heap_free(tablecontext);
437 else
438 *context = (void*)tablecontext;
439 return hr;
443 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace2 *iface, void *table_context)
445 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
446 struct dwrite_fonttablecontext *tablecontext = (struct dwrite_fonttablecontext*)table_context;
447 IDWriteFontFileStream *stream;
448 HRESULT hr;
449 TRACE("(%p)->(%p)\n", This, table_context);
451 if (tablecontext->magic != DWRITE_FONTTABLE_MAGIC)
453 TRACE("Invalid table magic\n");
454 return;
457 hr = _dwritefontfile_GetFontFileStream(This->data->files[tablecontext->file_index], &stream);
458 if (FAILED(hr))
459 return;
460 IDWriteFontFileStream_ReleaseFileFragment(stream, tablecontext->context);
461 IDWriteFontFileStream_Release(stream);
462 heap_free(tablecontext);
465 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace2 *iface, FLOAT emSize,
466 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
467 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
469 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
470 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
471 glyph_count, is_sideways, is_rtl, geometrysink);
472 return E_NOTIMPL;
475 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
476 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
478 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
479 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
480 return E_NOTIMPL;
483 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
484 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
486 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
487 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
488 return E_NOTIMPL;
491 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
492 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
493 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
495 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
496 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
497 glyph_count, metrics, is_sideways);
498 return E_NOTIMPL;
501 static HRESULT WINAPI dwritefontface1_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS1 *metrics)
503 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
504 FIXME("(%p)->(%p): stub\n", This, metrics);
505 return E_NOTIMPL;
508 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT em_size, FLOAT pixels_per_dip,
509 const DWRITE_MATRIX *transform, DWRITE_FONT_METRICS1 *metrics)
511 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
512 FIXME("(%p)->(%f %f %p %p): stub\n", This, em_size, pixels_per_dip, transform, metrics);
513 return E_NOTIMPL;
516 static void WINAPI dwritefontface1_GetCaretMetrics(IDWriteFontFace2 *iface, DWRITE_CARET_METRICS *metrics)
518 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
519 FIXME("(%p)->(%p): stub\n", This, metrics);
522 static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace2 *iface, UINT32 max_count,
523 DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
525 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
526 FIXME("(%p)->(%u %p %p): stub\n", This, max_count, ranges, count);
527 return E_NOTIMPL;
530 static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace2 *iface)
532 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
533 FIXME("(%p): stub\n", This);
534 return FALSE;
537 static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2 *iface,
538 UINT32 glyph_count, UINT16 const *indices, INT32 *advances, BOOL is_sideways)
540 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
541 FIXME("(%p)->(%u %p %p %d): stub\n", This, glyph_count, indices, advances, is_sideways);
542 return E_NOTIMPL;
545 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2 *iface,
546 FLOAT em_size, FLOAT pixels_per_dip, const DWRITE_MATRIX *transform, BOOL use_gdi_natural,
547 BOOL is_sideways, UINT32 glyph_count, UINT16 const *indices, INT32 *advances)
549 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
550 FIXME("(%p)->(%f %f %p %d %d %u %p %p): stub\n", This, em_size, pixels_per_dip, transform,
551 use_gdi_natural, is_sideways, glyph_count, indices, advances);
552 return E_NOTIMPL;
555 static HRESULT WINAPI dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2 *iface, UINT32 glyph_count,
556 const UINT16 *indices, INT32 *adjustments)
558 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
559 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, indices, adjustments);
560 return E_NOTIMPL;
563 static BOOL WINAPI dwritefontface1_HasKerningPairs(IDWriteFontFace2 *iface)
565 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
566 FIXME("(%p): stub\n", This);
567 return FALSE;
570 static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2 *iface,
571 FLOAT font_emsize, FLOAT dpiX, FLOAT dpiY, const DWRITE_MATRIX *transform, BOOL is_sideways,
572 DWRITE_OUTLINE_THRESHOLD threshold, DWRITE_MEASURING_MODE measuring_mode, DWRITE_RENDERING_MODE *rendering_mode)
574 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
575 FIXME("(%p)->(%f %f %f %p %d %d %d %p): stub\n", This, font_emsize, dpiX, dpiY, transform, is_sideways,
576 threshold, measuring_mode, rendering_mode);
577 return E_NOTIMPL;
580 static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2 *iface, UINT32 glyph_count,
581 const UINT16 *nominal_indices, UINT16 *vertical_indices)
583 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
584 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, nominal_indices, vertical_indices);
585 return E_NOTIMPL;
588 static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2 *iface)
590 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
591 FIXME("(%p): stub\n", This);
592 return FALSE;
595 static BOOL WINAPI dwritefontface2_IsColorFont(IDWriteFontFace2 *iface)
597 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
598 FIXME("(%p): stub\n", This);
599 return FALSE;
602 static UINT32 WINAPI dwritefontface2_GetColorPaletteCount(IDWriteFontFace2 *iface)
604 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
605 FIXME("(%p): stub\n", This);
606 return 0;
609 static UINT32 WINAPI dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2 *iface)
611 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
612 FIXME("(%p): stub\n", This);
613 return 0;
616 static HRESULT WINAPI dwritefontface2_GetPaletteEntries(IDWriteFontFace2 *iface, UINT32 palette_index,
617 UINT32 first_entry_index, UINT32 entry_count, DWRITE_COLOR_F *entries)
619 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
620 FIXME("(%p)->(%u %u %u %p): stub\n", This, palette_index, first_entry_index, entry_count, entries);
621 return E_NOTIMPL;
624 static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT fontEmSize,
625 FLOAT dpiX, FLOAT dpiY, DWRITE_MATRIX const *transform, BOOL is_sideways, DWRITE_OUTLINE_THRESHOLD threshold,
626 DWRITE_MEASURING_MODE measuringmode, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *renderingmode,
627 DWRITE_GRID_FIT_MODE *gridfitmode)
629 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
630 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This, fontEmSize, dpiX, dpiY, transform, is_sideways, threshold,
631 measuringmode, params, renderingmode, gridfitmode);
632 return E_NOTIMPL;
635 static const IDWriteFontFace2Vtbl dwritefontfacevtbl = {
636 dwritefontface_QueryInterface,
637 dwritefontface_AddRef,
638 dwritefontface_Release,
639 dwritefontface_GetType,
640 dwritefontface_GetFiles,
641 dwritefontface_GetIndex,
642 dwritefontface_GetSimulations,
643 dwritefontface_IsSymbolFont,
644 dwritefontface_GetMetrics,
645 dwritefontface_GetGlyphCount,
646 dwritefontface_GetDesignGlyphMetrics,
647 dwritefontface_GetGlyphIndices,
648 dwritefontface_TryGetFontTable,
649 dwritefontface_ReleaseFontTable,
650 dwritefontface_GetGlyphRunOutline,
651 dwritefontface_GetRecommendedRenderingMode,
652 dwritefontface_GetGdiCompatibleMetrics,
653 dwritefontface_GetGdiCompatibleGlyphMetrics,
654 dwritefontface1_GetMetrics,
655 dwritefontface1_GetGdiCompatibleMetrics,
656 dwritefontface1_GetCaretMetrics,
657 dwritefontface1_GetUnicodeRanges,
658 dwritefontface1_IsMonospacedFont,
659 dwritefontface1_GetDesignGlyphAdvances,
660 dwritefontface1_GetGdiCompatibleGlyphAdvances,
661 dwritefontface1_GetKerningPairAdjustments,
662 dwritefontface1_HasKerningPairs,
663 dwritefontface1_GetRecommendedRenderingMode,
664 dwritefontface1_GetVerticalGlyphVariants,
665 dwritefontface1_HasVerticalGlyphVariants,
666 dwritefontface2_IsColorFont,
667 dwritefontface2_GetColorPaletteCount,
668 dwritefontface2_GetPaletteEntryCount,
669 dwritefontface2_GetPaletteEntries,
670 dwritefontface2_GetRecommendedRenderingMode
673 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
675 struct dwrite_fontface *This;
677 *face = NULL;
679 This = heap_alloc(sizeof(struct dwrite_fontface));
680 if (!This) return E_OUTOFMEMORY;
681 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
682 if (!This->data)
684 heap_free(This);
685 return E_OUTOFMEMORY;
688 This->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
689 This->ref = 1;
690 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
691 This->data->file_count = 0;
692 This->data->files = NULL;
693 This->data->index = 0;
694 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
695 This->cmap.data = NULL;
696 This->cmap.context = NULL;
697 This->cmap.size = 0;
699 This->is_system = TRUE;
700 memset(&This->logfont, 0, sizeof(This->logfont));
701 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
702 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
703 This->logfont.lfWeight = font->data->weight;
704 strcpyW(This->logfont.lfFaceName, font->data->facename);
706 *face = (IDWriteFontFace*)&This->IDWriteFontFace2_iface;
708 return S_OK;
711 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
713 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace2((IDWriteFontFace2*)face);
715 *logfont = fontface->logfont;
717 return S_OK;
720 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont2 *iface, REFIID riid, void **obj)
722 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
724 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
726 if (IsEqualIID(riid, &IID_IDWriteFont2) ||
727 IsEqualIID(riid, &IID_IDWriteFont1) ||
728 IsEqualIID(riid, &IID_IDWriteFont) ||
729 IsEqualIID(riid, &IID_IUnknown))
731 *obj = iface;
732 IDWriteFont2_AddRef(iface);
733 return S_OK;
736 *obj = NULL;
737 return E_NOINTERFACE;
740 static ULONG WINAPI dwritefont_AddRef(IDWriteFont2 *iface)
742 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
743 ULONG ref = InterlockedIncrement(&This->ref);
744 TRACE("(%p)->(%d)\n", This, ref);
745 return ref;
748 static ULONG WINAPI dwritefont_Release(IDWriteFont2 *iface)
750 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
751 ULONG ref = InterlockedDecrement(&This->ref);
753 TRACE("(%p)->(%d)\n", This, ref);
755 if (!ref)
757 if (This->face) IDWriteFontFace_Release(This->face);
758 if (This->family) IDWriteFontFamily_Release(This->family);
759 _free_font_data(This->data);
760 heap_free(This);
763 return ref;
766 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont2 *iface, IDWriteFontFamily **family)
768 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
769 TRACE("(%p)->(%p)\n", This, family);
771 *family = This->family;
772 IDWriteFontFamily_AddRef(*family);
773 return S_OK;
776 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont2 *iface)
778 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
779 TRACE("(%p)\n", This);
780 return This->data->weight;
783 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont2 *iface)
785 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
786 TRACE("(%p)\n", This);
787 return This->data->stretch;
790 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont2 *iface)
792 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
793 TRACE("(%p)\n", This);
794 return This->data->style;
797 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont2 *iface)
799 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
800 FIXME("(%p): stub\n", This);
801 return FALSE;
804 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont2 *iface, IDWriteLocalizedStrings **names)
806 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
807 FIXME("(%p)->(%p): stub\n", This, names);
808 return E_NOTIMPL;
811 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont2 *iface,
812 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
814 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
815 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
816 return E_NOTIMPL;
819 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont2 *iface)
821 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
822 TRACE("(%p)\n", This);
823 return This->data->simulations;
826 static void WINAPI dwritefont_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS *metrics)
828 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
830 TRACE("(%p)->(%p)\n", This, metrics);
831 *metrics = This->data->metrics;
834 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont2 *iface, UINT32 value, BOOL *exists)
836 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
837 IDWriteFontFace *fontface;
838 UINT16 index;
839 HRESULT hr;
841 TRACE("(%p)->(0x%08x %p)\n", This, value, exists);
843 *exists = FALSE;
845 hr = IDWriteFont2_CreateFontFace(iface, &fontface);
846 if (FAILED(hr))
847 return hr;
849 index = 0;
850 hr = IDWriteFontFace_GetGlyphIndices(fontface, &value, 1, &index);
851 IDWriteFontFace_Release(fontface);
852 if (FAILED(hr))
853 return hr;
855 *exists = index != 0;
856 return S_OK;
859 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont2 *iface, IDWriteFontFace **face)
861 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
863 if (This->is_system)
865 TRACE("(%p)->(%p)\n", This, face);
867 if (!This->face)
869 HRESULT hr = create_system_fontface(This, &This->face);
870 if (FAILED(hr)) return hr;
873 *face = This->face;
874 IDWriteFontFace_AddRef(*face);
876 return S_OK;
878 else
880 TRACE("(%p)->(%p)\n", This, face);
882 if (!This->face)
884 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);
885 if (FAILED(hr)) return hr;
888 *face = This->face;
889 IDWriteFontFace_AddRef(*face);
891 return S_OK;
895 static void WINAPI dwritefont1_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS1 *metrics)
897 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
898 FIXME("(%p)->(%p): stub\n", This, metrics);
901 static void WINAPI dwritefont1_GetPanose(IDWriteFont2 *iface, DWRITE_PANOSE *panose)
903 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
904 FIXME("(%p)->(%p): stub\n", This, panose);
907 static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont2 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
909 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
910 FIXME("(%p)->(%u %p %p): stub\n", This, max_count, ranges, count);
911 return E_NOTIMPL;
914 static HRESULT WINAPI dwritefont1_IsMonospacedFont(IDWriteFont2 *iface)
916 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
917 FIXME("(%p): stub\n", This);
918 return FALSE;
921 static HRESULT WINAPI dwritefont2_IsColorFont(IDWriteFont2 *iface)
923 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
924 FIXME("(%p): stub\n", This);
925 return FALSE;
928 static const IDWriteFont2Vtbl dwritefontvtbl = {
929 dwritefont_QueryInterface,
930 dwritefont_AddRef,
931 dwritefont_Release,
932 dwritefont_GetFontFamily,
933 dwritefont_GetWeight,
934 dwritefont_GetStretch,
935 dwritefont_GetStyle,
936 dwritefont_IsSymbolFont,
937 dwritefont_GetFaceNames,
938 dwritefont_GetInformationalStrings,
939 dwritefont_GetSimulations,
940 dwritefont_GetMetrics,
941 dwritefont_HasCharacter,
942 dwritefont_CreateFontFace,
943 dwritefont1_GetMetrics,
944 dwritefont1_GetPanose,
945 dwritefont1_GetUnicodeRanges,
946 dwritefont1_IsMonospacedFont,
947 dwritefont2_IsColorFont
950 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
952 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
953 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
955 if (IsEqualIID(riid, &IID_IUnknown) ||
956 IsEqualIID(riid, &IID_IDWriteFontList) ||
957 IsEqualIID(riid, &IID_IDWriteFontFamily))
959 *obj = iface;
960 IDWriteFontFamily_AddRef(iface);
961 return S_OK;
964 *obj = NULL;
965 return E_NOINTERFACE;
968 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
970 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
971 ULONG ref = InterlockedIncrement(&This->ref);
972 TRACE("(%p)->(%d)\n", This, ref);
973 return ref;
976 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
978 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
979 ULONG ref = InterlockedDecrement(&This->ref);
981 TRACE("(%p)->(%d)\n", This, ref);
983 if (!ref)
985 if (This->collection)
986 IDWriteFontCollection_Release(This->collection);
987 _free_fontfamily_data(This->data);
988 heap_free(This);
991 return ref;
994 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
996 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
997 TRACE("(%p)->(%p)\n", This, collection);
998 if (This->collection)
1000 IDWriteFontCollection_AddRef(This->collection);
1001 *collection = This->collection;
1002 return S_OK;
1004 else
1005 return E_NOTIMPL;
1008 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
1010 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1011 TRACE("(%p)\n", This);
1012 return This->data->font_count;
1015 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
1017 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1018 TRACE("(%p)->(%u %p)\n", This, index, font);
1019 if (This->data->font_count > 0)
1021 if (index >= This->data->font_count)
1022 return E_INVALIDARG;
1023 return create_font_from_data(This->data->fonts[index], iface, font);
1025 else
1026 return E_NOTIMPL;
1029 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
1031 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1032 return clone_localizedstring(This->data->familyname, names);
1035 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1036 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
1038 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1039 LOGFONTW lf;
1041 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
1043 /* fallback for system font collections */
1044 if (This->data->font_count == 0)
1046 memset(&lf, 0, sizeof(lf));
1047 lf.lfWeight = weight;
1048 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
1049 IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE);
1051 return create_font_from_logfont(&lf, font);
1053 else
1055 int i;
1056 for (i = 0; i < This->data->font_count; i++)
1058 if (style == This->data->fonts[i]->style &&
1059 weight == This->data->fonts[i]->weight &&
1060 stretch == This->data->fonts[i]->stretch)
1062 return create_font_from_data(This->data->fonts[i], iface, font);
1065 return DWRITE_E_NOFONT;
1069 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1070 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
1072 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1073 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
1074 return E_NOTIMPL;
1077 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
1078 dwritefontfamily_QueryInterface,
1079 dwritefontfamily_AddRef,
1080 dwritefontfamily_Release,
1081 dwritefontfamily_GetFontCollection,
1082 dwritefontfamily_GetFontCount,
1083 dwritefontfamily_GetFont,
1084 dwritefontfamily_GetFamilyNames,
1085 dwritefontfamily_GetFirstMatchingFont,
1086 dwritefontfamily_GetMatchingFonts
1089 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
1091 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1092 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1094 if (IsEqualIID(riid, &IID_IUnknown) ||
1095 IsEqualIID(riid, &IID_IDWriteFontCollection))
1097 *obj = iface;
1098 IDWriteFontCollection_AddRef(iface);
1099 return S_OK;
1102 *obj = NULL;
1103 return E_NOINTERFACE;
1106 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
1108 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1109 ULONG ref = InterlockedIncrement(&This->ref);
1110 TRACE("(%p)->(%d)\n", This, ref);
1111 return ref;
1114 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
1116 unsigned int i;
1117 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1118 ULONG ref = InterlockedDecrement(&This->ref);
1119 TRACE("(%p)->(%d)\n", This, ref);
1121 if (!ref)
1123 for (i = 0; i < This->count; i++)
1124 heap_free(This->families[i]);
1125 heap_free(This->families);
1126 for (i = 0; i < This->data_count; i++)
1127 _free_fontfamily_data(This->family_data[i]);
1128 heap_free(This->family_data);
1129 heap_free(This);
1132 return ref;
1135 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
1137 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1138 TRACE("(%p)\n", This);
1139 if (This->data_count)
1140 return This->data_count;
1141 return This->count;
1144 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
1146 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1147 HRESULT hr;
1148 IDWriteLocalizedStrings *familyname;
1149 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1151 TRACE("(%p)->(%u %p)\n", This, index, family);
1153 if (This->data_count)
1155 if (index >= This->data_count)
1157 *family = NULL;
1158 return E_FAIL;
1160 else
1161 return create_fontfamily_from_data(This->family_data[index], iface, family);
1163 else
1165 if (index >= This->count)
1167 *family = NULL;
1168 return E_FAIL;
1171 hr = create_localizedstrings(&familyname);
1172 if (FAILED(hr))
1173 return hr;
1174 add_localizedstring(familyname, enusW, This->families[index]);
1176 return create_fontfamily(familyname, family);
1180 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
1182 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1183 UINT32 i;
1185 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
1187 if (This->data_count)
1189 for (i = 0; i < This->data_count; i++)
1191 HRESULT hr;
1192 IDWriteLocalizedStrings *family_name = This->family_data[i]->familyname;
1193 int j;
1194 for (j = 0; j < IDWriteLocalizedStrings_GetCount(family_name); j ++)
1196 WCHAR buffer[255];
1197 hr = IDWriteLocalizedStrings_GetString(family_name, j, buffer, 255);
1198 if (SUCCEEDED(hr))
1200 if (!strcmpW(buffer, name))
1202 *index = i;
1203 *exists = TRUE;
1204 return S_OK;
1209 *index = (UINT32)-1;
1210 *exists = FALSE;
1212 else
1214 for (i = 0; i < This->count; i++)
1215 if (!strcmpW(This->families[i], name))
1217 *index = i;
1218 *exists = TRUE;
1219 return S_OK;
1222 *index = (UINT32)-1;
1223 *exists = FALSE;
1226 return S_OK;
1229 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
1231 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1232 FIXME("(%p)->(%p %p): stub\n", This, face, font);
1233 return E_NOTIMPL;
1236 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
1237 dwritefontcollection_QueryInterface,
1238 dwritefontcollection_AddRef,
1239 dwritefontcollection_Release,
1240 dwritefontcollection_GetFontFamilyCount,
1241 dwritefontcollection_GetFontFamily,
1242 dwritefontcollection_FindFamilyName,
1243 dwritefontcollection_GetFontFromFontFace
1246 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
1248 /* check for duplicate family name */
1249 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
1251 /* double array length */
1252 if (collection->count == collection->alloc)
1254 collection->alloc *= 2;
1255 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
1258 collection->families[collection->count++] = heap_strdupW(family);
1259 TRACE("family name %s\n", debugstr_w(family));
1261 return S_OK;
1264 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1266 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1267 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1270 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1272 struct dwrite_fontcollection *This;
1273 LOGFONTW lf;
1274 HDC hdc;
1276 *collection = NULL;
1278 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1279 if (!This) return E_OUTOFMEMORY;
1281 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1282 This->ref = 1;
1283 This->alloc = 50;
1284 This->count = 0;
1285 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1286 if (!This->families)
1288 heap_free(This);
1289 return E_OUTOFMEMORY;
1291 This->data_count = 0;
1292 This->data_alloc = 2;
1293 This->family_data = heap_alloc(sizeof(*This->family_data)*2);
1294 if (!This->family_data)
1296 heap_free(This->families);
1297 heap_free(This);
1298 return E_OUTOFMEMORY;
1301 TRACE("building system font collection:\n");
1303 hdc = CreateCompatibleDC(0);
1304 memset(&lf, 0, sizeof(lf));
1305 lf.lfCharSet = DEFAULT_CHARSET;
1306 lf.lfPitchAndFamily = DEFAULT_PITCH;
1307 lf.lfFaceName[0] = 0;
1308 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1309 DeleteDC(hdc);
1311 *collection = &This->IDWriteFontCollection_iface;
1313 return S_OK;
1316 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family)
1318 struct dwrite_fontfamily *This;
1320 *family = NULL;
1322 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1323 if (!This) return E_OUTOFMEMORY;
1325 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1326 This->ref = 1;
1327 This->collection = collection;
1328 if (collection)
1329 IDWriteFontCollection_AddRef(collection);
1330 This->data = data;
1331 InterlockedIncrement(&This->data->ref);
1333 *family = &This->IDWriteFontFamily_iface;
1335 return S_OK;
1338 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family)
1340 struct dwrite_fontfamily_data *data;
1341 HRESULT ret;
1343 data = heap_alloc(sizeof(struct dwrite_fontfamily_data));
1344 if (!data) return E_OUTOFMEMORY;
1346 data->ref = 0;
1347 data->font_count = 0;
1348 data->alloc = 2;
1349 data->fonts = heap_alloc(sizeof(*data->fonts) * 2);
1350 if (!data->fonts)
1352 heap_free(data);
1353 return E_OUTOFMEMORY;
1355 data->familyname = familyname;
1357 ret = create_fontfamily_from_data(data, NULL, family);
1358 if (FAILED(ret))
1360 heap_free(data->fonts);
1361 heap_free(data);
1364 return ret;
1367 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFontFamily *family, IDWriteFont **font)
1369 struct dwrite_font *This;
1370 *font = NULL;
1372 This = heap_alloc(sizeof(struct dwrite_font));
1373 if (!This) return E_OUTOFMEMORY;
1375 This->IDWriteFont2_iface.lpVtbl = &dwritefontvtbl;
1376 This->ref = 1;
1377 This->face = NULL;
1378 This->family = family;
1379 if (family)
1380 IDWriteFontFamily_AddRef(family);
1381 This->is_system = FALSE;
1382 This->data = data;
1383 InterlockedIncrement(&This->data->ref);
1385 *font = (IDWriteFont*)&This->IDWriteFont2_iface;
1387 return S_OK;
1390 static HRESULT create_font_base(IDWriteFont **font)
1392 struct dwrite_font_data *data;
1393 HRESULT ret;
1395 *font = NULL;
1396 data = heap_alloc(sizeof(*data));
1397 if (!data) return E_OUTOFMEMORY;
1399 data->ref = 0;
1400 data->face_data = NULL;
1402 ret = create_font_from_data( data, NULL, font );
1403 if (FAILED(ret)) heap_free( data );
1404 return ret;
1407 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1409 const WCHAR* facename, *familyname;
1410 IDWriteLocalizedStrings *name;
1411 struct dwrite_font *This;
1412 IDWriteFontFamily *family;
1413 OUTLINETEXTMETRICW *otm;
1414 HRESULT hr;
1415 HFONT hfont;
1416 HDC hdc;
1417 int ret;
1418 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1419 LPVOID tt_os2 = NULL;
1420 LPVOID tt_head = NULL;
1421 LPVOID tt_post = NULL;
1422 LONG size;
1424 hr = create_font_base(font);
1425 if (FAILED(hr))
1426 return hr;
1428 This = impl_from_IDWriteFont2((IDWriteFont2*)*font);
1430 hfont = CreateFontIndirectW(logfont);
1431 if (!hfont)
1433 heap_free(This->data);
1434 heap_free(This);
1435 return DWRITE_E_NOFONT;
1438 hdc = CreateCompatibleDC(0);
1439 SelectObject(hdc, hfont);
1441 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1442 otm = heap_alloc(ret);
1443 if (!otm)
1445 heap_free(This->data);
1446 heap_free(This);
1447 DeleteDC(hdc);
1448 DeleteObject(hfont);
1449 return E_OUTOFMEMORY;
1451 otm->otmSize = ret;
1452 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1454 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1455 if (size != GDI_ERROR)
1457 tt_os2 = heap_alloc(size);
1458 GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size);
1460 size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0);
1461 if (size != GDI_ERROR)
1463 tt_head = heap_alloc(size);
1464 GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size);
1466 size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0);
1467 if (size != GDI_ERROR)
1469 tt_post = heap_alloc(size);
1470 GetFontData(hdc, MS_POST_TAG, 0, tt_post, size);
1473 get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style);
1474 heap_free(tt_os2);
1475 heap_free(tt_head);
1476 heap_free(tt_post);
1478 if (logfont->lfItalic)
1479 This->data->style = DWRITE_FONT_STYLE_ITALIC;
1481 DeleteDC(hdc);
1482 DeleteObject(hfont);
1484 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1485 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1486 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1488 hr = create_localizedstrings(&name);
1489 if (FAILED(hr))
1491 heap_free(This);
1492 return hr;
1494 add_localizedstring(name, enusW, familyname);
1495 hr = create_fontfamily(name, &family);
1497 heap_free(otm);
1498 if (hr != S_OK)
1500 heap_free(This->data);
1501 heap_free(This);
1502 return hr;
1505 This->is_system = TRUE;
1506 This->family = family;
1507 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1508 This->data->facename = heap_strdupW(logfont->lfFaceName);
1510 return S_OK;
1513 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1515 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1517 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1519 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1521 *obj = iface;
1522 IDWriteFontFile_AddRef(iface);
1523 return S_OK;
1526 *obj = NULL;
1527 return E_NOINTERFACE;
1530 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1532 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1533 ULONG ref = InterlockedIncrement(&This->ref);
1534 TRACE("(%p)->(%d)\n", This, ref);
1535 return ref;
1538 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1540 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1541 ULONG ref = InterlockedDecrement(&This->ref);
1543 TRACE("(%p)->(%d)\n", This, ref);
1545 if (!ref)
1547 IDWriteFontFileLoader_Release(This->loader);
1548 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1549 heap_free(This->reference_key);
1550 heap_free(This);
1553 return ref;
1556 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1558 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1559 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1560 *fontFileReferenceKey = This->reference_key;
1561 *fontFileReferenceKeySize = This->key_size;
1563 return S_OK;
1566 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1568 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1569 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1570 *fontFileLoader = This->loader;
1571 IDWriteFontFileLoader_AddRef(This->loader);
1573 return S_OK;
1576 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1578 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1579 IDWriteFontFileStream *stream;
1580 HRESULT hr;
1582 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1584 *isSupportedFontType = FALSE;
1585 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1586 if (fontFaceType)
1587 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1588 *numberOfFaces = 0;
1590 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1591 if (FAILED(hr))
1592 return S_OK;
1594 hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1596 /* TODO: Further Analysis */
1597 IDWriteFontFileStream_Release(stream);
1598 return S_OK;
1601 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1602 dwritefontfile_QueryInterface,
1603 dwritefontfile_AddRef,
1604 dwritefontfile_Release,
1605 dwritefontfile_GetReferenceKey,
1606 dwritefontfile_GetLoader,
1607 dwritefontfile_Analyze,
1610 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1612 struct dwrite_fontfile *This;
1614 This = heap_alloc(sizeof(struct dwrite_fontfile));
1615 if (!This) return E_OUTOFMEMORY;
1617 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1618 This->ref = 1;
1619 IDWriteFontFileLoader_AddRef(loader);
1620 This->loader = loader;
1621 This->stream = NULL;
1622 This->reference_key = heap_alloc(key_size);
1623 memcpy(This->reference_key, reference_key, key_size);
1624 This->key_size = key_size;
1626 *font_file = &This->IDWriteFontFile_iface;
1628 return S_OK;
1631 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)
1633 int i;
1634 struct dwrite_fontface *This;
1635 HRESULT hr = S_OK;
1637 *font_face = NULL;
1639 if (facetype != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION && index)
1640 return E_INVALIDARG;
1642 This = heap_alloc(sizeof(struct dwrite_fontface));
1643 if (!This) return E_OUTOFMEMORY;
1644 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1645 if (!This->data)
1647 heap_free(This);
1648 return E_OUTOFMEMORY;
1651 This->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
1652 This->ref = 1;
1653 This->data->ref = 1;
1654 This->data->type = facetype;
1655 This->data->file_count = files_number;
1656 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1657 This->cmap.data = NULL;
1658 This->cmap.context = NULL;
1659 This->cmap.size = 0;
1660 /* Verify font file streams */
1661 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1663 IDWriteFontFileStream *stream;
1664 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1665 if (SUCCEEDED(hr))
1666 IDWriteFontFileStream_Release(stream);
1668 if (FAILED(hr))
1670 heap_free(This->data->files);
1671 heap_free(This->data);
1672 heap_free(This);
1673 return hr;
1675 for (i = 0; i < This->data->file_count; i++)
1677 This->data->files[i] = font_files[i];
1678 IDWriteFontFile_AddRef(font_files[i]);
1681 This->data->index = index;
1682 This->data->simulations = sim_flags;
1683 This->is_system = FALSE;
1685 *font_face = (IDWriteFontFace*)&This->IDWriteFontFace2_iface;
1687 return S_OK;
1690 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1692 struct dwrite_localfontfilestream
1694 IDWriteFontFileStream IDWriteFontFileStream_iface;
1695 LONG ref;
1697 HANDLE handle;
1700 struct dwrite_localfontfileloader {
1701 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1702 LONG ref;
1705 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1707 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1710 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1712 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1715 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1717 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1718 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1719 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1721 *obj = iface;
1722 IDWriteFontFileStream_AddRef(iface);
1723 return S_OK;
1726 *obj = NULL;
1727 return E_NOINTERFACE;
1730 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1732 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1733 ULONG ref = InterlockedIncrement(&This->ref);
1734 TRACE("(%p)->(%d)\n", This, ref);
1735 return ref;
1738 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1740 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1741 ULONG ref = InterlockedDecrement(&This->ref);
1743 TRACE("(%p)->(%d)\n", This, ref);
1745 if (!ref)
1747 if (This->handle != INVALID_HANDLE_VALUE)
1748 CloseHandle(This->handle);
1749 heap_free(This);
1752 return ref;
1755 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1757 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1758 LARGE_INTEGER distance;
1759 DWORD bytes = fragment_size;
1760 DWORD read;
1762 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1763 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1765 *fragment_context = NULL;
1766 distance.QuadPart = offset;
1767 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1768 return E_FAIL;
1769 *fragment_start = *fragment_context = heap_alloc(bytes);
1770 if (!*fragment_context)
1771 return E_FAIL;
1772 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1774 heap_free(*fragment_context);
1775 return E_FAIL;
1778 return S_OK;
1781 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1783 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1784 TRACE("(%p)->(%p)\n", This, fragment_context);
1785 heap_free(fragment_context);
1788 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1790 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1791 LARGE_INTEGER li;
1792 TRACE("(%p)->(%p)\n",This, size);
1793 GetFileSizeEx(This->handle, &li);
1794 *size = li.QuadPart;
1795 return S_OK;
1798 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1800 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1801 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1802 *last_writetime = 0;
1803 return E_NOTIMPL;
1806 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1808 localfontfilestream_QueryInterface,
1809 localfontfilestream_AddRef,
1810 localfontfilestream_Release,
1811 localfontfilestream_ReadFileFragment,
1812 localfontfilestream_ReleaseFileFragment,
1813 localfontfilestream_GetFileSize,
1814 localfontfilestream_GetLastWriteTime
1817 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1819 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1820 if (!This)
1821 return E_OUTOFMEMORY;
1823 This->ref = 1;
1824 This->handle = handle;
1825 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1827 *iface = &This->IDWriteFontFileStream_iface;
1828 return S_OK;
1831 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1833 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1835 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1837 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1839 *obj = iface;
1840 IDWriteLocalFontFileLoader_AddRef(iface);
1841 return S_OK;
1844 *obj = NULL;
1845 return E_NOINTERFACE;
1848 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1850 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1851 ULONG ref = InterlockedIncrement(&This->ref);
1852 TRACE("(%p)->(%d)\n", This, ref);
1853 return ref;
1856 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1858 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1859 ULONG ref = InterlockedDecrement(&This->ref);
1861 TRACE("(%p)->(%d)\n", This, ref);
1863 if (!ref)
1864 heap_free(This);
1866 return ref;
1869 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1871 HANDLE handle;
1872 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1873 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1875 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1877 TRACE("name: %s\n",debugstr_w(name));
1878 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1879 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1881 if (handle == INVALID_HANDLE_VALUE)
1882 return E_FAIL;
1884 return create_localfontfilestream(handle, fontFileStream);
1887 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1889 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1890 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1891 *length = key_size;
1892 return S_OK;
1895 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1897 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1898 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1899 if (length < key_size)
1900 return E_INVALIDARG;
1901 lstrcpynW((WCHAR*)key, path, key_size);
1902 return S_OK;
1905 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1907 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1908 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1909 return E_NOTIMPL;
1912 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1913 localfontfileloader_QueryInterface,
1914 localfontfileloader_AddRef,
1915 localfontfileloader_Release,
1916 localfontfileloader_CreateStreamFromKey,
1917 localfontfileloader_GetFilePathLengthFromKey,
1918 localfontfileloader_GetFilePathFromKey,
1919 localfontfileloader_GetLastWriteTimeFromKey
1922 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1924 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1925 if (!This)
1926 return E_OUTOFMEMORY;
1928 This->ref = 1;
1929 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1931 *iface = &This->IDWriteLocalFontFileLoader_iface;
1932 return S_OK;