dwrite: Factory_release_cached_fontface() is unused so remove it.
[wine.git] / dlls / dwrite / main.c
blob0dce13343536e246042595ce5dab420992af52e2
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>
24 #include <math.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
30 #include "initguid.h"
32 #include "dwrite_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
37 static IDWriteFactory5 *shared_factory;
38 static void release_shared_factory(IDWriteFactory5*);
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 IDWriteRenderingParams3 IDWriteRenderingParams3_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_MODE1 mode;
66 DWRITE_GRID_FIT_MODE gridfit;
69 static inline struct renderingparams *impl_from_IDWriteRenderingParams3(IDWriteRenderingParams3 *iface)
71 return CONTAINING_RECORD(iface, struct renderingparams, IDWriteRenderingParams3_iface);
74 static HRESULT WINAPI renderingparams_QueryInterface(IDWriteRenderingParams3 *iface, REFIID riid, void **obj)
76 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
78 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
80 if (IsEqualIID(riid, &IID_IDWriteRenderingParams3) ||
81 IsEqualIID(riid, &IID_IDWriteRenderingParams2) ||
82 IsEqualIID(riid, &IID_IDWriteRenderingParams1) ||
83 IsEqualIID(riid, &IID_IDWriteRenderingParams) ||
84 IsEqualIID(riid, &IID_IUnknown))
86 *obj = iface;
87 IDWriteRenderingParams3_AddRef(iface);
88 return S_OK;
91 *obj = NULL;
93 return E_NOINTERFACE;
96 static ULONG WINAPI renderingparams_AddRef(IDWriteRenderingParams3 *iface)
98 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
99 ULONG ref = InterlockedIncrement(&This->ref);
100 TRACE("(%p)->(%d)\n", This, ref);
101 return ref;
104 static ULONG WINAPI renderingparams_Release(IDWriteRenderingParams3 *iface)
106 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
107 ULONG ref = InterlockedDecrement(&This->ref);
109 TRACE("(%p)->(%d)\n", This, ref);
111 if (!ref)
112 heap_free(This);
114 return ref;
117 static FLOAT WINAPI renderingparams_GetGamma(IDWriteRenderingParams3 *iface)
119 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
120 TRACE("(%p)\n", This);
121 return This->gamma;
124 static FLOAT WINAPI renderingparams_GetEnhancedContrast(IDWriteRenderingParams3 *iface)
126 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
127 TRACE("(%p)\n", This);
128 return This->contrast;
131 static FLOAT WINAPI renderingparams_GetClearTypeLevel(IDWriteRenderingParams3 *iface)
133 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
134 TRACE("(%p)\n", This);
135 return This->cleartype_level;
138 static DWRITE_PIXEL_GEOMETRY WINAPI renderingparams_GetPixelGeometry(IDWriteRenderingParams3 *iface)
140 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
141 TRACE("(%p)\n", This);
142 return This->geometry;
145 static DWRITE_RENDERING_MODE rendering_mode_from_mode1(DWRITE_RENDERING_MODE1 mode)
147 static const DWRITE_RENDERING_MODE rendering_modes[] = {
148 DWRITE_RENDERING_MODE_DEFAULT, /* DWRITE_RENDERING_MODE1_DEFAULT */
149 DWRITE_RENDERING_MODE_ALIASED, /* DWRITE_RENDERING_MODE1_ALIASED */
150 DWRITE_RENDERING_MODE_GDI_CLASSIC, /* DWRITE_RENDERING_MODE1_GDI_CLASSIC */
151 DWRITE_RENDERING_MODE_GDI_NATURAL, /* DWRITE_RENDERING_MODE1_GDI_NATURAL */
152 DWRITE_RENDERING_MODE_NATURAL, /* DWRITE_RENDERING_MODE1_NATURAL */
153 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, /* DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC */
154 DWRITE_RENDERING_MODE_OUTLINE, /* DWRITE_RENDERING_MODE1_OUTLINE */
155 DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC, /* DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED */
158 return rendering_modes[mode];
161 static DWRITE_RENDERING_MODE WINAPI renderingparams_GetRenderingMode(IDWriteRenderingParams3 *iface)
163 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
165 TRACE("(%p)\n", This);
167 return rendering_mode_from_mode1(This->mode);
170 static FLOAT WINAPI renderingparams1_GetGrayscaleEnhancedContrast(IDWriteRenderingParams3 *iface)
172 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
173 TRACE("(%p)\n", This);
174 return This->grayscalecontrast;
177 static DWRITE_GRID_FIT_MODE WINAPI renderingparams2_GetGridFitMode(IDWriteRenderingParams3 *iface)
179 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
180 TRACE("(%p)\n", This);
181 return This->gridfit;
184 static DWRITE_RENDERING_MODE1 WINAPI renderingparams3_GetRenderingMode1(IDWriteRenderingParams3 *iface)
186 struct renderingparams *This = impl_from_IDWriteRenderingParams3(iface);
187 TRACE("(%p)\n", This);
188 return This->mode;
191 static const struct IDWriteRenderingParams3Vtbl renderingparamsvtbl = {
192 renderingparams_QueryInterface,
193 renderingparams_AddRef,
194 renderingparams_Release,
195 renderingparams_GetGamma,
196 renderingparams_GetEnhancedContrast,
197 renderingparams_GetClearTypeLevel,
198 renderingparams_GetPixelGeometry,
199 renderingparams_GetRenderingMode,
200 renderingparams1_GetGrayscaleEnhancedContrast,
201 renderingparams2_GetGridFitMode,
202 renderingparams3_GetRenderingMode1
205 static HRESULT create_renderingparams(FLOAT gamma, FLOAT contrast, FLOAT grayscalecontrast, FLOAT cleartype_level,
206 DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE1 mode, DWRITE_GRID_FIT_MODE gridfit,
207 IDWriteRenderingParams3 **params)
209 struct renderingparams *This;
211 *params = NULL;
213 if (gamma <= 0.0f || contrast < 0.0f || grayscalecontrast < 0.0f || cleartype_level < 0.0f)
214 return E_INVALIDARG;
216 if ((UINT32)gridfit > DWRITE_GRID_FIT_MODE_ENABLED || (UINT32)geometry > DWRITE_PIXEL_GEOMETRY_BGR)
217 return E_INVALIDARG;
219 This = heap_alloc(sizeof(struct renderingparams));
220 if (!This) return E_OUTOFMEMORY;
222 This->IDWriteRenderingParams3_iface.lpVtbl = &renderingparamsvtbl;
223 This->ref = 1;
225 This->gamma = gamma;
226 This->contrast = contrast;
227 This->grayscalecontrast = grayscalecontrast;
228 This->cleartype_level = cleartype_level;
229 This->geometry = geometry;
230 This->mode = mode;
231 This->gridfit = gridfit;
233 *params = &This->IDWriteRenderingParams3_iface;
235 return S_OK;
238 struct localizedpair {
239 WCHAR *locale;
240 WCHAR *string;
243 struct localizedstrings {
244 IDWriteLocalizedStrings IDWriteLocalizedStrings_iface;
245 LONG ref;
247 struct localizedpair *data;
248 UINT32 count;
249 UINT32 alloc;
252 static inline struct localizedstrings *impl_from_IDWriteLocalizedStrings(IDWriteLocalizedStrings *iface)
254 return CONTAINING_RECORD(iface, struct localizedstrings, IDWriteLocalizedStrings_iface);
257 static HRESULT WINAPI localizedstrings_QueryInterface(IDWriteLocalizedStrings *iface, REFIID riid, void **obj)
259 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
261 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
263 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteLocalizedStrings))
265 *obj = iface;
266 IDWriteLocalizedStrings_AddRef(iface);
267 return S_OK;
270 *obj = NULL;
272 return E_NOINTERFACE;
275 static ULONG WINAPI localizedstrings_AddRef(IDWriteLocalizedStrings *iface)
277 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
278 ULONG ref = InterlockedIncrement(&This->ref);
279 TRACE("(%p)->(%d)\n", This, ref);
280 return ref;
283 static ULONG WINAPI localizedstrings_Release(IDWriteLocalizedStrings *iface)
285 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
286 ULONG ref = InterlockedDecrement(&This->ref);
288 TRACE("(%p)->(%d)\n", This, ref);
290 if (!ref) {
291 unsigned int i;
293 for (i = 0; i < This->count; i++) {
294 heap_free(This->data[i].locale);
295 heap_free(This->data[i].string);
298 heap_free(This->data);
299 heap_free(This);
302 return ref;
305 static UINT32 WINAPI localizedstrings_GetCount(IDWriteLocalizedStrings *iface)
307 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
308 TRACE("(%p)\n", This);
309 return This->count;
312 static HRESULT WINAPI localizedstrings_FindLocaleName(IDWriteLocalizedStrings *iface,
313 WCHAR const *locale_name, UINT32 *index, BOOL *exists)
315 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
316 UINT32 i;
318 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(locale_name), index, exists);
320 *exists = FALSE;
321 *index = ~0;
323 for (i = 0; i < This->count; i++) {
324 if (!strcmpiW(This->data[i].locale, locale_name)) {
325 *exists = TRUE;
326 *index = i;
327 break;
331 return S_OK;
334 static HRESULT WINAPI localizedstrings_GetLocaleNameLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
336 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
338 TRACE("(%p)->(%u %p)\n", This, index, length);
340 if (index >= This->count) {
341 *length = (UINT32)-1;
342 return E_FAIL;
345 *length = strlenW(This->data[index].locale);
346 return S_OK;
349 static HRESULT WINAPI localizedstrings_GetLocaleName(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
351 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
353 TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
355 if (index >= This->count) {
356 if (buffer) *buffer = 0;
357 return E_FAIL;
360 if (size < strlenW(This->data[index].locale)+1) {
361 if (buffer) *buffer = 0;
362 return E_NOT_SUFFICIENT_BUFFER;
365 strcpyW(buffer, This->data[index].locale);
366 return S_OK;
369 static HRESULT WINAPI localizedstrings_GetStringLength(IDWriteLocalizedStrings *iface, UINT32 index, UINT32 *length)
371 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
373 TRACE("(%p)->(%u %p)\n", This, index, length);
375 if (index >= This->count) {
376 *length = (UINT32)-1;
377 return E_FAIL;
380 *length = strlenW(This->data[index].string);
381 return S_OK;
384 static HRESULT WINAPI localizedstrings_GetString(IDWriteLocalizedStrings *iface, UINT32 index, WCHAR *buffer, UINT32 size)
386 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
388 TRACE("(%p)->(%u %p %u)\n", This, index, buffer, size);
390 if (index >= This->count) {
391 if (buffer) *buffer = 0;
392 return E_FAIL;
395 if (size < strlenW(This->data[index].string)+1) {
396 if (buffer) *buffer = 0;
397 return E_NOT_SUFFICIENT_BUFFER;
400 strcpyW(buffer, This->data[index].string);
401 return S_OK;
404 static const IDWriteLocalizedStringsVtbl localizedstringsvtbl = {
405 localizedstrings_QueryInterface,
406 localizedstrings_AddRef,
407 localizedstrings_Release,
408 localizedstrings_GetCount,
409 localizedstrings_FindLocaleName,
410 localizedstrings_GetLocaleNameLength,
411 localizedstrings_GetLocaleName,
412 localizedstrings_GetStringLength,
413 localizedstrings_GetString
416 HRESULT create_localizedstrings(IDWriteLocalizedStrings **strings)
418 struct localizedstrings *This;
420 *strings = NULL;
422 This = heap_alloc(sizeof(struct localizedstrings));
423 if (!This) return E_OUTOFMEMORY;
425 This->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
426 This->ref = 1;
427 This->count = 0;
428 This->data = heap_alloc_zero(sizeof(struct localizedpair));
429 if (!This->data) {
430 heap_free(This);
431 return E_OUTOFMEMORY;
433 This->alloc = 1;
435 *strings = &This->IDWriteLocalizedStrings_iface;
437 return S_OK;
440 HRESULT add_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *locale, const WCHAR *string)
442 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
443 UINT32 i;
445 /* make sure there's no duplicates */
446 for (i = 0; i < This->count; i++)
447 if (!strcmpW(This->data[i].locale, locale))
448 return S_OK;
450 if (This->count == This->alloc) {
451 void *ptr;
453 ptr = heap_realloc(This->data, 2*This->alloc*sizeof(struct localizedpair));
454 if (!ptr)
455 return E_OUTOFMEMORY;
457 This->alloc *= 2;
458 This->data = ptr;
461 This->data[This->count].locale = heap_strdupW(locale);
462 This->data[This->count].string = heap_strdupW(string);
463 if (!This->data[This->count].locale || !This->data[This->count].string) {
464 heap_free(This->data[This->count].locale);
465 heap_free(This->data[This->count].string);
466 return E_OUTOFMEMORY;
469 This->count++;
471 return S_OK;
474 HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **ret)
476 struct localizedstrings *strings, *strings_clone;
477 int i;
479 *ret = NULL;
481 if (!iface)
482 return S_FALSE;
484 strings = impl_from_IDWriteLocalizedStrings(iface);
485 strings_clone = heap_alloc(sizeof(struct localizedstrings));
486 if (!strings_clone) return E_OUTOFMEMORY;
488 strings_clone->IDWriteLocalizedStrings_iface.lpVtbl = &localizedstringsvtbl;
489 strings_clone->ref = 1;
490 strings_clone->count = strings->count;
491 strings_clone->data = heap_alloc(sizeof(struct localizedpair) * strings_clone->count);
492 if (!strings_clone->data) {
493 heap_free(strings_clone);
494 return E_OUTOFMEMORY;
496 for (i = 0; i < strings_clone->count; i++)
498 strings_clone->data[i].locale = heap_strdupW(strings->data[i].locale);
499 strings_clone->data[i].string = heap_strdupW(strings->data[i].string);
501 strings_clone->alloc = strings_clone->count;
503 *ret = &strings_clone->IDWriteLocalizedStrings_iface;
505 return S_OK;
508 void set_en_localizedstring(IDWriteLocalizedStrings *iface, const WCHAR *string)
510 static const WCHAR enusW[] = {'e','n','-','U','S',0};
511 struct localizedstrings *This = impl_from_IDWriteLocalizedStrings(iface);
512 UINT32 i;
514 for (i = 0; i < This->count; i++) {
515 if (!strcmpiW(This->data[i].locale, enusW)) {
516 heap_free(This->data[i].string);
517 This->data[i].string = heap_strdupW(string);
518 break;
523 struct collectionloader
525 struct list entry;
526 IDWriteFontCollectionLoader *loader;
529 struct fileloader
531 struct list entry;
532 struct list fontfaces;
533 IDWriteFontFileLoader *loader;
536 struct dwritefactory {
537 IDWriteFactory5 IDWriteFactory5_iface;
538 LONG ref;
540 IDWriteFontCollection1 *system_collection;
541 IDWriteFontCollection1 *eudc_collection;
542 IDWriteGdiInterop1 *gdiinterop;
543 IDWriteFontFallback *fallback;
545 IDWriteLocalFontFileLoader* localfontfileloader;
546 struct list localfontfaces;
548 struct list collection_loaders;
549 struct list file_loaders;
551 CRITICAL_SECTION cs;
554 static inline struct dwritefactory *impl_from_IDWriteFactory5(IDWriteFactory5 *iface)
556 return CONTAINING_RECORD(iface, struct dwritefactory, IDWriteFactory5_iface);
559 static void release_fontface_cache(struct list *fontfaces)
561 struct fontfacecached *fontface, *fontface2;
563 LIST_FOR_EACH_ENTRY_SAFE(fontface, fontface2, fontfaces, struct fontfacecached, entry) {
564 list_remove(&fontface->entry);
565 fontface_detach_from_cache(fontface->fontface);
566 heap_free(fontface);
570 static void release_fileloader(struct fileloader *fileloader)
572 list_remove(&fileloader->entry);
573 release_fontface_cache(&fileloader->fontfaces);
574 IDWriteFontFileLoader_Release(fileloader->loader);
575 heap_free(fileloader);
578 static void release_dwritefactory(struct dwritefactory *factory)
580 struct fileloader *fileloader, *fileloader2;
581 struct collectionloader *loader, *loader2;
583 if (factory->localfontfileloader)
584 IDWriteLocalFontFileLoader_Release(factory->localfontfileloader);
586 EnterCriticalSection(&factory->cs);
587 release_fontface_cache(&factory->localfontfaces);
588 LeaveCriticalSection(&factory->cs);
590 LIST_FOR_EACH_ENTRY_SAFE(loader, loader2, &factory->collection_loaders, struct collectionloader, entry) {
591 list_remove(&loader->entry);
592 IDWriteFontCollectionLoader_Release(loader->loader);
593 heap_free(loader);
596 LIST_FOR_EACH_ENTRY_SAFE(fileloader, fileloader2, &factory->file_loaders, struct fileloader, entry)
597 release_fileloader(fileloader);
599 if (factory->system_collection)
600 IDWriteFontCollection1_Release(factory->system_collection);
601 if (factory->eudc_collection)
602 IDWriteFontCollection1_Release(factory->eudc_collection);
603 if (factory->fallback)
604 release_system_fontfallback(factory->fallback);
606 factory->cs.DebugInfo->Spare[0] = 0;
607 DeleteCriticalSection(&factory->cs);
608 heap_free(factory);
611 static void release_shared_factory(IDWriteFactory5 *iface)
613 struct dwritefactory *factory;
614 if (!iface) return;
615 factory = impl_from_IDWriteFactory5(iface);
616 release_dwritefactory(factory);
619 static struct fileloader *factory_get_file_loader(struct dwritefactory *factory, IDWriteFontFileLoader *loader)
621 struct fileloader *entry, *found = NULL;
623 LIST_FOR_EACH_ENTRY(entry, &factory->file_loaders, struct fileloader, entry) {
624 if (entry->loader == loader) {
625 found = entry;
626 break;
630 return found;
633 static struct collectionloader *factory_get_collection_loader(struct dwritefactory *factory,
634 IDWriteFontCollectionLoader *loader)
636 struct collectionloader *entry, *found = NULL;
638 LIST_FOR_EACH_ENTRY(entry, &factory->collection_loaders, struct collectionloader, entry) {
639 if (entry->loader == loader) {
640 found = entry;
641 break;
645 return found;
648 static IDWriteFontCollection1 *factory_get_system_collection(struct dwritefactory *factory)
650 IDWriteFontCollection1 *collection;
651 HRESULT hr;
653 if (factory->system_collection) {
654 IDWriteFontCollection1_AddRef(factory->system_collection);
655 return factory->system_collection;
658 if (FAILED(hr = get_system_fontcollection(&factory->IDWriteFactory5_iface, &collection))) {
659 WARN("Failed to create system font collection, hr %#x.\n", hr);
660 return NULL;
663 if (InterlockedCompareExchangePointer((void **)&factory->system_collection, collection, NULL))
664 IDWriteFontCollection1_Release(collection);
666 return factory->system_collection;
669 static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory5 *iface, REFIID riid, void **obj)
671 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
673 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
675 if (IsEqualIID(riid, &IID_IDWriteFactory5) ||
676 IsEqualIID(riid, &IID_IDWriteFactory4) ||
677 IsEqualIID(riid, &IID_IDWriteFactory3) ||
678 IsEqualIID(riid, &IID_IDWriteFactory2) ||
679 IsEqualIID(riid, &IID_IDWriteFactory1) ||
680 IsEqualIID(riid, &IID_IDWriteFactory) ||
681 IsEqualIID(riid, &IID_IUnknown))
683 *obj = iface;
684 IDWriteFactory5_AddRef(iface);
685 return S_OK;
688 *obj = NULL;
690 return E_NOINTERFACE;
693 static ULONG WINAPI dwritefactory_AddRef(IDWriteFactory5 *iface)
695 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
696 ULONG ref = InterlockedIncrement(&This->ref);
697 TRACE("(%p)->(%d)\n", This, ref);
698 return ref;
701 static ULONG WINAPI dwritefactory_Release(IDWriteFactory5 *iface)
703 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
704 ULONG ref = InterlockedDecrement(&This->ref);
706 TRACE("(%p)->(%d)\n", This, ref);
708 if (!ref)
709 release_dwritefactory(This);
711 return ref;
714 static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory5 *iface,
715 IDWriteFontCollection **collection, BOOL check_for_updates)
717 return IDWriteFactory5_GetSystemFontCollection(iface, FALSE, (IDWriteFontCollection1 **)collection,
718 check_for_updates);
721 static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory5 *iface,
722 IDWriteFontCollectionLoader *loader, void const *key, UINT32 key_size, IDWriteFontCollection **collection)
724 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
725 IDWriteFontFileEnumerator *enumerator;
726 struct collectionloader *found;
727 HRESULT hr;
729 TRACE("(%p)->(%p %p %u %p)\n", This, loader, key, key_size, collection);
731 *collection = NULL;
733 if (!loader)
734 return E_INVALIDARG;
736 found = factory_get_collection_loader(This, loader);
737 if (!found)
738 return E_INVALIDARG;
740 hr = IDWriteFontCollectionLoader_CreateEnumeratorFromKey(found->loader, (IDWriteFactory*)iface,
741 key, key_size, &enumerator);
742 if (FAILED(hr))
743 return hr;
745 hr = create_font_collection(iface, enumerator, FALSE, (IDWriteFontCollection1**)collection);
746 IDWriteFontFileEnumerator_Release(enumerator);
747 return hr;
750 static HRESULT WINAPI dwritefactory_RegisterFontCollectionLoader(IDWriteFactory5 *iface,
751 IDWriteFontCollectionLoader *loader)
753 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
754 struct collectionloader *entry;
756 TRACE("(%p)->(%p)\n", This, loader);
758 if (!loader)
759 return E_INVALIDARG;
761 if (factory_get_collection_loader(This, loader))
762 return DWRITE_E_ALREADYREGISTERED;
764 entry = heap_alloc(sizeof(*entry));
765 if (!entry)
766 return E_OUTOFMEMORY;
768 entry->loader = loader;
769 IDWriteFontCollectionLoader_AddRef(loader);
770 list_add_tail(&This->collection_loaders, &entry->entry);
772 return S_OK;
775 static HRESULT WINAPI dwritefactory_UnregisterFontCollectionLoader(IDWriteFactory5 *iface,
776 IDWriteFontCollectionLoader *loader)
778 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
779 struct collectionloader *found;
781 TRACE("(%p)->(%p)\n", This, loader);
783 if (!loader)
784 return E_INVALIDARG;
786 found = factory_get_collection_loader(This, loader);
787 if (!found)
788 return E_INVALIDARG;
790 IDWriteFontCollectionLoader_Release(found->loader);
791 list_remove(&found->entry);
792 heap_free(found);
794 return S_OK;
797 static HRESULT WINAPI dwritefactory_CreateFontFileReference(IDWriteFactory5 *iface,
798 WCHAR const *path, FILETIME const *writetime, IDWriteFontFile **font_file)
800 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
801 UINT32 key_size;
802 HRESULT hr;
803 void *key;
805 TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(path), writetime, font_file);
807 *font_file = NULL;
809 if (!This->localfontfileloader)
811 hr = create_localfontfileloader(&This->localfontfileloader);
812 if (FAILED(hr))
813 return hr;
816 /* get a reference key used by local loader */
817 hr = get_local_refkey(path, writetime, &key, &key_size);
818 if (FAILED(hr))
819 return hr;
821 hr = create_font_file((IDWriteFontFileLoader*)This->localfontfileloader, key, key_size, font_file);
822 heap_free(key);
824 return hr;
827 static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory5 *iface,
828 void const *reference_key, UINT32 key_size, IDWriteFontFileLoader *loader, IDWriteFontFile **font_file)
830 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
832 TRACE("(%p)->(%p %u %p %p)\n", This, reference_key, key_size, loader, font_file);
834 *font_file = NULL;
836 /* local loader is accepted as well */
837 if (!loader || !(factory_get_file_loader(This, loader) ||
838 (IDWriteFontFileLoader*)This->localfontfileloader == loader))
839 return E_INVALIDARG;
841 return create_font_file(loader, reference_key, key_size, font_file);
844 void factory_lock(IDWriteFactory5 *iface)
846 struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
847 EnterCriticalSection(&factory->cs);
850 void factory_unlock(IDWriteFactory5 *iface)
852 struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
853 LeaveCriticalSection(&factory->cs);
856 HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * const *font_files, UINT32 index,
857 DWRITE_FONT_SIMULATIONS simulations, struct list **cached_list, REFIID riid, void **obj)
859 struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
860 struct fontfacecached *cached;
861 IDWriteFontFileLoader *loader;
862 struct list *fontfaces;
863 UINT32 key_size;
864 const void *key;
865 HRESULT hr;
867 *obj = NULL;
868 *cached_list = NULL;
870 hr = IDWriteFontFile_GetReferenceKey(*font_files, &key, &key_size);
871 if (FAILED(hr))
872 return hr;
874 hr = IDWriteFontFile_GetLoader(*font_files, &loader);
875 if (FAILED(hr))
876 return hr;
878 if (loader == (IDWriteFontFileLoader*)factory->localfontfileloader) {
879 fontfaces = &factory->localfontfaces;
880 IDWriteFontFileLoader_Release(loader);
882 else {
883 struct fileloader *fileloader = factory_get_file_loader(factory, loader);
884 IDWriteFontFileLoader_Release(loader);
885 if (!fileloader)
886 return E_INVALIDARG;
887 fontfaces = &fileloader->fontfaces;
890 *cached_list = fontfaces;
892 EnterCriticalSection(&factory->cs);
894 /* search through cache list */
895 LIST_FOR_EACH_ENTRY(cached, fontfaces, struct fontfacecached, entry) {
896 UINT32 cached_key_size, count = 1, cached_face_index;
897 DWRITE_FONT_SIMULATIONS cached_simulations;
898 const void *cached_key;
899 IDWriteFontFile *file;
901 cached_face_index = IDWriteFontFace4_GetIndex(cached->fontface);
902 cached_simulations = IDWriteFontFace4_GetSimulations(cached->fontface);
904 /* skip earlier */
905 if (cached_face_index != index || cached_simulations != simulations)
906 continue;
908 hr = IDWriteFontFace4_GetFiles(cached->fontface, &count, &file);
909 if (FAILED(hr))
910 break;
912 hr = IDWriteFontFile_GetReferenceKey(file, &cached_key, &cached_key_size);
913 IDWriteFontFile_Release(file);
914 if (FAILED(hr))
915 break;
917 if (cached_key_size == key_size && !memcmp(cached_key, key, key_size)) {
918 if (FAILED(hr = IDWriteFontFace4_QueryInterface(cached->fontface, riid, obj)))
919 WARN("Failed to get %s from fontface, hr %#x.\n", debugstr_guid(riid), hr);
921 TRACE("returning cached fontface %p\n", cached->fontface);
922 break;
926 LeaveCriticalSection(&factory->cs);
928 return *obj ? S_OK : S_FALSE;
931 struct fontfacecached *factory_cache_fontface(IDWriteFactory5 *iface, struct list *fontfaces,
932 IDWriteFontFace4 *fontface)
934 struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
935 struct fontfacecached *cached;
937 /* new cache entry */
938 cached = heap_alloc(sizeof(*cached));
939 if (!cached)
940 return NULL;
942 cached->fontface = fontface;
943 EnterCriticalSection(&factory->cs);
944 list_add_tail(fontfaces, &cached->entry);
945 LeaveCriticalSection(&factory->cs);
947 return cached;
950 static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory5 *iface, DWRITE_FONT_FACE_TYPE req_facetype,
951 UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS simulations,
952 IDWriteFontFace **fontface)
954 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
955 DWRITE_FONT_FILE_TYPE file_type;
956 DWRITE_FONT_FACE_TYPE face_type;
957 struct fontface_desc desc;
958 struct list *fontfaces;
959 BOOL is_supported;
960 UINT32 count;
961 HRESULT hr;
963 TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index,
964 simulations, fontface);
966 *fontface = NULL;
968 if (!is_face_type_supported(req_facetype))
969 return E_INVALIDARG;
971 if (req_facetype != DWRITE_FONT_FACE_TYPE_OPENTYPE_COLLECTION && index)
972 return E_INVALIDARG;
974 if (!is_simulation_valid(simulations))
975 return E_INVALIDARG;
977 /* check actual file/face type */
978 is_supported = FALSE;
979 face_type = DWRITE_FONT_FACE_TYPE_UNKNOWN;
980 hr = IDWriteFontFile_Analyze(*font_files, &is_supported, &file_type, &face_type, &count);
981 if (FAILED(hr))
982 return hr;
984 if (!is_supported)
985 return E_FAIL;
987 if (face_type != req_facetype)
988 return DWRITE_E_FILEFORMAT;
990 hr = factory_get_cached_fontface(iface, font_files, index, simulations, &fontfaces,
991 &IID_IDWriteFontFace, (void **)fontface);
992 if (hr != S_FALSE)
993 return hr;
995 desc.factory = iface;
996 desc.face_type = req_facetype;
997 desc.files = font_files;
998 desc.files_number = files_number;
999 desc.index = index;
1000 desc.simulations = simulations;
1001 desc.font_data = NULL;
1002 return create_fontface(&desc, fontfaces, (IDWriteFontFace4 **)fontface);
1005 static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory5 *iface, IDWriteRenderingParams **params)
1007 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1008 HMONITOR monitor;
1009 POINT pt;
1011 TRACE("(%p)->(%p)\n", This, params);
1013 pt.x = pt.y = 0;
1014 monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1015 return IDWriteFactory5_CreateMonitorRenderingParams(iface, monitor, params);
1018 static HRESULT WINAPI dwritefactory_CreateMonitorRenderingParams(IDWriteFactory5 *iface, HMONITOR monitor,
1019 IDWriteRenderingParams **params)
1021 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1022 IDWriteRenderingParams3 *params3;
1023 static int fixme_once = 0;
1024 HRESULT hr;
1026 TRACE("(%p)->(%p %p)\n", This, monitor, params);
1028 if (!fixme_once++)
1029 FIXME("(%p): monitor setting ignored\n", monitor);
1031 /* FIXME: use actual per-monitor gamma factor */
1032 hr = IDWriteFactory5_CreateCustomRenderingParams(iface, 2.0f, 0.0f, 1.0f, 0.0f, DWRITE_PIXEL_GEOMETRY_FLAT,
1033 DWRITE_RENDERING_MODE1_DEFAULT, DWRITE_GRID_FIT_MODE_DEFAULT, &params3);
1034 *params = (IDWriteRenderingParams*)params3;
1035 return hr;
1038 static HRESULT WINAPI dwritefactory_CreateCustomRenderingParams(IDWriteFactory5 *iface, FLOAT gamma,
1039 FLOAT enhancedContrast, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode,
1040 IDWriteRenderingParams **params)
1042 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1043 IDWriteRenderingParams3 *params3;
1044 HRESULT hr;
1046 TRACE("(%p)->(%f %f %f %d %d %p)\n", This, gamma, enhancedContrast, cleartype_level, geometry, mode, params);
1048 if ((UINT32)mode > DWRITE_RENDERING_MODE_OUTLINE) {
1049 *params = NULL;
1050 return E_INVALIDARG;
1053 hr = IDWriteFactory5_CreateCustomRenderingParams(iface, gamma, enhancedContrast, 1.0f, cleartype_level, geometry,
1054 (DWRITE_RENDERING_MODE1)mode, DWRITE_GRID_FIT_MODE_DEFAULT, &params3);
1055 *params = (IDWriteRenderingParams*)params3;
1056 return hr;
1059 static HRESULT WINAPI dwritefactory_RegisterFontFileLoader(IDWriteFactory5 *iface, IDWriteFontFileLoader *loader)
1061 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1062 struct fileloader *entry;
1064 TRACE("(%p)->(%p)\n", This, loader);
1066 if (!loader)
1067 return E_INVALIDARG;
1069 if ((IDWriteFontFileLoader*)This->localfontfileloader == loader)
1070 return S_OK;
1072 if (factory_get_file_loader(This, loader))
1073 return DWRITE_E_ALREADYREGISTERED;
1075 entry = heap_alloc(sizeof(*entry));
1076 if (!entry)
1077 return E_OUTOFMEMORY;
1079 entry->loader = loader;
1080 list_init(&entry->fontfaces);
1081 IDWriteFontFileLoader_AddRef(loader);
1082 list_add_tail(&This->file_loaders, &entry->entry);
1084 return S_OK;
1087 static HRESULT WINAPI dwritefactory_UnregisterFontFileLoader(IDWriteFactory5 *iface, IDWriteFontFileLoader *loader)
1089 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1090 struct fileloader *found;
1092 TRACE("(%p)->(%p)\n", This, loader);
1094 if (!loader)
1095 return E_INVALIDARG;
1097 if ((IDWriteFontFileLoader*)This->localfontfileloader == loader)
1098 return S_OK;
1100 found = factory_get_file_loader(This, loader);
1101 if (!found)
1102 return E_INVALIDARG;
1104 release_fileloader(found);
1105 return S_OK;
1108 static HRESULT WINAPI dwritefactory_CreateTextFormat(IDWriteFactory5 *iface, WCHAR const* family_name,
1109 IDWriteFontCollection *collection, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STYLE style,
1110 DWRITE_FONT_STRETCH stretch, FLOAT size, WCHAR const *locale, IDWriteTextFormat **format)
1112 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1113 HRESULT hr;
1115 TRACE("(%p)->(%s %p %d %d %d %f %s %p)\n", This, debugstr_w(family_name), collection, weight, style, stretch,
1116 size, debugstr_w(locale), format);
1118 if (collection)
1119 IDWriteFontCollection_AddRef(collection);
1120 else {
1121 collection = (IDWriteFontCollection *)factory_get_system_collection(This);
1122 if (!collection) {
1123 *format = NULL;
1124 return E_FAIL;
1128 hr = create_textformat(family_name, collection, weight, style, stretch, size, locale, format);
1129 IDWriteFontCollection_Release(collection);
1130 return hr;
1133 static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory5 *iface, IDWriteTypography **typography)
1135 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1136 TRACE("(%p)->(%p)\n", This, typography);
1137 return create_typography(typography);
1140 static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory5 *iface, IDWriteGdiInterop **gdi_interop)
1142 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1143 HRESULT hr = S_OK;
1145 TRACE("(%p)->(%p)\n", This, gdi_interop);
1147 if (This->gdiinterop)
1148 IDWriteGdiInterop1_AddRef(This->gdiinterop);
1149 else
1150 hr = create_gdiinterop(iface, &This->gdiinterop);
1152 *gdi_interop = (IDWriteGdiInterop *)This->gdiinterop;
1154 return hr;
1157 static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory5 *iface, WCHAR const* string,
1158 UINT32 length, IDWriteTextFormat *format, FLOAT max_width, FLOAT max_height, IDWriteTextLayout **layout)
1160 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1161 struct textlayout_desc desc;
1163 TRACE("(%p)->(%s:%u %p %f %f %p)\n", This, debugstr_wn(string, length), length, format, max_width, max_height, layout);
1165 desc.factory = iface;
1166 desc.string = string;
1167 desc.length = length;
1168 desc.format = format;
1169 desc.max_width = max_width;
1170 desc.max_height = max_height;
1171 desc.is_gdi_compatible = FALSE;
1172 desc.ppdip = 1.0f;
1173 desc.transform = NULL;
1174 desc.use_gdi_natural = FALSE;
1175 return create_textlayout(&desc, layout);
1178 static HRESULT WINAPI dwritefactory_CreateGdiCompatibleTextLayout(IDWriteFactory5 *iface, WCHAR const* string,
1179 UINT32 length, IDWriteTextFormat *format, FLOAT max_width, FLOAT max_height, FLOAT pixels_per_dip,
1180 DWRITE_MATRIX const* transform, BOOL use_gdi_natural, IDWriteTextLayout **layout)
1182 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1183 struct textlayout_desc desc;
1185 TRACE("(%p)->(%s:%u %p %f %f %f %p %d %p)\n", This, debugstr_wn(string, length), length, format, max_width,
1186 max_height, pixels_per_dip, transform, use_gdi_natural, layout);
1188 desc.factory = iface;
1189 desc.string = string;
1190 desc.length = length;
1191 desc.format = format;
1192 desc.max_width = max_width;
1193 desc.max_height = max_height;
1194 desc.is_gdi_compatible = TRUE;
1195 desc.ppdip = pixels_per_dip;
1196 desc.transform = transform;
1197 desc.use_gdi_natural = use_gdi_natural;
1198 return create_textlayout(&desc, layout);
1201 static HRESULT WINAPI dwritefactory_CreateEllipsisTrimmingSign(IDWriteFactory5 *iface, IDWriteTextFormat *format,
1202 IDWriteInlineObject **trimming_sign)
1204 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1205 TRACE("(%p)->(%p %p)\n", This, format, trimming_sign);
1206 return create_trimmingsign(iface, format, trimming_sign);
1209 static HRESULT WINAPI dwritefactory_CreateTextAnalyzer(IDWriteFactory5 *iface, IDWriteTextAnalyzer **analyzer)
1211 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1213 TRACE("(%p)->(%p)\n", This, analyzer);
1215 *analyzer = get_text_analyzer();
1217 return S_OK;
1220 static HRESULT WINAPI dwritefactory_CreateNumberSubstitution(IDWriteFactory5 *iface,
1221 DWRITE_NUMBER_SUBSTITUTION_METHOD method, WCHAR const* locale, BOOL ignore_user_override,
1222 IDWriteNumberSubstitution **substitution)
1224 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1225 TRACE("(%p)->(%d %s %d %p)\n", This, method, debugstr_w(locale), ignore_user_override, substitution);
1226 return create_numbersubstitution(method, locale, ignore_user_override, substitution);
1229 static HRESULT WINAPI dwritefactory_CreateGlyphRunAnalysis(IDWriteFactory5 *iface, DWRITE_GLYPH_RUN const *run,
1230 FLOAT ppdip, DWRITE_MATRIX const* transform, DWRITE_RENDERING_MODE rendering_mode,
1231 DWRITE_MEASURING_MODE measuring_mode, FLOAT originX, FLOAT originY, IDWriteGlyphRunAnalysis **analysis)
1233 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1234 struct glyphrunanalysis_desc desc;
1236 TRACE("(%p)->(%p %.2f %p %d %d %.2f %.2f %p)\n", This, run, ppdip, transform, rendering_mode,
1237 measuring_mode, originX, originY, analysis);
1239 if (ppdip <= 0.0f) {
1240 *analysis = NULL;
1241 return E_INVALIDARG;
1244 desc.run = run;
1245 desc.ppdip = ppdip;
1246 desc.transform = transform;
1247 desc.rendering_mode = (DWRITE_RENDERING_MODE1)rendering_mode;
1248 desc.measuring_mode = measuring_mode;
1249 desc.gridfit_mode = DWRITE_GRID_FIT_MODE_DEFAULT;
1250 desc.aa_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1251 desc.origin_x = originX;
1252 desc.origin_y = originY;
1253 return create_glyphrunanalysis(&desc, analysis);
1256 static HRESULT WINAPI dwritefactory1_GetEudcFontCollection(IDWriteFactory5 *iface, IDWriteFontCollection **collection,
1257 BOOL check_for_updates)
1259 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1260 HRESULT hr = S_OK;
1262 TRACE("(%p)->(%p %d)\n", This, collection, check_for_updates);
1264 if (check_for_updates)
1265 FIXME("checking for eudc updates not implemented\n");
1267 if (This->eudc_collection)
1268 IDWriteFontCollection1_AddRef(This->eudc_collection);
1269 else {
1270 IDWriteFontCollection1 *eudc_collection;
1272 if (FAILED(hr = get_eudc_fontcollection(iface, &eudc_collection))) {
1273 *collection = NULL;
1274 WARN("Failed to get EUDC collection, hr %#x.\n", hr);
1275 return hr;
1278 if (InterlockedCompareExchangePointer((void **)&This->eudc_collection, eudc_collection, NULL))
1279 IDWriteFontCollection1_Release(eudc_collection);
1282 *collection = (IDWriteFontCollection *)This->eudc_collection;
1284 return hr;
1287 static HRESULT WINAPI dwritefactory1_CreateCustomRenderingParams(IDWriteFactory5 *iface, FLOAT gamma,
1288 FLOAT enhcontrast, FLOAT enhcontrast_grayscale, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry,
1289 DWRITE_RENDERING_MODE mode, IDWriteRenderingParams1** params)
1291 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1292 IDWriteRenderingParams3 *params3;
1293 HRESULT hr;
1295 TRACE("(%p)->(%.2f %.2f %.2f %.2f %d %d %p)\n", This, gamma, enhcontrast, enhcontrast_grayscale,
1296 cleartype_level, geometry, mode, params);
1298 if ((UINT32)mode > DWRITE_RENDERING_MODE_OUTLINE) {
1299 *params = NULL;
1300 return E_INVALIDARG;
1303 hr = IDWriteFactory5_CreateCustomRenderingParams(iface, gamma, enhcontrast, enhcontrast_grayscale,
1304 cleartype_level, geometry, (DWRITE_RENDERING_MODE1)mode, DWRITE_GRID_FIT_MODE_DEFAULT, &params3);
1305 *params = (IDWriteRenderingParams1*)params3;
1306 return hr;
1309 static HRESULT WINAPI dwritefactory2_GetSystemFontFallback(IDWriteFactory5 *iface, IDWriteFontFallback **fallback)
1311 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1313 TRACE("(%p)->(%p)\n", This, fallback);
1315 *fallback = NULL;
1317 if (!This->fallback) {
1318 HRESULT hr = create_system_fontfallback(iface, &This->fallback);
1319 if (FAILED(hr))
1320 return hr;
1323 *fallback = This->fallback;
1324 IDWriteFontFallback_AddRef(*fallback);
1325 return S_OK;
1328 static HRESULT WINAPI dwritefactory2_CreateFontFallbackBuilder(IDWriteFactory5 *iface,
1329 IDWriteFontFallbackBuilder **fallbackbuilder)
1331 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1332 FIXME("(%p)->(%p): stub\n", This, fallbackbuilder);
1333 return E_NOTIMPL;
1336 static HRESULT WINAPI dwritefactory2_TranslateColorGlyphRun(IDWriteFactory5 *iface, FLOAT originX, FLOAT originY,
1337 const DWRITE_GLYPH_RUN *run, const DWRITE_GLYPH_RUN_DESCRIPTION *rundescr, DWRITE_MEASURING_MODE mode,
1338 const DWRITE_MATRIX *transform, UINT32 palette, IDWriteColorGlyphRunEnumerator **colorlayers)
1340 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1341 TRACE("(%p)->(%.2f %.2f %p %p %d %p %u %p)\n", This, originX, originY, run, rundescr, mode,
1342 transform, palette, colorlayers);
1343 return create_colorglyphenum(originX, originY, run, rundescr, mode, transform, palette, colorlayers);
1346 static HRESULT WINAPI dwritefactory2_CreateCustomRenderingParams(IDWriteFactory5 *iface, FLOAT gamma, FLOAT contrast,
1347 FLOAT grayscalecontrast, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY geometry, DWRITE_RENDERING_MODE mode,
1348 DWRITE_GRID_FIT_MODE gridfit, IDWriteRenderingParams2 **params)
1350 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1351 IDWriteRenderingParams3 *params3;
1352 HRESULT hr;
1354 TRACE("(%p)->(%.2f %.2f %.2f %.2f %d %d %d %p)\n", This, gamma, contrast, grayscalecontrast, cleartype_level,
1355 geometry, mode, gridfit, params);
1357 if ((UINT32)mode > DWRITE_RENDERING_MODE_OUTLINE) {
1358 *params = NULL;
1359 return E_INVALIDARG;
1362 hr = IDWriteFactory5_CreateCustomRenderingParams(iface, gamma, contrast, grayscalecontrast,
1363 cleartype_level, geometry, (DWRITE_RENDERING_MODE1)mode, DWRITE_GRID_FIT_MODE_DEFAULT, &params3);
1364 *params = (IDWriteRenderingParams2*)params3;
1365 return hr;
1368 static HRESULT WINAPI dwritefactory2_CreateGlyphRunAnalysis(IDWriteFactory5 *iface, const DWRITE_GLYPH_RUN *run,
1369 const DWRITE_MATRIX *transform, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1370 DWRITE_GRID_FIT_MODE gridfit_mode, DWRITE_TEXT_ANTIALIAS_MODE aa_mode, FLOAT originX, FLOAT originY,
1371 IDWriteGlyphRunAnalysis **analysis)
1373 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1374 struct glyphrunanalysis_desc desc;
1376 TRACE("(%p)->(%p %p %d %d %d %d %.2f %.2f %p)\n", This, run, transform, rendering_mode, measuring_mode,
1377 gridfit_mode, aa_mode, originX, originY, analysis);
1379 desc.run = run;
1380 desc.ppdip = 1.0f;
1381 desc.transform = transform;
1382 desc.rendering_mode = (DWRITE_RENDERING_MODE1)rendering_mode;
1383 desc.measuring_mode = measuring_mode;
1384 desc.gridfit_mode = gridfit_mode;
1385 desc.aa_mode = aa_mode;
1386 desc.origin_x = originX;
1387 desc.origin_y = originY;
1388 return create_glyphrunanalysis(&desc, analysis);
1391 static HRESULT WINAPI dwritefactory3_CreateGlyphRunAnalysis(IDWriteFactory5 *iface, DWRITE_GLYPH_RUN const *run,
1392 DWRITE_MATRIX const *transform, DWRITE_RENDERING_MODE1 rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1393 DWRITE_GRID_FIT_MODE gridfit_mode, DWRITE_TEXT_ANTIALIAS_MODE aa_mode, FLOAT originX, FLOAT originY,
1394 IDWriteGlyphRunAnalysis **analysis)
1396 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1397 struct glyphrunanalysis_desc desc;
1399 TRACE("(%p)->(%p %p %d %d %d %d %.2f %.2f %p)\n", This, run, transform, rendering_mode, measuring_mode,
1400 gridfit_mode, aa_mode, originX, originY, analysis);
1402 desc.run = run;
1403 desc.ppdip = 1.0f;
1404 desc.transform = transform;
1405 desc.rendering_mode = rendering_mode;
1406 desc.measuring_mode = measuring_mode;
1407 desc.gridfit_mode = gridfit_mode;
1408 desc.aa_mode = aa_mode;
1409 desc.origin_x = originX;
1410 desc.origin_y = originY;
1411 return create_glyphrunanalysis(&desc, analysis);
1414 static HRESULT WINAPI dwritefactory3_CreateCustomRenderingParams(IDWriteFactory5 *iface, FLOAT gamma, FLOAT contrast,
1415 FLOAT grayscale_contrast, FLOAT cleartype_level, DWRITE_PIXEL_GEOMETRY pixel_geometry,
1416 DWRITE_RENDERING_MODE1 rendering_mode, DWRITE_GRID_FIT_MODE gridfit_mode, IDWriteRenderingParams3 **params)
1418 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1420 TRACE("(%p)->(%.2f %.2f %.2f %.2f %d %d %d %p)\n", This, gamma, contrast, grayscale_contrast, cleartype_level,
1421 pixel_geometry, rendering_mode, gridfit_mode, params);
1423 return create_renderingparams(gamma, contrast, grayscale_contrast, cleartype_level, pixel_geometry, rendering_mode,
1424 gridfit_mode, params);
1427 static HRESULT WINAPI dwritefactory3_CreateFontFaceReference_(IDWriteFactory5 *iface, IDWriteFontFile *file,
1428 UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFaceReference **reference)
1430 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1432 TRACE("(%p)->(%p %u %x %p)\n", This, file, index, simulations, reference);
1434 return create_fontfacereference(iface, file, index, simulations, reference);
1437 static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory5 *iface, WCHAR const *path,
1438 FILETIME const *writetime, UINT32 index, DWRITE_FONT_SIMULATIONS simulations,
1439 IDWriteFontFaceReference **reference)
1441 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1442 IDWriteFontFile *file;
1443 HRESULT hr;
1445 TRACE("(%p)->(%s %p %u %x, %p)\n", This, debugstr_w(path), writetime, index, simulations, reference);
1447 hr = IDWriteFactory5_CreateFontFileReference(iface, path, writetime, &file);
1448 if (FAILED(hr)) {
1449 *reference = NULL;
1450 return hr;
1453 hr = IDWriteFactory5_CreateFontFaceReference_(iface, file, index, simulations, reference);
1454 IDWriteFontFile_Release(file);
1455 return hr;
1458 static HRESULT WINAPI dwritefactory3_GetSystemFontSet(IDWriteFactory5 *iface, IDWriteFontSet **fontset)
1460 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1462 FIXME("(%p)->(%p): stub\n", This, fontset);
1464 return E_NOTIMPL;
1467 static HRESULT WINAPI dwritefactory3_CreateFontSetBuilder(IDWriteFactory5 *iface, IDWriteFontSetBuilder **builder)
1469 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1471 FIXME("(%p)->(%p): stub\n", This, builder);
1473 return E_NOTIMPL;
1476 static HRESULT WINAPI dwritefactory3_CreateFontCollectionFromFontSet(IDWriteFactory5 *iface, IDWriteFontSet *fontset,
1477 IDWriteFontCollection1 **collection)
1479 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1481 FIXME("(%p)->(%p %p): stub\n", This, fontset, collection);
1483 return E_NOTIMPL;
1486 static HRESULT WINAPI dwritefactory3_GetSystemFontCollection(IDWriteFactory5 *iface, BOOL include_downloadable,
1487 IDWriteFontCollection1 **collection, BOOL check_for_updates)
1489 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1491 TRACE("(%p)->(%d %p %d)\n", This, include_downloadable, collection, check_for_updates);
1493 if (include_downloadable)
1494 FIXME("remote fonts are not supported\n");
1496 if (check_for_updates)
1497 FIXME("checking for system font updates not implemented\n");
1499 *collection = factory_get_system_collection(This);
1501 return *collection ? S_OK : E_FAIL;
1504 static HRESULT WINAPI dwritefactory3_GetFontDownloadQueue(IDWriteFactory5 *iface, IDWriteFontDownloadQueue **queue)
1506 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1508 FIXME("(%p)->(%p): stub\n", This, queue);
1510 return E_NOTIMPL;
1513 static HRESULT WINAPI dwritefactory4_TranslateColorGlyphRun(IDWriteFactory5 *iface, D2D1_POINT_2F baseline_origin,
1514 DWRITE_GLYPH_RUN const *run, DWRITE_GLYPH_RUN_DESCRIPTION const *run_desc,
1515 DWRITE_GLYPH_IMAGE_FORMATS desired_formats, DWRITE_MEASURING_MODE measuring_mode, DWRITE_MATRIX const *transform,
1516 UINT32 palette, IDWriteColorGlyphRunEnumerator1 **layers)
1518 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1520 FIXME("(%p)->(%p %p %u %d %p %u %p): stub\n", This, run, run_desc, desired_formats, measuring_mode,
1521 transform, palette, layers);
1523 return E_NOTIMPL;
1526 static HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode,
1527 D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins)
1529 IDWriteFontFace1 *fontface1 = NULL;
1530 DWRITE_FONT_METRICS metrics;
1531 FLOAT rtl_factor;
1532 HRESULT hr;
1533 UINT32 i;
1535 rtl_factor = run->bidiLevel & 1 ? -1.0f : 1.0f;
1537 if (run->fontFace) {
1538 IDWriteFontFace_GetMetrics(run->fontFace, &metrics);
1539 if (FAILED(hr = IDWriteFontFace_QueryInterface(run->fontFace, &IID_IDWriteFontFace1, (void **)&fontface1)))
1540 WARN("Failed to get IDWriteFontFace1, %#x.\n", hr);
1543 for (i = 0; i < run->glyphCount; i++) {
1544 FLOAT advance;
1546 /* Use nominal advances if not provided by caller. */
1547 if (run->glyphAdvances)
1548 advance = rtl_factor * run->glyphAdvances[i];
1549 else {
1550 INT32 a;
1552 advance = 0.0f;
1553 switch (measuring_mode)
1555 case DWRITE_MEASURING_MODE_NATURAL:
1556 if (SUCCEEDED(IDWriteFontFace1_GetDesignGlyphAdvances(fontface1, 1, run->glyphIndices + i, &a,
1557 run->isSideways)))
1558 advance = rtl_factor * get_scaled_advance_width(a, run->fontEmSize, &metrics);
1559 break;
1560 case DWRITE_MEASURING_MODE_GDI_CLASSIC:
1561 case DWRITE_MEASURING_MODE_GDI_NATURAL:
1562 if (SUCCEEDED(IDWriteFontFace1_GetGdiCompatibleGlyphAdvances(fontface1, run->fontEmSize,
1563 1.0f, transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL,
1564 run->isSideways, 1, run->glyphIndices + i, &a)))
1565 advance = rtl_factor * floorf(a * run->fontEmSize / metrics.designUnitsPerEm + 0.5f);
1566 break;
1567 default:
1572 origins[i] = baseline_origin;
1574 /* Apply offsets. */
1575 if (run->glyphOffsets) {
1576 FLOAT advanceoffset = rtl_factor * run->glyphOffsets[i].advanceOffset;
1577 FLOAT ascenderoffset = -run->glyphOffsets[i].ascenderOffset;
1579 if (run->isSideways) {
1580 origins[i].x += ascenderoffset;
1581 origins[i].y += advanceoffset;
1583 else {
1584 origins[i].x += advanceoffset;
1585 origins[i].y += ascenderoffset;
1589 if (run->isSideways)
1590 baseline_origin.y += advance;
1591 else
1592 baseline_origin.x += advance;
1595 if (fontface1)
1596 IDWriteFontFace1_Release(fontface1);
1597 return S_OK;
1600 static HRESULT WINAPI dwritefactory4_ComputeGlyphOrigins_(IDWriteFactory5 *iface, DWRITE_GLYPH_RUN const *run,
1601 D2D1_POINT_2F baseline_origin, D2D1_POINT_2F *origins)
1603 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1605 TRACE("(%p)->(%p (%f,%f) %p)\n", This, run, baseline_origin.x, baseline_origin.y, origins);
1607 return compute_glyph_origins(run, DWRITE_MEASURING_MODE_NATURAL, baseline_origin, NULL, origins);
1610 static HRESULT WINAPI dwritefactory4_ComputeGlyphOrigins(IDWriteFactory5 *iface, DWRITE_GLYPH_RUN const *run,
1611 DWRITE_MEASURING_MODE measuring_mode, D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform,
1612 D2D1_POINT_2F *origins)
1614 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1616 TRACE("(%p)->(%p %d (%f,%f) %p %p)\n", This, run, measuring_mode, baseline_origin.x, baseline_origin.y,
1617 transform, origins);
1619 return compute_glyph_origins(run, measuring_mode, baseline_origin, transform, origins);
1622 static HRESULT WINAPI dwritefactory5_CreateFontSetBuilder(IDWriteFactory5 *iface, IDWriteFontSetBuilder1 **builder)
1624 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1626 FIXME("(%p)->(%p): stub\n", This, builder);
1628 return E_NOTIMPL;
1631 static HRESULT WINAPI dwritefactory5_CreateInMemoryFontFileLoader(IDWriteFactory5 *iface, IDWriteFontFileLoader **loader)
1633 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1635 FIXME("(%p)->(%p): stub\n", This, loader);
1637 return E_NOTIMPL;
1640 static HRESULT WINAPI dwritefactory5_CreateHttpFontFileLoader(IDWriteFactory5 *iface, WCHAR const *referrer_url, WCHAR const *extra_headers,
1641 IDWriteRemoteFontFileLoader **loader)
1643 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1645 FIXME("(%p)->(%s %s %p): stub\n", This, debugstr_w(referrer_url), wine_dbgstr_w(extra_headers), loader);
1647 return E_NOTIMPL;
1650 static DWRITE_CONTAINER_TYPE WINAPI dwritefactory5_AnalyzeContainerType(IDWriteFactory5 *iface, void const *data, UINT32 data_size)
1652 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1654 FIXME("(%p)->(%p %u): stub\n", This, data, data_size);
1656 return DWRITE_CONTAINER_TYPE_UNKNOWN;
1659 static HRESULT WINAPI dwritefactory5_UnpackFontFile(IDWriteFactory5 *iface, DWRITE_CONTAINER_TYPE container_type, void const *data,
1660 UINT32 data_size, IDWriteFontFileStream **stream)
1662 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1664 FIXME("(%p)->(%d %p %u %p): stub\n", This, container_type, data, data_size, stream);
1666 return E_NOTIMPL;
1669 static const struct IDWriteFactory5Vtbl dwritefactoryvtbl = {
1670 dwritefactory_QueryInterface,
1671 dwritefactory_AddRef,
1672 dwritefactory_Release,
1673 dwritefactory_GetSystemFontCollection,
1674 dwritefactory_CreateCustomFontCollection,
1675 dwritefactory_RegisterFontCollectionLoader,
1676 dwritefactory_UnregisterFontCollectionLoader,
1677 dwritefactory_CreateFontFileReference,
1678 dwritefactory_CreateCustomFontFileReference,
1679 dwritefactory_CreateFontFace,
1680 dwritefactory_CreateRenderingParams,
1681 dwritefactory_CreateMonitorRenderingParams,
1682 dwritefactory_CreateCustomRenderingParams,
1683 dwritefactory_RegisterFontFileLoader,
1684 dwritefactory_UnregisterFontFileLoader,
1685 dwritefactory_CreateTextFormat,
1686 dwritefactory_CreateTypography,
1687 dwritefactory_GetGdiInterop,
1688 dwritefactory_CreateTextLayout,
1689 dwritefactory_CreateGdiCompatibleTextLayout,
1690 dwritefactory_CreateEllipsisTrimmingSign,
1691 dwritefactory_CreateTextAnalyzer,
1692 dwritefactory_CreateNumberSubstitution,
1693 dwritefactory_CreateGlyphRunAnalysis,
1694 dwritefactory1_GetEudcFontCollection,
1695 dwritefactory1_CreateCustomRenderingParams,
1696 dwritefactory2_GetSystemFontFallback,
1697 dwritefactory2_CreateFontFallbackBuilder,
1698 dwritefactory2_TranslateColorGlyphRun,
1699 dwritefactory2_CreateCustomRenderingParams,
1700 dwritefactory2_CreateGlyphRunAnalysis,
1701 dwritefactory3_CreateGlyphRunAnalysis,
1702 dwritefactory3_CreateCustomRenderingParams,
1703 dwritefactory3_CreateFontFaceReference_,
1704 dwritefactory3_CreateFontFaceReference,
1705 dwritefactory3_GetSystemFontSet,
1706 dwritefactory3_CreateFontSetBuilder,
1707 dwritefactory3_CreateFontCollectionFromFontSet,
1708 dwritefactory3_GetSystemFontCollection,
1709 dwritefactory3_GetFontDownloadQueue,
1710 dwritefactory4_TranslateColorGlyphRun,
1711 dwritefactory4_ComputeGlyphOrigins_,
1712 dwritefactory4_ComputeGlyphOrigins,
1713 dwritefactory5_CreateFontSetBuilder,
1714 dwritefactory5_CreateInMemoryFontFileLoader,
1715 dwritefactory5_CreateHttpFontFileLoader,
1716 dwritefactory5_AnalyzeContainerType,
1717 dwritefactory5_UnpackFontFile,
1720 static ULONG WINAPI shareddwritefactory_AddRef(IDWriteFactory5 *iface)
1722 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1723 TRACE("(%p)\n", This);
1724 return 2;
1727 static ULONG WINAPI shareddwritefactory_Release(IDWriteFactory5 *iface)
1729 struct dwritefactory *This = impl_from_IDWriteFactory5(iface);
1730 TRACE("(%p)\n", This);
1731 return 1;
1734 static const struct IDWriteFactory5Vtbl shareddwritefactoryvtbl = {
1735 dwritefactory_QueryInterface,
1736 shareddwritefactory_AddRef,
1737 shareddwritefactory_Release,
1738 dwritefactory_GetSystemFontCollection,
1739 dwritefactory_CreateCustomFontCollection,
1740 dwritefactory_RegisterFontCollectionLoader,
1741 dwritefactory_UnregisterFontCollectionLoader,
1742 dwritefactory_CreateFontFileReference,
1743 dwritefactory_CreateCustomFontFileReference,
1744 dwritefactory_CreateFontFace,
1745 dwritefactory_CreateRenderingParams,
1746 dwritefactory_CreateMonitorRenderingParams,
1747 dwritefactory_CreateCustomRenderingParams,
1748 dwritefactory_RegisterFontFileLoader,
1749 dwritefactory_UnregisterFontFileLoader,
1750 dwritefactory_CreateTextFormat,
1751 dwritefactory_CreateTypography,
1752 dwritefactory_GetGdiInterop,
1753 dwritefactory_CreateTextLayout,
1754 dwritefactory_CreateGdiCompatibleTextLayout,
1755 dwritefactory_CreateEllipsisTrimmingSign,
1756 dwritefactory_CreateTextAnalyzer,
1757 dwritefactory_CreateNumberSubstitution,
1758 dwritefactory_CreateGlyphRunAnalysis,
1759 dwritefactory1_GetEudcFontCollection,
1760 dwritefactory1_CreateCustomRenderingParams,
1761 dwritefactory2_GetSystemFontFallback,
1762 dwritefactory2_CreateFontFallbackBuilder,
1763 dwritefactory2_TranslateColorGlyphRun,
1764 dwritefactory2_CreateCustomRenderingParams,
1765 dwritefactory2_CreateGlyphRunAnalysis,
1766 dwritefactory3_CreateGlyphRunAnalysis,
1767 dwritefactory3_CreateCustomRenderingParams,
1768 dwritefactory3_CreateFontFaceReference_,
1769 dwritefactory3_CreateFontFaceReference,
1770 dwritefactory3_GetSystemFontSet,
1771 dwritefactory3_CreateFontSetBuilder,
1772 dwritefactory3_CreateFontCollectionFromFontSet,
1773 dwritefactory3_GetSystemFontCollection,
1774 dwritefactory3_GetFontDownloadQueue,
1775 dwritefactory4_TranslateColorGlyphRun,
1776 dwritefactory4_ComputeGlyphOrigins_,
1777 dwritefactory4_ComputeGlyphOrigins,
1778 dwritefactory5_CreateFontSetBuilder,
1779 dwritefactory5_CreateInMemoryFontFileLoader,
1780 dwritefactory5_CreateHttpFontFileLoader,
1781 dwritefactory5_AnalyzeContainerType,
1782 dwritefactory5_UnpackFontFile,
1785 static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYPE type)
1787 factory->IDWriteFactory5_iface.lpVtbl = type == DWRITE_FACTORY_TYPE_SHARED ?
1788 &shareddwritefactoryvtbl : &dwritefactoryvtbl;
1789 factory->ref = 1;
1790 factory->localfontfileloader = NULL;
1791 factory->system_collection = NULL;
1792 factory->eudc_collection = NULL;
1793 factory->gdiinterop = NULL;
1794 factory->fallback = NULL;
1796 list_init(&factory->collection_loaders);
1797 list_init(&factory->file_loaders);
1798 list_init(&factory->localfontfaces);
1800 InitializeCriticalSection(&factory->cs);
1801 factory->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": dwritefactory.lock");
1804 void factory_detach_fontcollection(IDWriteFactory5 *iface, IDWriteFontCollection1 *collection)
1806 struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
1807 InterlockedCompareExchangePointer((void **)&factory->system_collection, NULL, collection);
1808 InterlockedCompareExchangePointer((void **)&factory->eudc_collection, NULL, collection);
1809 IDWriteFactory5_Release(iface);
1812 void factory_detach_gdiinterop(IDWriteFactory5 *iface, IDWriteGdiInterop1 *interop)
1814 struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
1815 factory->gdiinterop = NULL;
1816 IDWriteFactory5_Release(iface);
1819 HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
1821 struct dwritefactory *factory;
1822 HRESULT hr;
1824 TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), ret);
1826 *ret = NULL;
1828 if (type == DWRITE_FACTORY_TYPE_SHARED && shared_factory)
1829 return IDWriteFactory5_QueryInterface(shared_factory, riid, (void**)ret);
1831 factory = heap_alloc(sizeof(struct dwritefactory));
1832 if (!factory) return E_OUTOFMEMORY;
1834 init_dwritefactory(factory, type);
1836 if (type == DWRITE_FACTORY_TYPE_SHARED)
1837 if (InterlockedCompareExchangePointer((void**)&shared_factory, &factory->IDWriteFactory5_iface, NULL)) {
1838 release_shared_factory(&factory->IDWriteFactory5_iface);
1839 return IDWriteFactory5_QueryInterface(shared_factory, riid, (void**)ret);
1842 hr = IDWriteFactory5_QueryInterface(&factory->IDWriteFactory5_iface, riid, (void**)ret);
1843 IDWriteFactory5_Release(&factory->IDWriteFactory5_iface);
1844 return hr;