riched20: Initial support for changing font properties.
[wine/multimedia.git] / dlls / dwrite / main.c
blob20f9d36a3a5cb5874ce493727b8a068d70332661
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);
51 release_freetype();
53 return TRUE;
56 struct renderingparams {
57 IDWriteRenderingParams2 IDWriteRenderingParams2_iface;
58 LONG ref;
60 FLOAT gamma;
61 FLOAT contrast;
62 FLOAT grayscalecontrast;
63 FLOAT cleartype_level;
64 DWRITE_PIXEL_GEOMETRY geometry;
65 DWRITE_RENDERING_MODE mode;
66 DWRITE_GRID_FIT_MODE gridfit;
69 static inline struct renderingparams *impl_from_IDWriteRenderingParams2(IDWriteRenderingParams2 *iface)
71 return CONTAINING_RECORD(iface, struct renderingparams, IDWriteRenderingParams2_iface);
74 static HRESULT WINAPI renderingparams_QueryInterface(IDWriteRenderingParams2 *iface, REFIID riid, void **obj)
76 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
78 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
80 if (IsEqualIID(riid, &IID_IDWriteRenderingParams2) ||
81 IsEqualIID(riid, &IID_IDWriteRenderingParams1) ||
82 IsEqualIID(riid, &IID_IDWriteRenderingParams) ||
83 IsEqualIID(riid, &IID_IUnknown))
85 *obj = iface;
86 IDWriteRenderingParams2_AddRef(iface);
87 return S_OK;
90 *obj = NULL;
92 return E_NOINTERFACE;
95 static ULONG WINAPI renderingparams_AddRef(IDWriteRenderingParams2 *iface)
97 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
98 ULONG ref = InterlockedIncrement(&This->ref);
99 TRACE("(%p)->(%d)\n", This, ref);
100 return ref;
103 static ULONG WINAPI renderingparams_Release(IDWriteRenderingParams2 *iface)
105 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
106 ULONG ref = InterlockedDecrement(&This->ref);
108 TRACE("(%p)->(%d)\n", This, ref);
110 if (!ref)
111 heap_free(This);
113 return ref;
116 static FLOAT WINAPI renderingparams_GetGamma(IDWriteRenderingParams2 *iface)
118 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
119 TRACE("(%p)\n", This);
120 return This->gamma;
123 static FLOAT WINAPI renderingparams_GetEnhancedContrast(IDWriteRenderingParams2 *iface)
125 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
126 TRACE("(%p)\n", This);
127 return This->contrast;
130 static FLOAT WINAPI renderingparams_GetClearTypeLevel(IDWriteRenderingParams2 *iface)
132 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
133 TRACE("(%p)\n", This);
134 return This->cleartype_level;
137 static DWRITE_PIXEL_GEOMETRY WINAPI renderingparams_GetPixelGeometry(IDWriteRenderingParams2 *iface)
139 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
140 TRACE("(%p)\n", This);
141 return This->geometry;
144 static DWRITE_RENDERING_MODE WINAPI renderingparams_GetRenderingMode(IDWriteRenderingParams2 *iface)
146 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
147 TRACE("(%p)\n", This);
148 return This->mode;
151 static FLOAT WINAPI renderingparams_GetGrayscaleEnhancedContrast(IDWriteRenderingParams2 *iface)
153 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
154 TRACE("(%p)\n", This);
155 return This->grayscalecontrast;
158 static DWRITE_GRID_FIT_MODE WINAPI renderingparams_GetGridFitMode(IDWriteRenderingParams2 *iface)
160 struct renderingparams *This = impl_from_IDWriteRenderingParams2(iface);
161 TRACE("(%p)\n", This);
162 return This->gridfit;
165 static const struct IDWriteRenderingParams2Vtbl renderingparamsvtbl = {
166 renderingparams_QueryInterface,
167 renderingparams_AddRef,
168 renderingparams_Release,
169 renderingparams_GetGamma,
170 renderingparams_GetEnhancedContrast,
171 renderingparams_GetClearTypeLevel,
172 renderingparams_GetPixelGeometry,
173 renderingparams_GetRenderingMode,
174 renderingparams_GetGrayscaleEnhancedContrast,
175 renderingparams_GetGridFitMode
178 static HRESULT create_renderingparams(FLOAT gamma, FLOAT contrast, FLOAT grayscalecontrast, FLOAT cleartype_level,
179 DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode, DWRITE_GRID_FIT_MODE gridfit, IDWriteRenderingParams2 **params)
181 struct renderingparams *This;
183 *params = NULL;
185 This = heap_alloc(sizeof(struct renderingparams));
186 if (!This) return E_OUTOFMEMORY;
188 This->IDWriteRenderingParams2_iface.lpVtbl = &renderingparamsvtbl;
189 This->ref = 1;
191 This->gamma = gamma;
192 This->contrast = contrast;
193 This->grayscalecontrast = grayscalecontrast;
194 This->cleartype_level = cleartype_level;
195 This->geometry = geometry;
196 This->mode = mode;
197 This->gridfit = gridfit;
199 *params = &This->IDWriteRenderingParams2_iface;
201 return S_OK;
204 struct localizedpair {
205 WCHAR *locale;
206 WCHAR *string;
209 struct localizedstrings {
210 IDWriteLocalizedStrings IDWriteLocalizedStrings_iface;
211 LONG ref;
213 struct localizedpair *data;
214 UINT32 count;
215 UINT32 alloc;
218 static inline struct localizedstrings *impl_from_IDWriteLocalizedStrings(IDWriteLocalizedStrings *iface)
220 return CONTAINING_RECORD(iface, struct localizedstrings, IDWriteLocalizedStrings_iface);
223 static HRESULT WINAPI localizedstrings_QueryInterface(IDWriteLocalizedStrings *iface, REFIID riid, void **obj)
225 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
227 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
229 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteLocalizedStrings))
231 *obj = iface;
232 IDWriteLocalizedStrings_AddRef(iface);
233 return S_OK;
236 *obj = NULL;
238 return E_NOINTERFACE;
241 static ULONG WINAPI localizedstrings_AddRef(IDWriteLocalizedStrings *iface)
243 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
244 ULONG ref = InterlockedIncrement(&This->ref);
245 TRACE("(%p)->(%d)\n", This, ref);
246 return ref;
249 static ULONG WINAPI localizedstrings_Release(IDWriteLocalizedStrings *iface)
251 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
252 ULONG ref = InterlockedDecrement(&This->ref);
254 TRACE("(%p)->(%d)\n", This, ref);
256 if (!ref) {
257 unsigned int i;
259 for (i = 0; i < This->count; i++) {
260 heap_free(This->data[i].locale);
261 heap_free(This->data[i].string);
264 heap_free(This->data);
265 heap_free(This);
268 return ref;
271 static UINT32 WINAPI localizedstrings_GetCount(IDWriteLocalizedStrings *iface)
273 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
274 TRACE("(%p)\n", This);
275 return This->count;
278 static HRESULT WINAPI localizedstrings_FindLocaleName(IDWriteLocalizedStrings *iface,
279 WCHAR const *locale_name, UINT32 *index, BOOL *exists)
281 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
282 UINT32 i;
284 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(locale_name), index, exists);
286 *exists = FALSE;
287 *index = ~0;
289 for (i = 0; i < This->count; i++) {
290 if (!strcmpiW(This->data[i].locale, locale_name)) {
291 *exists = TRUE;
292 *index = i;
293 break;
297 return S_OK;
300 static HRESULT WINAPI localizedstrings_GetLocaleNameLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
302 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
304 TRACE("(%p)->(%u %p)\n", This, index, length);
306 if (index >= This->count) {
307 *length = (UINT32)-1;
308 return E_FAIL;
311 *length = strlenW(This->data[index].locale);
312 return S_OK;
315 static HRESULT WINAPI localizedstrings_GetLocaleName(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
317 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
319 TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
321 if (index >= This->count) {
322 if (buffer) *buffer = 0;
323 return E_FAIL;
326 if (size < strlenW(This->data[index].locale)+1) {
327 if (buffer) *buffer = 0;
328 return E_NOT_SUFFICIENT_BUFFER;
331 strcpyW(buffer, This->data[index].locale);
332 return S_OK;
335 static HRESULT WINAPI localizedstrings_GetStringLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
337 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
339 TRACE("(%p)->(%u %p)\n", This, index, length);
341 if (index >= This->count) {
342 *length = (UINT32)-1;
343 return E_FAIL;
346 *length = strlenW(This->data[index].string);
347 return S_OK;
350 static HRESULT WINAPI localizedstrings_GetString(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
352 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
354 TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
356 if (index >= This->count) {
357 if (buffer) *buffer = 0;
358 return E_FAIL;
361 if (size < strlenW(This->data[index].string)+1) {
362 if (buffer) *buffer = 0;
363 return E_NOT_SUFFICIENT_BUFFER;
366 strcpyW(buffer, This->data[index].string);
367 return S_OK;
370 static const IDWriteLocalizedStringsVtbl localizedstringsvtbl = {
371 localizedstrings_QueryInterface,
372 localizedstrings_AddRef,
373 localizedstrings_Release,
374 localizedstrings_GetCount,
375 localizedstrings_FindLocaleName,
376 localizedstrings_GetLocaleNameLength,
377 localizedstrings_GetLocaleName,
378 localizedstrings_GetStringLength,
379 localizedstrings_GetString
382 HRESULT create_localizedstrings(IDWriteLocalizedStrings **strings)
384 struct localizedstrings *This;
386 *strings = NULL;
388 This = heap_alloc(sizeof(struct localizedstrings));
389 if (!This) return E_OUTOFMEMORY;
391 This->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
392 This->ref = 1;
393 This->count = 0;
394 This->data = heap_alloc_zero(sizeof(struct localizedpair));
395 if (!This->data) {
396 heap_free(This);
397 return E_OUTOFMEMORY;
399 This->alloc = 1;
401 *strings = &This->IDWriteLocalizedStrings_iface;
403 return S_OK;
406 HRESULT add_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *locale, const WCHAR *string)
408 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
409 UINT32 i;
411 /* make sure there's no duplicates */
412 for (i = 0; i < This->count; i++)
413 if (!strcmpW(This->data[i].locale, locale))
414 return S_OK;
416 if (This->count == This->alloc) {
417 void *ptr;
419 ptr = heap_realloc(This->data, 2*This->alloc*sizeof(struct localizedpair));
420 if (!ptr)
421 return E_OUTOFMEMORY;
423 This->alloc *= 2;
424 This->data = ptr;
427 This->data[This->count].locale = heap_strdupW(locale);
428 This->data[This->count].string = heap_strdupW(string);
429 if (!This->data[This->count].locale || !This->data[This->count].string) {
430 heap_free(This->data[This->count].locale);
431 heap_free(This->data[This->count].string);
432 return E_OUTOFMEMORY;
435 This->count++;
437 return S_OK;
440 HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **ret)
442 struct localizedstrings *strings, *strings_clone;
443 int i;
445 *ret = NULL;
447 if (!iface)
448 return S_FALSE;
450 strings = impl_from_IDWriteLocalizedStrings(iface);
451 strings_clone = heap_alloc(sizeof(struct localizedstrings));
452 if (!strings_clone) return E_OUTOFMEMORY;
454 strings_clone->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
455 strings_clone->ref = 1;
456 strings_clone->count = strings->count;
457 strings_clone->data = heap_alloc(sizeof(struct localizedpair) * strings_clone->count);
458 if (!strings_clone->data) {
459 heap_free(strings_clone);
460 return E_OUTOFMEMORY;
462 for (i = 0; i < strings_clone->count; i++)
464 strings_clone->data[i].locale = heap_strdupW(strings->data[i].locale);
465 strings_clone->data[i].string = heap_strdupW(strings->data[i].string);
467 strings_clone->alloc = strings_clone->count;
469 *ret = &strings_clone->IDWriteLocalizedStrings_iface;
471 return S_OK;
474 struct collectionloader
476 struct list entry;
477 IDWriteFontCollectionLoader *loader;
480 struct fontfacecached
482 struct list entry;
483 IDWriteFontFace *fontface;
486 struct fileloader
488 struct list entry;
489 struct list fontfaces;
490 IDWriteFontFileLoader *loader;
493 struct dwritefactory {
494 IDWriteFactory2 IDWriteFactory2_iface;
495 LONG ref;
497 IDWriteFontCollection *system_collection;
498 IDWriteFontCollection *eudc_collection;
499 IDWriteGdiInterop *gdiinterop;
501 IDWriteLocalFontFileLoader* localfontfileloader;
502 struct list localfontfaces;
504 struct list collection_loaders;
505 struct list file_loaders;
508 static inline struct dwritefactory *impl_from_IDWriteFactory2(IDWriteFactory2 *iface)
510 return CONTAINING_RECORD(iface, struct dwritefactory, IDWriteFactory2_iface);
513 static void release_fontface_cache(struct list *fontfaces)
515 struct fontfacecached *fontface, *fontface2;
516 LIST_FOR_EACH_ENTRY_SAFE(fontface, fontface2, fontfaces, struct fontfacecached, entry) {
517 list_remove(&fontface->entry);
518 IDWriteFontFace_Release(fontface->fontface);
519 heap_free(fontface);
523 static void release_fileloader(struct fileloader *fileloader)
525 list_remove(&fileloader->entry);
526 release_fontface_cache(&fileloader->fontfaces);
527 IDWriteFontFileLoader_Release(fileloader->loader);
528 heap_free(fileloader);
531 static void release_dwritefactory(struct dwritefactory *factory)
533 struct fileloader *fileloader, *fileloader2;
534 struct collectionloader *loader, *loader2;
536 if (factory->localfontfileloader)
537 IDWriteLocalFontFileLoader_Release(factory->localfontfileloader);
538 release_fontface_cache(&factory->localfontfaces);
540 LIST_FOR_EACH_ENTRY_SAFE(loader, loader2, &factory->collection_loaders, struct collectionloader, entry) {
541 list_remove(&loader->entry);
542 IDWriteFontCollectionLoader_Release(loader->loader);
543 heap_free(loader);
546 LIST_FOR_EACH_ENTRY_SAFE(fileloader, fileloader2, &factory->file_loaders, struct fileloader, entry)
547 release_fileloader(fileloader);
549 if (factory->system_collection)
550 IDWriteFontCollection_Release(factory->system_collection);
551 if (factory->eudc_collection)
552 IDWriteFontCollection_Release(factory->eudc_collection);
553 if (factory->gdiinterop)
554 release_gdiinterop(factory->gdiinterop);
555 heap_free(factory);
558 static void release_shared_factory(IDWriteFactory2 *iface)
560 struct dwritefactory *factory;
561 if (!iface) return;
562 factory = impl_from_IDWriteFactory2(iface);
563 release_dwritefactory(factory);
566 static struct fileloader *factory_get_file_loader(struct dwritefactory *factory, IDWriteFontFileLoader *loader)
568 struct fileloader *entry, *found = NULL;
570 LIST_FOR_EACH_ENTRY(entry, &factory->file_loaders, struct fileloader, entry) {
571 if (entry->loader == loader) {
572 found = entry;
573 break;
577 return found;
580 static struct collectionloader *factory_get_collection_loader(struct dwritefactory *factory, IDWriteFontCollectionLoader *loader)
582 struct collectionloader *entry, *found = NULL;
584 LIST_FOR_EACH_ENTRY(entry, &factory->collection_loaders, struct collectionloader, entry) {
585 if (entry->loader == loader) {
586 found = entry;
587 break;
591 return found;
594 static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory2 *iface, REFIID riid, void **obj)
596 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
598 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
600 if (IsEqualIID(riid, &IID_IDWriteFactory2) ||
601 IsEqualIID(riid, &IID_IDWriteFactory1) ||
602 IsEqualIID(riid, &IID_IDWriteFactory) ||
603 IsEqualIID(riid, &IID_IUnknown))
605 *obj = iface;
606 IDWriteFactory2_AddRef(iface);
607 return S_OK;
610 *obj = NULL;
612 return E_NOINTERFACE;
615 static ULONG WINAPI dwritefactory_AddRef(IDWriteFactory2 *iface)
617 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
618 ULONG ref = InterlockedIncrement(&This->ref);
619 TRACE("(%p)->(%d)\n", This, ref);
620 return ref;
623 static ULONG WINAPI dwritefactory_Release(IDWriteFactory2 *iface)
625 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
626 ULONG ref = InterlockedDecrement(&This->ref);
628 TRACE("(%p)->(%d)\n", This, ref);
630 if (!ref)
631 release_dwritefactory(This);
633 return ref;
636 static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory2 *iface,
637 IDWriteFontCollection **collection, BOOL check_for_updates)
639 HRESULT hr = S_OK;
640 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
641 TRACE("(%p)->(%p %d)\n", This, collection, check_for_updates);
643 if (check_for_updates)
644 FIXME("checking for system font updates not implemented\n");
646 if (!This->system_collection)
647 hr = get_system_fontcollection(iface, &This->system_collection);
649 if (SUCCEEDED(hr))
650 IDWriteFontCollection_AddRef(This->system_collection);
652 *collection = This->system_collection;
654 return hr;
657 static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory2 *iface,
658 IDWriteFontCollectionLoader *loader, void const *key, UINT32 key_size, IDWriteFontCollection **collection)
660 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
661 IDWriteFontFileEnumerator *enumerator;
662 struct collectionloader *found;
663 HRESULT hr;
665 TRACE("(%p)->(%p %p %u %p)\n", This, loader, key, key_size, collection);
667 *collection = NULL;
669 if (!loader)
670 return E_INVALIDARG;
672 found = factory_get_collection_loader(This, loader);
673 if (!found)
674 return E_INVALIDARG;
676 hr = IDWriteFontCollectionLoader_CreateEnumeratorFromKey(found->loader, (IDWriteFactory*)iface, key, key_size, &enumerator);
677 if (FAILED(hr))
678 return hr;
680 hr = create_font_collection(iface, enumerator, FALSE, collection);
681 IDWriteFontFileEnumerator_Release(enumerator);
682 return hr;
685 static HRESULT WINAPI dwritefactory_RegisterFontCollectionLoader(IDWriteFactory2 *iface,
686 IDWriteFontCollectionLoader *loader)
688 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
689 struct collectionloader *entry;
691 TRACE("(%p)->(%p)\n", This, loader);
693 if (!loader)
694 return E_INVALIDARG;
696 if (factory_get_collection_loader(This, loader))
697 return DWRITE_E_ALREADYREGISTERED;
699 entry = heap_alloc(sizeof(*entry));
700 if (!entry)
701 return E_OUTOFMEMORY;
703 entry->loader = loader;
704 IDWriteFontCollectionLoader_AddRef(loader);
705 list_add_tail(&This->collection_loaders, &entry->entry);
707 return S_OK;
710 static HRESULT WINAPI dwritefactory_UnregisterFontCollectionLoader(IDWriteFactory2 *iface,
711 IDWriteFontCollectionLoader *loader)
713 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
714 struct collectionloader *found;
716 TRACE("(%p)->(%p)\n", This, loader);
718 if (!loader)
719 return E_INVALIDARG;
721 found = factory_get_collection_loader(This, loader);
722 if (!found)
723 return E_INVALIDARG;
725 IDWriteFontCollectionLoader_Release(found->loader);
726 list_remove(&found->entry);
727 heap_free(found);
729 return S_OK;
732 static HRESULT WINAPI dwritefactory_CreateFontFileReference(IDWriteFactory2 *iface,
733 WCHAR const *path, FILETIME const *writetime, IDWriteFontFile **font_file)
735 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
736 UINT32 key_size;
737 HRESULT hr;
738 void *key;
740 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(path), writetime, font_file);
742 if (!This->localfontfileloader)
744 hr = create_localfontfileloader(&This->localfontfileloader);
745 if (FAILED(hr))
746 return hr;
749 /* get a reference key used by local loader */
750 hr = get_local_refkey(path, writetime, &key, &key_size);
751 if (FAILED(hr))
752 return hr;
754 hr = create_font_file((IDWriteFontFileLoader*)This->localfontfileloader, key, key_size, font_file);
755 heap_free(key);
757 return hr;
760 static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory2 *iface,
761 void const *reference_key, UINT32 key_size, IDWriteFontFileLoader *loader, IDWriteFontFile **font_file)
763 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
765 TRACE("(%p)->(%p %u %p %p)\n", This, reference_key, key_size, loader, font_file);
767 if (!loader || !factory_get_file_loader(This, loader))
768 return E_INVALIDARG;
770 return create_font_file(loader, reference_key, key_size, font_file);
773 static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory2 *iface,
774 DWRITE_FONT_FACE_TYPE req_facetype, UINT32 files_number, IDWriteFontFile* const* font_files,
775 UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face)
777 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
778 DWRITE_FONT_FILE_TYPE file_type;
779 DWRITE_FONT_FACE_TYPE face_type;
780 IDWriteFontFileLoader *loader;
781 struct fontfacecached *cached;
782 struct list *fontfaces;
783 IDWriteFontFace2 *face;
784 UINT32 key_size, count;
785 BOOL is_supported;
786 const void *key;
787 HRESULT hr;
789 TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, simulations, font_face);
791 *font_face = NULL;
793 if (!is_face_type_supported(req_facetype))
794 return E_INVALIDARG;
796 if (req_facetype != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION && index)
797 return E_INVALIDARG;
799 /* check actual file/face type */
800 is_supported = FALSE;
801 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
802 hr = IDWriteFontFile_Analyze(*font_files, &is_supported, &file_type, &face_type, &count);
803 if (FAILED(hr))
804 return hr;
806 if (!is_supported || (face_type != req_facetype))
807 return E_FAIL;
809 hr = IDWriteFontFile_GetReferenceKey(*font_files, &key, &key_size);
810 if (FAILED(hr))
811 return hr;
813 hr = IDWriteFontFile_GetLoader(*font_files, &loader);
814 if (FAILED(hr))
815 return hr;
817 if (loader == (IDWriteFontFileLoader*)This->localfontfileloader) {
818 fontfaces = &This->localfontfaces;
819 IDWriteFontFileLoader_Release(loader);
821 else {
822 struct fileloader *fileloader = factory_get_file_loader(This, loader);
823 IDWriteFontFileLoader_Release(loader);
824 if (!fileloader)
825 return E_INVALIDARG;
826 fontfaces = &fileloader->fontfaces;
829 /* search through cache list */
830 LIST_FOR_EACH_ENTRY(cached, fontfaces, struct fontfacecached, entry) {
831 UINT32 cached_key_size, count = 1, cached_face_index;
832 DWRITE_FONT_SIMULATIONS cached_simulations;
833 const void *cached_key;
834 IDWriteFontFile *file;
836 cached_face_index = IDWriteFontFace_GetIndex(cached->fontface);
837 cached_simulations = IDWriteFontFace_GetSimulations(cached->fontface);
839 /* skip earlier */
840 if (cached_face_index != index || cached_simulations != simulations)
841 continue;
843 hr = IDWriteFontFace_GetFiles(cached->fontface, &count, &file);
844 if (FAILED(hr))
845 return hr;
847 hr = IDWriteFontFile_GetReferenceKey(file, &cached_key, &cached_key_size);
848 IDWriteFontFile_Release(file);
849 if (FAILED(hr))
850 return hr;
852 if (cached_key_size == key_size && !memcmp(cached_key, key, key_size)) {
853 TRACE("returning cached fontface %p\n", cached->fontface);
854 *font_face = cached->fontface;
855 IDWriteFontFace_AddRef(*font_face);
856 return S_OK;
860 hr = create_fontface(req_facetype, files_number, font_files, index, simulations, &face);
861 if (FAILED(hr))
862 return hr;
864 /* new cache entry */
865 cached = heap_alloc(sizeof(*cached));
866 if (!cached) {
867 IDWriteFontFace2_Release(face);
868 return hr;
871 cached->fontface = (IDWriteFontFace*)face;
872 list_add_tail(fontfaces, &cached->entry);
874 *font_face = cached->fontface;
875 IDWriteFontFace_AddRef(*font_face);
877 return S_OK;
880 static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory2 *iface, IDWriteRenderingParams **params)
882 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
883 HMONITOR monitor;
884 POINT pt;
886 TRACE("(%p)->(%p)\n", This, params);
888 pt.x = pt.y = 0;
889 monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
890 return IDWriteFactory2_CreateMonitorRenderingParams(iface, monitor, params);
893 static HRESULT WINAPI dwritefactory_CreateMonitorRenderingParams(IDWriteFactory2 *iface, HMONITOR monitor,
894 IDWriteRenderingParams **params)
896 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
897 IDWriteRenderingParams2 *params2;
898 static int fixme_once = 0;
899 HRESULT hr;
901 TRACE("(%p)->(%p %p)\n", This, monitor, params);
903 if (!fixme_once++)
904 FIXME("(%p): monitor setting ignored\n", monitor);
906 hr = IDWriteFactory2_CreateCustomRenderingParams(iface, 0.0, 0.0, 1.0, 0.0, DWRITE_PIXEL_GEOMETRY_FLAT, DWRITE_RENDERING_MODE_DEFAULT,
907 DWRITE_GRID_FIT_MODE_DEFAULT, &params2);
908 *params = (IDWriteRenderingParams*)params2;
909 return hr;
912 static HRESULT WINAPI dwritefactory_CreateCustomRenderingParams(IDWriteFactory2 *iface, FLOAT gamma, FLOAT enhancedContrast,
913 FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode, IDWriteRenderingParams **params)
915 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
916 IDWriteRenderingParams2 *params2;
917 HRESULT hr;
919 TRACE("(%p)->(%f %f %f %d %d %p)\n", This, gamma, enhancedContrast, cleartype_level, geometry, mode, params);
921 hr = IDWriteFactory2_CreateCustomRenderingParams(iface, gamma, enhancedContrast, 1.0, cleartype_level, geometry,
922 mode, DWRITE_GRID_FIT_MODE_DEFAULT, &params2);
923 *params = (IDWriteRenderingParams*)params2;
924 return hr;
927 static HRESULT WINAPI dwritefactory_RegisterFontFileLoader(IDWriteFactory2 *iface, IDWriteFontFileLoader *loader)
929 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
930 struct fileloader *entry;
932 TRACE("(%p)->(%p)\n", This, loader);
934 if (!loader)
935 return E_INVALIDARG;
937 if ((IDWriteFontFileLoader*)This->localfontfileloader == loader)
938 return S_OK;
940 if (factory_get_file_loader(This, loader))
941 return DWRITE_E_ALREADYREGISTERED;
943 entry = heap_alloc(sizeof(*entry));
944 if (!entry)
945 return E_OUTOFMEMORY;
947 entry->loader = loader;
948 list_init(&entry->fontfaces);
949 IDWriteFontFileLoader_AddRef(loader);
950 list_add_tail(&This->file_loaders, &entry->entry);
952 return S_OK;
955 static HRESULT WINAPI dwritefactory_UnregisterFontFileLoader(IDWriteFactory2 *iface, IDWriteFontFileLoader *loader)
957 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
958 struct fileloader *found;
960 TRACE("(%p)->(%p)\n", This, loader);
962 if (!loader)
963 return E_INVALIDARG;
965 if ((IDWriteFontFileLoader*)This->localfontfileloader == loader)
966 return S_OK;
968 found = factory_get_file_loader(This, loader);
969 if (!found)
970 return E_INVALIDARG;
972 release_fileloader(found);
973 return S_OK;
976 static HRESULT WINAPI dwritefactory_CreateTextFormat(IDWriteFactory2 *iface, WCHAR const* family_name,
977 IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
978 DWRITE_FONT_STRETCH stretch, FLOAT size, WCHAR const *locale, IDWriteTextFormat **format)
980 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
981 IDWriteFontCollection *syscollection = NULL;
982 HRESULT hr;
984 TRACE("(%p)->(%s %p %d %d %d %f %s %p)\n", This, debugstr_w(family_name), collection, weight, style, stretch,
985 size, debugstr_w(locale), format);
987 if (!collection) {
988 hr = IDWriteFactory2_GetSystemFontCollection(iface, &syscollection, FALSE);
989 if (FAILED(hr))
990 return hr;
993 hr = create_textformat(family_name, collection ? collection : syscollection, weight, style, stretch, size, locale, format);
994 if (syscollection)
995 IDWriteFontCollection_Release(syscollection);
996 return hr;
999 static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory2 *iface, IDWriteTypography **typography)
1001 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1002 TRACE("(%p)->(%p)\n", This, typography);
1003 return create_typography(typography);
1006 static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory2 *iface, IDWriteGdiInterop **gdi_interop)
1008 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1010 TRACE("(%p)->(%p)\n", This, gdi_interop);
1012 *gdi_interop = NULL;
1014 if (!This->gdiinterop) {
1015 HRESULT hr = create_gdiinterop(iface, &This->gdiinterop);
1016 if (FAILED(hr))
1017 return hr;
1020 *gdi_interop = This->gdiinterop;
1021 IDWriteGdiInterop_AddRef(*gdi_interop);
1023 return S_OK;
1026 static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory2 *iface, WCHAR const* string,
1027 UINT32 len, IDWriteTextFormat *format, FLOAT max_width, FLOAT max_height, IDWriteTextLayout **layout)
1029 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1030 TRACE("(%p)->(%s:%u %p %f %f %p)\n", This, debugstr_wn(string, len), len, format, max_width, max_height, layout);
1032 if (!format) return E_INVALIDARG;
1033 return create_textlayout(string, len, format, max_width, max_height, layout);
1036 static HRESULT WINAPI dwritefactory_CreateGdiCompatibleTextLayout(IDWriteFactory2 *iface, WCHAR const* string,
1037 UINT32 len, IDWriteTextFormat *format, FLOAT layout_width, FLOAT layout_height, FLOAT pixels_per_dip,
1038 DWRITE_MATRIX const* transform, BOOL use_gdi_natural, IDWriteTextLayout **layout)
1040 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1042 TRACE("(%p)->(%s:%u %p %f %f %f %p %d %p)\n", This, debugstr_wn(string, len), len, format, layout_width, layout_height,
1043 pixels_per_dip, transform, use_gdi_natural, layout);
1045 if (!format) return E_INVALIDARG;
1046 return create_gdicompat_textlayout(string, len, format, layout_width, layout_height, pixels_per_dip, transform,
1047 use_gdi_natural, layout);
1050 static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory2 *iface, IDWriteTextFormat *format,
1051 IDWriteInlineObject **trimming_sign)
1053 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1054 FIXME("(%p)->(%p %p): semi-stub\n", This, format, trimming_sign);
1055 return create_trimmingsign(trimming_sign);
1058 static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory2 *iface, IDWriteTextAnalyzer **analyzer)
1060 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1061 TRACE("(%p)->(%p)\n", This, analyzer);
1062 return get_textanalyzer(analyzer);
1065 static HRESULT WINAPI dwritefactory_CreateNumberSubstitution(IDWriteFactory2 *iface, DWRITE_NUMBER_SUBSTITUTION_METHOD method,
1066 WCHAR const* locale, BOOL ignore_user_override, IDWriteNumberSubstitution **substitution)
1068 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1069 TRACE("(%p)->(%d %s %d %p)\n", This, method, debugstr_w(locale), ignore_user_override, substitution);
1070 return create_numbersubstitution(method, locale, ignore_user_override, substitution);
1073 static HRESULT WINAPI dwritefactory_CreateGlyphRunAnalysis(IDWriteFactory2 *iface, DWRITE_GLYPH_RUN const *glyph_run,
1074 FLOAT pixels_per_dip, DWRITE_MATRIX const* transform, DWRITE_RENDERING_MODE rendering_mode,
1075 DWRITE_MEASURING_MODE measuring_mode, FLOAT baseline_x, FLOAT baseline_y, IDWriteGlyphRunAnalysis **analysis)
1077 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1079 TRACE("(%p)->(%p %f %p %d %d %f %f %p)\n", This, glyph_run, pixels_per_dip, transform, rendering_mode,
1080 measuring_mode, baseline_x, baseline_y, analysis);
1082 return create_glyphrunanalysis(rendering_mode, analysis);
1085 static HRESULT WINAPI dwritefactory1_GetEudcFontCollection(IDWriteFactory2 *iface, IDWriteFontCollection **collection,
1086 BOOL check_for_updates)
1088 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1089 HRESULT hr = S_OK;
1091 TRACE("(%p)->(%p %d)\n", This, collection, check_for_updates);
1093 if (check_for_updates)
1094 FIXME("checking for eudc updates not implemented\n");
1096 if (!This->eudc_collection)
1097 hr = get_eudc_fontcollection(iface, &This->eudc_collection);
1099 if (SUCCEEDED(hr))
1100 IDWriteFontCollection_AddRef(This->eudc_collection);
1102 *collection = This->eudc_collection;
1104 return hr;
1107 static HRESULT WINAPI dwritefactory1_CreateCustomRenderingParams(IDWriteFactory2 *iface, FLOAT gamma,
1108 FLOAT enhcontrast, FLOAT enhcontrast_grayscale, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry,
1109 DWRITE_RENDERING_MODE mode, IDWriteRenderingParams1** params)
1111 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1112 IDWriteRenderingParams2 *params2;
1113 HRESULT hr;
1115 TRACE("(%p)->(%.2f %.2f %.2f %.2f %d %d %p)\n", This, gamma, enhcontrast, enhcontrast_grayscale,
1116 cleartype_level, geometry, mode, params);
1117 hr = IDWriteFactory2_CreateCustomRenderingParams(iface, gamma, enhcontrast, enhcontrast_grayscale,
1118 cleartype_level, geometry, mode, DWRITE_GRID_FIT_MODE_DEFAULT, &params2);
1119 *params = (IDWriteRenderingParams1*)params2;
1120 return hr;
1123 static HRESULT WINAPI dwritefactory2_GetSystemFontFallback(IDWriteFactory2 *iface, IDWriteFontFallback **fallback)
1125 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1126 FIXME("(%p)->(%p): stub\n", This, fallback);
1127 return E_NOTIMPL;
1130 static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory2 *iface, IDWriteFontFallbackBuilder **fallbackbuilder)
1132 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1133 FIXME("(%p)->(%p): stub\n", This, fallbackbuilder);
1134 return E_NOTIMPL;
1137 static HRESULT WINAPI dwritefactory2_TranslateColorGlyphRun(IDWriteFactory2 *iface, FLOAT originX, FLOAT originY,
1138 const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE mode,
1139 const DWRITE_MATRIX *transform, UINT32 palette_index, IDWriteColorGlyphRunEnumerator **colorlayers)
1141 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1142 FIXME("(%p)->(%.2f %.2f %p %p %d %p %u %p): stub\n", This, originX, originY, run, rundescr, mode,
1143 transform, palette_index, colorlayers);
1144 return E_NOTIMPL;
1147 static HRESULT WINAPI dwritefactory2_CreateCustomRenderingParams(IDWriteFactory2 *iface, FLOAT gamma, FLOAT contrast,
1148 FLOAT grayscalecontrast, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode,
1149 DWRITE_GRID_FIT_MODE gridfit, IDWriteRenderingParams2 **params)
1151 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1152 TRACE("(%p)->(%.2f %.2f %.2f %.2f %d %d %d %p)\n", This, gamma, contrast, grayscalecontrast, cleartype_level,
1153 geometry, mode, gridfit, params);
1154 return create_renderingparams(gamma, contrast, grayscalecontrast, cleartype_level, geometry, mode, gridfit, params);
1157 static HRESULT WINAPI dwritefactory2_CreateGlyphRunAnalysis(IDWriteFactory2 *iface, const DWRITE_GLYPH_RUN *run,
1158 const DWRITE_MATRIX *transform, DWRITE_RENDERING_MODE renderingMode, DWRITE_MEASURING_MODE measuringMode,
1159 DWRITE_GRID_FIT_MODE gridFitMode, DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, FLOAT originX, FLOAT originY,
1160 IDWriteGlyphRunAnalysis **analysis)
1162 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1163 FIXME("(%p)->(%p %p %d %d %d %d %.2f %.2f %p): stub\n", This, run, transform, renderingMode, measuringMode,
1164 gridFitMode, antialiasMode, originX, originY, analysis);
1165 return E_NOTIMPL;
1168 static const struct IDWriteFactory2Vtbl dwritefactoryvtbl = {
1169 dwritefactory_QueryInterface,
1170 dwritefactory_AddRef,
1171 dwritefactory_Release,
1172 dwritefactory_GetSystemFontCollection,
1173 dwritefactory_CreateCustomFontCollection,
1174 dwritefactory_RegisterFontCollectionLoader,
1175 dwritefactory_UnregisterFontCollectionLoader,
1176 dwritefactory_CreateFontFileReference,
1177 dwritefactory_CreateCustomFontFileReference,
1178 dwritefactory_CreateFontFace,
1179 dwritefactory_CreateRenderingParams,
1180 dwritefactory_CreateMonitorRenderingParams,
1181 dwritefactory_CreateCustomRenderingParams,
1182 dwritefactory_RegisterFontFileLoader,
1183 dwritefactory_UnregisterFontFileLoader,
1184 dwritefactory_CreateTextFormat,
1185 dwritefactory_CreateTypography,
1186 dwritefactory_GetGdiInterop,
1187 dwritefactory_CreateTextLayout,
1188 dwritefactory_CreateGdiCompatibleTextLayout,
1189 dwritefactory_CreateEllipsisTrimmingSign,
1190 dwritefactory_CreateTextAnalyzer,
1191 dwritefactory_CreateNumberSubstitution,
1192 dwritefactory_CreateGlyphRunAnalysis,
1193 dwritefactory1_GetEudcFontCollection,
1194 dwritefactory1_CreateCustomRenderingParams,
1195 dwritefactory2_GetSystemFontFallback,
1196 dwritefactory2_CreateFontFallbackBuilder,
1197 dwritefactory2_TranslateColorGlyphRun,
1198 dwritefactory2_CreateCustomRenderingParams,
1199 dwritefactory2_CreateGlyphRunAnalysis
1202 static ULONG WINAPI shareddwritefactory_AddRef(IDWriteFactory2 *iface)
1204 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1205 TRACE("(%p)\n", This);
1206 return 2;
1209 static ULONG WINAPI shareddwritefactory_Release(IDWriteFactory2 *iface)
1211 struct dwritefactory *This = impl_from_IDWriteFactory2(iface);
1212 TRACE("(%p)\n", This);
1213 return 1;
1216 static const struct IDWriteFactory2Vtbl shareddwritefactoryvtbl = {
1217 dwritefactory_QueryInterface,
1218 shareddwritefactory_AddRef,
1219 shareddwritefactory_Release,
1220 dwritefactory_GetSystemFontCollection,
1221 dwritefactory_CreateCustomFontCollection,
1222 dwritefactory_RegisterFontCollectionLoader,
1223 dwritefactory_UnregisterFontCollectionLoader,
1224 dwritefactory_CreateFontFileReference,
1225 dwritefactory_CreateCustomFontFileReference,
1226 dwritefactory_CreateFontFace,
1227 dwritefactory_CreateRenderingParams,
1228 dwritefactory_CreateMonitorRenderingParams,
1229 dwritefactory_CreateCustomRenderingParams,
1230 dwritefactory_RegisterFontFileLoader,
1231 dwritefactory_UnregisterFontFileLoader,
1232 dwritefactory_CreateTextFormat,
1233 dwritefactory_CreateTypography,
1234 dwritefactory_GetGdiInterop,
1235 dwritefactory_CreateTextLayout,
1236 dwritefactory_CreateGdiCompatibleTextLayout,
1237 dwritefactory_CreateEllipsisTrimmingSign,
1238 dwritefactory_CreateTextAnalyzer,
1239 dwritefactory_CreateNumberSubstitution,
1240 dwritefactory_CreateGlyphRunAnalysis,
1241 dwritefactory1_GetEudcFontCollection,
1242 dwritefactory1_CreateCustomRenderingParams,
1243 dwritefactory2_GetSystemFontFallback,
1244 dwritefactory2_CreateFontFallbackBuilder,
1245 dwritefactory2_TranslateColorGlyphRun,
1246 dwritefactory2_CreateCustomRenderingParams,
1247 dwritefactory2_CreateGlyphRunAnalysis
1250 static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYPE type)
1252 factory->IDWriteFactory2_iface.lpVtbl = type == DWRITE_FACTORY_TYPE_SHARED ? &shareddwritefactoryvtbl : &dwritefactoryvtbl;
1253 factory->ref = 1;
1254 factory->localfontfileloader = NULL;
1255 factory->system_collection = NULL;
1256 factory->eudc_collection = NULL;
1257 factory->gdiinterop = NULL;
1259 list_init(&factory->collection_loaders);
1260 list_init(&factory->file_loaders);
1261 list_init(&factory->localfontfaces);
1264 HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
1266 struct dwritefactory *factory;
1268 TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), ret);
1270 *ret = NULL;
1272 if (!IsEqualIID(riid, &IID_IDWriteFactory) &&
1273 !IsEqualIID(riid, &IID_IDWriteFactory1) &&
1274 !IsEqualIID(riid, &IID_IDWriteFactory2))
1275 return E_FAIL;
1277 if (type == DWRITE_FACTORY_TYPE_SHARED && shared_factory) {
1278 *ret = (IUnknown*)shared_factory;
1279 IDWriteFactory2_AddRef(shared_factory);
1280 return S_OK;
1283 factory = heap_alloc(sizeof(struct dwritefactory));
1284 if (!factory) return E_OUTOFMEMORY;
1286 init_dwritefactory(factory, type);
1288 if (type == DWRITE_FACTORY_TYPE_SHARED)
1289 if (InterlockedCompareExchangePointer((void**)&shared_factory, &factory->IDWriteFactory2_iface, NULL)) {
1290 release_shared_factory(&factory->IDWriteFactory2_iface);
1291 *ret = (IUnknown*)shared_factory;
1292 IDWriteFactory2_AddRef(shared_factory);
1293 return S_OK;
1296 *ret = (IUnknown*)&factory->IDWriteFactory2_iface;
1297 return S_OK;