gdi32: Don't overflow the buffer in GetGlyphOutline.
[wine/multimedia.git] / dlls / dwrite / font.c
blob77121ec5f5bfcccca5e7a1d422433e6767e0e071
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 LONG ref;
60 IDWriteLocalizedStrings *familyname;
62 struct dwrite_font_data **fonts;
63 UINT32 font_count;
64 UINT32 alloc;
67 struct dwrite_fontcollection {
68 IDWriteFontCollection IDWriteFontCollection_iface;
69 LONG ref;
71 WCHAR **families;
72 UINT32 count;
73 int alloc;
75 struct dwrite_fontfamily_data **family_data;
76 DWORD data_count;
77 int data_alloc;
80 struct dwrite_fontfamily {
81 IDWriteFontFamily IDWriteFontFamily_iface;
82 LONG ref;
84 struct dwrite_fontfamily_data *data;
86 IDWriteFontCollection* collection;
89 struct dwrite_font {
90 IDWriteFont IDWriteFont_iface;
91 LONG ref;
93 BOOL is_system;
94 IDWriteFontFamily *family;
95 IDWriteFontFace *face;
97 struct dwrite_font_data *data;
100 #define DWRITE_FONTTABLE_MAGIC 0xededfafa
102 struct dwrite_fonttablecontext {
103 UINT32 magic;
104 void *context;
105 UINT32 file_index;
108 struct dwrite_fonttable {
109 void *data;
110 void *context;
111 UINT32 size;
114 struct dwrite_fontface {
115 IDWriteFontFace IDWriteFontFace_iface;
116 LONG ref;
118 struct dwrite_fontface_data *data;
119 struct dwrite_fonttable cmap;
121 BOOL is_system;
122 LOGFONTW logfont;
125 struct dwrite_fontfile {
126 IDWriteFontFile IDWriteFontFile_iface;
127 LONG ref;
129 IDWriteFontFileLoader *loader;
130 void *reference_key;
131 UINT32 key_size;
132 IDWriteFontFileStream *stream;
135 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family);
136 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family);
137 static HRESULT create_font_base(IDWriteFont **font);
138 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font);
140 static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface)
142 return CONTAINING_RECORD(iface, struct dwrite_fontface, IDWriteFontFace_iface);
145 static inline struct dwrite_font *impl_from_IDWriteFont(IDWriteFont *iface)
147 return CONTAINING_RECORD(iface, struct dwrite_font, IDWriteFont_iface);
150 static inline struct dwrite_fontfile *impl_from_IDWriteFontFile(IDWriteFontFile *iface)
152 return CONTAINING_RECORD(iface, struct dwrite_fontfile, IDWriteFontFile_iface);
155 static inline struct dwrite_fontfamily *impl_from_IDWriteFontFamily(IDWriteFontFamily *iface)
157 return CONTAINING_RECORD(iface, struct dwrite_fontfamily, IDWriteFontFamily_iface);
160 static inline struct dwrite_fontcollection *impl_from_IDWriteFontCollection(IDWriteFontCollection *iface)
162 return CONTAINING_RECORD(iface, struct dwrite_fontcollection, IDWriteFontCollection_iface);
165 static HRESULT _dwritefontfile_GetFontFileStream(IDWriteFontFile *iface, IDWriteFontFileStream **stream)
167 HRESULT hr;
168 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
169 if (!This->stream)
171 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &This->stream);
172 if (FAILED(hr))
173 return hr;
175 if (This->stream)
177 IDWriteFontFileStream_AddRef(This->stream);
178 *stream = This->stream;
179 return S_OK;
181 return E_FAIL;
184 static VOID _free_fontface_data(struct dwrite_fontface_data *data)
186 int i;
187 if (!data)
188 return;
189 i = InterlockedDecrement(&data->ref);
190 if (i > 0)
191 return;
192 for (i = 0; i < data->file_count; i++)
193 IDWriteFontFile_Release(data->files[i]);
194 heap_free(data->files);
195 heap_free(data);
198 static VOID _free_font_data(struct dwrite_font_data *data)
200 int i;
201 if (!data)
202 return;
203 i = InterlockedDecrement(&data->ref);
204 if (i > 0)
205 return;
206 _free_fontface_data(data->face_data);
207 heap_free(data->facename);
208 heap_free(data);
211 static VOID _free_fontfamily_data(struct dwrite_fontfamily_data *data)
213 int i;
214 if (!data)
215 return;
216 i = InterlockedDecrement(&data->ref);
217 if (i > 0)
218 return;
219 for (i = 0; i < data->font_count; i++)
220 _free_font_data(data->fonts[i]);
221 heap_free(data->fonts);
222 IDWriteLocalizedStrings_Release(data->familyname);
223 heap_free(data);
226 static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj)
228 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
230 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
232 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFace))
234 *obj = iface;
235 IDWriteFontFace_AddRef(iface);
236 return S_OK;
239 *obj = NULL;
240 return E_NOINTERFACE;
243 static ULONG WINAPI dwritefontface_AddRef(IDWriteFontFace *iface)
245 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
246 ULONG ref = InterlockedIncrement(&This->ref);
247 TRACE("(%p)->(%d)\n", This, ref);
248 return ref;
251 static ULONG WINAPI dwritefontface_Release(IDWriteFontFace *iface)
253 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
254 ULONG ref = InterlockedDecrement(&This->ref);
256 TRACE("(%p)->(%d)\n", This, ref);
258 if (!ref)
260 if (This->cmap.context)
261 IDWriteFontFace_ReleaseFontTable(iface, This->cmap.context);
262 _free_fontface_data(This->data);
263 heap_free(This);
266 return ref;
269 static DWRITE_FONT_FACE_TYPE WINAPI dwritefontface_GetType(IDWriteFontFace *iface)
271 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
272 TRACE("(%p)\n", This);
273 return This->data->type;
276 static HRESULT WINAPI dwritefontface_GetFiles(IDWriteFontFace *iface, UINT32 *number_of_files,
277 IDWriteFontFile **fontfiles)
279 int i;
280 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
281 TRACE("(%p)->(%p %p)\n", This, number_of_files, fontfiles);
282 if (fontfiles == NULL)
284 *number_of_files = This->data->file_count;
285 return S_OK;
287 if (*number_of_files < This->data->file_count)
288 return E_INVALIDARG;
290 for (i = 0; i < This->data->file_count; i++)
292 IDWriteFontFile_AddRef(This->data->files[i]);
293 fontfiles[i] = This->data->files[i];
296 return S_OK;
299 static UINT32 WINAPI dwritefontface_GetIndex(IDWriteFontFace *iface)
301 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
302 TRACE("(%p)\n", This);
303 return This->data->index;
306 static DWRITE_FONT_SIMULATIONS WINAPI dwritefontface_GetSimulations(IDWriteFontFace *iface)
308 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
309 TRACE("(%p)\n", This);
310 return This->data->simulations;
313 static BOOL WINAPI dwritefontface_IsSymbolFont(IDWriteFontFace *iface)
315 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
316 FIXME("(%p): stub\n", This);
317 return FALSE;
320 static void WINAPI dwritefontface_GetMetrics(IDWriteFontFace *iface, DWRITE_FONT_METRICS *metrics)
322 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
323 FIXME("(%p)->(%p): stub\n", This, metrics);
326 static UINT16 WINAPI dwritefontface_GetGlyphCount(IDWriteFontFace *iface)
328 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
329 FIXME("(%p): stub\n", This);
330 return 0;
333 static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace *iface,
334 UINT16 const *glyph_indices, UINT32 glyph_count, DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
336 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
337 FIXME("(%p)->(%p %u %p %d): stub\n", This, glyph_indices, glyph_count, metrics, is_sideways);
338 return E_NOTIMPL;
341 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace *iface, UINT32 const *codepoints,
342 UINT32 count, UINT16 *glyph_indices)
344 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
345 unsigned int i;
347 if (This->is_system)
349 HFONT hfont;
350 WCHAR *str;
351 HDC hdc;
353 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
355 str = heap_alloc(count*sizeof(WCHAR));
356 if (!str) return E_OUTOFMEMORY;
358 for (i = 0; i < count; i++)
359 str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?';
361 hdc = CreateCompatibleDC(0);
362 hfont = CreateFontIndirectW(&This->logfont);
363 SelectObject(hdc, hfont);
365 GetGlyphIndicesW(hdc, str, count, glyph_indices, 0);
366 heap_free(str);
368 DeleteDC(hdc);
369 DeleteObject(hfont);
371 return S_OK;
373 else
375 HRESULT hr;
376 TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices);
377 if (!This->cmap.data)
379 BOOL exists = FALSE;
380 hr = IDWriteFontFace_TryGetFontTable(iface, MS_CMAP_TAG, (const void**)&This->cmap.data, &This->cmap.size, &This->cmap.context, &exists);
381 if (FAILED(hr) || !exists)
383 ERR("Font does not have a CMAP table\n");
384 return E_FAIL;
388 for (i = 0; i < count; i++)
390 OpenType_CMAP_GetGlyphIndex(This->cmap.data, codepoints[i], &glyph_indices[i], 0);
392 return S_OK;
396 static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace *iface, UINT32 table_tag,
397 const void **table_data, UINT32 *table_size, void **context, BOOL *exists)
399 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
400 if (This->is_system)
402 FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists);
403 return E_NOTIMPL;
405 else
407 HRESULT hr = S_OK;
408 int i;
409 struct dwrite_fonttablecontext *tablecontext;
411 TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists);
413 tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext));
414 if (!tablecontext)
415 return E_OUTOFMEMORY;
416 tablecontext->magic = DWRITE_FONTTABLE_MAGIC;
418 *exists = FALSE;
419 for (i = 0; i < This->data->file_count && !(*exists); i++)
421 IDWriteFontFileStream *stream;
422 hr = _dwritefontfile_GetFontFileStream(This->data->files[i], &stream);
423 if (FAILED(hr))
424 continue;
425 tablecontext->file_index = i;
427 hr = find_font_table(stream, This->data->index, table_tag, table_data, &tablecontext->context, table_size, exists);
429 IDWriteFontFileStream_Release(stream);
431 if (FAILED(hr) && !*exists)
432 heap_free(tablecontext);
433 else
434 *context = (void*)tablecontext;
435 return hr;
439 static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace *iface, void *table_context)
441 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
442 struct dwrite_fonttablecontext *tablecontext = (struct dwrite_fonttablecontext*)table_context;
443 IDWriteFontFileStream *stream;
444 HRESULT hr;
445 TRACE("(%p)->(%p)\n", This, table_context);
447 if (tablecontext->magic != DWRITE_FONTTABLE_MAGIC)
449 TRACE("Invalid table magic\n");
450 return;
453 hr = _dwritefontfile_GetFontFileStream(This->data->files[tablecontext->file_index], &stream);
454 if (FAILED(hr))
455 return;
456 IDWriteFontFileStream_ReleaseFileFragment(stream, tablecontext->context);
457 IDWriteFontFileStream_Release(stream);
458 heap_free(tablecontext);
461 static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace *iface, FLOAT emSize,
462 UINT16 const *glyph_indices, FLOAT const* glyph_advances, DWRITE_GLYPH_OFFSET const *glyph_offsets,
463 UINT32 glyph_count, BOOL is_sideways, BOOL is_rtl, IDWriteGeometrySink *geometrysink)
465 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
466 FIXME("(%p)->(%f %p %p %p %u %d %d %p): stub\n", This, emSize, glyph_indices, glyph_advances, glyph_offsets,
467 glyph_count, is_sideways, is_rtl, geometrysink);
468 return E_NOTIMPL;
471 static HRESULT WINAPI dwritefontface_GetRecommendedRenderingMode(IDWriteFontFace *iface, FLOAT emSize,
472 FLOAT pixels_per_dip, DWRITE_MEASURING_MODE mode, IDWriteRenderingParams* params, DWRITE_RENDERING_MODE* rendering_mode)
474 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
475 FIXME("(%p)->(%f %f %d %p %p): stub\n", This, emSize, pixels_per_dip, mode, params, rendering_mode);
476 return E_NOTIMPL;
479 static HRESULT WINAPI dwritefontface_GetGdiCompatibleMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
480 DWRITE_MATRIX const *transform, DWRITE_FONT_METRICS *metrics)
482 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
483 FIXME("(%p)->(%f %f %p %p): stub\n", This, emSize, pixels_per_dip, transform, metrics);
484 return E_NOTIMPL;
487 static HRESULT WINAPI dwritefontface_GetGdiCompatibleGlyphMetrics(IDWriteFontFace *iface, FLOAT emSize, FLOAT pixels_per_dip,
488 DWRITE_MATRIX const *transform, BOOL use_gdi_natural, UINT16 const *glyph_indices, UINT32 glyph_count,
489 DWRITE_GLYPH_METRICS *metrics, BOOL is_sideways)
491 struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface);
492 FIXME("(%p)->(%f %f %p %d %p %u %p %d): stub\n", This, emSize, pixels_per_dip, transform, use_gdi_natural, glyph_indices,
493 glyph_count, metrics, is_sideways);
494 return E_NOTIMPL;
497 static const IDWriteFontFaceVtbl dwritefontfacevtbl = {
498 dwritefontface_QueryInterface,
499 dwritefontface_AddRef,
500 dwritefontface_Release,
501 dwritefontface_GetType,
502 dwritefontface_GetFiles,
503 dwritefontface_GetIndex,
504 dwritefontface_GetSimulations,
505 dwritefontface_IsSymbolFont,
506 dwritefontface_GetMetrics,
507 dwritefontface_GetGlyphCount,
508 dwritefontface_GetDesignGlyphMetrics,
509 dwritefontface_GetGlyphIndices,
510 dwritefontface_TryGetFontTable,
511 dwritefontface_ReleaseFontTable,
512 dwritefontface_GetGlyphRunOutline,
513 dwritefontface_GetRecommendedRenderingMode,
514 dwritefontface_GetGdiCompatibleMetrics,
515 dwritefontface_GetGdiCompatibleGlyphMetrics
518 static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face)
520 struct dwrite_fontface *This;
522 *face = NULL;
524 This = heap_alloc(sizeof(struct dwrite_fontface));
525 if (!This) return E_OUTOFMEMORY;
526 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
527 if (!This->data)
529 heap_free(This);
530 return E_OUTOFMEMORY;
533 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
534 This->ref = 1;
535 This->data->type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
536 This->data->file_count = 0;
537 This->data->files = NULL;
538 This->data->index = 0;
539 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
540 This->cmap.data = NULL;
541 This->cmap.context = NULL;
542 This->cmap.size = 0;
544 This->is_system = TRUE;
545 memset(&This->logfont, 0, sizeof(This->logfont));
546 This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC;
547 /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */
548 This->logfont.lfWeight = font->data->weight;
549 strcpyW(This->logfont.lfFaceName, font->data->facename);
551 *face = &This->IDWriteFontFace_iface;
553 return S_OK;
556 HRESULT convert_fontface_to_logfont(IDWriteFontFace *face, LOGFONTW *logfont)
558 struct dwrite_fontface *fontface = impl_from_IDWriteFontFace(face);
560 *logfont = fontface->logfont;
562 return S_OK;
565 static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont *iface, REFIID riid, void **obj)
567 struct dwrite_font *This = impl_from_IDWriteFont(iface);
569 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
571 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFont))
573 *obj = iface;
574 IDWriteFont_AddRef(iface);
575 return S_OK;
578 *obj = NULL;
579 return E_NOINTERFACE;
582 static ULONG WINAPI dwritefont_AddRef(IDWriteFont *iface)
584 struct dwrite_font *This = impl_from_IDWriteFont(iface);
585 ULONG ref = InterlockedIncrement(&This->ref);
586 TRACE("(%p)->(%d)\n", This, ref);
587 return ref;
590 static ULONG WINAPI dwritefont_Release(IDWriteFont *iface)
592 struct dwrite_font *This = impl_from_IDWriteFont(iface);
593 ULONG ref = InterlockedDecrement(&This->ref);
595 TRACE("(%p)->(%d)\n", This, ref);
597 if (!ref)
599 if (This->face) IDWriteFontFace_Release(This->face);
600 if (This->family) IDWriteFontFamily_Release(This->family);
601 _free_font_data(This->data);
602 heap_free(This);
605 return ref;
608 static HRESULT WINAPI dwritefont_GetFontFamily(IDWriteFont *iface, IDWriteFontFamily **family)
610 struct dwrite_font *This = impl_from_IDWriteFont(iface);
611 TRACE("(%p)->(%p)\n", This, family);
613 *family = This->family;
614 IDWriteFontFamily_AddRef(*family);
615 return S_OK;
618 static DWRITE_FONT_WEIGHT WINAPI dwritefont_GetWeight(IDWriteFont *iface)
620 struct dwrite_font *This = impl_from_IDWriteFont(iface);
621 TRACE("(%p)\n", This);
622 return This->data->weight;
625 static DWRITE_FONT_STRETCH WINAPI dwritefont_GetStretch(IDWriteFont *iface)
627 struct dwrite_font *This = impl_from_IDWriteFont(iface);
628 TRACE("(%p)\n", This);
629 return This->data->stretch;
632 static DWRITE_FONT_STYLE WINAPI dwritefont_GetStyle(IDWriteFont *iface)
634 struct dwrite_font *This = impl_from_IDWriteFont(iface);
635 TRACE("(%p)\n", This);
636 return This->data->style;
639 static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont *iface)
641 struct dwrite_font *This = impl_from_IDWriteFont(iface);
642 FIXME("(%p): stub\n", This);
643 return FALSE;
646 static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont *iface, IDWriteLocalizedStrings **names)
648 struct dwrite_font *This = impl_from_IDWriteFont(iface);
649 FIXME("(%p)->(%p): stub\n", This, names);
650 return E_NOTIMPL;
653 static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont *iface,
654 DWRITE_INFORMATIONAL_STRING_ID stringid, IDWriteLocalizedStrings **strings, BOOL *exists)
656 struct dwrite_font *This = impl_from_IDWriteFont(iface);
657 FIXME("(%p)->(%d %p %p): stub\n", This, stringid, strings, exists);
658 return E_NOTIMPL;
661 static DWRITE_FONT_SIMULATIONS WINAPI dwritefont_GetSimulations(IDWriteFont *iface)
663 struct dwrite_font *This = impl_from_IDWriteFont(iface);
664 TRACE("(%p)\n", This);
665 return This->data->simulations;
668 static void WINAPI dwritefont_GetMetrics(IDWriteFont *iface, DWRITE_FONT_METRICS *metrics)
670 struct dwrite_font *This = impl_from_IDWriteFont(iface);
672 TRACE("(%p)->(%p)\n", This, metrics);
673 *metrics = This->data->metrics;
676 static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont *iface, UINT32 value, BOOL *exists)
678 struct dwrite_font *This = impl_from_IDWriteFont(iface);
679 FIXME("(%p)->(0x%08x %p): stub\n", This, value, exists);
680 return E_NOTIMPL;
683 static HRESULT WINAPI dwritefont_CreateFontFace(IDWriteFont *iface, IDWriteFontFace **face)
685 struct dwrite_font *This = impl_from_IDWriteFont(iface);
687 if (This->is_system)
689 TRACE("(%p)->(%p)\n", This, face);
691 if (!This->face)
693 HRESULT hr = create_system_fontface(This, &This->face);
694 if (FAILED(hr)) return hr;
697 *face = This->face;
698 IDWriteFontFace_AddRef(*face);
700 return S_OK;
702 else
704 TRACE("(%p)->(%p)\n", This, face);
706 if (!This->face)
708 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);
709 if (FAILED(hr)) return hr;
712 *face = This->face;
713 IDWriteFontFace_AddRef(*face);
715 return S_OK;
719 static const IDWriteFontVtbl dwritefontvtbl = {
720 dwritefont_QueryInterface,
721 dwritefont_AddRef,
722 dwritefont_Release,
723 dwritefont_GetFontFamily,
724 dwritefont_GetWeight,
725 dwritefont_GetStretch,
726 dwritefont_GetStyle,
727 dwritefont_IsSymbolFont,
728 dwritefont_GetFaceNames,
729 dwritefont_GetInformationalStrings,
730 dwritefont_GetSimulations,
731 dwritefont_GetMetrics,
732 dwritefont_HasCharacter,
733 dwritefont_CreateFontFace
736 static HRESULT WINAPI dwritefontfamily_QueryInterface(IDWriteFontFamily *iface, REFIID riid, void **obj)
738 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
739 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
741 if (IsEqualIID(riid, &IID_IUnknown) ||
742 IsEqualIID(riid, &IID_IDWriteFontList) ||
743 IsEqualIID(riid, &IID_IDWriteFontFamily))
745 *obj = iface;
746 IDWriteFontFamily_AddRef(iface);
747 return S_OK;
750 *obj = NULL;
751 return E_NOINTERFACE;
754 static ULONG WINAPI dwritefontfamily_AddRef(IDWriteFontFamily *iface)
756 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
757 ULONG ref = InterlockedIncrement(&This->ref);
758 TRACE("(%p)->(%d)\n", This, ref);
759 return ref;
762 static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface)
764 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
765 ULONG ref = InterlockedDecrement(&This->ref);
767 TRACE("(%p)->(%d)\n", This, ref);
769 if (!ref)
771 if (This->collection)
772 IDWriteFontCollection_Release(This->collection);
773 _free_fontfamily_data(This->data);
774 heap_free(This);
777 return ref;
780 static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *iface, IDWriteFontCollection **collection)
782 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
783 TRACE("(%p)->(%p)\n", This, collection);
784 if (This->collection)
786 IDWriteFontCollection_AddRef(This->collection);
787 *collection = This->collection;
788 return S_OK;
790 else
791 return E_NOTIMPL;
794 static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface)
796 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
797 TRACE("(%p)\n", This);
798 return This->data->font_count;
801 static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font)
803 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
804 TRACE("(%p)->(%u %p)\n", This, index, font);
805 if (This->data->font_count > 0)
807 HRESULT hr;
808 if (index >= This->data->font_count)
809 return E_INVALIDARG;
810 hr = create_font_from_data(This->data->fonts[index], font);
811 if (SUCCEEDED(hr))
813 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
814 font_data->family = iface;
815 IDWriteFontFamily_AddRef(iface);
817 return hr;
819 else
820 return E_NOTIMPL;
823 static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names)
825 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
826 return clone_localizedstring(This->data->familyname, names);
829 static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
830 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font)
832 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
833 LOGFONTW lf;
835 TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font);
837 /* fallback for system font collections */
838 if (This->data->font_count == 0)
840 memset(&lf, 0, sizeof(lf));
841 lf.lfWeight = weight;
842 lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC;
843 IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE);
845 return create_font_from_logfont(&lf, font);
847 else
849 int i;
850 for (i = 0; i < This->data->font_count; i++)
852 if (style == This->data->fonts[i]->style &&
853 weight == This->data->fonts[i]->weight &&
854 stretch == This->data->fonts[i]->stretch)
856 HRESULT hr;
857 hr = create_font_from_data(This->data->fonts[i], font);
858 if (SUCCEEDED(hr))
860 struct dwrite_font *font_data = impl_from_IDWriteFont(*font);
861 font_data->family = iface;
862 IDWriteFontFamily_AddRef(iface);
864 return hr;
867 return DWRITE_E_NOFONT;
871 static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight,
872 DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **fonts)
874 struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface);
875 FIXME("(%p)->(%d %d %d %p): stub\n", This, weight, stretch, style, fonts);
876 return E_NOTIMPL;
879 static const IDWriteFontFamilyVtbl fontfamilyvtbl = {
880 dwritefontfamily_QueryInterface,
881 dwritefontfamily_AddRef,
882 dwritefontfamily_Release,
883 dwritefontfamily_GetFontCollection,
884 dwritefontfamily_GetFontCount,
885 dwritefontfamily_GetFont,
886 dwritefontfamily_GetFamilyNames,
887 dwritefontfamily_GetFirstMatchingFont,
888 dwritefontfamily_GetMatchingFonts
891 static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection *iface, REFIID riid, void **obj)
893 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
894 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
896 if (IsEqualIID(riid, &IID_IUnknown) ||
897 IsEqualIID(riid, &IID_IDWriteFontCollection))
899 *obj = iface;
900 IDWriteFontCollection_AddRef(iface);
901 return S_OK;
904 *obj = NULL;
905 return E_NOINTERFACE;
908 static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface)
910 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
911 ULONG ref = InterlockedIncrement(&This->ref);
912 TRACE("(%p)->(%d)\n", This, ref);
913 return ref;
916 static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
918 unsigned int i;
919 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
920 ULONG ref = InterlockedDecrement(&This->ref);
921 TRACE("(%p)->(%d)\n", This, ref);
923 if (!ref)
925 for (i = 0; i < This->count; i++)
926 heap_free(This->families[i]);
927 heap_free(This->families);
928 for (i = 0; i < This->data_count; i++)
929 _free_fontfamily_data(This->family_data[i]);
930 heap_free(This->family_data);
931 heap_free(This);
934 return ref;
937 static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
939 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
940 TRACE("(%p)\n", This);
941 if (This->data_count)
942 return This->data_count;
943 return This->count;
946 static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family)
948 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
949 HRESULT hr;
950 IDWriteLocalizedStrings *familyname;
951 static const WCHAR enusW[] = {'e','n','-','u','s',0};
953 TRACE("(%p)->(%u %p)\n", This, index, family);
955 if (This->data_count)
957 if (index >= This->data_count)
959 *family = NULL;
960 return E_FAIL;
962 else
963 return create_fontfamily_from_data(This->family_data[index], iface, family);
965 else
967 if (index >= This->count)
969 *family = NULL;
970 return E_FAIL;
973 hr = create_localizedstrings(&familyname);
974 if (FAILED(hr))
975 return hr;
976 add_localizedstring(familyname, enusW, This->families[index]);
978 return create_fontfamily(familyname, family);
982 static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists)
984 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
985 UINT32 i;
987 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists);
989 if (This->data_count)
991 for (i = 0; i < This->data_count; i++)
993 HRESULT hr;
994 IDWriteLocalizedStrings *family_name = This->family_data[i]->familyname;
995 int j;
996 for (j = 0; j < IDWriteLocalizedStrings_GetCount(family_name); j ++)
998 WCHAR buffer[255];
999 hr = IDWriteLocalizedStrings_GetString(family_name, j, buffer, 255);
1000 if (SUCCEEDED(hr))
1002 if (!strcmpW(buffer, name))
1004 *index = i;
1005 *exists = TRUE;
1006 return S_OK;
1011 *index = (UINT32)-1;
1012 *exists = FALSE;
1014 else
1016 for (i = 0; i < This->count; i++)
1017 if (!strcmpW(This->families[i], name))
1019 *index = i;
1020 *exists = TRUE;
1021 return S_OK;
1024 *index = (UINT32)-1;
1025 *exists = FALSE;
1028 return S_OK;
1031 static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollection *iface, IDWriteFontFace *face, IDWriteFont **font)
1033 struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
1034 FIXME("(%p)->(%p %p): stub\n", This, face, font);
1035 return E_NOTIMPL;
1038 static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
1039 dwritefontcollection_QueryInterface,
1040 dwritefontcollection_AddRef,
1041 dwritefontcollection_Release,
1042 dwritefontcollection_GetFontFamilyCount,
1043 dwritefontcollection_GetFontFamily,
1044 dwritefontcollection_FindFamilyName,
1045 dwritefontcollection_GetFontFromFontFace
1048 static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family)
1050 /* check for duplicate family name */
1051 if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK;
1053 /* double array length */
1054 if (collection->count == collection->alloc)
1056 collection->alloc *= 2;
1057 collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*));
1060 collection->families[collection->count++] = heap_strdupW(family);
1061 TRACE("family name %s\n", debugstr_w(family));
1063 return S_OK;
1066 static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam)
1068 struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam;
1069 return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
1072 HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
1074 struct dwrite_fontcollection *This;
1075 LOGFONTW lf;
1076 HDC hdc;
1078 *collection = NULL;
1080 This = heap_alloc(sizeof(struct dwrite_fontcollection));
1081 if (!This) return E_OUTOFMEMORY;
1083 This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
1084 This->ref = 1;
1085 This->alloc = 50;
1086 This->count = 0;
1087 This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
1088 if (!This->families)
1090 heap_free(This);
1091 return E_OUTOFMEMORY;
1093 This->data_count = 0;
1094 This->data_alloc = 2;
1095 This->family_data = heap_alloc(sizeof(*This->family_data)*2);
1096 if (!This->family_data)
1098 heap_free(This->families);
1099 heap_free(This);
1100 return E_OUTOFMEMORY;
1103 TRACE("building system font collection:\n");
1105 hdc = CreateCompatibleDC(0);
1106 memset(&lf, 0, sizeof(lf));
1107 lf.lfCharSet = DEFAULT_CHARSET;
1108 lf.lfPitchAndFamily = DEFAULT_PITCH;
1109 lf.lfFaceName[0] = 0;
1110 EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
1111 DeleteDC(hdc);
1113 *collection = &This->IDWriteFontCollection_iface;
1115 return S_OK;
1118 static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family)
1120 struct dwrite_fontfamily *This;
1122 *family = NULL;
1124 This = heap_alloc(sizeof(struct dwrite_fontfamily));
1125 if (!This) return E_OUTOFMEMORY;
1127 This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl;
1128 This->ref = 1;
1129 This->collection = collection;
1130 if (collection)
1131 IDWriteFontCollection_AddRef(collection);
1132 This->data = data;
1133 InterlockedIncrement(&This->data->ref);
1135 *family = &This->IDWriteFontFamily_iface;
1137 return S_OK;
1140 static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family)
1142 struct dwrite_fontfamily_data *data;
1143 HRESULT ret;
1145 data = heap_alloc(sizeof(struct dwrite_fontfamily_data));
1146 if (!data) return E_OUTOFMEMORY;
1148 data->ref = 0;
1149 data->font_count = 0;
1150 data->alloc = 2;
1151 data->fonts = heap_alloc(sizeof(*data->fonts) * 2);
1152 if (!data->fonts)
1154 heap_free(data);
1155 return E_OUTOFMEMORY;
1157 data->familyname = familyname;
1159 ret = create_fontfamily_from_data(data, NULL, family);
1160 if (FAILED(ret))
1162 heap_free(data->fonts);
1163 heap_free(data);
1166 return ret;
1169 static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font)
1171 struct dwrite_font *This;
1172 *font = NULL;
1174 This = heap_alloc(sizeof(struct dwrite_font));
1175 if (!This) return E_OUTOFMEMORY;
1177 This->IDWriteFont_iface.lpVtbl = &dwritefontvtbl;
1178 This->ref = 1;
1179 This->face = NULL;
1180 This->family = NULL;
1181 This->is_system = FALSE;
1182 This->data = data;
1183 InterlockedIncrement(&This->data->ref);
1185 *font = &This->IDWriteFont_iface;
1187 return S_OK;
1190 static HRESULT create_font_base(IDWriteFont **font)
1192 struct dwrite_font_data *data;
1193 HRESULT ret;
1195 *font = NULL;
1196 data = heap_alloc(sizeof(*data));
1197 if (!data) return E_OUTOFMEMORY;
1199 data->ref = 0;
1200 data->face_data = NULL;
1202 ret = create_font_from_data( data, font );
1203 if (FAILED(ret)) heap_free( data );
1204 return ret;
1207 HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font)
1209 const WCHAR* facename, *familyname;
1210 IDWriteLocalizedStrings *name;
1211 struct dwrite_font *This;
1212 IDWriteFontFamily *family;
1213 OUTLINETEXTMETRICW *otm;
1214 HRESULT hr;
1215 HFONT hfont;
1216 HDC hdc;
1217 int ret;
1218 static const WCHAR enusW[] = {'e','n','-','u','s',0};
1219 LPVOID tt_os2 = NULL;
1220 LPVOID tt_head = NULL;
1221 LPVOID tt_post = NULL;
1222 LONG size;
1224 hr = create_font_base(font);
1225 if (FAILED(hr))
1226 return hr;
1228 This = impl_from_IDWriteFont(*font);
1230 hfont = CreateFontIndirectW(logfont);
1231 if (!hfont)
1233 heap_free(This->data);
1234 heap_free(This);
1235 return DWRITE_E_NOFONT;
1238 hdc = CreateCompatibleDC(0);
1239 SelectObject(hdc, hfont);
1241 ret = GetOutlineTextMetricsW(hdc, 0, NULL);
1242 otm = heap_alloc(ret);
1243 if (!otm)
1245 heap_free(This->data);
1246 heap_free(This);
1247 DeleteDC(hdc);
1248 DeleteObject(hfont);
1249 return E_OUTOFMEMORY;
1251 otm->otmSize = ret;
1252 ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm);
1254 size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
1255 if (size != GDI_ERROR)
1257 tt_os2 = heap_alloc(size);
1258 GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size);
1260 size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0);
1261 if (size != GDI_ERROR)
1263 tt_head = heap_alloc(size);
1264 GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size);
1266 size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0);
1267 if (size != GDI_ERROR)
1269 tt_post = heap_alloc(size);
1270 GetFontData(hdc, MS_POST_TAG, 0, tt_post, size);
1273 get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style);
1274 heap_free(tt_os2);
1275 heap_free(tt_head);
1276 heap_free(tt_post);
1278 if (logfont->lfItalic)
1279 This->data->style = DWRITE_FONT_STYLE_ITALIC;
1281 DeleteDC(hdc);
1282 DeleteObject(hfont);
1284 facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName);
1285 familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName);
1286 TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname));
1288 hr = create_localizedstrings(&name);
1289 if (FAILED(hr))
1291 heap_free(This);
1292 return hr;
1294 add_localizedstring(name, enusW, familyname);
1295 hr = create_fontfamily(name, &family);
1297 heap_free(otm);
1298 if (hr != S_OK)
1300 heap_free(This->data);
1301 heap_free(This);
1302 return hr;
1305 This->is_system = TRUE;
1306 This->family = family;
1307 This->data->simulations = DWRITE_FONT_SIMULATIONS_NONE;
1308 This->data->facename = heap_strdupW(logfont->lfFaceName);
1310 return S_OK;
1313 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
1315 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1317 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1319 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFile))
1321 *obj = iface;
1322 IDWriteFontFile_AddRef(iface);
1323 return S_OK;
1326 *obj = NULL;
1327 return E_NOINTERFACE;
1330 static ULONG WINAPI dwritefontfile_AddRef(IDWriteFontFile *iface)
1332 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1333 ULONG ref = InterlockedIncrement(&This->ref);
1334 TRACE("(%p)->(%d)\n", This, ref);
1335 return ref;
1338 static ULONG WINAPI dwritefontfile_Release(IDWriteFontFile *iface)
1340 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1341 ULONG ref = InterlockedDecrement(&This->ref);
1343 TRACE("(%p)->(%d)\n", This, ref);
1345 if (!ref)
1347 IDWriteFontFileLoader_Release(This->loader);
1348 if (This->stream) IDWriteFontFileStream_Release(This->stream);
1349 heap_free(This->reference_key);
1350 heap_free(This);
1353 return ref;
1356 static HRESULT WINAPI dwritefontfile_GetReferenceKey(IDWriteFontFile *iface, const void **fontFileReferenceKey, UINT32 *fontFileReferenceKeySize)
1358 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1359 TRACE("(%p)->(%p, %p)\n", This, fontFileReferenceKey, fontFileReferenceKeySize);
1360 *fontFileReferenceKey = This->reference_key;
1361 *fontFileReferenceKeySize = This->key_size;
1363 return S_OK;
1366 static HRESULT WINAPI dwritefontfile_GetLoader(IDWriteFontFile *iface, IDWriteFontFileLoader **fontFileLoader)
1368 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1369 TRACE("(%p)->(%p)\n", This, fontFileLoader);
1370 *fontFileLoader = This->loader;
1371 IDWriteFontFileLoader_AddRef(This->loader);
1373 return S_OK;
1376 static HRESULT WINAPI dwritefontfile_Analyze(IDWriteFontFile *iface, BOOL *isSupportedFontType, DWRITE_FONT_FILE_TYPE *fontFileType, DWRITE_FONT_FACE_TYPE *fontFaceType, UINT32 *numberOfFaces)
1378 struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface);
1379 IDWriteFontFileStream *stream;
1380 HRESULT hr;
1382 FIXME("(%p)->(%p, %p, %p, %p): Stub\n", This, isSupportedFontType, fontFileType, fontFaceType, numberOfFaces);
1384 *isSupportedFontType = FALSE;
1385 *fontFileType = DWRITE_FONT_FILE_TYPE_UNKNOWN;
1386 if (fontFaceType)
1387 *fontFaceType = DWRITE_FONT_FACE_TYPE_UNKNOWN;
1388 *numberOfFaces = 0;
1390 hr = IDWriteFontFileLoader_CreateStreamFromKey(This->loader, This->reference_key, This->key_size, &stream);
1391 if (FAILED(hr))
1392 return S_OK;
1394 hr = opentype_analyze_font(stream, numberOfFaces, fontFileType, fontFaceType, isSupportedFontType);
1396 /* TODO: Further Analysis */
1397 IDWriteFontFileStream_Release(stream);
1398 return S_OK;
1401 static const IDWriteFontFileVtbl dwritefontfilevtbl = {
1402 dwritefontfile_QueryInterface,
1403 dwritefontfile_AddRef,
1404 dwritefontfile_Release,
1405 dwritefontfile_GetReferenceKey,
1406 dwritefontfile_GetLoader,
1407 dwritefontfile_Analyze,
1410 HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file)
1412 struct dwrite_fontfile *This;
1414 This = heap_alloc(sizeof(struct dwrite_fontfile));
1415 if (!This) return E_OUTOFMEMORY;
1417 This->IDWriteFontFile_iface.lpVtbl = &dwritefontfilevtbl;
1418 This->ref = 1;
1419 IDWriteFontFileLoader_AddRef(loader);
1420 This->loader = loader;
1421 This->stream = NULL;
1422 This->reference_key = heap_alloc(key_size);
1423 memcpy(This->reference_key, reference_key, key_size);
1424 This->key_size = key_size;
1426 *font_file = &This->IDWriteFontFile_iface;
1428 return S_OK;
1431 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)
1433 int i;
1434 struct dwrite_fontface *This;
1435 HRESULT hr = S_OK;
1437 *font_face = NULL;
1439 This = heap_alloc(sizeof(struct dwrite_fontface));
1440 if (!This) return E_OUTOFMEMORY;
1441 This->data = heap_alloc(sizeof(struct dwrite_fontface_data));
1442 if (!This->data)
1444 heap_free(This);
1445 return E_OUTOFMEMORY;
1448 This->IDWriteFontFace_iface.lpVtbl = &dwritefontfacevtbl;
1449 This->ref = 1;
1450 This->data->ref = 1;
1451 This->data->type = facetype;
1452 This->data->file_count = files_number;
1453 This->data->files = heap_alloc(sizeof(*This->data->files) * files_number);
1454 This->cmap.data = NULL;
1455 This->cmap.context = NULL;
1456 This->cmap.size = 0;
1457 /* Verify font file streams */
1458 for (i = 0; i < This->data->file_count && SUCCEEDED(hr); i++)
1460 IDWriteFontFileStream *stream;
1461 hr = _dwritefontfile_GetFontFileStream(font_files[i], &stream);
1462 if (SUCCEEDED(hr))
1463 IDWriteFontFileStream_Release(stream);
1465 if (FAILED(hr))
1467 heap_free(This->data->files);
1468 heap_free(This->data);
1469 heap_free(This);
1470 return hr;
1472 for (i = 0; i < This->data->file_count; i++)
1474 This->data->files[i] = font_files[i];
1475 IDWriteFontFile_AddRef(font_files[i]);
1478 This->data->index = index;
1479 This->data->simulations = sim_flags;
1480 This->is_system = FALSE;
1482 *font_face = &This->IDWriteFontFace_iface;
1484 return S_OK;
1487 /* IDWriteLocalFontFileLoader and its required IDWriteFontFileStream */
1489 struct dwrite_localfontfilestream
1491 IDWriteFontFileStream IDWriteFontFileStream_iface;
1492 LONG ref;
1494 HANDLE handle;
1497 struct dwrite_localfontfileloader {
1498 IDWriteLocalFontFileLoader IDWriteLocalFontFileLoader_iface;
1499 LONG ref;
1502 static inline struct dwrite_localfontfileloader *impl_from_IDWriteLocalFontFileLoader(IDWriteLocalFontFileLoader *iface)
1504 return CONTAINING_RECORD(iface, struct dwrite_localfontfileloader, IDWriteLocalFontFileLoader_iface);
1507 static inline struct dwrite_localfontfilestream *impl_from_IDWriteFontFileStream(IDWriteFontFileStream *iface)
1509 return CONTAINING_RECORD(iface, struct dwrite_localfontfilestream, IDWriteFontFileStream_iface);
1512 static HRESULT WINAPI localfontfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
1514 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1515 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1516 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileStream))
1518 *obj = iface;
1519 IDWriteFontFileStream_AddRef(iface);
1520 return S_OK;
1523 *obj = NULL;
1524 return E_NOINTERFACE;
1527 static ULONG WINAPI localfontfilestream_AddRef(IDWriteFontFileStream *iface)
1529 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1530 ULONG ref = InterlockedIncrement(&This->ref);
1531 TRACE("(%p)->(%d)\n", This, ref);
1532 return ref;
1535 static ULONG WINAPI localfontfilestream_Release(IDWriteFontFileStream *iface)
1537 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1538 ULONG ref = InterlockedDecrement(&This->ref);
1540 TRACE("(%p)->(%d)\n", This, ref);
1542 if (!ref)
1544 if (This->handle != INVALID_HANDLE_VALUE)
1545 CloseHandle(This->handle);
1546 heap_free(This);
1549 return ref;
1552 static HRESULT WINAPI localfontfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start, UINT64 offset, UINT64 fragment_size, void **fragment_context)
1554 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1555 LARGE_INTEGER distance;
1556 DWORD bytes = fragment_size;
1557 DWORD read;
1559 TRACE("(%p)->(%p, %s, %s, %p)\n",This, fragment_start,
1560 wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
1562 *fragment_context = NULL;
1563 distance.QuadPart = offset;
1564 if (!SetFilePointerEx(This->handle, distance, NULL, FILE_BEGIN))
1565 return E_FAIL;
1566 *fragment_start = *fragment_context = heap_alloc(bytes);
1567 if (!*fragment_context)
1568 return E_FAIL;
1569 if (!ReadFile(This->handle, *fragment_context, bytes, &read, NULL))
1571 heap_free(*fragment_context);
1572 return E_FAIL;
1575 return S_OK;
1578 static void WINAPI localfontfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
1580 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1581 TRACE("(%p)->(%p)\n", This, fragment_context);
1582 heap_free(fragment_context);
1585 static HRESULT WINAPI localfontfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
1587 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1588 LARGE_INTEGER li;
1589 TRACE("(%p)->(%p)\n",This, size);
1590 GetFileSizeEx(This->handle, &li);
1591 *size = li.QuadPart;
1592 return S_OK;
1595 static HRESULT WINAPI localfontfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
1597 struct dwrite_localfontfilestream *This = impl_from_IDWriteFontFileStream(iface);
1598 FIXME("(%p)->(%p): stub\n",This, last_writetime);
1599 *last_writetime = 0;
1600 return E_NOTIMPL;
1603 static const IDWriteFontFileStreamVtbl localfontfilestreamvtbl =
1605 localfontfilestream_QueryInterface,
1606 localfontfilestream_AddRef,
1607 localfontfilestream_Release,
1608 localfontfilestream_ReadFileFragment,
1609 localfontfilestream_ReleaseFileFragment,
1610 localfontfilestream_GetFileSize,
1611 localfontfilestream_GetLastWriteTime
1614 static HRESULT create_localfontfilestream(HANDLE handle, IDWriteFontFileStream** iface)
1616 struct dwrite_localfontfilestream *This = heap_alloc(sizeof(struct dwrite_localfontfilestream));
1617 if (!This)
1618 return E_OUTOFMEMORY;
1620 This->ref = 1;
1621 This->handle = handle;
1622 This->IDWriteFontFileStream_iface.lpVtbl = &localfontfilestreamvtbl;
1624 *iface = &This->IDWriteFontFileStream_iface;
1625 return S_OK;
1628 static HRESULT WINAPI localfontfileloader_QueryInterface(IDWriteLocalFontFileLoader *iface, REFIID riid, void **obj)
1630 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1632 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1634 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteFontFileLoader) || IsEqualIID(riid, &IID_IDWriteLocalFontFileLoader))
1636 *obj = iface;
1637 IDWriteLocalFontFileLoader_AddRef(iface);
1638 return S_OK;
1641 *obj = NULL;
1642 return E_NOINTERFACE;
1645 static ULONG WINAPI localfontfileloader_AddRef(IDWriteLocalFontFileLoader *iface)
1647 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1648 ULONG ref = InterlockedIncrement(&This->ref);
1649 TRACE("(%p)->(%d)\n", This, ref);
1650 return ref;
1653 static ULONG WINAPI localfontfileloader_Release(IDWriteLocalFontFileLoader *iface)
1655 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1656 ULONG ref = InterlockedDecrement(&This->ref);
1658 TRACE("(%p)->(%d)\n", This, ref);
1660 if (!ref)
1661 heap_free(This);
1663 return ref;
1666 static HRESULT WINAPI localfontfileloader_CreateStreamFromKey(IDWriteLocalFontFileLoader *iface, const void *fontFileReferenceKey, UINT32 fontFileReferenceKeySize, IDWriteFontFileStream **fontFileStream)
1668 HANDLE handle;
1669 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1670 const WCHAR *name = (const WCHAR*)fontFileReferenceKey;
1672 TRACE("(%p)->(%p, %i, %p)\n",This, fontFileReferenceKey, fontFileReferenceKeySize, fontFileStream);
1674 TRACE("name: %s\n",debugstr_w(name));
1675 handle = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
1676 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1678 if (handle == INVALID_HANDLE_VALUE)
1679 return E_FAIL;
1681 return create_localfontfilestream(handle, fontFileStream);
1684 static HRESULT WINAPI localfontfileloader_GetFilePathLengthFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, UINT32 *length)
1686 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1687 TRACE("(%p)->(%p, %i, %p)\n",This, key, key_size, length);
1688 *length = key_size;
1689 return S_OK;
1692 static HRESULT WINAPI localfontfileloader_GetFilePathFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, WCHAR *path, UINT32 length)
1694 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1695 TRACE("(%p)->(%p, %i, %p, %i)\n",This, key, key_size, path, length);
1696 if (length < key_size)
1697 return E_INVALIDARG;
1698 lstrcpynW((WCHAR*)key, path, key_size);
1699 return S_OK;
1702 static HRESULT WINAPI localfontfileloader_GetLastWriteTimeFromKey(IDWriteLocalFontFileLoader *iface, void const *key, UINT32 key_size, FILETIME *writetime)
1704 struct dwrite_localfontfileloader *This = impl_from_IDWriteLocalFontFileLoader(iface);
1705 FIXME("(%p)->(%p, %i, %p):stub\n",This, key, key_size, writetime);
1706 return E_NOTIMPL;
1709 static const struct IDWriteLocalFontFileLoaderVtbl localfontfileloadervtbl = {
1710 localfontfileloader_QueryInterface,
1711 localfontfileloader_AddRef,
1712 localfontfileloader_Release,
1713 localfontfileloader_CreateStreamFromKey,
1714 localfontfileloader_GetFilePathLengthFromKey,
1715 localfontfileloader_GetFilePathFromKey,
1716 localfontfileloader_GetLastWriteTimeFromKey
1719 HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface)
1721 struct dwrite_localfontfileloader *This = heap_alloc(sizeof(struct dwrite_localfontfileloader));
1722 if (!This)
1723 return E_OUTOFMEMORY;
1725 This->ref = 1;
1726 This->IDWriteLocalFontFileLoader_iface.lpVtbl = &localfontfileloadervtbl;
1728 *iface = &This->IDWriteLocalFontFileLoader_iface;
1729 return S_OK;