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