shlwapi: Remove unnecessary internal function SHLWAPI_DupSharedHandle.
[wine/wine-gecko.git] / dlls / dwrite / font.c
blob25b47ef2243300585468e565f41e15d441924316
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_MAKE_TAG(ch0, ch1, ch2, ch3) \
29 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
30 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
32 #define MS_HEAD_TAG MS_MAKE_TAG('h','e','a','d')
33 #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
34 #define MS_POST_TAG MS_MAKE_TAG('p','o','s','t')
35 #define MS_CMAP_TAG MS_MAKE_TAG('c','m','a','p')
37 struct dwrite_fontface_data {
38 LONG ref;
40 DWRITE_FONT_FACE_TYPE type;
41 UINT32 file_count;
42 IDWriteFontFile ** files;
43 DWRITE_FONT_SIMULATIONS simulations;
44 UINT32 index;
47 struct dwrite_font_data {
48 LONG ref;
50 DWRITE_FONT_STYLE style;
51 DWRITE_FONT_STRETCH stretch;
52 DWRITE_FONT_WEIGHT weight;
53 DWRITE_FONT_SIMULATIONS simulations;
54 DWRITE_FONT_METRICS metrics;
56 struct dwrite_fontface_data *face_data;
58 WCHAR *facename;
61 struct dwrite_fontfamily_data {
62 IDWriteLocalizedStrings *familyname;
64 struct dwrite_font_data **fonts;
65 UINT32 font_count;
66 UINT32 alloc;
69 struct dwrite_fontcollection {
70 IDWriteFontCollection IDWriteFontCollection_iface;
71 LONG ref;
73 WCHAR **families;
74 UINT32 count;
75 int 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 IDWriteFont IDWriteFont_iface;
89 LONG ref;
91 BOOL is_system;
92 IDWriteFontFamily *family;
93 IDWriteFontFace *face;
95 struct dwrite_font_data *data;
98 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
100 struct dwrite_fonttable {
101 UINT32 magic;
102 LPVOID context;
103 UINT32 file_index;
106 struct dwrite_fontface {
107 IDWriteFontFace IDWriteFontFace_iface;
108 LONG ref;
110 struct dwrite_fontface_data *data;
112 LPVOID CMAP_table;
113 LPVOID CMAP_context;
114 DWORD CMAP_size;
116 BOOL is_system;
117 LOGFONTW logfont;
120 struct dwrite_fontfile {
121 IDWriteFontFile IDWriteFontFile_iface;
122 LONG ref;
124 IDWriteFontFileLoader *loader;
125 void *reference_key;
126 UINT32 key_size;
127 IDWriteFontFileStream *stream;
130 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family);
131 static HRESULT create_font_base(IDWriteFont **font);
132 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font);
134 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
136 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
139 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
141 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
144 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
146 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
149 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
151 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
154 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
156 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
159 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
161 HRESULT hr;
162 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
163 if (!This->stream)
165 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
166 if (FAILED(hr))
167 return hr;
169 if (This->stream)
171 IDWriteFontFileStream_AddRef(This->stream);
172 *stream = This->stream;
173 return S_OK;
175 return E_FAIL;
178 static VOID _free_fontface_data(struct dwrite_fontface_data *data)
180 int i;
181 if (!data)
182 return;
183 i = InterlockedDecrement(&data->ref);
184 if (i > 0)
185 return;
186 for (i = 0; i < data->file_count; i++)
187 IDWriteFontFile_Release(data->files[i]);
188 heap_free(data->files);
189 heap_free(data);
192 static VOID _free_font_data(struct dwrite_font_data *data)
194 int i;
195 if (!data)
196 return;
197 i = InterlockedDecrement(&data->ref);
198 if (i > 0)
199 return;
200 _free_fontface_data(data->face_data);
201 heap_free(data->facename);
202 heap_free(data);
205 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
207 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
209 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
211 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
213 *obj = iface;
214 IDWriteFontFace_AddRef(iface);
215 return S_OK;
218 *obj = NULL;
219 return E_NOINTERFACE;
222 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
224 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
225 ULONG ref = InterlockedIncrement(&This->ref);
226 TRACE("(%p)->(%d)\n", This, ref);
227 return ref;
230 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
232 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
233 ULONG ref = InterlockedDecrement(&This->ref);
235 TRACE("(%p)->(%d)\n", This, ref);
237 if (!ref)
239 if (This->CMAP_context)
240 IDWriteFontFace_ReleaseFontTable(iface, This->CMAP_context);
241 _free_fontface_data(This->data);
242 heap_free(This);
245 return ref;
248 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
250 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
251 TRACE("(%p)\n", This);
252 return This->data->type;
255 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
256 IDWriteFontFile **fontfiles)
258 int i;
259 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
260 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
261 if (fontfiles == NULL)
263 *number_of_files = This->data->file_count;
264 return S_OK;
266 if (*number_of_files < This->data->file_count)
267 return E_INVALIDARG;
269 for (i = 0; i < This->data->file_count; i++)
271 IDWriteFontFile_AddRef(This->data->files[i]);
272 fontfiles[i] = This->data->files[i];
275 return S_OK;
278 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
280 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
281 TRACE("(%p)\n", This);
282 return This->data->index;
285 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
287 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
288 TRACE("(%p)\n", This);
289 return This->data->simulations;
292 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
294 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
295 FIXME("(%p): stub\n", This);
296 return FALSE;
299 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
301 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
302 FIXME("(%p)->(%p): stub\n", This, metrics);
305 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
307 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
308 FIXME("(%p): stub\n", This);
309 return 0;
312 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
313 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
315 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
316 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
317 return E_NOTIMPL;
320 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
321 UINT32 count, UINT16 *glyph_indices)
323 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
324 unsigned int i;
326 if (This->is_system)
328 HFONT hfont;
329 WCHAR *str;
330 HDC hdc;
332 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
334 str = heap_alloc(count*sizeof(WCHAR));
335 if (!str) return E_OUTOFMEMORY;
337 for (i = 0; i < count; i++)
338 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
340 hdc = CreateCompatibleDC(0);
341 hfont = CreateFontIndirectW(&This->logfont);
342 SelectObject(hdc, hfont);
344 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
345 heap_free(str);
347 DeleteDC(hdc);
348 DeleteObject(hfont);
350 return S_OK;
352 else
354 HRESULT hr;
355 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
356 if (!This->CMAP_table)
358 BOOL exists = FALSE;
359 hr = IDWriteFontFace_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->CMAP_table, &This->CMAP_size, &This->CMAP_context, &exists);
360 if (FAILED(hr) || !exists)
362 ERR("Font does not have a CMAP table\n");
363 return E_FAIL;
367 for (i = 0; i < count; i++)
369 OpenType_CMAP_GetGlyphIndex(This->CMAP_table, codepoints[i], &glyph_indices[i], 0);
371 return S_OK;
375 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
376 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
378 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
379 if (This->is_system)
381 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
382 return E_NOTIMPL;
384 else
386 HRESULT hr = S_OK;
387 int i;
388 struct dwrite_fonttable *table;
390 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
392 table = heap_alloc(sizeof(struct dwrite_fonttable));
393 if (!table)
394 return E_OUTOFMEMORY;
395 table->magic = DWRITE_FONTTABLE_MAGIC;
397 *exists = FALSE;
398 for (i = 0; i < This->data->file_count && !(*exists); i++)
400 IDWriteFontFileStream *stream;
401 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
402 if (FAILED(hr))
403 continue;
404 table->file_index = i;
406 hr = find_font_table(stream, This->data->index, table_tag, table_data, &table->context, table_size, exists);
408 IDWriteFontFileStream_Release(stream);
410 if (FAILED(hr) && !*exists)
411 heap_free(table);
412 else
413 *context = (LPVOID)table;
414 return hr;
418 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
420 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
421 struct dwrite_fonttable *table = (struct dwrite_fonttable *)table_context;
422 IDWriteFontFileStream *stream;
423 HRESULT hr;
424 TRACE("(%p)->(%p)\n", This, table_context);
426 if (table->magic != DWRITE_FONTTABLE_MAGIC)
428 TRACE("Invalid table magic\n");
429 return;
432 hr = _dwritefontfile_GetFontFileStream(This->data->files[table->file_index], &stream);
433 if (FAILED(hr))
434 return;
435 IDWriteFontFileStream_ReleaseFileFragment(stream, table->context);
436 IDWriteFontFileStream_Release(stream);
437 heap_free(table);
440 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
441 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
442 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
444 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
445 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
446 glyph_count, is_sideways, is_rtl, geometrysink);
447 return E_NOTIMPL;
450 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
451 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
453 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
454 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
455 return E_NOTIMPL;
458 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
459 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
461 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
462 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
463 return E_NOTIMPL;
466 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
467 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
468 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
470 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
471 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
472 glyph_count, metrics, is_sideways);
473 return E_NOTIMPL;
476 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
477 dwritefontface_QueryInterface,
478 dwritefontface_AddRef,
479 dwritefontface_Release,
480 dwritefontface_GetType,
481 dwritefontface_GetFiles,
482 dwritefontface_GetIndex,
483 dwritefontface_GetSimulations,
484 dwritefontface_IsSymbolFont,
485 dwritefontface_GetMetrics,
486 dwritefontface_GetGlyphCount,
487 dwritefontface_GetDesignGlyphMetrics,
488 dwritefontface_GetGlyphIndices,
489 dwritefontface_TryGetFontTable,
490 dwritefontface_ReleaseFontTable,
491 dwritefontface_GetGlyphRunOutline,
492 dwritefontface_GetRecommendedRenderingMode,
493 dwritefontface_GetGdiCompatibleMetrics,
494 dwritefontface_GetGdiCompatibleGlyphMetrics
497 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
499 struct dwrite_fontface *This;
501 *face = NULL;
503 This = heap_alloc(sizeof(struct dwrite_fontface));
504 if (!This) return E_OUTOFMEMORY;
505 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
506 if (!This->data)
508 heap_free(This);
509 return E_OUTOFMEMORY;
512 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
513 This->ref = 1;
514 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
515 This->data->file_count = 0;
516 This->data->files = NULL;
517 This->data->index = 0;
518 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
519 This->CMAP_table = NULL;
520 This->CMAP_context = NULL;
521 This->CMAP_size = 0;
523 This->is_system = TRUE;
524 memset(&This->logfont, 0, sizeof(This->logfont));
525 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
526 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
527 This->logfont.lfWeight = font->data->weight;
528 strcpyW(This->logfont.lfFaceName, font->data->facename);
530 *face = &This->IDWriteFontFace_iface;
532 return S_OK;
535 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
537 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace(face);
539 *logfont = fontface->logfont;
541 return S_OK;
544 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
546 struct dwrite_font *This = impl_from_IDWriteFont(iface);
548 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
550 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
552 *obj = iface;
553 IDWriteFont_AddRef(iface);
554 return S_OK;
557 *obj = NULL;
558 return E_NOINTERFACE;
561 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
563 struct dwrite_font *This = impl_from_IDWriteFont(iface);
564 ULONG ref = InterlockedIncrement(&This->ref);
565 TRACE("(%p)->(%d)\n", This, ref);
566 return ref;
569 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
571 struct dwrite_font *This = impl_from_IDWriteFont(iface);
572 ULONG ref = InterlockedDecrement(&This->ref);
574 TRACE("(%p)->(%d)\n", This, ref);
576 if (!ref)
578 if (This->face) IDWriteFontFace_Release(This->face);
579 if (This->family) IDWriteFontFamily_Release(This->family);
580 _free_font_data(This->data);
581 heap_free(This);
584 return ref;
587 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
589 struct dwrite_font *This = impl_from_IDWriteFont(iface);
590 TRACE("(%p)->(%p)\n", This, family);
592 *family = This->family;
593 IDWriteFontFamily_AddRef(*family);
594 return S_OK;
597 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
599 struct dwrite_font *This = impl_from_IDWriteFont(iface);
600 TRACE("(%p)\n", This);
601 return This->data->weight;
604 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
606 struct dwrite_font *This = impl_from_IDWriteFont(iface);
607 TRACE("(%p)\n", This);
608 return This->data->stretch;
611 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
613 struct dwrite_font *This = impl_from_IDWriteFont(iface);
614 TRACE("(%p)\n", This);
615 return This->data->style;
618 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
620 struct dwrite_font *This = impl_from_IDWriteFont(iface);
621 FIXME("(%p): stub\n", This);
622 return FALSE;
625 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
627 struct dwrite_font *This = impl_from_IDWriteFont(iface);
628 FIXME("(%p)->(%p): stub\n", This, names);
629 return E_NOTIMPL;
632 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
633 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
635 struct dwrite_font *This = impl_from_IDWriteFont(iface);
636 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
637 return E_NOTIMPL;
640 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
642 struct dwrite_font *This = impl_from_IDWriteFont(iface);
643 TRACE("(%p)\n", This);
644 return This->data->simulations;
647 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
649 struct dwrite_font *This = impl_from_IDWriteFont(iface);
651 TRACE("(%p)->(%p)\n", This, metrics);
652 *metrics = This->data->metrics;
655 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
657 struct dwrite_font *This = impl_from_IDWriteFont(iface);
658 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
659 return E_NOTIMPL;
662 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
664 struct dwrite_font *This = impl_from_IDWriteFont(iface);
666 if (This->is_system)
668 TRACE("(%p)->(%p)\n", This, face);
670 if (!This->face)
672 HRESULT hr = create_system_fontface(This, &This->face);
673 if (FAILED(hr)) return hr;
676 *face = This->face;
677 IDWriteFontFace_AddRef(*face);
679 return S_OK;
681 else
683 TRACE("(%p)->(%p)\n", This, face);
685 if (!This->face)
687 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);
688 if (FAILED(hr)) return hr;
691 *face = This->face;
692 IDWriteFontFace_AddRef(*face);
694 return S_OK;
698 static const IDWriteFontVtbl dwritefontvtbl = {
699 dwritefont_QueryInterface,
700 dwritefont_AddRef,
701 dwritefont_Release,
702 dwritefont_GetFontFamily,
703 dwritefont_GetWeight,
704 dwritefont_GetStretch,
705 dwritefont_GetStyle,
706 dwritefont_IsSymbolFont,
707 dwritefont_GetFaceNames,
708 dwritefont_GetInformationalStrings,
709 dwritefont_GetSimulations,
710 dwritefont_GetMetrics,
711 dwritefont_HasCharacter,
712 dwritefont_CreateFontFace
715 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
717 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
718 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
720 if (IsEqualIID(riid, &IID_IUnknown) ||
721 IsEqualIID(riid, &IID_IDWriteFontList) ||
722 IsEqualIID(riid, &IID_IDWriteFontFamily))
724 *obj = iface;
725 IDWriteFontFamily_AddRef(iface);
726 return S_OK;
729 *obj = NULL;
730 return E_NOINTERFACE;
733 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
735 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
736 ULONG ref = InterlockedIncrement(&This->ref);
737 TRACE("(%p)->(%d)\n", This, ref);
738 return ref;
741 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
743 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
744 ULONG ref = InterlockedDecrement(&This->ref);
746 TRACE("(%p)->(%d)\n", This, ref);
748 if (!ref)
750 int i;
751 IDWriteLocalizedStrings_Release(This->data->familyname);
753 if (This->collection)
754 IDWriteFontCollection_Release(This->collection);
755 for (i = 0; i < This->data->font_count; i++)
756 _free_font_data(This->data->fonts[i]);
757 heap_free(This->data->fonts);
758 heap_free(This->data);
759 heap_free(This);
762 return ref;
765 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
767 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
768 TRACE("(%p)->(%p)\n", This, collection);
769 if (This->collection)
771 IDWriteFontCollection_AddRef(This->collection);
772 *collection = This->collection;
773 return S_OK;
775 else
776 return E_NOTIMPL;
779 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
781 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
782 TRACE("(%p)\n", This);
783 return This->data->font_count;
786 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
788 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
789 TRACE("(%p)->(%u %p)\n", This, index, font);
790 if (This->data->font_count > 0)
792 HRESULT hr;
793 if (index >= This->data->font_count)
794 return E_INVALIDARG;
795 hr = create_font_from_data(This->data->fonts[index], font);
796 if (SUCCEEDED(hr))
798 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
799 font_data->family = iface;
800 IDWriteFontFamily_AddRef(iface);
802 return hr;
804 else
805 return E_NOTIMPL;
808 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
810 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
811 return clone_localizedstring(This->data->familyname, names);
814 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
815 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
817 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
818 LOGFONTW lf;
820 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
822 /* fallback for system font collections */
823 if (This->data->font_count == 0)
825 memset(&lf, 0, sizeof(lf));
826 lf.lfWeight = weight;
827 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
828 IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE);
830 return create_font_from_logfont(&lf, font);
832 else
834 int i;
835 for (i = 0; i < This->data->font_count; i++)
837 if (style == This->data->fonts[i]->style &&
838 weight == This->data->fonts[i]->weight &&
839 stretch == This->data->fonts[i]->stretch)
841 HRESULT hr;
842 hr = create_font_from_data(This->data->fonts[i], font);
843 if (SUCCEEDED(hr))
845 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
846 font_data->family = iface;
847 IDWriteFontFamily_AddRef(iface);
849 return hr;
852 return DWRITE_E_NOFONT;
856 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
857 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
859 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
860 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
861 return E_NOTIMPL;
864 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
865 dwritefontfamily_QueryInterface,
866 dwritefontfamily_AddRef,
867 dwritefontfamily_Release,
868 dwritefontfamily_GetFontCollection,
869 dwritefontfamily_GetFontCount,
870 dwritefontfamily_GetFont,
871 dwritefontfamily_GetFamilyNames,
872 dwritefontfamily_GetFirstMatchingFont,
873 dwritefontfamily_GetMatchingFonts
876 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
878 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
879 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
881 if (IsEqualIID(riid, &IID_IUnknown) ||
882 IsEqualIID(riid, &IID_IDWriteFontCollection))
884 *obj = iface;
885 IDWriteFontCollection_AddRef(iface);
886 return S_OK;
889 *obj = NULL;
890 return E_NOINTERFACE;
893 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
895 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
896 ULONG ref = InterlockedIncrement(&This->ref);
897 TRACE("(%p)->(%d)\n", This, ref);
898 return ref;
901 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
903 unsigned int i;
904 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
905 ULONG ref = InterlockedDecrement(&This->ref);
906 TRACE("(%p)->(%d)\n", This, ref);
908 if (!ref)
910 for (i = 0; i < This->count; i++)
911 heap_free(This->families[i]);
912 heap_free(This->families);
913 heap_free(This);
916 return ref;
919 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
921 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
922 TRACE("(%p)\n", This);
923 return This->count;
926 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
928 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
929 HRESULT hr;
930 IDWriteLocalizedStrings *familyname;
931 static const WCHAR enusW[] = {'e','n','-','u','s',0};
933 TRACE("(%p)->(%u %p)\n", This, index, family);
935 if (index >= This->count)
937 *family = NULL;
938 return E_FAIL;
941 hr = create_localizedstrings(&familyname);
942 if (FAILED(hr))
943 return hr;
944 add_localizedstring(familyname, enusW, This->families[index]);
946 return create_fontfamily(familyname, family);
949 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
951 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
952 UINT32 i;
954 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
956 for (i = 0; i < This->count; i++)
957 if (!strcmpW(This->families[i], name))
959 *index = i;
960 *exists = TRUE;
961 return S_OK;
964 *index = (UINT32)-1;
965 *exists = FALSE;
967 return S_OK;
970 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
972 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
973 FIXME("(%p)->(%p %p): stub\n", This, face, font);
974 return E_NOTIMPL;
977 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
978 dwritefontcollection_QueryInterface,
979 dwritefontcollection_AddRef,
980 dwritefontcollection_Release,
981 dwritefontcollection_GetFontFamilyCount,
982 dwritefontcollection_GetFontFamily,
983 dwritefontcollection_FindFamilyName,
984 dwritefontcollection_GetFontFromFontFace
987 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
989 /* check for duplicate family name */
990 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
992 /* double array length */
993 if (collection->count == collection->alloc)
995 collection->alloc *= 2;
996 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
999 collection->families[collection->count++] = heap_strdupW(family);
1000 TRACE("family name %s\n", debugstr_w(family));
1002 return S_OK;
1005 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1007 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1008 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1011 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1013 struct dwrite_fontcollection *This;
1014 LOGFONTW lf;
1015 HDC hdc;
1017 *collection = NULL;
1019 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1020 if (!This) return E_OUTOFMEMORY;
1022 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1023 This->ref = 1;
1024 This->alloc = 50;
1025 This->count = 0;
1026 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1028 TRACE("building system font collection:\n");
1030 hdc = CreateCompatibleDC(0);
1031 memset(&lf, 0, sizeof(lf));
1032 lf.lfCharSet = DEFAULT_CHARSET;
1033 lf.lfPitchAndFamily = DEFAULT_PITCH;
1034 lf.lfFaceName[0] = 0;
1035 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1036 DeleteDC(hdc);
1038 *collection = &This->IDWriteFontCollection_iface;
1040 return S_OK;
1043 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family)
1045 struct dwrite_fontfamily *This;
1047 *family = NULL;
1049 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1050 if (!This) return E_OUTOFMEMORY;
1051 This->data = heap_alloc(sizeof(struct dwrite_fontfamily_data));
1052 if (!This->data)
1054 heap_free(This);
1055 return E_OUTOFMEMORY;
1058 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1059 This->ref = 1;
1060 This->data->font_count = 0;
1061 This->data->alloc = 2;
1062 This->data->fonts = heap_alloc(sizeof(*This->data->fonts) * 2);
1063 This->collection = NULL;
1064 This->data->familyname = familyname;
1066 *family = &This->IDWriteFontFamily_iface;
1068 return S_OK;
1071 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font)
1073 struct dwrite_font *This;
1074 *font = NULL;
1076 This = heap_alloc(sizeof(struct dwrite_font));
1077 if (!This) return E_OUTOFMEMORY;
1079 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
1080 This->ref = 1;
1081 This->face = NULL;
1082 This->family = NULL;
1083 This->is_system = FALSE;
1084 This->data = data;
1085 InterlockedIncrement(&This->data->ref);
1087 *font = &This->IDWriteFont_iface;
1089 return S_OK;
1092 static HRESULT create_font_base(IDWriteFont **font)
1094 struct dwrite_font_data *data;
1095 HRESULT ret;
1097 *font = NULL;
1098 data = heap_alloc(sizeof(*data));
1099 if (!data) return E_OUTOFMEMORY;
1101 data->ref = 0;
1102 data->face_data = NULL;
1104 ret = create_font_from_data( data, font );
1105 if (FAILED(ret)) heap_free( data );
1106 return ret;
1109 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1111 const WCHAR* facename, *familyname;
1112 IDWriteLocalizedStrings *name;
1113 struct dwrite_font *This;
1114 IDWriteFontFamily *family;
1115 OUTLINETEXTMETRICW *otm;
1116 HRESULT hr;
1117 HFONT hfont;
1118 HDC hdc;
1119 int ret;
1120 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1121 LPVOID tt_os2 = NULL;
1122 LPVOID tt_head = NULL;
1123 LPVOID tt_post = NULL;
1124 LONG size;
1126 hr = create_font_base(font);
1127 if (FAILED(hr))
1128 return hr;
1130 This = impl_from_IDWriteFont(*font);
1132 hfont = CreateFontIndirectW(logfont);
1133 if (!hfont)
1135 heap_free(This->data);
1136 heap_free(This);
1137 return DWRITE_E_NOFONT;
1140 hdc = CreateCompatibleDC(0);
1141 SelectObject(hdc, hfont);
1143 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1144 otm = heap_alloc(ret);
1145 if (!otm)
1147 heap_free(This->data);
1148 heap_free(This);
1149 DeleteDC(hdc);
1150 DeleteObject(hfont);
1151 return E_OUTOFMEMORY;
1153 otm->otmSize = ret;
1154 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1156 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1157 if (size != GDI_ERROR)
1159 tt_os2 = heap_alloc(size);
1160 GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size);
1162 size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0);
1163 if (size != GDI_ERROR)
1165 tt_head = heap_alloc(size);
1166 GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size);
1168 size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0);
1169 if (size != GDI_ERROR)
1171 tt_post = heap_alloc(size);
1172 GetFontData(hdc, MS_POST_TAG, 0, tt_post, size);
1175 get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style);
1176 heap_free(tt_os2);
1177 heap_free(tt_head);
1178 heap_free(tt_post);
1180 if (logfont->lfItalic)
1181 This->data->style = DWRITE_FONT_STYLE_ITALIC;
1183 DeleteDC(hdc);
1184 DeleteObject(hfont);
1186 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1187 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1188 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1190 hr = create_localizedstrings(&name);
1191 if (FAILED(hr))
1193 heap_free(This);
1194 return hr;
1196 add_localizedstring(name, enusW, familyname);
1197 hr = create_fontfamily(name, &family);
1199 heap_free(otm);
1200 if (hr != S_OK)
1202 heap_free(This->data);
1203 heap_free(This);
1204 return hr;
1207 This->is_system = TRUE;
1208 This->family = family;
1209 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1210 This->data->facename = heap_strdupW(logfont->lfFaceName);
1212 return S_OK;
1215 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1217 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1219 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1221 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1223 *obj = iface;
1224 IDWriteFontFile_AddRef(iface);
1225 return S_OK;
1228 *obj = NULL;
1229 return E_NOINTERFACE;
1232 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1234 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1235 ULONG ref = InterlockedIncrement(&This->ref);
1236 TRACE("(%p)->(%d)\n", This, ref);
1237 return ref;
1240 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1242 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1243 ULONG ref = InterlockedDecrement(&This->ref);
1245 TRACE("(%p)->(%d)\n", This, ref);
1247 if (!ref)
1249 IDWriteFontFileLoader_Release(This->loader);
1250 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1251 heap_free(This->reference_key);
1252 heap_free(This);
1255 return ref;
1258 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1260 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1261 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1262 *fontFileReferenceKey = This->reference_key;
1263 *fontFileReferenceKeySize = This->key_size;
1265 return S_OK;
1268 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1270 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1271 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1272 *fontFileLoader = This->loader;
1273 IDWriteFontFileLoader_AddRef(This->loader);
1275 return S_OK;
1278 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1280 HRESULT hr;
1281 const void *font_data;
1282 void *context;
1283 IDWriteFontFileStream *stream;
1285 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1286 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1288 *isSupportedFontType = FALSE;
1289 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1290 if (fontFaceType)
1291 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1292 *numberOfFaces = 0;
1294 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1295 if (FAILED(hr))
1296 return S_OK;
1297 hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, 28, &context);
1298 if (SUCCEEDED(hr))
1300 hr = analyze_opentype_font(font_data, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1301 IDWriteFontFileStream_ReleaseFileFragment(stream, context);
1303 /* TODO: Further Analysis */
1304 IDWriteFontFileStream_Release(stream);
1305 return S_OK;
1308 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1309 dwritefontfile_QueryInterface,
1310 dwritefontfile_AddRef,
1311 dwritefontfile_Release,
1312 dwritefontfile_GetReferenceKey,
1313 dwritefontfile_GetLoader,
1314 dwritefontfile_Analyze,
1317 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1319 struct dwrite_fontfile *This;
1321 This = heap_alloc(sizeof(struct dwrite_fontfile));
1322 if (!This) return E_OUTOFMEMORY;
1324 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1325 This->ref = 1;
1326 IDWriteFontFileLoader_AddRef(loader);
1327 This->loader = loader;
1328 This->stream = NULL;
1329 This->reference_key = heap_alloc(key_size);
1330 memcpy(This->reference_key, reference_key, key_size);
1331 This->key_size = key_size;
1333 *font_file = &This->IDWriteFontFile_iface;
1335 return S_OK;
1338 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)
1340 int i;
1341 struct dwrite_fontface *This;
1342 HRESULT hr = S_OK;
1344 *font_face = NULL;
1346 This = heap_alloc(sizeof(struct dwrite_fontface));
1347 if (!This) return E_OUTOFMEMORY;
1348 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1349 if (!This->data)
1351 heap_free(This);
1352 return E_OUTOFMEMORY;
1355 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
1356 This->ref = 1;
1357 This->data->ref = 1;
1358 This->data->type = facetype;
1359 This->data->file_count = files_number;
1360 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1361 This->CMAP_table = NULL;
1362 This->CMAP_context = NULL;
1363 This->CMAP_size = 0;
1364 /* Verify font file streams */
1365 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1367 IDWriteFontFileStream *stream;
1368 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1369 if (SUCCEEDED(hr))
1370 IDWriteFontFileStream_Release(stream);
1372 if (FAILED(hr))
1374 heap_free(This->data->files);
1375 heap_free(This->data);
1376 heap_free(This);
1377 return hr;
1379 for (i = 0; i < This->data->file_count; i++)
1381 This->data->files[i] = font_files[i];
1382 IDWriteFontFile_AddRef(font_files[i]);
1385 This->data->index = index;
1386 This->data->simulations = sim_flags;
1387 This->is_system = FALSE;
1389 *font_face = &This->IDWriteFontFace_iface;
1391 return S_OK;
1394 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1396 struct dwrite_localfontfilestream
1398 IDWriteFontFileStream IDWriteFontFileStream_iface;
1399 LONG ref;
1401 HANDLE handle;
1404 struct dwrite_localfontfileloader {
1405 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1406 LONG ref;
1409 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1411 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1414 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1416 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1419 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1421 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1422 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1423 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1425 *obj = iface;
1426 IDWriteFontFileStream_AddRef(iface);
1427 return S_OK;
1430 *obj = NULL;
1431 return E_NOINTERFACE;
1434 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1436 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1437 ULONG ref = InterlockedIncrement(&This->ref);
1438 TRACE("(%p)->(%d)\n", This, ref);
1439 return ref;
1442 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1444 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1445 ULONG ref = InterlockedDecrement(&This->ref);
1447 TRACE("(%p)->(%d)\n", This, ref);
1449 if (!ref)
1451 if (This->handle != INVALID_HANDLE_VALUE)
1452 CloseHandle(This->handle);
1453 heap_free(This);
1456 return ref;
1459 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1461 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1462 LARGE_INTEGER distance;
1463 DWORD bytes = fragment_size;
1464 DWORD read;
1466 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1467 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1469 *fragment_context = NULL;
1470 distance.QuadPart = offset;
1471 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1472 return E_FAIL;
1473 *fragment_start = *fragment_context = heap_alloc(bytes);
1474 if (!*fragment_context)
1475 return E_FAIL;
1476 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1478 heap_free(*fragment_context);
1479 return E_FAIL;
1482 return S_OK;
1485 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1487 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1488 TRACE("(%p)->(%p)\n", This, fragment_context);
1489 heap_free(fragment_context);
1492 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1494 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1495 LARGE_INTEGER li;
1496 TRACE("(%p)->(%p)\n",This, size);
1497 GetFileSizeEx(This->handle, &li);
1498 *size = li.QuadPart;
1499 return S_OK;
1502 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1504 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1505 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1506 *last_writetime = 0;
1507 return E_NOTIMPL;
1510 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1512 localfontfilestream_QueryInterface,
1513 localfontfilestream_AddRef,
1514 localfontfilestream_Release,
1515 localfontfilestream_ReadFileFragment,
1516 localfontfilestream_ReleaseFileFragment,
1517 localfontfilestream_GetFileSize,
1518 localfontfilestream_GetLastWriteTime
1521 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1523 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1524 if (!This)
1525 return E_OUTOFMEMORY;
1527 This->ref = 1;
1528 This->handle = handle;
1529 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1531 *iface = &This->IDWriteFontFileStream_iface;
1532 return S_OK;
1535 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1537 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1539 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1541 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1543 *obj = iface;
1544 IDWriteLocalFontFileLoader_AddRef(iface);
1545 return S_OK;
1548 *obj = NULL;
1549 return E_NOINTERFACE;
1552 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1554 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1555 ULONG ref = InterlockedIncrement(&This->ref);
1556 TRACE("(%p)->(%d)\n", This, ref);
1557 return ref;
1560 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1562 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1563 ULONG ref = InterlockedDecrement(&This->ref);
1565 TRACE("(%p)->(%d)\n", This, ref);
1567 if (!ref)
1568 heap_free(This);
1570 return ref;
1573 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1575 HANDLE handle;
1576 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1577 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1579 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1581 TRACE("name: %s\n",debugstr_w(name));
1582 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1583 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1585 if (handle == INVALID_HANDLE_VALUE)
1586 return E_FAIL;
1588 return create_localfontfilestream(handle, fontFileStream);
1591 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1593 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1594 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1595 *length = key_size;
1596 return S_OK;
1599 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1601 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1602 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1603 if (length < key_size)
1604 return E_INVALIDARG;
1605 lstrcpynW((WCHAR*)key, path, key_size);
1606 return S_OK;
1609 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1611 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1612 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1613 return E_NOTIMPL;
1616 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1617 localfontfileloader_QueryInterface,
1618 localfontfileloader_AddRef,
1619 localfontfileloader_Release,
1620 localfontfileloader_CreateStreamFromKey,
1621 localfontfileloader_GetFilePathLengthFromKey,
1622 localfontfileloader_GetFilePathFromKey,
1623 localfontfileloader_GetLastWriteTimeFromKey
1626 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1628 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1629 if (!This)
1630 return E_OUTOFMEMORY;
1632 This->ref = 1;
1633 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1635 *iface = &This->IDWriteLocalFontFileLoader_iface;
1636 return S_OK;