Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dwrite/dwrite_private.h | 9 +++++++++ dlls/dwrite/font.c | 35 ++++++++++++++++++++++++++++++++-- dlls/dwrite/freetype.c | 37 ++++++++++++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 4 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 7cca4c5c4f9..9735ffd2605 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -241,6 +241,10 @@ extern UINT16 opentype_cmap_get_glyph(const struct dwrite_cmap *cmap, unsigned i extern HRESULT opentype_cmap_get_unicode_ranges(const struct dwrite_cmap *cmap, unsigned int max_count, DWRITE_UNICODE_RANGE *ranges, unsigned int *count) DECLSPEC_HIDDEN;
+struct dwrite_fontface; +typedef void * font_object_handle; +typedef font_object_handle (*p_dwrite_fontface_get_font_object)(struct dwrite_fontface *fontface); + struct dwrite_fontface { IDWriteFontFace5 IDWriteFontFace5_iface; @@ -253,6 +257,9 @@ struct dwrite_fontface
IDWriteFactory7 *factory; struct fontfacecached *cached; + font_object_handle font_object; + void *data_context; + p_dwrite_fontface_get_font_object get_font_object;
USHORT simulations; DWRITE_FONT_FACE_TYPE type; @@ -731,6 +738,8 @@ struct font_callback_funcs
struct font_backend_funcs { + font_object_handle (CDECL *create_font_object)(const void *data_ptr, UINT64 data_size, unsigned int index); + void (CDECL *release_font_object)(font_object_handle object); void (CDECL *notify_release)(void *key); int (CDECL *get_glyph_outline)(void *key, float em_size, unsigned int simulations, UINT16 glyph, struct dwrite_outline *outline); diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index b7071314bb2..85868c6bfd8 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -636,8 +636,6 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface) IDWriteFontFace5_ReleaseFontTable(iface, fontface->kern.context); if (fontface->file) IDWriteFontFile_Release(fontface->file); - if (fontface->stream) - IDWriteFontFileStream_Release(fontface->stream); if (fontface->names) IDWriteLocalizedStrings_Release(fontface->names); if (fontface->family_names) @@ -652,6 +650,12 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface) heap_free(fontface->glyphs[i]);
font_funcs->notify_release(iface); + font_funcs->release_font_object(fontface->font_object); + if (fontface->stream) + { + IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, fontface->data_context); + IDWriteFontFileStream_Release(fontface->stream); + }
dwrite_cmap_release(&fontface->cmap); IDWriteFactory7_Release(fontface->factory); @@ -5013,6 +5017,32 @@ HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_ke return S_OK; }
+static font_object_handle dwrite_fontface_get_font_object(struct dwrite_fontface *fontface) +{ + font_object_handle font_object; + const void *data_ptr; + void *data_context; + UINT64 size; + + if (!fontface->font_object && SUCCEEDED(IDWriteFontFileStream_GetFileSize(fontface->stream, &size))) + { + if (SUCCEEDED(IDWriteFontFileStream_ReadFileFragment(fontface->stream, &data_ptr, 0, size, &data_context))) + { + if (!(font_object = font_funcs->create_font_object(data_ptr, size, fontface->index))) + { + WARN("Backend failed to create font object.\n"); + IDWriteFontFileStream_ReleaseFileFragment(fontface->stream, data_context); + return NULL; + } + + if (InterlockedCompareExchangePointer((void **)&fontface->font_object, font_object, NULL)) + font_funcs->release_font_object(font_object); + } + } + + return fontface->font_object; +} + HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_list, IDWriteFontFace5 **ret) { struct file_stream_desc stream_desc; @@ -5102,6 +5132,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li release_font_data(font_data);
fontface->cached = factory_cache_fontface(fontface->factory, cached_list, &fontface->IDWriteFontFace5_iface); + fontface->get_font_object = dwrite_fontface_get_font_object;
*ret = &fontface->IDWriteFontFace5_iface;
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c index 1ece99e08c9..5c32ec725f6 100644 --- a/dlls/dwrite/freetype.c +++ b/dlls/dwrite/freetype.c @@ -69,6 +69,7 @@ typedef struct static const struct font_callback_funcs *callback_funcs;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL +MAKE_FUNCPTR(FT_Done_Face); MAKE_FUNCPTR(FT_Done_FreeType); MAKE_FUNCPTR(FT_Done_Glyph); MAKE_FUNCPTR(FT_Get_First_Char); @@ -143,12 +144,14 @@ static BOOL init_freetype(void) FT_Version_t FT_Version;
ft_handle = dlopen(SONAME_LIBFREETYPE, RTLD_NOW); - if (!ft_handle) { + if (!ft_handle) + { WINE_MESSAGE("Wine cannot find the FreeType font library.\n"); - return FALSE; + return FALSE; }
#define LOAD_FUNCPTR(f) if((p##f = dlsym(ft_handle, #f)) == NULL){WARN("Can't find symbol %s\n", #f); goto sym_not_found;} + LOAD_FUNCPTR(FT_Done_Face) LOAD_FUNCPTR(FT_Done_FreeType) LOAD_FUNCPTR(FT_Done_Glyph) LOAD_FUNCPTR(FT_Get_First_Char) @@ -211,6 +214,23 @@ sym_not_found: return FALSE; }
+static font_object_handle CDECL freetype_create_font_object(const void *data_ptr, UINT64 data_size, unsigned int index) +{ + FT_Face face = NULL; + FT_Error fterror; + + fterror = pFT_New_Memory_Face(library, data_ptr, data_size, index, &face); + if (fterror != FT_Err_Ok) + WARN("Failed to create a face object, error %d.\n", fterror); + + return face; +} + +static void CDECL freetype_release_font_object(font_object_handle object) +{ + pFT_Done_Face(object); +} + static void CDECL freetype_notify_release(void *key) { RtlEnterCriticalSection(&freetype_cs); @@ -777,6 +797,8 @@ static INT32 CDECL freetype_get_glyph_advance(void *key, float emSize, UINT16 in
const static struct font_backend_funcs freetype_funcs = { + freetype_create_font_object, + freetype_release_font_object, freetype_notify_release, freetype_get_glyph_outline, freetype_get_glyph_count, @@ -803,6 +825,15 @@ static NTSTATUS release_freetype_lib(void)
#else /* HAVE_FREETYPE */
+static font_object_handle CDECL null_create_font_object(const void *data_ptr, UINT64 data_size, unsigned int index) +{ + return NULL; +} + +static void CDECL null_release_font_object(font_object_handle object) +{ +} + static void CDECL null_notify_release(void *key) { } @@ -842,6 +873,8 @@ static void CDECL null_get_design_glyph_metrics(void *key, UINT16 upem, UINT16 a
const static struct font_backend_funcs null_funcs = { + null_create_font_object, + null_release_font_object, null_notify_release, null_get_glyph_outline, null_get_glyph_count,