dwrite: Create backend font objects for faces.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-12-02 15:37:15 +03:00 committed by Alexandre Julliard
parent 78fbea1672
commit 7639820cfb
3 changed files with 77 additions and 4 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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,