dwrite: Added stub EUDC font collection.
[wine.git] / dlls / dwrite / main.c
blob8ad5097af96c530be8cb9a4783383cb5c0893a49
1 /*
2 * DWrite
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 <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
29 #include "initguid.h"
31 #include "dwrite_private.h"
32 #include "wine/debug.h"
33 #include "wine/list.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
37 static IDWriteFactory2 *shared_factory;
38 static void release_shared_factory(IDWriteFactory2*);
40 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
42 switch (reason)
44 case DLL_PROCESS_ATTACH:
45 DisableThreadLibraryCalls( hinstDLL );
46 init_freetype();
47 break;
48 case DLL_PROCESS_DETACH:
49 if (reserved) break;
50 release_shared_factory(shared_factory);
52 return TRUE;
55 struct renderingparams {
56 IDWriteRenderingParams IDWriteRenderingParams_iface;
57 LONG ref;
59 FLOAT gamma;
60 FLOAT enh_contrast;
61 FLOAT cleartype_level;
62 DWRITE_PIXEL_GEOMETRY geometry;
63 DWRITE_RENDERING_MODE mode;
66 static inline struct renderingparams *impl_from_IDWriteRenderingParams(IDWriteRenderingParams *iface)
68 return CONTAINING_RECORD(iface, struct renderingparams, IDWriteRenderingParams_iface);
71 static HRESULT WINAPI renderingparams_QueryInterface(IDWriteRenderingParams *iface, REFIID riid, void **obj)
73 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
75 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
77 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteRenderingParams))
79 *obj = iface;
80 IDWriteRenderingParams_AddRef(iface);
81 return S_OK;
84 *obj = NULL;
86 return E_NOINTERFACE;
89 static ULONG WINAPI renderingparams_AddRef(IDWriteRenderingParams *iface)
91 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
92 ULONG ref = InterlockedIncrement(&This->ref);
93 TRACE("(%p)->(%d)\n", This, ref);
94 return ref;
97 static ULONG WINAPI renderingparams_Release(IDWriteRenderingParams *iface)
99 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
100 ULONG ref = InterlockedDecrement(&This->ref);
102 TRACE("(%p)->(%d)\n", This, ref);
104 if (!ref)
105 heap_free(This);
107 return ref;
110 static FLOAT WINAPI renderingparams_GetGamma(IDWriteRenderingParams *iface)
112 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
113 TRACE("(%p)\n", This);
114 return This->gamma;
117 static FLOAT WINAPI renderingparams_GetEnhancedContrast(IDWriteRenderingParams *iface)
119 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
120 TRACE("(%p)\n", This);
121 return This->enh_contrast;
124 static FLOAT WINAPI renderingparams_GetClearTypeLevel(IDWriteRenderingParams *iface)
126 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
127 TRACE("(%p)\n", This);
128 return This->cleartype_level;
131 static DWRITE_PIXEL_GEOMETRY WINAPI renderingparams_GetPixelGeometry(IDWriteRenderingParams *iface)
133 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
134 TRACE("(%p)\n", This);
135 return This->geometry;
138 static DWRITE_RENDERING_MODE WINAPI renderingparams_GetRenderingMode(IDWriteRenderingParams *iface)
140 struct renderingparams *This = impl_from_IDWriteRenderingParams(iface);
141 TRACE("(%p)\n", This);
142 return This->mode;
145 static const struct IDWriteRenderingParamsVtbl renderingparamsvtbl = {
146 renderingparams_QueryInterface,
147 renderingparams_AddRef,
148 renderingparams_Release,
149 renderingparams_GetGamma,
150 renderingparams_GetEnhancedContrast,
151 renderingparams_GetClearTypeLevel,
152 renderingparams_GetPixelGeometry,
153 renderingparams_GetRenderingMode
156 static HRESULT create_renderingparams(FLOAT gamma, FLOAT enhancedContrast, FLOAT cleartype_level,
157 DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode, IDWriteRenderingParams **params)
159 struct renderingparams *This;
161 *params = NULL;
163 This = heap_alloc(sizeof(struct renderingparams));
164 if (!This) return E_OUTOFMEMORY;
166 This->IDWriteRenderingParams_iface.lpVtbl = &renderingparamsvtbl;
167 This->ref = 1;
169 This->gamma = gamma;
170 This->enh_contrast = enhancedContrast;
171 This->cleartype_level = cleartype_level;
172 This->geometry = geometry;
173 This->mode = mode;
175 *params = &This->IDWriteRenderingParams_iface;
177 return S_OK;
180 struct localizedpair {
181 WCHAR *locale;
182 WCHAR *string;
185 struct localizedstrings {
186 IDWriteLocalizedStrings IDWriteLocalizedStrings_iface;
187 LONG ref;
189 struct localizedpair *data;
190 UINT32 count;
191 UINT32 alloc;
194 static inline struct localizedstrings *impl_from_IDWriteLocalizedStrings(IDWriteLocalizedStrings *iface)
196 return CONTAINING_RECORD(iface, struct localizedstrings, IDWriteLocalizedStrings_iface);
199 static HRESULT WINAPI localizedstrings_QueryInterface(IDWriteLocalizedStrings *iface, REFIID riid, void **obj)
201 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
203 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
205 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteLocalizedStrings))
207 *obj = iface;
208 IDWriteLocalizedStrings_AddRef(iface);
209 return S_OK;
212 *obj = NULL;
214 return E_NOINTERFACE;
217 static ULONG WINAPI localizedstrings_AddRef(IDWriteLocalizedStrings *iface)
219 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
220 ULONG ref = InterlockedIncrement(&This->ref);
221 TRACE("(%p)->(%d)\n", This, ref);
222 return ref;
225 static ULONG WINAPI localizedstrings_Release(IDWriteLocalizedStrings *iface)
227 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
228 ULONG ref = InterlockedDecrement(&This->ref);
230 TRACE("(%p)->(%d)\n", This, ref);
232 if (!ref) {
233 unsigned int i;
235 for (i = 0; i < This->count; i++) {
236 heap_free(This->data[i].locale);
237 heap_free(This->data[i].string);
240 heap_free(This->data);
241 heap_free(This);
244 return ref;
247 static UINT32 WINAPI localizedstrings_GetCount(IDWriteLocalizedStrings *iface)
249 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
250 TRACE("(%p)\n", This);
251 return This->count;
254 static HRESULT WINAPI localizedstrings_FindLocaleName(IDWriteLocalizedStrings *iface,
255 WCHAR const *locale_name, UINT32 *index, BOOL *exists)
257 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
258 UINT32 i;
260 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(locale_name), index, exists);
262 *exists = FALSE;
263 *index = ~0;
265 for (i = 0; i < This->count; i++) {
266 if (!strcmpiW(This->data[i].locale, locale_name)) {
267 *exists = TRUE;
268 *index = i;
269 break;
273 return S_OK;
276 static HRESULT WINAPI localizedstrings_GetLocaleNameLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
278 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
280 TRACE("(%p)->(%u %p)\n", This, index, length);
282 if (index >= This->count) {
283 *length = (UINT32)-1;
284 return E_FAIL;
287 *length = strlenW(This->data[index].locale);
288 return S_OK;
291 static HRESULT WINAPI localizedstrings_GetLocaleName(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
293 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
295 TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
297 if (index >= This->count) {
298 if (buffer) *buffer = 0;
299 return E_FAIL;
302 if (size < strlenW(This->data[index].locale)+1) {
303 if (buffer) *buffer = 0;
304 return E_NOT_SUFFICIENT_BUFFER;
307 strcpyW(buffer, This->data[index].locale);
308 return S_OK;
311 static HRESULT WINAPI localizedstrings_GetStringLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
313 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
315 TRACE("(%p)->(%u %p)\n", This, index, length);
317 if (index >= This->count) {
318 *length = (UINT32)-1;
319 return E_FAIL;
322 *length = strlenW(This->data[index].string);
323 return S_OK;
326 static HRESULT WINAPI localizedstrings_GetString(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
328 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
330 TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
332 if (index >= This->count) {
333 if (buffer) *buffer = 0;
334 return E_FAIL;
337 if (size < strlenW(This->data[index].string)+1) {
338 if (buffer) *buffer = 0;
339 return E_NOT_SUFFICIENT_BUFFER;
342 strcpyW(buffer, This->data[index].string);
343 return S_OK;
346 static const IDWriteLocalizedStringsVtbl localizedstringsvtbl = {
347 localizedstrings_QueryInterface,
348 localizedstrings_AddRef,
349 localizedstrings_Release,
350 localizedstrings_GetCount,
351 localizedstrings_FindLocaleName,
352 localizedstrings_GetLocaleNameLength,
353 localizedstrings_GetLocaleName,
354 localizedstrings_GetStringLength,
355 localizedstrings_GetString
358 HRESULT create_localizedstrings(IDWriteLocalizedStrings **strings)
360 struct localizedstrings *This;
362 *strings = NULL;
364 This = heap_alloc(sizeof(struct localizedstrings));
365 if (!This) return E_OUTOFMEMORY;
367 This->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
368 This->ref = 1;
369 This->count = 0;
370 This->data = heap_alloc_zero(sizeof(struct localizedpair));
371 if (!This->data) {
372 heap_free(This);
373 return E_OUTOFMEMORY;
375 This->alloc = 1;
377 *strings = &This->IDWriteLocalizedStrings_iface;
379 return S_OK;
382 HRESULT add_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *locale, const WCHAR *string)
384 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
386 if (This->count == This->alloc) {
387 This->alloc *= 2;
388 This->data = heap_realloc(This->data, This->alloc*sizeof(struct localizedpair));
391 This->data[This->count].locale = heap_strdupW(locale);
392 This->data[This->count].string = heap_strdupW(string);
393 This->count++;
395 return S_OK;
398 HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **ret)
400 struct localizedstrings *strings, *strings_clone;
401 int i;
403 *ret = NULL;
405 if (!iface)
406 return S_FALSE;
408 strings = impl_from_IDWriteLocalizedStrings(iface);
409 strings_clone = heap_alloc(sizeof(struct localizedstrings));
410 if (!strings_clone) return E_OUTOFMEMORY;
412 strings_clone->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
413 strings_clone->ref = 1;
414 strings_clone->count = strings->count;
415 strings_clone->data = heap_alloc(sizeof(struct localizedpair) * strings_clone->count);
416 if (!strings_clone->data) {
417 heap_free(strings_clone);
418 return E_OUTOFMEMORY;
420 for (i = 0; i < strings_clone->count; i++)
422 strings_clone->data[i].locale = heap_strdupW(strings->data[i].locale);
423 strings_clone->data[i].string = heap_strdupW(strings->data[i].string);
425 strings_clone->alloc = strings_clone->count;
427 *ret = &strings_clone->IDWriteLocalizedStrings_iface;
429 return S_OK;
432 struct collectionloader
434 struct list entry;
435 IDWriteFontCollectionLoader *loader;
438 struct fontfacecached
440 struct list entry;
441 IDWriteFontFace *fontface;
444 struct fileloader
446 struct list entry;
447 struct list fontfaces;
448 IDWriteFontFileLoader *loader;
451 struct dwritefactory {
452 IDWriteFactory2 IDWriteFactory2_iface;
453 LONG ref;
455 IDWriteFontCollection *system_collection;
456 IDWriteFontCollection *eudc_collection;
457 IDWriteGdiInterop *gdiinterop;
459 IDWriteLocalFontFileLoader* localfontfileloader;
460 struct list localfontfaces;
462 struct list collection_loaders;
463 struct list file_loaders;
466 static inline struct dwritefactory *impl_from_IDWriteFactory2(IDWriteFactory2 *iface)
468 return CONTAINING_RECORD(iface, struct dwritefactory, IDWriteFactory2_iface);
471 static void release_fontface_cache(struct list *fontfaces)
473 struct fontfacecached *fontface, *fontface2;
474 LIST_FOR_EACH_ENTRY_SAFE(fontface, fontface2, fontfaces, struct fontfacecached, entry) {
475 list_remove(&fontface->entry);
476 IDWriteFontFace_Release(fontface->fontface);
477 heap_free(fontface);
481 static void release_fileloader(struct fileloader *fileloader)
483 list_remove(&fileloader->entry);
484 release_fontface_cache(&fileloader->fontfaces);
485 IDWriteFontFileLoader_Release(fileloader->loader);
486 heap_free(fileloader);
489 static void release_dwritefactory(struct dwritefactory *factory)
491 struct fileloader *fileloader, *fileloader2;
492 struct collectionloader *loader, *loader2;
494 if (factory->localfontfileloader)
495 IDWriteLocalFontFileLoader_Release(factory->localfontfileloader);
496 release_fontface_cache(&factory->localfontfaces);
498 LIST_FOR_EACH_ENTRY_SAFE(loader, loader2, &factory->collection_loaders, struct collectionloader, entry) {
499 list_remove(&loader->entry);
500 IDWriteFontCollectionLoader_Release(loader->loader);
501 heap_free(loader);
504 LIST_FOR_EACH_ENTRY_SAFE(fileloader, fileloader2, &factory->file_loaders, struct fileloader, entry)
505 release_fileloader(fileloader);
507 if (factory->system_collection)
508 IDWriteFontCollection_Release(factory->system_collection);
509 if (factory->eudc_collection)
510 IDWriteFontCollection_Release(factory->eudc_collection);
511 if (factory->gdiinterop)
512 release_gdiinterop(factory->gdiinterop);
513 heap_free(factory);
516 static void release_shared_factory(IDWriteFactory2 *iface)
518 struct dwritefactory *factory;
519 if (!iface) return;
520 factory = impl_from_IDWriteFactory2(iface);
521 release_dwritefactory(factory);
524 static struct fileloader *factory_get_file_loader(struct dwritefactory *factory, IDWriteFontFileLoader *loader)
526 struct fileloader *entry, *found = NULL;
528 LIST_FOR_EACH_ENTRY(entry, &factory->file_loaders, struct fileloader, entry) {
529 if (entry->loader == loader) {
530 found = entry;
531 break;
535 return found;
538 static struct collectionloader *factory_get_collection_loader(struct dwritefactory *factory, IDWriteFontCollectionLoader *loader)
540 struct collectionloader *entry, *found = NULL;
542 LIST_FOR_EACH_ENTRY(entry, &factory->collection_loaders, struct collectionloader, entry) {
543 if (entry->loader == loader) {
544 found = entry;
545 break;
549 return found;
552 static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory2 *iface, REFIID riid, void **obj)
554 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
556 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
558 if (IsEqualIID(riid, &IID_IDWriteFactory2) ||
559 IsEqualIID(riid, &IID_IDWriteFactory1) ||
560 IsEqualIID(riid, &IID_IDWriteFactory) ||
561 IsEqualIID(riid, &IID_IUnknown))
563 *obj = iface;
564 IDWriteFactory2_AddRef(iface);
565 return S_OK;
568 *obj = NULL;
570 return E_NOINTERFACE;
573 static ULONG WINAPI dwritefactory_AddRef(IDWriteFactory2 *iface)
575 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
576 ULONG ref = InterlockedIncrement(&This->ref);
577 TRACE("(%p)->(%d)\n", This, ref);
578 return ref;
581 static ULONG WINAPI dwritefactory_Release(IDWriteFactory2 *iface)
583 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
584 ULONG ref = InterlockedDecrement(&This->ref);
586 TRACE("(%p)->(%d)\n", This, ref);
588 if (!ref)
589 release_dwritefactory(This);
591 return ref;
594 static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory2 *iface,
595 IDWriteFontCollection **collection, BOOL check_for_updates)
597 HRESULT hr = S_OK;
598 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
599 TRACE("(%p)->(%p %d)\n", This, collection, check_for_updates);
601 if (check_for_updates)
602 FIXME("checking for system font updates not implemented\n");
604 if (!This->system_collection)
605 hr = get_system_fontcollection(iface, &This->system_collection);
607 if (SUCCEEDED(hr))
608 IDWriteFontCollection_AddRef(This->system_collection);
610 *collection = This->system_collection;
612 return hr;
615 static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory2 *iface,
616 IDWriteFontCollectionLoader *loader, void const *key, UINT32 key_size, IDWriteFontCollection **collection)
618 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
619 IDWriteFontFileEnumerator *enumerator;
620 struct collectionloader *found;
621 HRESULT hr;
623 TRACE("(%p)->(%p %p %u %p)\n", This, loader, key, key_size, collection);
625 *collection = NULL;
627 if (!loader)
628 return E_INVALIDARG;
630 found = factory_get_collection_loader(This, loader);
631 if (!found)
632 return E_INVALIDARG;
634 hr = IDWriteFontCollectionLoader_CreateEnumeratorFromKey(found->loader, (IDWriteFactory*)iface, key, key_size, &enumerator);
635 if (FAILED(hr))
636 return hr;
638 hr = create_font_collection(iface, enumerator, FALSE, collection);
639 IDWriteFontFileEnumerator_Release(enumerator);
640 return hr;
643 static HRESULT WINAPI dwritefactory_RegisterFontCollectionLoader(IDWriteFactory2 *iface,
644 IDWriteFontCollectionLoader *loader)
646 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
647 struct collectionloader *entry;
649 TRACE("(%p)->(%p)\n", This, loader);
651 if (!loader)
652 return E_INVALIDARG;
654 if (factory_get_collection_loader(This, loader))
655 return DWRITE_E_ALREADYREGISTERED;
657 entry = heap_alloc(sizeof(*entry));
658 if (!entry)
659 return E_OUTOFMEMORY;
661 entry->loader = loader;
662 IDWriteFontCollectionLoader_AddRef(loader);
663 list_add_tail(&This->collection_loaders, &entry->entry);
665 return S_OK;
668 static HRESULT WINAPI dwritefactory_UnregisterFontCollectionLoader(IDWriteFactory2 *iface,
669 IDWriteFontCollectionLoader *loader)
671 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
672 struct collectionloader *found;
674 TRACE("(%p)->(%p)\n", This, loader);
676 if (!loader)
677 return E_INVALIDARG;
679 found = factory_get_collection_loader(This, loader);
680 if (!found)
681 return E_INVALIDARG;
683 IDWriteFontCollectionLoader_Release(found->loader);
684 list_remove(&found->entry);
685 heap_free(found);
687 return S_OK;
690 static HRESULT WINAPI dwritefactory_CreateFontFileReference(IDWriteFactory2 *iface,
691 WCHAR const *path, FILETIME const *writetime, IDWriteFontFile **font_file)
693 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
694 UINT32 key_size;
695 HRESULT hr;
696 void *key;
698 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(path), writetime, font_file);
700 if (!This->localfontfileloader)
702 hr = create_localfontfileloader(&This->localfontfileloader);
703 if (FAILED(hr))
704 return hr;
707 /* get a reference key used by local loader */
708 hr = get_local_refkey(path, writetime, &key, &key_size);
709 if (FAILED(hr))
710 return hr;
712 hr = create_font_file((IDWriteFontFileLoader*)This->localfontfileloader, key, key_size, font_file);
713 heap_free(key);
715 return hr;
718 static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory2 *iface,
719 void const *reference_key, UINT32 key_size, IDWriteFontFileLoader *loader, IDWriteFontFile **font_file)
721 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
723 TRACE("(%p)->(%p %u %p %p)\n", This, reference_key, key_size, loader, font_file);
725 if (!loader || !factory_get_file_loader(This, loader))
726 return E_INVALIDARG;
728 return create_font_file(loader, reference_key, key_size, font_file);
731 static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory2 *iface,
732 DWRITE_FONT_FACE_TYPE req_facetype, UINT32 files_number, IDWriteFontFile* const* font_files,
733 UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face)
735 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
736 DWRITE_FONT_FILE_TYPE file_type;
737 DWRITE_FONT_FACE_TYPE face_type;
738 IDWriteFontFileLoader *loader;
739 struct fontfacecached *cached;
740 struct list *fontfaces;
741 IDWriteFontFace2 *face;
742 UINT32 key_size, count;
743 BOOL is_supported;
744 const void *key;
745 HRESULT hr;
747 TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, simulations, font_face);
749 *font_face = NULL;
751 if (!is_face_type_supported(req_facetype))
752 return E_INVALIDARG;
754 if (req_facetype != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION && index)
755 return E_INVALIDARG;
757 /* check actual file/face type */
758 is_supported = FALSE;
759 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
760 hr = IDWriteFontFile_Analyze(*font_files, &is_supported, &file_type, &face_type, &count);
761 if (FAILED(hr))
762 return hr;
764 if (!is_supported || (face_type != req_facetype))
765 return E_FAIL;
767 hr = IDWriteFontFile_GetReferenceKey(*font_files, &key, &key_size);
768 if (FAILED(hr))
769 return hr;
771 hr = IDWriteFontFile_GetLoader(*font_files, &loader);
772 if (FAILED(hr))
773 return hr;
775 if (loader == (IDWriteFontFileLoader*)This->localfontfileloader) {
776 fontfaces = &This->localfontfaces;
777 IDWriteFontFileLoader_Release(loader);
779 else {
780 struct fileloader *fileloader = factory_get_file_loader(This, loader);
781 IDWriteFontFileLoader_Release(loader);
782 if (!fileloader)
783 return E_INVALIDARG;
784 fontfaces = &fileloader->fontfaces;
787 /* search through cache list */
788 LIST_FOR_EACH_ENTRY(cached, fontfaces, struct fontfacecached, entry) {
789 UINT32 cached_key_size, count = 1, cached_face_index;
790 DWRITE_FONT_SIMULATIONS cached_simulations;
791 const void *cached_key;
792 IDWriteFontFile *file;
794 cached_face_index = IDWriteFontFace_GetIndex(cached->fontface);
795 cached_simulations = IDWriteFontFace_GetSimulations(cached->fontface);
797 /* skip earlier */
798 if (cached_face_index != index || cached_simulations != simulations)
799 continue;
801 hr = IDWriteFontFace_GetFiles(cached->fontface, &count, &file);
802 if (FAILED(hr))
803 return hr;
805 hr = IDWriteFontFile_GetReferenceKey(file, &cached_key, &cached_key_size);
806 IDWriteFontFile_Release(file);
807 if (FAILED(hr))
808 return hr;
810 if (cached_key_size == key_size && !memcmp(cached_key, key, key_size)) {
811 TRACE("returning cached fontface %p\n", cached->fontface);
812 *font_face = cached->fontface;
813 IDWriteFontFace_AddRef(*font_face);
814 return S_OK;
818 hr = create_fontface(req_facetype, files_number, font_files, index, simulations, &face);
819 if (FAILED(hr))
820 return hr;
822 /* new cache entry */
823 cached = heap_alloc(sizeof(*cached));
824 if (!cached) {
825 IDWriteFontFace2_Release(face);
826 return hr;
829 cached->fontface = (IDWriteFontFace*)face;
830 list_add_tail(fontfaces, &cached->entry);
832 *font_face = cached->fontface;
833 IDWriteFontFace_AddRef(*font_face);
835 return S_OK;
838 static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory2 *iface, IDWriteRenderingParams **params)
840 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
841 HMONITOR monitor;
842 POINT pt;
844 TRACE("(%p)->(%p)\n", This, params);
846 pt.x = pt.y = 0;
847 monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
848 return IDWriteFactory2_CreateMonitorRenderingParams(iface, monitor, params);
851 static HRESULT WINAPI dwritefactory_CreateMonitorRenderingParams(IDWriteFactory2 *iface, HMONITOR monitor,
852 IDWriteRenderingParams **params)
854 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
855 static int fixme_once = 0;
857 TRACE("(%p)->(%p %p)\n", This, monitor, params);
859 if (!fixme_once++)
860 FIXME("(%p): monitor setting ignored\n", monitor);
861 return IDWriteFactory_CreateCustomRenderingParams((IDWriteFactory*)iface, 0.0, 0.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT,
862 DWRITE_RENDERING_MODE_DEFAULT, params);
865 static HRESULT WINAPI dwritefactory_CreateCustomRenderingParams(IDWriteFactory2 *iface, FLOAT gamma, FLOAT enhancedContrast,
866 FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode, IDWriteRenderingParams **params)
868 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
869 TRACE("(%p)->(%f %f %f %d %d %p)\n", This, gamma, enhancedContrast, cleartype_level, geometry, mode, params);
870 return create_renderingparams(gamma, enhancedContrast, cleartype_level, geometry, mode, params);
873 static HRESULT WINAPI dwritefactory_RegisterFontFileLoader(IDWriteFactory2 *iface, IDWriteFontFileLoader *loader)
875 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
876 struct fileloader *entry;
878 TRACE("(%p)->(%p)\n", This, loader);
880 if (!loader)
881 return E_INVALIDARG;
883 if ((IDWriteFontFileLoader*)This->localfontfileloader == loader)
884 return S_OK;
886 if (factory_get_file_loader(This, loader))
887 return DWRITE_E_ALREADYREGISTERED;
889 entry = heap_alloc(sizeof(*entry));
890 if (!entry)
891 return E_OUTOFMEMORY;
893 entry->loader = loader;
894 list_init(&entry->fontfaces);
895 IDWriteFontFileLoader_AddRef(loader);
896 list_add_tail(&This->file_loaders, &entry->entry);
898 return S_OK;
901 static HRESULT WINAPI dwritefactory_UnregisterFontFileLoader(IDWriteFactory2 *iface, IDWriteFontFileLoader *loader)
903 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
904 struct fileloader *found;
906 TRACE("(%p)->(%p)\n", This, loader);
908 if (!loader)
909 return E_INVALIDARG;
911 if ((IDWriteFontFileLoader*)This->localfontfileloader == loader)
912 return S_OK;
914 found = factory_get_file_loader(This, loader);
915 if (!found)
916 return E_INVALIDARG;
918 release_fileloader(found);
919 return S_OK;
922 static HRESULT WINAPI dwritefactory_CreateTextFormat(IDWriteFactory2 *iface, WCHAR const* family_name,
923 IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
924 DWRITE_FONT_STRETCH stretch, FLOAT size, WCHAR const *locale, IDWriteTextFormat **format)
926 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
927 IDWriteFontCollection *syscollection = NULL;
928 HRESULT hr;
930 TRACE("(%p)->(%s %p %d %d %d %f %s %p)\n", This, debugstr_w(family_name), collection, weight, style, stretch,
931 size, debugstr_w(locale), format);
933 if (!collection) {
934 hr = IDWriteFactory2_GetSystemFontCollection(iface, &syscollection, FALSE);
935 if (FAILED(hr))
936 return hr;
939 hr = create_textformat(family_name, collection ? collection : syscollection, weight, style, stretch, size, locale, format);
940 if (syscollection)
941 IDWriteFontCollection_Release(syscollection);
942 return hr;
945 static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory2 *iface, IDWriteTypography **typography)
947 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
948 TRACE("(%p)->(%p)\n", This, typography);
949 return create_typography(typography);
952 static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory2 *iface, IDWriteGdiInterop **gdi_interop)
954 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
956 TRACE("(%p)->(%p)\n", This, gdi_interop);
958 *gdi_interop = NULL;
960 if (!This->gdiinterop) {
961 HRESULT hr = create_gdiinterop(iface, &This->gdiinterop);
962 if (FAILED(hr))
963 return hr;
966 *gdi_interop = This->gdiinterop;
967 IDWriteGdiInterop_AddRef(*gdi_interop);
969 return S_OK;
972 static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory2 *iface, WCHAR const* string,
973 UINT32 len, IDWriteTextFormat *format, FLOAT max_width, FLOAT max_height, IDWriteTextLayout **layout)
975 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
976 TRACE("(%p)->(%s %u %p %f %f %p)\n", This, debugstr_w(string), len, format, max_width, max_height, layout);
978 if (!format) return E_INVALIDARG;
979 return create_textlayout(string, len, format, max_width, max_height, layout);
982 static HRESULT WINAPI dwritefactory_CreateGdiCompatibleTextLayout(IDWriteFactory2 *iface, WCHAR const* string,
983 UINT32 len, IDWriteTextFormat *format, FLOAT layout_width, FLOAT layout_height, FLOAT pixels_per_dip,
984 DWRITE_MATRIX const* transform, BOOL use_gdi_natural, IDWriteTextLayout **layout)
986 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
987 FIXME("(%p)->(%s:%u %p %f %f %f %p %d %p): semi-stub\n", This, debugstr_wn(string, len), len, format, layout_width, layout_height,
988 pixels_per_dip, transform, use_gdi_natural, layout);
990 if (!format) return E_INVALIDARG;
991 return create_textlayout(string, len, format, layout_width, layout_height, layout);
994 static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory2 *iface, IDWriteTextFormat *format,
995 IDWriteInlineObject **trimming_sign)
997 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
998 FIXME("(%p)->(%p %p): semi-stub\n", This, format, trimming_sign);
999 return create_trimmingsign(trimming_sign);
1002 static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory2 *iface, IDWriteTextAnalyzer **analyzer)
1004 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1005 TRACE("(%p)->(%p)\n", This, analyzer);
1006 return get_textanalyzer(analyzer);
1009 static HRESULT WINAPI dwritefactory_CreateNumberSubstitution(IDWriteFactory2 *iface, DWRITE_NUMBER_SUBSTITUTION_METHOD method,
1010 WCHAR const* locale, BOOL ignore_user_override, IDWriteNumberSubstitution **substitution)
1012 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1013 TRACE("(%p)->(%d %s %d %p)\n", This, method, debugstr_w(locale), ignore_user_override, substitution);
1014 return create_numbersubstitution(method, locale, ignore_user_override, substitution);
1017 static HRESULT WINAPI dwritefactory_CreateGlyphRunAnalysis(IDWriteFactory2 *iface, DWRITE_GLYPH_RUN const *glyph_run,
1018 FLOAT pixels_per_dip, DWRITE_MATRIX const* transform, DWRITE_RENDERING_MODE rendering_mode,
1019 DWRITE_MEASURING_MODE measuring_mode, FLOAT baseline_x, FLOAT baseline_y, IDWriteGlyphRunAnalysis **analysis)
1021 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1022 FIXME("(%p)->(%p %f %p %d %d %f %f %p): stub\n", This, glyph_run, pixels_per_dip, transform, rendering_mode,
1023 measuring_mode, baseline_x, baseline_y, analysis);
1024 return E_NOTIMPL;
1027 static HRESULT WINAPI dwritefactory1_GetEudcFontCollection(IDWriteFactory2 *iface, IDWriteFontCollection **collection,
1028 BOOL check_for_updates)
1030 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1031 HRESULT hr = S_OK;
1033 TRACE("(%p)->(%p %d)\n", This, collection, check_for_updates);
1035 if (check_for_updates)
1036 FIXME("checking for eudc updates not implemented\n");
1038 if (!This->eudc_collection)
1039 hr = get_eudc_fontcollection(iface, &This->eudc_collection);
1041 if (SUCCEEDED(hr))
1042 IDWriteFontCollection_AddRef(This->eudc_collection);
1044 *collection = This->eudc_collection;
1046 return hr;
1049 static HRESULT WINAPI dwritefactory1_CreateCustomRenderingParams(IDWriteFactory2 *iface, FLOAT gamma,
1050 FLOAT enhcontrast, FLOAT enhcontrast_grayscale, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry,
1051 DWRITE_RENDERING_MODE mode, IDWriteRenderingParams1** params)
1053 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1054 FIXME("(%p)->(%.2f %.2f %.2f %.2f %d %d %p): stub\n", This, gamma, enhcontrast, enhcontrast_grayscale,
1055 cleartype_level, geometry, mode, params);
1056 return E_NOTIMPL;
1059 static HRESULT WINAPI dwritefactory2_GetSystemFontFallback(IDWriteFactory2 *iface, IDWriteFontFallback **fallback)
1061 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1062 FIXME("(%p)->(%p): stub\n", This, fallback);
1063 return E_NOTIMPL;
1066 static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory2 *iface, IDWriteFontFallbackBuilder **fallbackbuilder)
1068 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1069 FIXME("(%p)->(%p): stub\n", This, fallbackbuilder);
1070 return E_NOTIMPL;
1073 static HRESULT WINAPI dwritefactory2_TranslateColorGlyphRun(IDWriteFactory2 *iface, FLOAT originX, FLOAT originY,
1074 const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE mode,
1075 const DWRITE_MATRIX *transform, UINT32 palette_index, IDWriteColorGlyphRunEnumerator **colorlayers)
1077 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1078 FIXME("(%p)->(%.2f %.2f %p %p %d %p %u %p): stub\n", This, originX, originY, run, rundescr, mode,
1079 transform, palette_index, colorlayers);
1080 return E_NOTIMPL;
1083 static HRESULT WINAPI dwritefactory2_CreateCustomRenderingParams(IDWriteFactory2 *iface, FLOAT gamma, FLOAT contrast,
1084 FLOAT grayscalecontrast, FLOAT cleartypeLevel, DWRITE_PIXEL_GEOMETRY pixelGeometry, DWRITE_RENDERING_MODE renderingMode,
1085 DWRITE_GRID_FIT_MODE gridFitMode, IDWriteRenderingParams2 **params)
1087 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1088 FIXME("(%p)->(%.2f %.2f %.2f %.2f %d %d %d %p): stub\n", This, gamma, contrast, grayscalecontrast, cleartypeLevel,
1089 pixelGeometry, renderingMode, gridFitMode, params);
1090 return E_NOTIMPL;
1093 static HRESULT WINAPI dwritefactory2_CreateGlyphRunAnalysis(IDWriteFactory2 *iface, const DWRITE_GLYPH_RUN *run,
1094 const DWRITE_MATRIX *transform, DWRITE_RENDERING_MODE renderingMode, DWRITE_MEASURING_MODE measuringMode,
1095 DWRITE_GRID_FIT_MODE gridFitMode, DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, FLOAT originX, FLOAT originY,
1096 IDWriteGlyphRunAnalysis **analysis)
1098 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1099 FIXME("(%p)->(%p %p %d %d %d %d %.2f %.2f %p): stub\n", This, run, transform, renderingMode, measuringMode,
1100 gridFitMode, antialiasMode, originX, originY, analysis);
1101 return E_NOTIMPL;
1104 static const struct IDWriteFactory2Vtbl dwritefactoryvtbl = {
1105 dwritefactory_QueryInterface,
1106 dwritefactory_AddRef,
1107 dwritefactory_Release,
1108 dwritefactory_GetSystemFontCollection,
1109 dwritefactory_CreateCustomFontCollection,
1110 dwritefactory_RegisterFontCollectionLoader,
1111 dwritefactory_UnregisterFontCollectionLoader,
1112 dwritefactory_CreateFontFileReference,
1113 dwritefactory_CreateCustomFontFileReference,
1114 dwritefactory_CreateFontFace,
1115 dwritefactory_CreateRenderingParams,
1116 dwritefactory_CreateMonitorRenderingParams,
1117 dwritefactory_CreateCustomRenderingParams,
1118 dwritefactory_RegisterFontFileLoader,
1119 dwritefactory_UnregisterFontFileLoader,
1120 dwritefactory_CreateTextFormat,
1121 dwritefactory_CreateTypography,
1122 dwritefactory_GetGdiInterop,
1123 dwritefactory_CreateTextLayout,
1124 dwritefactory_CreateGdiCompatibleTextLayout,
1125 dwritefactory_CreateEllipsisTrimmingSign,
1126 dwritefactory_CreateTextAnalyzer,
1127 dwritefactory_CreateNumberSubstitution,
1128 dwritefactory_CreateGlyphRunAnalysis,
1129 dwritefactory1_GetEudcFontCollection,
1130 dwritefactory1_CreateCustomRenderingParams,
1131 dwritefactory2_GetSystemFontFallback,
1132 dwritefactory2_CreateFontFallbackBuilder,
1133 dwritefactory2_TranslateColorGlyphRun,
1134 dwritefactory2_CreateCustomRenderingParams,
1135 dwritefactory2_CreateGlyphRunAnalysis
1138 static ULONG WINAPI shareddwritefactory_AddRef(IDWriteFactory2 *iface)
1140 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1141 TRACE("(%p)\n", This);
1142 return 2;
1145 static ULONG WINAPI shareddwritefactory_Release(IDWriteFactory2 *iface)
1147 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1148 TRACE("(%p)\n", This);
1149 return 1;
1152 static const struct IDWriteFactory2Vtbl shareddwritefactoryvtbl = {
1153 dwritefactory_QueryInterface,
1154 shareddwritefactory_AddRef,
1155 shareddwritefactory_Release,
1156 dwritefactory_GetSystemFontCollection,
1157 dwritefactory_CreateCustomFontCollection,
1158 dwritefactory_RegisterFontCollectionLoader,
1159 dwritefactory_UnregisterFontCollectionLoader,
1160 dwritefactory_CreateFontFileReference,
1161 dwritefactory_CreateCustomFontFileReference,
1162 dwritefactory_CreateFontFace,
1163 dwritefactory_CreateRenderingParams,
1164 dwritefactory_CreateMonitorRenderingParams,
1165 dwritefactory_CreateCustomRenderingParams,
1166 dwritefactory_RegisterFontFileLoader,
1167 dwritefactory_UnregisterFontFileLoader,
1168 dwritefactory_CreateTextFormat,
1169 dwritefactory_CreateTypography,
1170 dwritefactory_GetGdiInterop,
1171 dwritefactory_CreateTextLayout,
1172 dwritefactory_CreateGdiCompatibleTextLayout,
1173 dwritefactory_CreateEllipsisTrimmingSign,
1174 dwritefactory_CreateTextAnalyzer,
1175 dwritefactory_CreateNumberSubstitution,
1176 dwritefactory_CreateGlyphRunAnalysis,
1177 dwritefactory1_GetEudcFontCollection,
1178 dwritefactory1_CreateCustomRenderingParams,
1179 dwritefactory2_GetSystemFontFallback,
1180 dwritefactory2_CreateFontFallbackBuilder,
1181 dwritefactory2_TranslateColorGlyphRun,
1182 dwritefactory2_CreateCustomRenderingParams,
1183 dwritefactory2_CreateGlyphRunAnalysis
1186 static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYPE type)
1188 factory->IDWriteFactory2_iface.lpVtbl = type == DWRITE_FACTORY_TYPE_SHARED ? &shareddwritefactoryvtbl : &dwritefactoryvtbl;
1189 factory->ref = 1;
1190 factory->localfontfileloader = NULL;
1191 factory->system_collection = NULL;
1192 factory->eudc_collection = NULL;
1193 factory->gdiinterop = NULL;
1195 list_init(&factory->collection_loaders);
1196 list_init(&factory->file_loaders);
1197 list_init(&factory->localfontfaces);
1200 HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
1202 struct dwritefactory *factory;
1204 TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), ret);
1206 *ret = NULL;
1208 if (!IsEqualIID(riid, &IID_IDWriteFactory) &&
1209 !IsEqualIID(riid, &IID_IDWriteFactory1) &&
1210 !IsEqualIID(riid, &IID_IDWriteFactory2))
1211 return E_FAIL;
1213 if (type == DWRITE_FACTORY_TYPE_SHARED && shared_factory) {
1214 *ret = (IUnknown*)shared_factory;
1215 IDWriteFactory2_AddRef(shared_factory);
1216 return S_OK;
1219 factory = heap_alloc(sizeof(struct dwritefactory));
1220 if (!factory) return E_OUTOFMEMORY;
1222 init_dwritefactory(factory, type);
1224 if (type == DWRITE_FACTORY_TYPE_SHARED)
1225 if (InterlockedCompareExchangePointer((void**)&shared_factory, &factory->IDWriteFactory2_iface, NULL)) {
1226 release_shared_factory(&factory->IDWriteFactory2_iface);
1227 *ret = (IUnknown*)shared_factory;
1228 IDWriteFactory2_AddRef(shared_factory);
1229 return S_OK;
1232 *ret = (IUnknown*)&factory->IDWriteFactory2_iface;
1233 return S_OK;