dwrite: Protect cached fontface list when accessed from multiple threads.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d53b711f27
commit
fb5079d887
|
@ -157,6 +157,12 @@ struct fontface_desc
|
||||||
struct dwrite_font_data *font_data; /* could be NULL when face is created directly with IDWriteFactory::CreateFontFace() */
|
struct dwrite_font_data *font_data; /* could be NULL when face is created directly with IDWriteFactory::CreateFontFace() */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fontfacecached
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
IDWriteFontFace4 *fontface;
|
||||||
|
};
|
||||||
|
|
||||||
extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN;
|
extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
|
extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH,
|
||||||
FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN;
|
FLOAT,const WCHAR*,IDWriteTextFormat**) DECLSPEC_HIDDEN;
|
||||||
|
@ -189,16 +195,17 @@ extern HRESULT create_matching_font(IDWriteFontCollection*,const WCHAR*,DWRITE_F
|
||||||
IDWriteFont**) DECLSPEC_HIDDEN;
|
IDWriteFont**) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT create_fontfacereference(IDWriteFactory5*,IDWriteFontFile*,UINT32,DWRITE_FONT_SIMULATIONS,
|
extern HRESULT create_fontfacereference(IDWriteFactory5*,IDWriteFontFile*,UINT32,DWRITE_FONT_SIMULATIONS,
|
||||||
IDWriteFontFaceReference**) DECLSPEC_HIDDEN;
|
IDWriteFontFaceReference**) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT factory_get_cached_fontface(IDWriteFactory5*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace**,
|
extern HRESULT factory_get_cached_fontface(IDWriteFactory5*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,
|
||||||
struct list**) DECLSPEC_HIDDEN;
|
struct list**,REFIID,void**) DECLSPEC_HIDDEN;
|
||||||
extern void factory_detach_fontcollection(IDWriteFactory5*,IDWriteFontCollection1*) DECLSPEC_HIDDEN;
|
extern void factory_detach_fontcollection(IDWriteFactory5*,IDWriteFontCollection1*) DECLSPEC_HIDDEN;
|
||||||
extern void factory_detach_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN;
|
extern void factory_detach_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN;
|
||||||
extern struct fontfacecached *factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN;
|
extern struct fontfacecached *factory_cache_fontface(IDWriteFactory5*,struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN;
|
||||||
extern void factory_release_cached_fontface(struct fontfacecached*) DECLSPEC_HIDDEN;
|
|
||||||
extern void get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN;
|
extern void get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN;
|
||||||
extern void get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN;
|
extern void get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT create_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1**) DECLSPEC_HIDDEN;
|
extern HRESULT create_gdiinterop(IDWriteFactory5*,IDWriteGdiInterop1**) DECLSPEC_HIDDEN;
|
||||||
extern void fontface_detach_from_cache(IDWriteFontFace4*) DECLSPEC_HIDDEN;
|
extern void fontface_detach_from_cache(IDWriteFontFace4*) DECLSPEC_HIDDEN;
|
||||||
|
extern void factory_lock(IDWriteFactory5*) DECLSPEC_HIDDEN;
|
||||||
|
extern void factory_unlock(IDWriteFactory5*) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Opentype font table functions */
|
/* Opentype font table functions */
|
||||||
struct dwrite_font_props {
|
struct dwrite_font_props {
|
||||||
|
|
|
@ -463,7 +463,11 @@ static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace4 *iface, REF
|
||||||
IsEqualIID(riid, &IID_IUnknown))
|
IsEqualIID(riid, &IID_IUnknown))
|
||||||
{
|
{
|
||||||
*obj = iface;
|
*obj = iface;
|
||||||
IDWriteFontFace4_AddRef(iface);
|
if (InterlockedIncrement(&This->ref) == 1) {
|
||||||
|
InterlockedDecrement(&This->ref);
|
||||||
|
*obj = NULL;
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,6 +493,13 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace4 *iface)
|
||||||
if (!ref) {
|
if (!ref) {
|
||||||
UINT32 i;
|
UINT32 i;
|
||||||
|
|
||||||
|
factory_lock(This->factory);
|
||||||
|
|
||||||
|
if (This->cached) {
|
||||||
|
list_remove(&This->cached->entry);
|
||||||
|
heap_free(This->cached);
|
||||||
|
}
|
||||||
|
|
||||||
if (This->cmap.context)
|
if (This->cmap.context)
|
||||||
IDWriteFontFace4_ReleaseFontTable(iface, This->cmap.context);
|
IDWriteFontFace4_ReleaseFontTable(iface, This->cmap.context);
|
||||||
if (This->vdmx.context)
|
if (This->vdmx.context)
|
||||||
|
@ -512,10 +523,9 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace4 *iface)
|
||||||
heap_free(This->glyphs[i]);
|
heap_free(This->glyphs[i]);
|
||||||
|
|
||||||
freetype_notify_cacheremove(iface);
|
freetype_notify_cacheremove(iface);
|
||||||
if (This->cached)
|
|
||||||
factory_release_cached_fontface(This->cached);
|
factory_unlock(This->factory);
|
||||||
if (This->factory)
|
IDWriteFactory5_Release(This->factory);
|
||||||
IDWriteFactory5_Release(This->factory);
|
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1378,11 +1388,9 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace4
|
||||||
*fontface = NULL;
|
*fontface = NULL;
|
||||||
|
|
||||||
hr = factory_get_cached_fontface(font->family->collection->factory, &data->file, data->face_index,
|
hr = factory_get_cached_fontface(font->family->collection->factory, &data->file, data->face_index,
|
||||||
font->data->simulations, (IDWriteFontFace **)fontface, &cached_list);
|
font->data->simulations, &cached_list, &IID_IDWriteFontFace4, (void **)fontface);
|
||||||
if (hr == S_OK) {
|
if (hr == S_OK)
|
||||||
IDWriteFontFace4_AddRef(*fontface);
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
|
||||||
|
|
||||||
desc.factory = font->family->collection->factory;
|
desc.factory = font->family->collection->factory;
|
||||||
desc.face_type = data->face_type;
|
desc.face_type = data->face_type;
|
||||||
|
@ -4325,6 +4333,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
|
||||||
fontface->colr.exists = TRUE;
|
fontface->colr.exists = TRUE;
|
||||||
fontface->index = desc->index;
|
fontface->index = desc->index;
|
||||||
fontface->simulations = desc->simulations;
|
fontface->simulations = desc->simulations;
|
||||||
|
IDWriteFactory5_AddRef(fontface->factory = desc->factory);
|
||||||
|
|
||||||
for (i = 0; i < fontface->file_count; i++) {
|
for (i = 0; i < fontface->file_count; i++) {
|
||||||
hr = get_stream_from_file(desc->files[i], &fontface->streams[i]);
|
hr = get_stream_from_file(desc->files[i], &fontface->streams[i]);
|
||||||
|
@ -4392,8 +4401,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
|
||||||
release_font_data(data);
|
release_font_data(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fontface->cached = factory_cache_fontface(cached_list, &fontface->IDWriteFontFace4_iface);
|
fontface->cached = factory_cache_fontface(fontface->factory, cached_list, &fontface->IDWriteFontFace4_iface);
|
||||||
IDWriteFactory5_AddRef(fontface->factory = desc->factory);
|
|
||||||
|
|
||||||
*ret = &fontface->IDWriteFontFace4_iface;
|
*ret = &fontface->IDWriteFontFace4_iface;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -526,12 +526,6 @@ struct collectionloader
|
||||||
IDWriteFontCollectionLoader *loader;
|
IDWriteFontCollectionLoader *loader;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fontfacecached
|
|
||||||
{
|
|
||||||
struct list entry;
|
|
||||||
IDWriteFontFace4 *fontface;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct fileloader
|
struct fileloader
|
||||||
{
|
{
|
||||||
struct list entry;
|
struct list entry;
|
||||||
|
@ -553,6 +547,8 @@ struct dwritefactory {
|
||||||
|
|
||||||
struct list collection_loaders;
|
struct list collection_loaders;
|
||||||
struct list file_loaders;
|
struct list file_loaders;
|
||||||
|
|
||||||
|
CRITICAL_SECTION cs;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct dwritefactory *impl_from_IDWriteFactory5(IDWriteFactory5 *iface)
|
static inline struct dwritefactory *impl_from_IDWriteFactory5(IDWriteFactory5 *iface)
|
||||||
|
@ -586,7 +582,10 @@ static void release_dwritefactory(struct dwritefactory *factory)
|
||||||
|
|
||||||
if (factory->localfontfileloader)
|
if (factory->localfontfileloader)
|
||||||
IDWriteLocalFontFileLoader_Release(factory->localfontfileloader);
|
IDWriteLocalFontFileLoader_Release(factory->localfontfileloader);
|
||||||
|
|
||||||
|
EnterCriticalSection(&factory->cs);
|
||||||
release_fontface_cache(&factory->localfontfaces);
|
release_fontface_cache(&factory->localfontfaces);
|
||||||
|
LeaveCriticalSection(&factory->cs);
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY_SAFE(loader, loader2, &factory->collection_loaders, struct collectionloader, entry) {
|
LIST_FOR_EACH_ENTRY_SAFE(loader, loader2, &factory->collection_loaders, struct collectionloader, entry) {
|
||||||
list_remove(&loader->entry);
|
list_remove(&loader->entry);
|
||||||
|
@ -603,6 +602,9 @@ static void release_dwritefactory(struct dwritefactory *factory)
|
||||||
IDWriteFontCollection1_Release(factory->eudc_collection);
|
IDWriteFontCollection1_Release(factory->eudc_collection);
|
||||||
if (factory->fallback)
|
if (factory->fallback)
|
||||||
release_system_fontfallback(factory->fallback);
|
release_system_fontfallback(factory->fallback);
|
||||||
|
|
||||||
|
factory->cs.DebugInfo->Spare[0] = 0;
|
||||||
|
DeleteCriticalSection(&factory->cs);
|
||||||
heap_free(factory);
|
heap_free(factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,8 +820,20 @@ static HRESULT WINAPI dwritefactory_CreateCustomFontFileReference(IDWriteFactory
|
||||||
return create_font_file(loader, reference_key, key_size, font_file);
|
return create_font_file(loader, reference_key, key_size, font_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * const *font_files,
|
void factory_lock(IDWriteFactory5 *iface)
|
||||||
UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face, struct list **cached_list)
|
{
|
||||||
|
struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
|
||||||
|
EnterCriticalSection(&factory->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void factory_unlock(IDWriteFactory5 *iface)
|
||||||
|
{
|
||||||
|
struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
|
||||||
|
LeaveCriticalSection(&factory->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * const *font_files, UINT32 index,
|
||||||
|
DWRITE_FONT_SIMULATIONS simulations, struct list **cached_list, REFIID riid, void **obj)
|
||||||
{
|
{
|
||||||
struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
|
struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
|
||||||
struct fontfacecached *cached;
|
struct fontfacecached *cached;
|
||||||
|
@ -829,7 +843,7 @@ HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * co
|
||||||
const void *key;
|
const void *key;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
*font_face = NULL;
|
*obj = NULL;
|
||||||
*cached_list = NULL;
|
*cached_list = NULL;
|
||||||
|
|
||||||
hr = IDWriteFontFile_GetReferenceKey(*font_files, &key, &key_size);
|
hr = IDWriteFontFile_GetReferenceKey(*font_files, &key, &key_size);
|
||||||
|
@ -854,6 +868,8 @@ HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * co
|
||||||
|
|
||||||
*cached_list = fontfaces;
|
*cached_list = fontfaces;
|
||||||
|
|
||||||
|
EnterCriticalSection(&factory->cs);
|
||||||
|
|
||||||
/* search through cache list */
|
/* search through cache list */
|
||||||
LIST_FOR_EACH_ENTRY(cached, fontfaces, struct fontfacecached, entry) {
|
LIST_FOR_EACH_ENTRY(cached, fontfaces, struct fontfacecached, entry) {
|
||||||
UINT32 cached_key_size, count = 1, cached_face_index;
|
UINT32 cached_key_size, count = 1, cached_face_index;
|
||||||
|
@ -870,25 +886,31 @@ HRESULT factory_get_cached_fontface(IDWriteFactory5 *iface, IDWriteFontFile * co
|
||||||
|
|
||||||
hr = IDWriteFontFace4_GetFiles(cached->fontface, &count, &file);
|
hr = IDWriteFontFace4_GetFiles(cached->fontface, &count, &file);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
break;
|
||||||
|
|
||||||
hr = IDWriteFontFile_GetReferenceKey(file, &cached_key, &cached_key_size);
|
hr = IDWriteFontFile_GetReferenceKey(file, &cached_key, &cached_key_size);
|
||||||
IDWriteFontFile_Release(file);
|
IDWriteFontFile_Release(file);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
break;
|
||||||
|
|
||||||
if (cached_key_size == key_size && !memcmp(cached_key, key, key_size)) {
|
if (cached_key_size == key_size && !memcmp(cached_key, key, key_size)) {
|
||||||
|
if (FAILED(hr = IDWriteFontFace4_QueryInterface(cached->fontface, riid, obj)))
|
||||||
|
WARN("Failed to get %s from fontface, hr %#x.\n", debugstr_guid(riid), hr);
|
||||||
|
|
||||||
TRACE("returning cached fontface %p\n", cached->fontface);
|
TRACE("returning cached fontface %p\n", cached->fontface);
|
||||||
*font_face = (IDWriteFontFace*)cached->fontface;
|
break;
|
||||||
return S_OK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_FALSE;
|
LeaveCriticalSection(&factory->cs);
|
||||||
|
|
||||||
|
return *obj ? S_OK : S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fontfacecached *factory_cache_fontface(struct list *fontfaces, IDWriteFontFace4 *fontface)
|
struct fontfacecached *factory_cache_fontface(IDWriteFactory5 *iface, struct list *fontfaces,
|
||||||
|
IDWriteFontFace4 *fontface)
|
||||||
{
|
{
|
||||||
|
struct dwritefactory *factory = impl_from_IDWriteFactory5(iface);
|
||||||
struct fontfacecached *cached;
|
struct fontfacecached *cached;
|
||||||
|
|
||||||
/* new cache entry */
|
/* new cache entry */
|
||||||
|
@ -897,7 +919,9 @@ struct fontfacecached *factory_cache_fontface(struct list *fontfaces, IDWriteFon
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cached->fontface = fontface;
|
cached->fontface = fontface;
|
||||||
|
EnterCriticalSection(&factory->cs);
|
||||||
list_add_tail(fontfaces, &cached->entry);
|
list_add_tail(fontfaces, &cached->entry);
|
||||||
|
LeaveCriticalSection(&factory->cs);
|
||||||
|
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
@ -948,10 +972,8 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory5 *iface, DWRIT
|
||||||
if (face_type != req_facetype)
|
if (face_type != req_facetype)
|
||||||
return DWRITE_E_FILEFORMAT;
|
return DWRITE_E_FILEFORMAT;
|
||||||
|
|
||||||
hr = factory_get_cached_fontface(iface, font_files, index, simulations, fontface, &fontfaces);
|
hr = factory_get_cached_fontface(iface, font_files, index, simulations, &fontfaces,
|
||||||
if (hr == S_OK)
|
&IID_IDWriteFontFace, (void **)fontface);
|
||||||
IDWriteFontFace_AddRef(*fontface);
|
|
||||||
|
|
||||||
if (hr != S_FALSE)
|
if (hr != S_FALSE)
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
@ -1749,6 +1771,9 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP
|
||||||
list_init(&factory->collection_loaders);
|
list_init(&factory->collection_loaders);
|
||||||
list_init(&factory->file_loaders);
|
list_init(&factory->file_loaders);
|
||||||
list_init(&factory->localfontfaces);
|
list_init(&factory->localfontfaces);
|
||||||
|
|
||||||
|
InitializeCriticalSection(&factory->cs);
|
||||||
|
factory->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": dwritefactory.lock");
|
||||||
}
|
}
|
||||||
|
|
||||||
void factory_detach_fontcollection(IDWriteFactory5 *iface, IDWriteFontCollection1 *collection)
|
void factory_detach_fontcollection(IDWriteFactory5 *iface, IDWriteFontCollection1 *collection)
|
||||||
|
|
Loading…
Reference in New Issue