dwrite: Pass stream pointer to OpenType parsing code.
[wine.git] / dlls / dwrite / font.c
bloba00b784ae9f137110f87258c0d9371700f1f6a7c
1 /*
2 * Font and collections
4 * Copyright 2012 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "dwrite.h"
24 #include "dwrite_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
28 #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')
33 struct dwrite_fontface_data {
34 LONG ref;
36 DWRITE_FONT_FACE_TYPE type;
37 UINT32 file_count;
38 IDWriteFontFile ** files;
39 DWRITE_FONT_SIMULATIONS simulations;
40 UINT32 index;
43 struct dwrite_font_data {
44 LONG ref;
46 DWRITE_FONT_STYLE style;
47 DWRITE_FONT_STRETCH stretch;
48 DWRITE_FONT_WEIGHT weight;
49 DWRITE_FONT_SIMULATIONS simulations;
50 DWRITE_FONT_METRICS metrics;
52 struct dwrite_fontface_data *face_data;
54 WCHAR *facename;
57 struct dwrite_fontfamily_data {
58 IDWriteLocalizedStrings *familyname;
60 struct dwrite_font_data **fonts;
61 UINT32 font_count;
62 UINT32 alloc;
65 struct dwrite_fontcollection {
66 IDWriteFontCollection IDWriteFontCollection_iface;
67 LONG ref;
69 WCHAR **families;
70 UINT32 count;
71 int alloc;
74 struct dwrite_fontfamily {
75 IDWriteFontFamily IDWriteFontFamily_iface;
76 LONG ref;
78 struct dwrite_fontfamily_data *data;
80 IDWriteFontCollection* collection;
83 struct dwrite_font {
84 IDWriteFont IDWriteFont_iface;
85 LONG ref;
87 BOOL is_system;
88 IDWriteFontFamily *family;
89 IDWriteFontFace *face;
91 struct dwrite_font_data *data;
94 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
96 struct dwrite_fonttablecontext {
97 UINT32 magic;
98 void *context;
99 UINT32 file_index;
102 struct dwrite_fonttable {
103 void *data;
104 void *context;
105 UINT32 size;
108 struct dwrite_fontface {
109 IDWriteFontFace IDWriteFontFace_iface;
110 LONG ref;
112 struct dwrite_fontface_data *data;
113 struct dwrite_fonttable cmap;
115 BOOL is_system;
116 LOGFONTW logfont;
119 struct dwrite_fontfile {
120 IDWriteFontFile IDWriteFontFile_iface;
121 LONG ref;
123 IDWriteFontFileLoader *loader;
124 void *reference_key;
125 UINT32 key_size;
126 IDWriteFontFileStream *stream;
129 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family);
130 static HRESULT create_font_base(IDWriteFont **font);
131 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font);
133 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
135 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
138 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
140 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
143 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
145 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
148 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
150 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
153 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
155 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
158 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
160 HRESULT hr;
161 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
162 if (!This->stream)
164 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
165 if (FAILED(hr))
166 return hr;
168 if (This->stream)
170 IDWriteFontFileStream_AddRef(This->stream);
171 *stream = This->stream;
172 return S_OK;
174 return E_FAIL;
177 static VOID _free_fontface_data(struct dwrite_fontface_data *data)
179 int i;
180 if (!data)
181 return;
182 i = InterlockedDecrement(&data->ref);
183 if (i > 0)
184 return;
185 for (i = 0; i < data->file_count; i++)
186 IDWriteFontFile_Release(data->files[i]);
187 heap_free(data->files);
188 heap_free(data);
191 static VOID _free_font_data(struct dwrite_font_data *data)
193 int i;
194 if (!data)
195 return;
196 i = InterlockedDecrement(&data->ref);
197 if (i > 0)
198 return;
199 _free_fontface_data(data->face_data);
200 heap_free(data->facename);
201 heap_free(data);
204 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
206 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
208 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
210 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
212 *obj = iface;
213 IDWriteFontFace_AddRef(iface);
214 return S_OK;
217 *obj = NULL;
218 return E_NOINTERFACE;
221 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
223 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
224 ULONG ref = InterlockedIncrement(&This->ref);
225 TRACE("(%p)->(%d)\n", This, ref);
226 return ref;
229 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
231 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
232 ULONG ref = InterlockedDecrement(&This->ref);
234 TRACE("(%p)->(%d)\n", This, ref);
236 if (!ref)
238 if (This->cmap.context)
239 IDWriteFontFace_ReleaseFontTable(iface, This->cmap.context);
240 _free_fontface_data(This->data);
241 heap_free(This);
244 return ref;
247 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
249 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
250 TRACE("(%p)\n", This);
251 return This->data->type;
254 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
255 IDWriteFontFile **fontfiles)
257 int i;
258 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
259 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
260 if (fontfiles == NULL)
262 *number_of_files = This->data->file_count;
263 return S_OK;
265 if (*number_of_files < This->data->file_count)
266 return E_INVALIDARG;
268 for (i = 0; i < This->data->file_count; i++)
270 IDWriteFontFile_AddRef(This->data->files[i]);
271 fontfiles[i] = This->data->files[i];
274 return S_OK;
277 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
279 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
280 TRACE("(%p)\n", This);
281 return This->data->index;
284 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
286 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
287 TRACE("(%p)\n", This);
288 return This->data->simulations;
291 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
293 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
294 FIXME("(%p): stub\n", This);
295 return FALSE;
298 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
300 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
301 FIXME("(%p)->(%p): stub\n", This, metrics);
304 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
306 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
307 FIXME("(%p): stub\n", This);
308 return 0;
311 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
312 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
314 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
315 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
316 return E_NOTIMPL;
319 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
320 UINT32 count, UINT16 *glyph_indices)
322 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
323 unsigned int i;
325 if (This->is_system)
327 HFONT hfont;
328 WCHAR *str;
329 HDC hdc;
331 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
333 str = heap_alloc(count*sizeof(WCHAR));
334 if (!str) return E_OUTOFMEMORY;
336 for (i = 0; i < count; i++)
337 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
339 hdc = CreateCompatibleDC(0);
340 hfont = CreateFontIndirectW(&This->logfont);
341 SelectObject(hdc, hfont);
343 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
344 heap_free(str);
346 DeleteDC(hdc);
347 DeleteObject(hfont);
349 return S_OK;
351 else
353 HRESULT hr;
354 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
355 if (!This->cmap.data)
357 BOOL exists = FALSE;
358 hr = IDWriteFontFace_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->cmap.data, &This->cmap.size, &This->cmap.context, &exists);
359 if (FAILED(hr) || !exists)
361 ERR("Font does not have a CMAP table\n");
362 return E_FAIL;
366 for (i = 0; i < count; i++)
368 OpenType_CMAP_GetGlyphIndex(This->cmap.data, codepoints[i], &glyph_indices[i], 0);
370 return S_OK;
374 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
375 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
377 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
378 if (This->is_system)
380 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
381 return E_NOTIMPL;
383 else
385 HRESULT hr = S_OK;
386 int i;
387 struct dwrite_fonttablecontext *tablecontext;
389 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
391 tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext));
392 if (!tablecontext)
393 return E_OUTOFMEMORY;
394 tablecontext->magic = DWRITE_FONTTABLE_MAGIC;
396 *exists = FALSE;
397 for (i = 0; i < This->data->file_count && !(*exists); i++)
399 IDWriteFontFileStream *stream;
400 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
401 if (FAILED(hr))
402 continue;
403 tablecontext->file_index = i;
405 hr = find_font_table(stream, This->data->index, table_tag, table_data, &tablecontext->context, table_size, exists);
407 IDWriteFontFileStream_Release(stream);
409 if (FAILED(hr) && !*exists)
410 heap_free(tablecontext);
411 else
412 *context = (void*)tablecontext;
413 return hr;
417 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
419 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
420 struct dwrite_fonttablecontext *tablecontext = (struct dwrite_fonttablecontext*)table_context;
421 IDWriteFontFileStream *stream;
422 HRESULT hr;
423 TRACE("(%p)->(%p)\n", This, table_context);
425 if (tablecontext->magic != DWRITE_FONTTABLE_MAGIC)
427 TRACE("Invalid table magic\n");
428 return;
431 hr = _dwritefontfile_GetFontFileStream(This->data->files[tablecontext->file_index], &stream);
432 if (FAILED(hr))
433 return;
434 IDWriteFontFileStream_ReleaseFileFragment(stream, tablecontext->context);
435 IDWriteFontFileStream_Release(stream);
436 heap_free(tablecontext);
439 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
440 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
441 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
443 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
444 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
445 glyph_count, is_sideways, is_rtl, geometrysink);
446 return E_NOTIMPL;
449 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
450 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
452 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
453 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
454 return E_NOTIMPL;
457 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
458 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
460 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
461 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
462 return E_NOTIMPL;
465 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
466 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
467 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
469 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
470 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
471 glyph_count, metrics, is_sideways);
472 return E_NOTIMPL;
475 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
476 dwritefontface_QueryInterface,
477 dwritefontface_AddRef,
478 dwritefontface_Release,
479 dwritefontface_GetType,
480 dwritefontface_GetFiles,
481 dwritefontface_GetIndex,
482 dwritefontface_GetSimulations,
483 dwritefontface_IsSymbolFont,
484 dwritefontface_GetMetrics,
485 dwritefontface_GetGlyphCount,
486 dwritefontface_GetDesignGlyphMetrics,
487 dwritefontface_GetGlyphIndices,
488 dwritefontface_TryGetFontTable,
489 dwritefontface_ReleaseFontTable,
490 dwritefontface_GetGlyphRunOutline,
491 dwritefontface_GetRecommendedRenderingMode,
492 dwritefontface_GetGdiCompatibleMetrics,
493 dwritefontface_GetGdiCompatibleGlyphMetrics
496 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
498 struct dwrite_fontface *This;
500 *face = NULL;
502 This = heap_alloc(sizeof(struct dwrite_fontface));
503 if (!This) return E_OUTOFMEMORY;
504 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
505 if (!This->data)
507 heap_free(This);
508 return E_OUTOFMEMORY;
511 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
512 This->ref = 1;
513 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
514 This->data->file_count = 0;
515 This->data->files = NULL;
516 This->data->index = 0;
517 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
518 This->cmap.data = NULL;
519 This->cmap.context = NULL;
520 This->cmap.size = 0;
522 This->is_system = TRUE;
523 memset(&This->logfont, 0, sizeof(This->logfont));
524 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
525 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
526 This->logfont.lfWeight = font->data->weight;
527 strcpyW(This->logfont.lfFaceName, font->data->facename);
529 *face = &This->IDWriteFontFace_iface;
531 return S_OK;
534 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
536 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace(face);
538 *logfont = fontface->logfont;
540 return S_OK;
543 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
545 struct dwrite_font *This = impl_from_IDWriteFont(iface);
547 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
549 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
551 *obj = iface;
552 IDWriteFont_AddRef(iface);
553 return S_OK;
556 *obj = NULL;
557 return E_NOINTERFACE;
560 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
562 struct dwrite_font *This = impl_from_IDWriteFont(iface);
563 ULONG ref = InterlockedIncrement(&This->ref);
564 TRACE("(%p)->(%d)\n", This, ref);
565 return ref;
568 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
570 struct dwrite_font *This = impl_from_IDWriteFont(iface);
571 ULONG ref = InterlockedDecrement(&This->ref);
573 TRACE("(%p)->(%d)\n", This, ref);
575 if (!ref)
577 if (This->face) IDWriteFontFace_Release(This->face);
578 if (This->family) IDWriteFontFamily_Release(This->family);
579 _free_font_data(This->data);
580 heap_free(This);
583 return ref;
586 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
588 struct dwrite_font *This = impl_from_IDWriteFont(iface);
589 TRACE("(%p)->(%p)\n", This, family);
591 *family = This->family;
592 IDWriteFontFamily_AddRef(*family);
593 return S_OK;
596 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
598 struct dwrite_font *This = impl_from_IDWriteFont(iface);
599 TRACE("(%p)\n", This);
600 return This->data->weight;
603 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
605 struct dwrite_font *This = impl_from_IDWriteFont(iface);
606 TRACE("(%p)\n", This);
607 return This->data->stretch;
610 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
612 struct dwrite_font *This = impl_from_IDWriteFont(iface);
613 TRACE("(%p)\n", This);
614 return This->data->style;
617 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
619 struct dwrite_font *This = impl_from_IDWriteFont(iface);
620 FIXME("(%p): stub\n", This);
621 return FALSE;
624 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
626 struct dwrite_font *This = impl_from_IDWriteFont(iface);
627 FIXME("(%p)->(%p): stub\n", This, names);
628 return E_NOTIMPL;
631 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
632 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
634 struct dwrite_font *This = impl_from_IDWriteFont(iface);
635 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
636 return E_NOTIMPL;
639 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
641 struct dwrite_font *This = impl_from_IDWriteFont(iface);
642 TRACE("(%p)\n", This);
643 return This->data->simulations;
646 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
648 struct dwrite_font *This = impl_from_IDWriteFont(iface);
650 TRACE("(%p)->(%p)\n", This, metrics);
651 *metrics = This->data->metrics;
654 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
656 struct dwrite_font *This = impl_from_IDWriteFont(iface);
657 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
658 return E_NOTIMPL;
661 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
663 struct dwrite_font *This = impl_from_IDWriteFont(iface);
665 if (This->is_system)
667 TRACE("(%p)->(%p)\n", This, face);
669 if (!This->face)
671 HRESULT hr = create_system_fontface(This, &This->face);
672 if (FAILED(hr)) return hr;
675 *face = This->face;
676 IDWriteFontFace_AddRef(*face);
678 return S_OK;
680 else
682 TRACE("(%p)->(%p)\n", This, face);
684 if (!This->face)
686 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);
687 if (FAILED(hr)) return hr;
690 *face = This->face;
691 IDWriteFontFace_AddRef(*face);
693 return S_OK;
697 static const IDWriteFontVtbl dwritefontvtbl = {
698 dwritefont_QueryInterface,
699 dwritefont_AddRef,
700 dwritefont_Release,
701 dwritefont_GetFontFamily,
702 dwritefont_GetWeight,
703 dwritefont_GetStretch,
704 dwritefont_GetStyle,
705 dwritefont_IsSymbolFont,
706 dwritefont_GetFaceNames,
707 dwritefont_GetInformationalStrings,
708 dwritefont_GetSimulations,
709 dwritefont_GetMetrics,
710 dwritefont_HasCharacter,
711 dwritefont_CreateFontFace
714 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
716 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
717 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
719 if (IsEqualIID(riid, &IID_IUnknown) ||
720 IsEqualIID(riid, &IID_IDWriteFontList) ||
721 IsEqualIID(riid, &IID_IDWriteFontFamily))
723 *obj = iface;
724 IDWriteFontFamily_AddRef(iface);
725 return S_OK;
728 *obj = NULL;
729 return E_NOINTERFACE;
732 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
734 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
735 ULONG ref = InterlockedIncrement(&This->ref);
736 TRACE("(%p)->(%d)\n", This, ref);
737 return ref;
740 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
742 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
743 ULONG ref = InterlockedDecrement(&This->ref);
745 TRACE("(%p)->(%d)\n", This, ref);
747 if (!ref)
749 int i;
750 IDWriteLocalizedStrings_Release(This->data->familyname);
752 if (This->collection)
753 IDWriteFontCollection_Release(This->collection);
754 for (i = 0; i < This->data->font_count; i++)
755 _free_font_data(This->data->fonts[i]);
756 heap_free(This->data->fonts);
757 heap_free(This->data);
758 heap_free(This);
761 return ref;
764 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
766 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
767 TRACE("(%p)->(%p)\n", This, collection);
768 if (This->collection)
770 IDWriteFontCollection_AddRef(This->collection);
771 *collection = This->collection;
772 return S_OK;
774 else
775 return E_NOTIMPL;
778 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
780 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
781 TRACE("(%p)\n", This);
782 return This->data->font_count;
785 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
787 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
788 TRACE("(%p)->(%u %p)\n", This, index, font);
789 if (This->data->font_count > 0)
791 HRESULT hr;
792 if (index >= This->data->font_count)
793 return E_INVALIDARG;
794 hr = create_font_from_data(This->data->fonts[index], font);
795 if (SUCCEEDED(hr))
797 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
798 font_data->family = iface;
799 IDWriteFontFamily_AddRef(iface);
801 return hr;
803 else
804 return E_NOTIMPL;
807 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
809 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
810 return clone_localizedstring(This->data->familyname, names);
813 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
814 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
816 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
817 LOGFONTW lf;
819 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
821 /* fallback for system font collections */
822 if (This->data->font_count == 0)
824 memset(&lf, 0, sizeof(lf));
825 lf.lfWeight = weight;
826 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
827 IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE);
829 return create_font_from_logfont(&lf, font);
831 else
833 int i;
834 for (i = 0; i < This->data->font_count; i++)
836 if (style == This->data->fonts[i]->style &&
837 weight == This->data->fonts[i]->weight &&
838 stretch == This->data->fonts[i]->stretch)
840 HRESULT hr;
841 hr = create_font_from_data(This->data->fonts[i], font);
842 if (SUCCEEDED(hr))
844 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
845 font_data->family = iface;
846 IDWriteFontFamily_AddRef(iface);
848 return hr;
851 return DWRITE_E_NOFONT;
855 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
856 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
858 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
859 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
860 return E_NOTIMPL;
863 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
864 dwritefontfamily_QueryInterface,
865 dwritefontfamily_AddRef,
866 dwritefontfamily_Release,
867 dwritefontfamily_GetFontCollection,
868 dwritefontfamily_GetFontCount,
869 dwritefontfamily_GetFont,
870 dwritefontfamily_GetFamilyNames,
871 dwritefontfamily_GetFirstMatchingFont,
872 dwritefontfamily_GetMatchingFonts
875 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
877 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
878 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
880 if (IsEqualIID(riid, &IID_IUnknown) ||
881 IsEqualIID(riid, &IID_IDWriteFontCollection))
883 *obj = iface;
884 IDWriteFontCollection_AddRef(iface);
885 return S_OK;
888 *obj = NULL;
889 return E_NOINTERFACE;
892 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
894 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
895 ULONG ref = InterlockedIncrement(&This->ref);
896 TRACE("(%p)->(%d)\n", This, ref);
897 return ref;
900 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
902 unsigned int i;
903 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
904 ULONG ref = InterlockedDecrement(&This->ref);
905 TRACE("(%p)->(%d)\n", This, ref);
907 if (!ref)
909 for (i = 0; i < This->count; i++)
910 heap_free(This->families[i]);
911 heap_free(This->families);
912 heap_free(This);
915 return ref;
918 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
920 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
921 TRACE("(%p)\n", This);
922 return This->count;
925 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
927 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
928 HRESULT hr;
929 IDWriteLocalizedStrings *familyname;
930 static const WCHAR enusW[] = {'e','n','-','u','s',0};
932 TRACE("(%p)->(%u %p)\n", This, index, family);
934 if (index >= This->count)
936 *family = NULL;
937 return E_FAIL;
940 hr = create_localizedstrings(&familyname);
941 if (FAILED(hr))
942 return hr;
943 add_localizedstring(familyname, enusW, This->families[index]);
945 return create_fontfamily(familyname, family);
948 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
950 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
951 UINT32 i;
953 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
955 for (i = 0; i < This->count; i++)
956 if (!strcmpW(This->families[i], name))
958 *index = i;
959 *exists = TRUE;
960 return S_OK;
963 *index = (UINT32)-1;
964 *exists = FALSE;
966 return S_OK;
969 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
971 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
972 FIXME("(%p)->(%p %p): stub\n", This, face, font);
973 return E_NOTIMPL;
976 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
977 dwritefontcollection_QueryInterface,
978 dwritefontcollection_AddRef,
979 dwritefontcollection_Release,
980 dwritefontcollection_GetFontFamilyCount,
981 dwritefontcollection_GetFontFamily,
982 dwritefontcollection_FindFamilyName,
983 dwritefontcollection_GetFontFromFontFace
986 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
988 /* check for duplicate family name */
989 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
991 /* double array length */
992 if (collection->count == collection->alloc)
994 collection->alloc *= 2;
995 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
998 collection->families[collection->count++] = heap_strdupW(family);
999 TRACE("family name %s\n", debugstr_w(family));
1001 return S_OK;
1004 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1006 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1007 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1010 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1012 struct dwrite_fontcollection *This;
1013 LOGFONTW lf;
1014 HDC hdc;
1016 *collection = NULL;
1018 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1019 if (!This) return E_OUTOFMEMORY;
1021 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1022 This->ref = 1;
1023 This->alloc = 50;
1024 This->count = 0;
1025 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1027 TRACE("building system font collection:\n");
1029 hdc = CreateCompatibleDC(0);
1030 memset(&lf, 0, sizeof(lf));
1031 lf.lfCharSet = DEFAULT_CHARSET;
1032 lf.lfPitchAndFamily = DEFAULT_PITCH;
1033 lf.lfFaceName[0] = 0;
1034 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1035 DeleteDC(hdc);
1037 *collection = &This->IDWriteFontCollection_iface;
1039 return S_OK;
1042 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family)
1044 struct dwrite_fontfamily *This;
1046 *family = NULL;
1048 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1049 if (!This) return E_OUTOFMEMORY;
1050 This->data = heap_alloc(sizeof(struct dwrite_fontfamily_data));
1051 if (!This->data)
1053 heap_free(This);
1054 return E_OUTOFMEMORY;
1057 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1058 This->ref = 1;
1059 This->data->font_count = 0;
1060 This->data->alloc = 2;
1061 This->data->fonts = heap_alloc(sizeof(*This->data->fonts) * 2);
1062 This->collection = NULL;
1063 This->data->familyname = familyname;
1065 *family = &This->IDWriteFontFamily_iface;
1067 return S_OK;
1070 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font)
1072 struct dwrite_font *This;
1073 *font = NULL;
1075 This = heap_alloc(sizeof(struct dwrite_font));
1076 if (!This) return E_OUTOFMEMORY;
1078 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
1079 This->ref = 1;
1080 This->face = NULL;
1081 This->family = NULL;
1082 This->is_system = FALSE;
1083 This->data = data;
1084 InterlockedIncrement(&This->data->ref);
1086 *font = &This->IDWriteFont_iface;
1088 return S_OK;
1091 static HRESULT create_font_base(IDWriteFont **font)
1093 struct dwrite_font_data *data;
1094 HRESULT ret;
1096 *font = NULL;
1097 data = heap_alloc(sizeof(*data));
1098 if (!data) return E_OUTOFMEMORY;
1100 data->ref = 0;
1101 data->face_data = NULL;
1103 ret = create_font_from_data( data, font );
1104 if (FAILED(ret)) heap_free( data );
1105 return ret;
1108 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1110 const WCHAR* facename, *familyname;
1111 IDWriteLocalizedStrings *name;
1112 struct dwrite_font *This;
1113 IDWriteFontFamily *family;
1114 OUTLINETEXTMETRICW *otm;
1115 HRESULT hr;
1116 HFONT hfont;
1117 HDC hdc;
1118 int ret;
1119 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1120 LPVOID tt_os2 = NULL;
1121 LPVOID tt_head = NULL;
1122 LPVOID tt_post = NULL;
1123 LONG size;
1125 hr = create_font_base(font);
1126 if (FAILED(hr))
1127 return hr;
1129 This = impl_from_IDWriteFont(*font);
1131 hfont = CreateFontIndirectW(logfont);
1132 if (!hfont)
1134 heap_free(This->data);
1135 heap_free(This);
1136 return DWRITE_E_NOFONT;
1139 hdc = CreateCompatibleDC(0);
1140 SelectObject(hdc, hfont);
1142 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1143 otm = heap_alloc(ret);
1144 if (!otm)
1146 heap_free(This->data);
1147 heap_free(This);
1148 DeleteDC(hdc);
1149 DeleteObject(hfont);
1150 return E_OUTOFMEMORY;
1152 otm->otmSize = ret;
1153 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1155 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1156 if (size != GDI_ERROR)
1158 tt_os2 = heap_alloc(size);
1159 GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size);
1161 size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0);
1162 if (size != GDI_ERROR)
1164 tt_head = heap_alloc(size);
1165 GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size);
1167 size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0);
1168 if (size != GDI_ERROR)
1170 tt_post = heap_alloc(size);
1171 GetFontData(hdc, MS_POST_TAG, 0, tt_post, size);
1174 get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style);
1175 heap_free(tt_os2);
1176 heap_free(tt_head);
1177 heap_free(tt_post);
1179 if (logfont->lfItalic)
1180 This->data->style = DWRITE_FONT_STYLE_ITALIC;
1182 DeleteDC(hdc);
1183 DeleteObject(hfont);
1185 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1186 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1187 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1189 hr = create_localizedstrings(&name);
1190 if (FAILED(hr))
1192 heap_free(This);
1193 return hr;
1195 add_localizedstring(name, enusW, familyname);
1196 hr = create_fontfamily(name, &family);
1198 heap_free(otm);
1199 if (hr != S_OK)
1201 heap_free(This->data);
1202 heap_free(This);
1203 return hr;
1206 This->is_system = TRUE;
1207 This->family = family;
1208 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1209 This->data->facename = heap_strdupW(logfont->lfFaceName);
1211 return S_OK;
1214 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1216 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1218 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1220 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1222 *obj = iface;
1223 IDWriteFontFile_AddRef(iface);
1224 return S_OK;
1227 *obj = NULL;
1228 return E_NOINTERFACE;
1231 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1233 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1234 ULONG ref = InterlockedIncrement(&This->ref);
1235 TRACE("(%p)->(%d)\n", This, ref);
1236 return ref;
1239 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1241 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1242 ULONG ref = InterlockedDecrement(&This->ref);
1244 TRACE("(%p)->(%d)\n", This, ref);
1246 if (!ref)
1248 IDWriteFontFileLoader_Release(This->loader);
1249 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1250 heap_free(This->reference_key);
1251 heap_free(This);
1254 return ref;
1257 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1259 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1260 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1261 *fontFileReferenceKey = This->reference_key;
1262 *fontFileReferenceKeySize = This->key_size;
1264 return S_OK;
1267 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1269 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1270 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1271 *fontFileLoader = This->loader;
1272 IDWriteFontFileLoader_AddRef(This->loader);
1274 return S_OK;
1277 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1279 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1280 IDWriteFontFileStream *stream;
1281 HRESULT hr;
1283 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1285 *isSupportedFontType = FALSE;
1286 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1287 if (fontFaceType)
1288 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1289 *numberOfFaces = 0;
1291 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1292 if (FAILED(hr))
1293 return S_OK;
1295 hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1297 /* TODO: Further Analysis */
1298 IDWriteFontFileStream_Release(stream);
1299 return S_OK;
1302 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1303 dwritefontfile_QueryInterface,
1304 dwritefontfile_AddRef,
1305 dwritefontfile_Release,
1306 dwritefontfile_GetReferenceKey,
1307 dwritefontfile_GetLoader,
1308 dwritefontfile_Analyze,
1311 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1313 struct dwrite_fontfile *This;
1315 This = heap_alloc(sizeof(struct dwrite_fontfile));
1316 if (!This) return E_OUTOFMEMORY;
1318 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1319 This->ref = 1;
1320 IDWriteFontFileLoader_AddRef(loader);
1321 This->loader = loader;
1322 This->stream = NULL;
1323 This->reference_key = heap_alloc(key_size);
1324 memcpy(This->reference_key, reference_key, key_size);
1325 This->key_size = key_size;
1327 *font_file = &This->IDWriteFontFile_iface;
1329 return S_OK;
1332 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)
1334 int i;
1335 struct dwrite_fontface *This;
1336 HRESULT hr = S_OK;
1338 *font_face = NULL;
1340 This = heap_alloc(sizeof(struct dwrite_fontface));
1341 if (!This) return E_OUTOFMEMORY;
1342 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1343 if (!This->data)
1345 heap_free(This);
1346 return E_OUTOFMEMORY;
1349 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
1350 This->ref = 1;
1351 This->data->ref = 1;
1352 This->data->type = facetype;
1353 This->data->file_count = files_number;
1354 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1355 This->cmap.data = NULL;
1356 This->cmap.context = NULL;
1357 This->cmap.size = 0;
1358 /* Verify font file streams */
1359 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1361 IDWriteFontFileStream *stream;
1362 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1363 if (SUCCEEDED(hr))
1364 IDWriteFontFileStream_Release(stream);
1366 if (FAILED(hr))
1368 heap_free(This->data->files);
1369 heap_free(This->data);
1370 heap_free(This);
1371 return hr;
1373 for (i = 0; i < This->data->file_count; i++)
1375 This->data->files[i] = font_files[i];
1376 IDWriteFontFile_AddRef(font_files[i]);
1379 This->data->index = index;
1380 This->data->simulations = sim_flags;
1381 This->is_system = FALSE;
1383 *font_face = &This->IDWriteFontFace_iface;
1385 return S_OK;
1388 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1390 struct dwrite_localfontfilestream
1392 IDWriteFontFileStream IDWriteFontFileStream_iface;
1393 LONG ref;
1395 HANDLE handle;
1398 struct dwrite_localfontfileloader {
1399 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1400 LONG ref;
1403 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1405 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1408 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1410 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1413 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1415 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1416 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1417 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1419 *obj = iface;
1420 IDWriteFontFileStream_AddRef(iface);
1421 return S_OK;
1424 *obj = NULL;
1425 return E_NOINTERFACE;
1428 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1430 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1431 ULONG ref = InterlockedIncrement(&This->ref);
1432 TRACE("(%p)->(%d)\n", This, ref);
1433 return ref;
1436 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1438 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1439 ULONG ref = InterlockedDecrement(&This->ref);
1441 TRACE("(%p)->(%d)\n", This, ref);
1443 if (!ref)
1445 if (This->handle != INVALID_HANDLE_VALUE)
1446 CloseHandle(This->handle);
1447 heap_free(This);
1450 return ref;
1453 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1455 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1456 LARGE_INTEGER distance;
1457 DWORD bytes = fragment_size;
1458 DWORD read;
1460 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1461 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1463 *fragment_context = NULL;
1464 distance.QuadPart = offset;
1465 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1466 return E_FAIL;
1467 *fragment_start = *fragment_context = heap_alloc(bytes);
1468 if (!*fragment_context)
1469 return E_FAIL;
1470 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1472 heap_free(*fragment_context);
1473 return E_FAIL;
1476 return S_OK;
1479 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1481 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1482 TRACE("(%p)->(%p)\n", This, fragment_context);
1483 heap_free(fragment_context);
1486 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1488 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1489 LARGE_INTEGER li;
1490 TRACE("(%p)->(%p)\n",This, size);
1491 GetFileSizeEx(This->handle, &li);
1492 *size = li.QuadPart;
1493 return S_OK;
1496 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1498 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1499 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1500 *last_writetime = 0;
1501 return E_NOTIMPL;
1504 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1506 localfontfilestream_QueryInterface,
1507 localfontfilestream_AddRef,
1508 localfontfilestream_Release,
1509 localfontfilestream_ReadFileFragment,
1510 localfontfilestream_ReleaseFileFragment,
1511 localfontfilestream_GetFileSize,
1512 localfontfilestream_GetLastWriteTime
1515 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1517 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1518 if (!This)
1519 return E_OUTOFMEMORY;
1521 This->ref = 1;
1522 This->handle = handle;
1523 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1525 *iface = &This->IDWriteFontFileStream_iface;
1526 return S_OK;
1529 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1531 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1533 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1535 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1537 *obj = iface;
1538 IDWriteLocalFontFileLoader_AddRef(iface);
1539 return S_OK;
1542 *obj = NULL;
1543 return E_NOINTERFACE;
1546 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1548 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1549 ULONG ref = InterlockedIncrement(&This->ref);
1550 TRACE("(%p)->(%d)\n", This, ref);
1551 return ref;
1554 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1556 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1557 ULONG ref = InterlockedDecrement(&This->ref);
1559 TRACE("(%p)->(%d)\n", This, ref);
1561 if (!ref)
1562 heap_free(This);
1564 return ref;
1567 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1569 HANDLE handle;
1570 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1571 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1573 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1575 TRACE("name: %s\n",debugstr_w(name));
1576 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1577 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1579 if (handle == INVALID_HANDLE_VALUE)
1580 return E_FAIL;
1582 return create_localfontfilestream(handle, fontFileStream);
1585 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1587 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1588 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1589 *length = key_size;
1590 return S_OK;
1593 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1595 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1596 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1597 if (length < key_size)
1598 return E_INVALIDARG;
1599 lstrcpynW((WCHAR*)key, path, key_size);
1600 return S_OK;
1603 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1605 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1606 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1607 return E_NOTIMPL;
1610 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1611 localfontfileloader_QueryInterface,
1612 localfontfileloader_AddRef,
1613 localfontfileloader_Release,
1614 localfontfileloader_CreateStreamFromKey,
1615 localfontfileloader_GetFilePathLengthFromKey,
1616 localfontfileloader_GetFilePathFromKey,
1617 localfontfileloader_GetLastWriteTimeFromKey
1620 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1622 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1623 if (!This)
1624 return E_OUTOFMEMORY;
1626 This->ref = 1;
1627 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1629 *iface = &This->IDWriteLocalFontFileLoader_iface;
1630 return S_OK;