dwrite: Implement GetFontFromFontFace().
[wine.git] / dlls / dwrite / font.c
blob50c3acb22b522dfdf60358c872ed85b021862b07
1 /*
2 * Font and collections
4 * Copyright 2012, 2014 Nikolay Sivov for CodeWeavers
5 * Copyright 2014 Aric Stewart for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
24 #include "dwrite_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
28 #define MS_HEAD_TAG DWRITE_MAKE_OPENTYPE_TAG('h','e','a','d')
29 #define MS_OS2_TAG DWRITE_MAKE_OPENTYPE_TAG('O','S','/','2')
30 #define MS_POST_TAG DWRITE_MAKE_OPENTYPE_TAG('p','o','s','t')
31 #define MS_CMAP_TAG DWRITE_MAKE_OPENTYPE_TAG('c','m','a','p')
32 #define MS_NAME_TAG DWRITE_MAKE_OPENTYPE_TAG('n','a','m','e')
34 struct dwrite_font_data {
35 LONG ref;
37 DWRITE_FONT_STYLE style;
38 DWRITE_FONT_STRETCH stretch;
39 DWRITE_FONT_WEIGHT weight;
40 DWRITE_FONT_SIMULATIONS simulations;
41 DWRITE_FONT_METRICS metrics;
42 IDWriteLocalizedStrings *info_strings[DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1];
44 /* data needed to create fontface instance */
45 IDWriteFactory *factory;
46 DWRITE_FONT_FACE_TYPE face_type;
47 IDWriteFontFile *file;
48 UINT32 face_index;
50 IDWriteFontFace2 *face;
52 WCHAR *facename;
55 struct dwrite_fontfamily_data {
56 LONG ref;
58 IDWriteLocalizedStrings *familyname;
60 struct dwrite_font_data **fonts;
61 UINT32 font_count;
62 UINT32 font_alloc;
65 struct dwrite_fontcollection {
66 IDWriteFontCollection IDWriteFontCollection_iface;
67 LONG ref;
69 WCHAR **families;
70 UINT32 count;
71 int alloc;
73 struct dwrite_fontfamily_data **family_data;
74 DWORD data_count;
75 int data_alloc;
78 struct dwrite_fontfamily {
79 IDWriteFontFamily IDWriteFontFamily_iface;
80 LONG ref;
82 struct dwrite_fontfamily_data *data;
84 IDWriteFontCollection* collection;
87 struct dwrite_font {
88 IDWriteFont2 IDWriteFont2_iface;
89 LONG ref;
91 BOOL is_system;
92 IDWriteFontFamily *family;
94 struct dwrite_font_data *data;
97 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
99 struct dwrite_fonttablecontext {
100 UINT32 magic;
101 void *context;
102 UINT32 file_index;
105 struct dwrite_fonttable {
106 void *data;
107 void *context;
108 UINT32 size;
111 struct dwrite_fontface {
112 IDWriteFontFace2 IDWriteFontFace2_iface;
113 LONG ref;
115 IDWriteFontFile **files;
116 UINT32 file_count;
117 UINT32 index;
119 DWRITE_FONT_SIMULATIONS simulations;
120 DWRITE_FONT_FACE_TYPE type;
122 struct dwrite_fonttable cmap;
124 BOOL is_system;
125 LOGFONTW logfont;
128 struct dwrite_fontfile {
129 IDWriteFontFile IDWriteFontFile_iface;
130 LONG ref;
132 IDWriteFontFileLoader *loader;
133 void *reference_key;
134 UINT32 key_size;
135 IDWriteFontFileStream *stream;
138 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family);
139 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family);
140 static HRESULT create_font_base(IDWriteFont **font);
141 static HRESULT create_font_from_data(struct dwrite_font_data*,IDWriteFontFamily*,IDWriteFont**);
143 static inline struct dwrite_fontface *impl_from_IDWriteFontFace2(IDWriteFontFace2 *iface)
145 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace2_iface);
148 static inline struct dwrite_font *impl_from_IDWriteFont2(IDWriteFont2 *iface)
150 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont2_iface);
153 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
155 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
158 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
160 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
163 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
165 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
168 static inline void* get_fontface_cmap(struct dwrite_fontface *fontface)
170 BOOL exists = FALSE;
171 HRESULT hr;
173 if (fontface->cmap.data)
174 return fontface->cmap.data;
176 hr = IDWriteFontFace2_TryGetFontTable(&fontface->IDWriteFontFace2_iface, MS_CMAP_TAG, (const void**)&fontface->cmap.data,
177 &fontface->cmap.size, &fontface->cmap.context, &exists);
178 if (FAILED(hr) || !exists) {
179 ERR("Font does not have a CMAP table\n");
180 return NULL;
183 return fontface->cmap.data;
186 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
188 HRESULT hr;
189 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
190 if (!This->stream)
192 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
193 if (FAILED(hr))
194 return hr;
196 if (This->stream)
198 IDWriteFontFileStream_AddRef(This->stream);
199 *stream = This->stream;
200 return S_OK;
202 return E_FAIL;
205 static void release_font_data(struct dwrite_font_data *data)
207 int i;
208 if (!data)
209 return;
210 i = InterlockedDecrement(&data->ref);
211 if (i > 0)
212 return;
214 for (i = DWRITE_INFORMATIONAL_STRING_NONE; i < sizeof(data->info_strings)/sizeof(data->info_strings[0]); i++) {
215 if (data->info_strings[i])
216 IDWriteLocalizedStrings_Release(data->info_strings[i]);
219 /* FIXME: factory and file will be always set once system collection is working */
220 if (data->file)
221 IDWriteFontFile_Release(data->file);
222 if (data->factory)
223 IDWriteFactory_Release(data->factory);
224 if (data->face)
225 IDWriteFontFace2_Release(data->face);
226 heap_free(data->facename);
227 heap_free(data);
230 static VOID _free_fontfamily_data(struct dwrite_fontfamily_data *data)
232 int i;
233 if (!data)
234 return;
235 i = InterlockedDecrement(&data->ref);
236 if (i > 0)
237 return;
238 for (i = 0; i < data->font_count; i++)
239 release_font_data(data->fonts[i]);
240 heap_free(data->fonts);
241 IDWriteLocalizedStrings_Release(data->familyname);
242 heap_free(data);
245 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace2 *iface, REFIID riid, void **obj)
247 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
249 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
251 if (IsEqualIID(riid, &IID_IDWriteFontFace2) ||
252 IsEqualIID(riid, &IID_IDWriteFontFace1) ||
253 IsEqualIID(riid, &IID_IDWriteFontFace) ||
254 IsEqualIID(riid, &IID_IUnknown))
256 *obj = iface;
257 IDWriteFontFace2_AddRef(iface);
258 return S_OK;
261 *obj = NULL;
262 return E_NOINTERFACE;
265 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace2 *iface)
267 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
268 ULONG ref = InterlockedIncrement(&This->ref);
269 TRACE("(%p)->(%d)\n", This, ref);
270 return ref;
273 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace2 *iface)
275 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
276 ULONG ref = InterlockedDecrement(&This->ref);
278 TRACE("(%p)->(%d)\n", This, ref);
280 if (!ref) {
281 UINT32 i;
283 if (This->cmap.context)
284 IDWriteFontFace2_ReleaseFontTable(iface, This->cmap.context);
285 for (i = 0; i < This->file_count; i++)
286 IDWriteFontFile_Release(This->files[i]);
287 heap_free(This);
290 return ref;
293 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace2 *iface)
295 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
296 TRACE("(%p)\n", This);
297 return This->type;
300 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace2 *iface, UINT32 *number_of_files,
301 IDWriteFontFile **fontfiles)
303 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
304 int i;
306 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
307 if (fontfiles == NULL)
309 *number_of_files = This->file_count;
310 return S_OK;
312 if (*number_of_files < This->file_count)
313 return E_INVALIDARG;
315 for (i = 0; i < This->file_count; i++)
317 IDWriteFontFile_AddRef(This->files[i]);
318 fontfiles[i] = This->files[i];
321 return S_OK;
324 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace2 *iface)
326 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
327 TRACE("(%p)\n", This);
328 return This->index;
331 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace2 *iface)
333 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
334 TRACE("(%p)\n", This);
335 return This->simulations;
338 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace2 *iface)
340 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
341 FIXME("(%p): stub\n", This);
342 return FALSE;
345 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS *metrics)
347 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
348 FIXME("(%p)->(%p): stub\n", This, metrics);
351 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace2 *iface)
353 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
354 FIXME("(%p): stub\n", This);
355 return 0;
358 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace2 *iface,
359 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
361 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
362 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
363 return E_NOTIMPL;
366 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UINT32 const *codepoints,
367 UINT32 count, UINT16 *glyph_indices)
369 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
370 unsigned int i;
372 if (This->is_system)
374 HFONT hfont;
375 WCHAR *str;
376 HDC hdc;
378 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
380 str = heap_alloc(count*sizeof(WCHAR));
381 if (!str) return E_OUTOFMEMORY;
383 for (i = 0; i < count; i++)
384 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
386 hdc = CreateCompatibleDC(0);
387 hfont = CreateFontIndirectW(&This->logfont);
388 SelectObject(hdc, hfont);
390 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
391 heap_free(str);
393 DeleteDC(hdc);
394 DeleteObject(hfont);
396 return S_OK;
398 else
400 void *data;
402 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
404 data = get_fontface_cmap(This);
405 if (!data)
406 return E_FAIL;
408 for (i = 0; i < count; i++)
409 opentype_cmap_get_glyphindex(data, codepoints[i], &glyph_indices[i]);
411 return S_OK;
415 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace2 *iface, UINT32 table_tag,
416 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
418 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
419 if (This->is_system)
421 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
422 return E_NOTIMPL;
424 else
426 HRESULT hr = S_OK;
427 int i;
428 struct dwrite_fonttablecontext *tablecontext;
430 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
432 tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext));
433 if (!tablecontext)
434 return E_OUTOFMEMORY;
435 tablecontext->magic = DWRITE_FONTTABLE_MAGIC;
437 *exists = FALSE;
438 for (i = 0; i < This->file_count && !(*exists); i++)
440 IDWriteFontFileStream *stream;
441 hr = _dwritefontfile_GetFontFileStream(This->files[i], &stream);
442 if (FAILED(hr))
443 continue;
444 tablecontext->file_index = i;
446 hr = opentype_get_font_table(stream, This->type, This->index, table_tag, table_data, &tablecontext->context, table_size, exists);
448 IDWriteFontFileStream_Release(stream);
450 if (FAILED(hr) && !*exists)
451 heap_free(tablecontext);
452 else
453 *context = (void*)tablecontext;
454 return hr;
458 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace2 *iface, void *table_context)
460 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
461 struct dwrite_fonttablecontext *tablecontext = (struct dwrite_fonttablecontext*)table_context;
462 IDWriteFontFileStream *stream;
463 HRESULT hr;
464 TRACE("(%p)->(%p)\n", This, table_context);
466 if (tablecontext->magic != DWRITE_FONTTABLE_MAGIC)
468 TRACE("Invalid table magic\n");
469 return;
472 hr = _dwritefontfile_GetFontFileStream(This->files[tablecontext->file_index], &stream);
473 if (FAILED(hr))
474 return;
475 IDWriteFontFileStream_ReleaseFileFragment(stream, tablecontext->context);
476 IDWriteFontFileStream_Release(stream);
477 heap_free(tablecontext);
480 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace2 *iface, FLOAT emSize,
481 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
482 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
484 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
485 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
486 glyph_count, is_sideways, is_rtl, geometrysink);
487 return E_NOTIMPL;
490 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT emSize,
491 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
493 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
494 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
495 return E_NOTIMPL;
498 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
499 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
501 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
502 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
503 return E_NOTIMPL;
506 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace2 *iface, FLOAT emSize, FLOAT pixels_per_dip,
507 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
508 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
510 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
511 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
512 glyph_count, metrics, is_sideways);
513 return E_NOTIMPL;
516 static HRESULT WINAPI dwritefontface1_GetMetrics(IDWriteFontFace2 *iface, DWRITE_FONT_METRICS1 *metrics)
518 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
519 FIXME("(%p)->(%p): stub\n", This, metrics);
520 return E_NOTIMPL;
523 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleMetrics(IDWriteFontFace2 *iface, FLOAT em_size, FLOAT pixels_per_dip,
524 const DWRITE_MATRIX *transform, DWRITE_FONT_METRICS1 *metrics)
526 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
527 FIXME("(%p)->(%f %f %p %p): stub\n", This, em_size, pixels_per_dip, transform, metrics);
528 return E_NOTIMPL;
531 static void WINAPI dwritefontface1_GetCaretMetrics(IDWriteFontFace2 *iface, DWRITE_CARET_METRICS *metrics)
533 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
534 FIXME("(%p)->(%p): stub\n", This, metrics);
537 static HRESULT WINAPI dwritefontface1_GetUnicodeRanges(IDWriteFontFace2 *iface, UINT32 max_count,
538 DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
540 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
542 TRACE("(%p)->(%u %p %p)\n", This, max_count, ranges, count);
544 *count = 0;
545 if (max_count && !ranges)
546 return E_INVALIDARG;
548 return opentype_cmap_get_unicode_ranges(get_fontface_cmap(This), max_count, ranges, count);
551 static BOOL WINAPI dwritefontface1_IsMonospacedFont(IDWriteFontFace2 *iface)
553 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
554 FIXME("(%p): stub\n", This);
555 return FALSE;
558 static HRESULT WINAPI dwritefontface1_GetDesignGlyphAdvances(IDWriteFontFace2 *iface,
559 UINT32 glyph_count, UINT16 const *indices, INT32 *advances, BOOL is_sideways)
561 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
562 FIXME("(%p)->(%u %p %p %d): stub\n", This, glyph_count, indices, advances, is_sideways);
563 return E_NOTIMPL;
566 static HRESULT WINAPI dwritefontface1_GetGdiCompatibleGlyphAdvances(IDWriteFontFace2 *iface,
567 FLOAT em_size, FLOAT pixels_per_dip, const DWRITE_MATRIX *transform, BOOL use_gdi_natural,
568 BOOL is_sideways, UINT32 glyph_count, UINT16 const *indices, INT32 *advances)
570 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
571 FIXME("(%p)->(%f %f %p %d %d %u %p %p): stub\n", This, em_size, pixels_per_dip, transform,
572 use_gdi_natural, is_sideways, glyph_count, indices, advances);
573 return E_NOTIMPL;
576 static HRESULT WINAPI dwritefontface1_GetKerningPairAdjustments(IDWriteFontFace2 *iface, UINT32 glyph_count,
577 const UINT16 *indices, INT32 *adjustments)
579 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
580 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, indices, adjustments);
581 return E_NOTIMPL;
584 static BOOL WINAPI dwritefontface1_HasKerningPairs(IDWriteFontFace2 *iface)
586 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
587 FIXME("(%p): stub\n", This);
588 return FALSE;
591 static HRESULT WINAPI dwritefontface1_GetRecommendedRenderingMode(IDWriteFontFace2 *iface,
592 FLOAT font_emsize, FLOAT dpiX, FLOAT dpiY, const DWRITE_MATRIX *transform, BOOL is_sideways,
593 DWRITE_OUTLINE_THRESHOLD threshold, DWRITE_MEASURING_MODE measuring_mode, DWRITE_RENDERING_MODE *rendering_mode)
595 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
596 FIXME("(%p)->(%f %f %f %p %d %d %d %p): stub\n", This, font_emsize, dpiX, dpiY, transform, is_sideways,
597 threshold, measuring_mode, rendering_mode);
598 return E_NOTIMPL;
601 static HRESULT WINAPI dwritefontface1_GetVerticalGlyphVariants(IDWriteFontFace2 *iface, UINT32 glyph_count,
602 const UINT16 *nominal_indices, UINT16 *vertical_indices)
604 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
605 FIXME("(%p)->(%u %p %p): stub\n", This, glyph_count, nominal_indices, vertical_indices);
606 return E_NOTIMPL;
609 static BOOL WINAPI dwritefontface1_HasVerticalGlyphVariants(IDWriteFontFace2 *iface)
611 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
612 FIXME("(%p): stub\n", This);
613 return FALSE;
616 static BOOL WINAPI dwritefontface2_IsColorFont(IDWriteFontFace2 *iface)
618 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
619 FIXME("(%p): stub\n", This);
620 return FALSE;
623 static UINT32 WINAPI dwritefontface2_GetColorPaletteCount(IDWriteFontFace2 *iface)
625 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
626 FIXME("(%p): stub\n", This);
627 return 0;
630 static UINT32 WINAPI dwritefontface2_GetPaletteEntryCount(IDWriteFontFace2 *iface)
632 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
633 FIXME("(%p): stub\n", This);
634 return 0;
637 static HRESULT WINAPI dwritefontface2_GetPaletteEntries(IDWriteFontFace2 *iface, UINT32 palette_index,
638 UINT32 first_entry_index, UINT32 entry_count, DWRITE_COLOR_F *entries)
640 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
641 FIXME("(%p)->(%u %u %u %p): stub\n", This, palette_index, first_entry_index, entry_count, entries);
642 return E_NOTIMPL;
645 static HRESULT WINAPI dwritefontface2_GetRecommendedRenderingMode(IDWriteFontFace2 *iface, FLOAT fontEmSize,
646 FLOAT dpiX, FLOAT dpiY, DWRITE_MATRIX const *transform, BOOL is_sideways, DWRITE_OUTLINE_THRESHOLD threshold,
647 DWRITE_MEASURING_MODE measuringmode, IDWriteRenderingParams *params, DWRITE_RENDERING_MODE *renderingmode,
648 DWRITE_GRID_FIT_MODE *gridfitmode)
650 struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface);
651 FIXME("(%p)->(%f %f %f %p %d %d %d %p %p %p): stub\n", This, fontEmSize, dpiX, dpiY, transform, is_sideways, threshold,
652 measuringmode, params, renderingmode, gridfitmode);
653 return E_NOTIMPL;
656 static const IDWriteFontFace2Vtbl dwritefontfacevtbl = {
657 dwritefontface_QueryInterface,
658 dwritefontface_AddRef,
659 dwritefontface_Release,
660 dwritefontface_GetType,
661 dwritefontface_GetFiles,
662 dwritefontface_GetIndex,
663 dwritefontface_GetSimulations,
664 dwritefontface_IsSymbolFont,
665 dwritefontface_GetMetrics,
666 dwritefontface_GetGlyphCount,
667 dwritefontface_GetDesignGlyphMetrics,
668 dwritefontface_GetGlyphIndices,
669 dwritefontface_TryGetFontTable,
670 dwritefontface_ReleaseFontTable,
671 dwritefontface_GetGlyphRunOutline,
672 dwritefontface_GetRecommendedRenderingMode,
673 dwritefontface_GetGdiCompatibleMetrics,
674 dwritefontface_GetGdiCompatibleGlyphMetrics,
675 dwritefontface1_GetMetrics,
676 dwritefontface1_GetGdiCompatibleMetrics,
677 dwritefontface1_GetCaretMetrics,
678 dwritefontface1_GetUnicodeRanges,
679 dwritefontface1_IsMonospacedFont,
680 dwritefontface1_GetDesignGlyphAdvances,
681 dwritefontface1_GetGdiCompatibleGlyphAdvances,
682 dwritefontface1_GetKerningPairAdjustments,
683 dwritefontface1_HasKerningPairs,
684 dwritefontface1_GetRecommendedRenderingMode,
685 dwritefontface1_GetVerticalGlyphVariants,
686 dwritefontface1_HasVerticalGlyphVariants,
687 dwritefontface2_IsColorFont,
688 dwritefontface2_GetColorPaletteCount,
689 dwritefontface2_GetPaletteEntryCount,
690 dwritefontface2_GetPaletteEntries,
691 dwritefontface2_GetRecommendedRenderingMode
694 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
696 struct dwrite_fontface *This;
698 *face = NULL;
700 This = heap_alloc(sizeof(struct dwrite_fontface));
701 if (!This) return E_OUTOFMEMORY;
703 This->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
704 This->ref = 1;
705 This->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
706 This->file_count = 0;
707 This->files = NULL;
708 This->index = 0;
709 This->simulations = DWRITE_FONT_SIMULATIONS_NONE;
710 This->cmap.data = NULL;
711 This->cmap.context = NULL;
712 This->cmap.size = 0;
714 This->is_system = TRUE;
715 memset(&This->logfont, 0, sizeof(This->logfont));
716 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
717 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
718 This->logfont.lfWeight = font->data->weight;
719 strcpyW(This->logfont.lfFaceName, font->data->facename);
721 *face = (IDWriteFontFace*)&This->IDWriteFontFace2_iface;
723 return S_OK;
726 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
728 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace2((IDWriteFontFace2*)face);
730 *logfont = fontface->logfont;
732 return S_OK;
735 static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace2 **fontface)
737 HRESULT hr = S_OK;
739 *fontface = NULL;
741 if (!font->data->face) {
742 struct dwrite_font_data *data = font->data;
743 IDWriteFontFace *face;
745 hr = font->is_system ? create_system_fontface(font, &face) :
746 IDWriteFactory_CreateFontFace(data->factory, data->face_type, 1, &data->file,
747 data->face_index, DWRITE_FONT_SIMULATIONS_NONE, &face);
748 if (FAILED(hr))
749 return hr;
751 hr = IDWriteFontFace_QueryInterface(face, &IID_IDWriteFontFace2, (void**)&font->data->face);
752 IDWriteFontFace_Release(face);
755 *fontface = font->data->face;
756 return hr;
759 static HRESULT create_font_base(IDWriteFont **font)
761 struct dwrite_font_data *data;
762 HRESULT ret;
764 *font = NULL;
765 data = heap_alloc_zero(sizeof(*data));
766 if (!data) return E_OUTOFMEMORY;
768 ret = create_font_from_data( data, NULL, font );
769 if (FAILED(ret)) heap_free( data );
770 return ret;
773 static HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
775 const WCHAR* facename, *familyname;
776 IDWriteLocalizedStrings *name;
777 struct dwrite_font *This;
778 IDWriteFontFamily *family;
779 OUTLINETEXTMETRICW *otm;
780 HRESULT hr;
781 HFONT hfont;
782 HDC hdc;
783 int ret;
784 static const WCHAR enusW[] = {'e','n','-','u','s',0};
785 LPVOID tt_os2 = NULL;
786 LPVOID tt_head = NULL;
787 LPVOID tt_post = NULL;
788 LONG size;
790 hr = create_font_base(font);
791 if (FAILED(hr))
792 return hr;
794 This = impl_from_IDWriteFont2((IDWriteFont2*)*font);
796 hfont = CreateFontIndirectW(logfont);
797 if (!hfont)
799 heap_free(This->data);
800 heap_free(This);
801 return DWRITE_E_NOFONT;
804 hdc = CreateCompatibleDC(0);
805 SelectObject(hdc, hfont);
807 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
808 otm = heap_alloc(ret);
809 if (!otm)
811 heap_free(This->data);
812 heap_free(This);
813 DeleteDC(hdc);
814 DeleteObject(hfont);
815 return E_OUTOFMEMORY;
817 otm->otmSize = ret;
818 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
820 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
821 if (size != GDI_ERROR)
823 tt_os2 = heap_alloc(size);
824 GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size);
826 size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0);
827 if (size != GDI_ERROR)
829 tt_head = heap_alloc(size);
830 GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size);
832 size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0);
833 if (size != GDI_ERROR)
835 tt_post = heap_alloc(size);
836 GetFontData(hdc, MS_POST_TAG, 0, tt_post, size);
839 get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style);
840 heap_free(tt_os2);
841 heap_free(tt_head);
842 heap_free(tt_post);
844 if (logfont->lfItalic)
845 This->data->style = DWRITE_FONT_STYLE_ITALIC;
847 DeleteDC(hdc);
848 DeleteObject(hfont);
850 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
851 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
852 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
854 hr = create_localizedstrings(&name);
855 if (FAILED(hr))
857 heap_free(This);
858 return hr;
860 add_localizedstring(name, enusW, familyname);
861 hr = create_fontfamily(name, &family);
863 heap_free(otm);
864 if (hr != S_OK)
866 heap_free(This->data);
867 heap_free(This);
868 return hr;
871 This->is_system = TRUE;
872 This->family = family;
873 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
874 This->data->facename = heap_strdupW(logfont->lfFaceName);
876 return S_OK;
879 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont2 *iface, REFIID riid, void **obj)
881 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
883 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
885 if (IsEqualIID(riid, &IID_IDWriteFont2) ||
886 IsEqualIID(riid, &IID_IDWriteFont1) ||
887 IsEqualIID(riid, &IID_IDWriteFont) ||
888 IsEqualIID(riid, &IID_IUnknown))
890 *obj = iface;
891 IDWriteFont2_AddRef(iface);
892 return S_OK;
895 *obj = NULL;
896 return E_NOINTERFACE;
899 static ULONG WINAPI dwritefont_AddRef(IDWriteFont2 *iface)
901 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
902 ULONG ref = InterlockedIncrement(&This->ref);
903 TRACE("(%p)->(%d)\n", This, ref);
904 return ref;
907 static ULONG WINAPI dwritefont_Release(IDWriteFont2 *iface)
909 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
910 ULONG ref = InterlockedDecrement(&This->ref);
912 TRACE("(%p)->(%d)\n", This, ref);
914 if (!ref) {
915 if (This->family) IDWriteFontFamily_Release(This->family);
916 release_font_data(This->data);
917 heap_free(This);
920 return ref;
923 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont2 *iface, IDWriteFontFamily **family)
925 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
926 TRACE("(%p)->(%p)\n", This, family);
928 *family = This->family;
929 IDWriteFontFamily_AddRef(*family);
930 return S_OK;
933 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont2 *iface)
935 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
936 TRACE("(%p)\n", This);
937 return This->data->weight;
940 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont2 *iface)
942 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
943 TRACE("(%p)\n", This);
944 return This->data->stretch;
947 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont2 *iface)
949 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
950 TRACE("(%p)\n", This);
951 return This->data->style;
954 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont2 *iface)
956 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
957 FIXME("(%p): stub\n", This);
958 return FALSE;
961 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont2 *iface, IDWriteLocalizedStrings **names)
963 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
964 FIXME("(%p)->(%p): stub\n", This, names);
965 return E_NOTIMPL;
968 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont2 *iface,
969 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
971 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
972 struct dwrite_font_data *data = This->data;
973 HRESULT hr;
975 TRACE("(%p)->(%d %p %p)\n", This, stringid, strings, exists);
977 *exists = FALSE;
978 *strings = NULL;
980 if (stringid > DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME || stringid == DWRITE_INFORMATIONAL_STRING_NONE)
981 return S_OK;
983 if (!data->info_strings[stringid]) {
984 IDWriteFontFace2 *fontface;
985 const void *table_data;
986 BOOL table_exists;
987 void *context;
988 UINT32 size;
990 hr = get_fontface_from_font(This, &fontface);
991 if (FAILED(hr))
992 return hr;
994 table_exists = FALSE;
995 hr = IDWriteFontFace2_TryGetFontTable(fontface, MS_NAME_TAG, &table_data, &size, &context, &table_exists);
996 if (FAILED(hr) || !table_exists)
997 WARN("no NAME table found.\n");
999 if (table_exists) {
1000 hr = opentype_get_font_strings_from_id(table_data, stringid, &data->info_strings[stringid]);
1001 if (FAILED(hr) || !data->info_strings[stringid])
1002 return hr;
1003 IDWriteFontFace2_ReleaseFontTable(fontface, context);
1007 hr = clone_localizedstring(data->info_strings[stringid], strings);
1008 if (FAILED(hr))
1009 return hr;
1011 *exists = TRUE;
1012 return S_OK;
1015 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont2 *iface)
1017 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1018 TRACE("(%p)\n", This);
1019 return This->data->simulations;
1022 static void WINAPI dwritefont_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS *metrics)
1024 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1026 TRACE("(%p)->(%p)\n", This, metrics);
1027 *metrics = This->data->metrics;
1030 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont2 *iface, UINT32 value, BOOL *exists)
1032 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1033 IDWriteFontFace2 *fontface;
1034 UINT16 index;
1035 HRESULT hr;
1037 TRACE("(%p)->(0x%08x %p)\n", This, value, exists);
1039 *exists = FALSE;
1041 hr = get_fontface_from_font(This, &fontface);
1042 if (FAILED(hr))
1043 return hr;
1045 index = 0;
1046 hr = IDWriteFontFace2_GetGlyphIndices(fontface, &value, 1, &index);
1047 if (FAILED(hr))
1048 return hr;
1050 *exists = index != 0;
1051 return S_OK;
1054 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont2 *iface, IDWriteFontFace **face)
1056 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1057 HRESULT hr;
1059 TRACE("(%p)->(%p)\n", This, face);
1061 hr = get_fontface_from_font(This, (IDWriteFontFace2**)face);
1062 if (hr == S_OK)
1063 IDWriteFontFace_AddRef(*face);
1065 return hr;
1068 static void WINAPI dwritefont1_GetMetrics(IDWriteFont2 *iface, DWRITE_FONT_METRICS1 *metrics)
1070 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1071 FIXME("(%p)->(%p): stub\n", This, metrics);
1074 static void WINAPI dwritefont1_GetPanose(IDWriteFont2 *iface, DWRITE_PANOSE *panose)
1076 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1077 FIXME("(%p)->(%p): stub\n", This, panose);
1080 static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont2 *iface, UINT32 max_count, DWRITE_UNICODE_RANGE *ranges, UINT32 *count)
1082 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1083 IDWriteFontFace2 *fontface;
1084 HRESULT hr;
1086 TRACE("(%p)->(%u %p %p)\n", This, max_count, ranges, count);
1088 hr = get_fontface_from_font(This, &fontface);
1089 if (FAILED(hr))
1090 return hr;
1092 return IDWriteFontFace2_GetUnicodeRanges(fontface, max_count, ranges, count);
1095 static HRESULT WINAPI dwritefont1_IsMonospacedFont(IDWriteFont2 *iface)
1097 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1098 FIXME("(%p): stub\n", This);
1099 return FALSE;
1102 static HRESULT WINAPI dwritefont2_IsColorFont(IDWriteFont2 *iface)
1104 struct dwrite_font *This = impl_from_IDWriteFont2(iface);
1105 FIXME("(%p): stub\n", This);
1106 return FALSE;
1109 static const IDWriteFont2Vtbl dwritefontvtbl = {
1110 dwritefont_QueryInterface,
1111 dwritefont_AddRef,
1112 dwritefont_Release,
1113 dwritefont_GetFontFamily,
1114 dwritefont_GetWeight,
1115 dwritefont_GetStretch,
1116 dwritefont_GetStyle,
1117 dwritefont_IsSymbolFont,
1118 dwritefont_GetFaceNames,
1119 dwritefont_GetInformationalStrings,
1120 dwritefont_GetSimulations,
1121 dwritefont_GetMetrics,
1122 dwritefont_HasCharacter,
1123 dwritefont_CreateFontFace,
1124 dwritefont1_GetMetrics,
1125 dwritefont1_GetPanose,
1126 dwritefont1_GetUnicodeRanges,
1127 dwritefont1_IsMonospacedFont,
1128 dwritefont2_IsColorFont
1131 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
1133 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1134 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1136 if (IsEqualIID(riid, &IID_IUnknown) ||
1137 IsEqualIID(riid, &IID_IDWriteFontList) ||
1138 IsEqualIID(riid, &IID_IDWriteFontFamily))
1140 *obj = iface;
1141 IDWriteFontFamily_AddRef(iface);
1142 return S_OK;
1145 *obj = NULL;
1146 return E_NOINTERFACE;
1149 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
1151 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1152 ULONG ref = InterlockedIncrement(&This->ref);
1153 TRACE("(%p)->(%d)\n", This, ref);
1154 return ref;
1157 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
1159 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1160 ULONG ref = InterlockedDecrement(&This->ref);
1162 TRACE("(%p)->(%d)\n", This, ref);
1164 if (!ref)
1166 if (This->collection)
1167 IDWriteFontCollection_Release(This->collection);
1168 _free_fontfamily_data(This->data);
1169 heap_free(This);
1172 return ref;
1175 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
1177 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1178 TRACE("(%p)->(%p)\n", This, collection);
1179 if (This->collection)
1181 IDWriteFontCollection_AddRef(This->collection);
1182 *collection = This->collection;
1183 return S_OK;
1185 else
1186 return E_NOTIMPL;
1189 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
1191 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1192 TRACE("(%p)\n", This);
1193 return This->data->font_count;
1196 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
1198 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1199 TRACE("(%p)->(%u %p)\n", This, index, font);
1200 if (This->data->font_count > 0)
1202 if (index >= This->data->font_count)
1203 return E_INVALIDARG;
1204 return create_font_from_data(This->data->fonts[index], iface, font);
1206 else
1207 return E_NOTIMPL;
1210 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
1212 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1213 return clone_localizedstring(This->data->familyname, names);
1216 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1217 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
1219 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1220 LOGFONTW lf;
1222 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
1224 /* fallback for system font collections */
1225 if (This->data->font_count == 0)
1227 memset(&lf, 0, sizeof(lf));
1228 lf.lfWeight = weight;
1229 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
1230 IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE);
1232 return create_font_from_logfont(&lf, font);
1234 else
1236 int i;
1237 for (i = 0; i < This->data->font_count; i++)
1239 if (style == This->data->fonts[i]->style &&
1240 weight == This->data->fonts[i]->weight &&
1241 stretch == This->data->fonts[i]->stretch)
1243 return create_font_from_data(This->data->fonts[i], iface, font);
1246 return DWRITE_E_NOFONT;
1250 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
1251 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
1253 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
1254 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
1255 return E_NOTIMPL;
1258 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
1259 dwritefontfamily_QueryInterface,
1260 dwritefontfamily_AddRef,
1261 dwritefontfamily_Release,
1262 dwritefontfamily_GetFontCollection,
1263 dwritefontfamily_GetFontCount,
1264 dwritefontfamily_GetFont,
1265 dwritefontfamily_GetFamilyNames,
1266 dwritefontfamily_GetFirstMatchingFont,
1267 dwritefontfamily_GetMatchingFonts
1270 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
1272 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1273 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1275 if (IsEqualIID(riid, &IID_IUnknown) ||
1276 IsEqualIID(riid, &IID_IDWriteFontCollection))
1278 *obj = iface;
1279 IDWriteFontCollection_AddRef(iface);
1280 return S_OK;
1283 *obj = NULL;
1284 return E_NOINTERFACE;
1287 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
1289 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1290 ULONG ref = InterlockedIncrement(&This->ref);
1291 TRACE("(%p)->(%d)\n", This, ref);
1292 return ref;
1295 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
1297 unsigned int i;
1298 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1299 ULONG ref = InterlockedDecrement(&This->ref);
1300 TRACE("(%p)->(%d)\n", This, ref);
1302 if (!ref)
1304 for (i = 0; i < This->count; i++)
1305 heap_free(This->families[i]);
1306 heap_free(This->families);
1307 for (i = 0; i < This->data_count; i++)
1308 _free_fontfamily_data(This->family_data[i]);
1309 heap_free(This->family_data);
1310 heap_free(This);
1313 return ref;
1316 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
1318 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1319 TRACE("(%p)\n", This);
1320 if (This->data_count)
1321 return This->data_count;
1322 return This->count;
1325 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
1327 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1328 HRESULT hr;
1329 IDWriteLocalizedStrings *familyname;
1330 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1332 TRACE("(%p)->(%u %p)\n", This, index, family);
1334 if (This->data_count)
1336 if (index >= This->data_count)
1338 *family = NULL;
1339 return E_FAIL;
1341 else
1342 return create_fontfamily_from_data(This->family_data[index], iface, family);
1344 else
1346 if (index >= This->count)
1348 *family = NULL;
1349 return E_FAIL;
1352 hr = create_localizedstrings(&familyname);
1353 if (FAILED(hr))
1354 return hr;
1355 add_localizedstring(familyname, enusW, This->families[index]);
1357 return create_fontfamily(familyname, family);
1361 static HRESULT collection_find_family(struct dwrite_fontcollection *collection, const WCHAR *name, UINT32 *index, BOOL *exists)
1363 UINT32 i;
1365 if (collection->data_count) {
1366 for (i = 0; i < collection->data_count; i++) {
1367 IDWriteLocalizedStrings *family_name = collection->family_data[i]->familyname;
1368 HRESULT hr;
1369 int j;
1371 for (j = 0; j < IDWriteLocalizedStrings_GetCount(family_name); j++) {
1372 WCHAR buffer[255];
1373 hr = IDWriteLocalizedStrings_GetString(family_name, j, buffer, 255);
1374 if (SUCCEEDED(hr)) {
1375 if (!strcmpW(buffer, name)) {
1376 *index = i;
1377 *exists = TRUE;
1378 return S_OK;
1383 *index = (UINT32)-1;
1384 *exists = FALSE;
1386 else {
1387 for (i = 0; i < collection->count; i++)
1388 if (!strcmpW(collection->families[i], name)) {
1389 *index = i;
1390 *exists = TRUE;
1391 return S_OK;
1394 *index = (UINT32)-1;
1395 *exists = FALSE;
1398 return S_OK;
1401 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
1403 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1404 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
1405 return collection_find_family(This, name, index, exists);
1408 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
1410 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1411 struct dwrite_fontfamily_data *found_family = NULL;
1412 struct dwrite_font_data *found_font = NULL;
1413 IDWriteFontFamily *family;
1414 UINT32 i, j;
1415 HRESULT hr;
1417 TRACE("(%p)->(%p %p)\n", This, face, font);
1419 *font = NULL;
1421 if (!face)
1422 return E_INVALIDARG;
1424 for (i = 0; i < This->data_count; i++) {
1425 struct dwrite_fontfamily_data *family_data = This->family_data[i];
1426 for (j = 0; j < family_data->font_count; j++) {
1427 if ((IDWriteFontFace*)family_data->fonts[j]->face == face) {
1428 found_font = family_data->fonts[j];
1429 found_family = family_data;
1430 break;
1435 if (!found_font)
1436 return E_INVALIDARG;
1438 hr = create_fontfamily_from_data(found_family, iface, &family);
1439 if (FAILED(hr))
1440 return hr;
1442 hr = create_font_from_data(found_font, family, font);
1443 IDWriteFontFamily_Release(family);
1444 return hr;
1447 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
1448 dwritefontcollection_QueryInterface,
1449 dwritefontcollection_AddRef,
1450 dwritefontcollection_Release,
1451 dwritefontcollection_GetFontFamilyCount,
1452 dwritefontcollection_GetFontFamily,
1453 dwritefontcollection_FindFamilyName,
1454 dwritefontcollection_GetFontFromFontFace
1457 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
1459 /* check for duplicate family name */
1460 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
1462 /* double array length */
1463 if (collection->count == collection->alloc)
1465 collection->alloc *= 2;
1466 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
1469 collection->families[collection->count++] = heap_strdupW(family);
1470 TRACE("family name %s\n", debugstr_w(family));
1472 return S_OK;
1475 static HRESULT fontfamily_add_font(struct dwrite_fontfamily_data *family_data, struct dwrite_font_data *font_data)
1477 if (family_data->font_count + 1 >= family_data->font_alloc) {
1478 struct dwrite_font_data **new_list;
1479 UINT32 new_alloc;
1481 new_alloc = family_data->font_alloc * 2;
1482 new_list = heap_realloc(family_data->fonts, sizeof(*family_data->fonts) * new_alloc);
1483 if (!new_list)
1484 return E_OUTOFMEMORY;
1485 family_data->fonts = new_list;
1486 family_data->font_alloc = new_alloc;
1489 family_data->fonts[family_data->font_count] = font_data;
1490 InterlockedIncrement(&font_data->ref);
1491 family_data->font_count++;
1492 return S_OK;
1495 static HRESULT fontcollection_add_family(struct dwrite_fontcollection *collection, struct dwrite_fontfamily_data *family)
1497 if (collection->data_alloc < collection->data_count + 1) {
1498 struct dwrite_fontfamily_data **new_list;
1499 UINT32 new_alloc;
1501 new_alloc = collection->data_alloc * 2;
1502 new_list = heap_realloc(collection->family_data, sizeof(*new_list) * new_alloc);
1503 if (!new_list)
1504 return E_OUTOFMEMORY;
1506 collection->data_alloc = new_alloc;
1507 collection->family_data = new_list;
1510 collection->family_data[collection->data_count] = family;
1511 collection->data_count++;
1513 return S_OK;
1516 static HRESULT init_font_collection(struct dwrite_fontcollection *collection)
1518 collection->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1519 collection->ref = 1;
1520 collection->data_count = 0;
1521 collection->data_alloc = 2;
1522 collection->count = 0;
1523 collection->alloc = 0;
1524 collection->families = NULL;
1526 collection->family_data = heap_alloc(sizeof(*collection->family_data)*2);
1527 if (!collection->family_data)
1528 return E_OUTOFMEMORY;
1530 return S_OK;
1533 static HRESULT get_filestream_from_file(IDWriteFontFile *file, IDWriteFontFileStream **stream)
1535 IDWriteFontFileLoader *loader;
1536 const void *key;
1537 UINT32 key_size;
1538 HRESULT hr;
1540 *stream = NULL;
1542 hr = IDWriteFontFile_GetReferenceKey(file, &key, &key_size);
1543 if (FAILED(hr))
1544 return hr;
1546 hr = IDWriteFontFile_GetLoader(file, &loader);
1547 if (FAILED(hr))
1548 return hr;
1550 hr = IDWriteFontFileLoader_CreateStreamFromKey(loader, key, key_size, stream);
1551 IDWriteFontFileLoader_Release(loader);
1552 if (FAILED(hr))
1553 return hr;
1555 return hr;
1558 static HRESULT init_font_data(IDWriteFactory *factory, IDWriteFontFile *file, UINT32 face_index, DWRITE_FONT_FACE_TYPE face_type, struct dwrite_font_data *data)
1560 void *os2_context, *head_context, *post_context;
1561 const void *tt_os2 = NULL, *tt_head = NULL, *tt_post = NULL;
1562 IDWriteFontFileStream *stream;
1563 HRESULT hr;
1565 hr = get_filestream_from_file(file, &stream);
1566 if (FAILED(hr))
1567 return hr;
1569 data->factory = factory;
1570 data->file = file;
1571 data->face = NULL;
1572 data->face_index = face_index;
1573 data->face_type = face_type;
1574 IDWriteFontFile_AddRef(file);
1575 IDWriteFactory_AddRef(factory);
1577 opentype_get_font_table(stream, face_type, face_index, MS_OS2_TAG, &tt_os2, &os2_context, NULL, NULL);
1578 opentype_get_font_table(stream, face_type, face_index, MS_HEAD_TAG, &tt_head, &head_context, NULL, NULL);
1579 opentype_get_font_table(stream, face_type, face_index, MS_POST_TAG, &tt_post, &post_context, NULL, NULL);
1581 get_font_properties(tt_os2, tt_head, tt_post, &data->metrics, &data->stretch, &data->weight, &data->style);
1583 if (tt_os2)
1584 IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
1585 if (tt_head)
1586 IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
1587 if (tt_post)
1588 IDWriteFontFileStream_ReleaseFileFragment(stream, post_context);
1589 IDWriteFontFileStream_Release(stream);
1591 return S_OK;
1594 static HRESULT init_fontfamily_data(IDWriteLocalizedStrings *familyname, struct dwrite_fontfamily_data *data)
1596 data->ref = 1;
1597 data->font_count = 0;
1598 data->font_alloc = 2;
1600 data->fonts = heap_alloc(sizeof(*data->fonts)*data->font_alloc);
1601 if (!data->fonts) {
1602 heap_free(data);
1603 return E_OUTOFMEMORY;
1606 data->familyname = familyname;
1607 IDWriteLocalizedStrings_AddRef(familyname);
1609 return S_OK;
1612 HRESULT create_font_collection(IDWriteFactory* factory, IDWriteFontFileEnumerator *enumerator, IDWriteFontCollection **ret)
1614 struct dwrite_fontcollection *collection;
1615 BOOL current = FALSE;
1616 HRESULT hr;
1618 *ret = NULL;
1620 collection = heap_alloc(sizeof(struct dwrite_fontcollection));
1621 if (!collection) return E_OUTOFMEMORY;
1623 hr = init_font_collection(collection);
1624 if (FAILED(hr)) {
1625 heap_free(collection);
1626 return hr;
1629 *ret = &collection->IDWriteFontCollection_iface;
1631 TRACE("building font collection:\n");
1633 while (1) {
1634 DWRITE_FONT_FACE_TYPE face_type;
1635 DWRITE_FONT_FILE_TYPE file_type;
1636 IDWriteFontFile *file;
1637 UINT32 face_count;
1638 BOOL supported;
1639 int i;
1641 current = FALSE;
1642 hr = IDWriteFontFileEnumerator_MoveNext(enumerator, &current);
1643 if (FAILED(hr) || !current)
1644 break;
1646 hr = IDWriteFontFileEnumerator_GetCurrentFontFile(enumerator, &file);
1647 if (FAILED(hr))
1648 break;
1650 hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &face_count);
1651 if (FAILED(hr) || !supported || face_count == 0) {
1652 TRACE("unsupported font (0x%08x, %d, %u)\n", hr, supported, face_count);
1653 IDWriteFontFile_Release(file);
1654 continue;
1657 for (i = 0; i < face_count; i++) {
1658 IDWriteLocalizedStrings *family_name = NULL;
1659 struct dwrite_font_data *font_data;
1660 const void *name_table;
1661 void *name_context;
1662 IDWriteFontFileStream *stream;
1663 WCHAR buffer[255];
1664 UINT32 index;
1665 BOOL exists;
1667 /* alloc and init new font data structure */
1668 font_data = heap_alloc_zero(sizeof(struct dwrite_font_data));
1669 init_font_data(factory, file, i, face_type, font_data);
1671 hr = get_filestream_from_file(file, &stream);
1672 if (FAILED(hr))
1673 return hr;
1675 /* get family name from font file */
1676 name_table = NULL;
1677 opentype_get_font_table(stream, face_type, i, MS_NAME_TAG, &name_table, &name_context, NULL, NULL);
1678 if (name_table)
1679 hr = opentype_get_font_strings_from_id(name_table, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &family_name);
1680 IDWriteFontFileStream_Release(stream);
1682 if (FAILED(hr) || !family_name) {
1683 WARN("unable to get family name from font\n");
1684 continue;
1687 buffer[0] = 0;
1688 IDWriteLocalizedStrings_GetString(family_name, 0, buffer, sizeof(buffer)/sizeof(WCHAR));
1690 exists = FALSE;
1691 hr = collection_find_family(collection, buffer, &index, &exists);
1692 if (exists)
1693 hr = fontfamily_add_font(collection->family_data[index], font_data);
1694 else {
1695 struct dwrite_fontfamily_data *family_data;
1697 /* create and init new family */
1698 family_data = heap_alloc(sizeof(*family_data));
1699 init_fontfamily_data(family_name, family_data);
1701 /* add font to family, family - to collection */
1702 fontfamily_add_font(family_data, font_data);
1703 fontcollection_add_family(collection, family_data);
1706 IDWriteLocalizedStrings_Release(family_name);
1709 IDWriteFontFile_Release(file);
1712 return S_OK;
1715 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1717 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1718 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1721 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1723 struct dwrite_fontcollection *This;
1724 LOGFONTW lf;
1725 HDC hdc;
1727 *collection = NULL;
1729 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1730 if (!This) return E_OUTOFMEMORY;
1732 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1733 This->ref = 1;
1734 This->alloc = 50;
1735 This->count = 0;
1736 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1737 if (!This->families)
1739 heap_free(This);
1740 return E_OUTOFMEMORY;
1742 This->data_count = 0;
1743 This->data_alloc = 2;
1744 This->family_data = heap_alloc(sizeof(*This->family_data)*2);
1745 if (!This->family_data)
1747 heap_free(This->families);
1748 heap_free(This);
1749 return E_OUTOFMEMORY;
1752 TRACE("building system font collection:\n");
1754 hdc = CreateCompatibleDC(0);
1755 memset(&lf, 0, sizeof(lf));
1756 lf.lfCharSet = DEFAULT_CHARSET;
1757 lf.lfPitchAndFamily = DEFAULT_PITCH;
1758 lf.lfFaceName[0] = 0;
1759 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1760 DeleteDC(hdc);
1762 *collection = &This->IDWriteFontCollection_iface;
1764 return S_OK;
1767 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family)
1769 struct dwrite_fontfamily *This;
1771 *family = NULL;
1773 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1774 if (!This) return E_OUTOFMEMORY;
1776 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1777 This->ref = 1;
1778 This->collection = collection;
1779 if (collection)
1780 IDWriteFontCollection_AddRef(collection);
1781 This->data = data;
1782 InterlockedIncrement(&This->data->ref);
1784 *family = &This->IDWriteFontFamily_iface;
1786 return S_OK;
1789 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family)
1791 struct dwrite_fontfamily_data *data;
1792 HRESULT ret;
1794 data = heap_alloc(sizeof(struct dwrite_fontfamily_data));
1795 if (!data) return E_OUTOFMEMORY;
1797 data->ref = 0;
1798 data->font_count = 0;
1799 data->font_alloc = 2;
1800 data->fonts = heap_alloc(sizeof(*data->fonts) * 2);
1801 if (!data->fonts)
1803 heap_free(data);
1804 return E_OUTOFMEMORY;
1806 data->familyname = familyname;
1808 ret = create_fontfamily_from_data(data, NULL, family);
1809 if (FAILED(ret))
1811 heap_free(data->fonts);
1812 heap_free(data);
1815 return ret;
1818 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFontFamily *family, IDWriteFont **font)
1820 struct dwrite_font *This;
1821 *font = NULL;
1823 This = heap_alloc(sizeof(struct dwrite_font));
1824 if (!This) return E_OUTOFMEMORY;
1826 This->IDWriteFont2_iface.lpVtbl = &dwritefontvtbl;
1827 This->ref = 1;
1828 This->family = family;
1829 if (family)
1830 IDWriteFontFamily_AddRef(family);
1831 This->is_system = FALSE;
1832 This->data = data;
1833 InterlockedIncrement(&This->data->ref);
1835 *font = (IDWriteFont*)&This->IDWriteFont2_iface;
1837 return S_OK;
1840 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1842 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1844 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1846 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1848 *obj = iface;
1849 IDWriteFontFile_AddRef(iface);
1850 return S_OK;
1853 *obj = NULL;
1854 return E_NOINTERFACE;
1857 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1859 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1860 ULONG ref = InterlockedIncrement(&This->ref);
1861 TRACE("(%p)->(%d)\n", This, ref);
1862 return ref;
1865 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1867 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1868 ULONG ref = InterlockedDecrement(&This->ref);
1870 TRACE("(%p)->(%d)\n", This, ref);
1872 if (!ref)
1874 IDWriteFontFileLoader_Release(This->loader);
1875 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1876 heap_free(This->reference_key);
1877 heap_free(This);
1880 return ref;
1883 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1885 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1886 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1887 *fontFileReferenceKey = This->reference_key;
1888 *fontFileReferenceKeySize = This->key_size;
1890 return S_OK;
1893 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1895 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1896 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1897 *fontFileLoader = This->loader;
1898 IDWriteFontFileLoader_AddRef(This->loader);
1900 return S_OK;
1903 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1905 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1906 IDWriteFontFileStream *stream;
1907 HRESULT hr;
1909 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1911 *isSupportedFontType = FALSE;
1912 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1913 if (fontFaceType)
1914 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1915 *numberOfFaces = 0;
1917 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1918 if (FAILED(hr))
1919 return S_OK;
1921 hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1923 /* TODO: Further Analysis */
1924 IDWriteFontFileStream_Release(stream);
1925 return S_OK;
1928 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1929 dwritefontfile_QueryInterface,
1930 dwritefontfile_AddRef,
1931 dwritefontfile_Release,
1932 dwritefontfile_GetReferenceKey,
1933 dwritefontfile_GetLoader,
1934 dwritefontfile_Analyze,
1937 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1939 struct dwrite_fontfile *This;
1941 This = heap_alloc(sizeof(struct dwrite_fontfile));
1942 if (!This) return E_OUTOFMEMORY;
1944 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1945 This->ref = 1;
1946 IDWriteFontFileLoader_AddRef(loader);
1947 This->loader = loader;
1948 This->stream = NULL;
1949 This->reference_key = heap_alloc(key_size);
1950 memcpy(This->reference_key, reference_key, key_size);
1951 This->key_size = key_size;
1953 *font_file = &This->IDWriteFontFile_iface;
1955 return S_OK;
1958 HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index,
1959 DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace2 **ret)
1961 struct dwrite_fontface *fontface;
1962 HRESULT hr = S_OK;
1963 int i;
1965 fontface = heap_alloc(sizeof(struct dwrite_fontface));
1966 if (!fontface)
1967 return E_OUTOFMEMORY;
1969 fontface->files = heap_alloc(sizeof(*fontface->files) * files_number);
1970 if (!fontface->files) {
1971 heap_free(fontface);
1972 return E_OUTOFMEMORY;
1975 fontface->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl;
1976 fontface->ref = 1;
1977 fontface->type = facetype;
1978 fontface->file_count = files_number;
1979 fontface->cmap.data = NULL;
1980 fontface->cmap.context = NULL;
1981 fontface->cmap.size = 0;
1983 /* Verify font file streams */
1984 for (i = 0; i < fontface->file_count && SUCCEEDED(hr); i++)
1986 IDWriteFontFileStream *stream;
1987 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1988 if (SUCCEEDED(hr))
1989 IDWriteFontFileStream_Release(stream);
1992 if (FAILED(hr)) {
1993 heap_free(fontface->files);
1994 heap_free(fontface);
1995 return hr;
1998 for (i = 0; i < fontface->file_count; i++) {
1999 fontface->files[i] = font_files[i];
2000 IDWriteFontFile_AddRef(font_files[i]);
2003 fontface->index = index;
2004 fontface->simulations = simulations;
2005 fontface->is_system = FALSE;
2007 *ret = &fontface->IDWriteFontFace2_iface;
2008 return S_OK;
2011 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
2013 struct dwrite_localfontfilestream
2015 IDWriteFontFileStream IDWriteFontFileStream_iface;
2016 LONG ref;
2018 HANDLE handle;
2021 struct dwrite_localfontfileloader {
2022 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
2023 LONG ref;
2026 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
2028 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
2031 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
2033 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
2036 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
2038 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2039 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2040 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
2042 *obj = iface;
2043 IDWriteFontFileStream_AddRef(iface);
2044 return S_OK;
2047 *obj = NULL;
2048 return E_NOINTERFACE;
2051 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
2053 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2054 ULONG ref = InterlockedIncrement(&This->ref);
2055 TRACE("(%p)->(%d)\n", This, ref);
2056 return ref;
2059 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
2061 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2062 ULONG ref = InterlockedDecrement(&This->ref);
2064 TRACE("(%p)->(%d)\n", This, ref);
2066 if (!ref)
2068 if (This->handle != INVALID_HANDLE_VALUE)
2069 CloseHandle(This->handle);
2070 heap_free(This);
2073 return ref;
2076 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
2078 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2079 LARGE_INTEGER distance;
2080 DWORD bytes = fragment_size;
2081 DWORD read;
2083 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
2084 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
2086 *fragment_context = NULL;
2087 distance.QuadPart = offset;
2088 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
2089 return E_FAIL;
2090 *fragment_start = *fragment_context = heap_alloc(bytes);
2091 if (!*fragment_context)
2092 return E_FAIL;
2093 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
2095 heap_free(*fragment_context);
2096 return E_FAIL;
2099 return S_OK;
2102 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
2104 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2105 TRACE("(%p)->(%p)\n", This, fragment_context);
2106 heap_free(fragment_context);
2109 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
2111 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2112 LARGE_INTEGER li;
2113 TRACE("(%p)->(%p)\n",This, size);
2114 GetFileSizeEx(This->handle, &li);
2115 *size = li.QuadPart;
2116 return S_OK;
2119 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
2121 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
2122 FIXME("(%p)->(%p): stub\n",This, last_writetime);
2123 *last_writetime = 0;
2124 return E_NOTIMPL;
2127 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
2129 localfontfilestream_QueryInterface,
2130 localfontfilestream_AddRef,
2131 localfontfilestream_Release,
2132 localfontfilestream_ReadFileFragment,
2133 localfontfilestream_ReleaseFileFragment,
2134 localfontfilestream_GetFileSize,
2135 localfontfilestream_GetLastWriteTime
2138 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
2140 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
2141 if (!This)
2142 return E_OUTOFMEMORY;
2144 This->ref = 1;
2145 This->handle = handle;
2146 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
2148 *iface = &This->IDWriteFontFileStream_iface;
2149 return S_OK;
2152 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
2154 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2156 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
2158 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
2160 *obj = iface;
2161 IDWriteLocalFontFileLoader_AddRef(iface);
2162 return S_OK;
2165 *obj = NULL;
2166 return E_NOINTERFACE;
2169 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
2171 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2172 ULONG ref = InterlockedIncrement(&This->ref);
2173 TRACE("(%p)->(%d)\n", This, ref);
2174 return ref;
2177 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
2179 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2180 ULONG ref = InterlockedDecrement(&This->ref);
2182 TRACE("(%p)->(%d)\n", This, ref);
2184 if (!ref)
2185 heap_free(This);
2187 return ref;
2190 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
2192 HANDLE handle;
2193 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2194 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
2196 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
2198 TRACE("name: %s\n",debugstr_w(name));
2199 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
2200 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2202 if (handle == INVALID_HANDLE_VALUE)
2203 return E_FAIL;
2205 return create_localfontfilestream(handle, fontFileStream);
2208 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
2210 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2211 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
2212 *length = key_size;
2213 return S_OK;
2216 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
2218 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2219 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
2220 if (length < key_size)
2221 return E_INVALIDARG;
2222 lstrcpynW((WCHAR*)key, path, key_size);
2223 return S_OK;
2226 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
2228 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
2229 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
2230 return E_NOTIMPL;
2233 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
2234 localfontfileloader_QueryInterface,
2235 localfontfileloader_AddRef,
2236 localfontfileloader_Release,
2237 localfontfileloader_CreateStreamFromKey,
2238 localfontfileloader_GetFilePathLengthFromKey,
2239 localfontfileloader_GetFilePathFromKey,
2240 localfontfileloader_GetLastWriteTimeFromKey
2243 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
2245 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
2246 if (!This)
2247 return E_OUTOFMEMORY;
2249 This->ref = 1;
2250 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
2252 *iface = &This->IDWriteLocalFontFileLoader_iface;
2253 return S_OK;