dwrite: Introduce callback interface to initialize freetype face objects.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-03-29 10:48:51 +03:00 committed by Alexandre Julliard
parent ff983fe75f
commit f3d777ba7d
4 changed files with 145 additions and 73 deletions

View file

@ -486,9 +486,6 @@ extern int dwrite_outline_push_tag(struct dwrite_outline *outline, unsigned char
extern int dwrite_outline_push_points(struct dwrite_outline *outline, const D2D1_POINT_2F *points,
unsigned int count) DECLSPEC_HIDDEN;
extern BOOL init_freetype(void) DECLSPEC_HIDDEN;
extern void release_freetype(void) DECLSPEC_HIDDEN;
extern HRESULT freetype_get_design_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph,
DWRITE_GLYPH_METRICS *metrics) DECLSPEC_HIDDEN;
extern void freetype_notify_cacheremove(IDWriteFontFace5 *fontface) DECLSPEC_HIDDEN;
@ -734,3 +731,17 @@ extern HRESULT shape_get_typographic_features(struct scriptshaping_context *cont
unsigned int max_tagcount, unsigned int *actual_tagcount, unsigned int *tags) DECLSPEC_HIDDEN;
extern HRESULT shape_check_typographic_feature(struct scriptshaping_context *context, const unsigned int *scripts,
unsigned int tag, unsigned int glyph_count, const UINT16 *glyphs, UINT8 *feature_applies) DECLSPEC_HIDDEN;
struct font_data_context;
extern HMODULE dwrite_module DECLSPEC_HIDDEN;
struct font_callback_funcs
{
int (CDECL *get_font_data)(void *key, const void **data_ptr, UINT64 *data_size, unsigned int *index,
struct font_data_context **context);
void (CDECL *release_font_data)(struct font_data_context *context);
};
extern NTSTATUS CDECL init_font_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out) DECLSPEC_HIDDEN;
extern void init_font_backend(void) DECLSPEC_HIDDEN;
extern void release_font_backend(void) DECLSPEC_HIDDEN;

View file

@ -7958,3 +7958,82 @@ HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2
return S_OK;
}
struct font_data_context
{
IDWriteFontFileStream *stream;
void *context;
};
static int CDECL get_font_data_cb(void *key, const void **data_ptr, UINT64 *data_size,
unsigned int *index, struct font_data_context **ret_context)
{
IDWriteFontFace *fontface = key;
struct font_data_context *context;
IDWriteFontFileStream *stream;
IDWriteFontFile *file;
unsigned int count;
void *data_context;
HRESULT hr;
*ret_context = NULL;
count = 1;
if (FAILED(IDWriteFontFace_GetFiles(fontface, &count, &file))) return 1;
hr = get_filestream_from_file(file, &stream);
IDWriteFontFile_Release(file);
if (FAILED(hr)) return 1;
hr = IDWriteFontFileStream_GetFileSize(stream, data_size);
if (FAILED(hr))
{
IDWriteFontFileStream_Release(stream);
return 1;
}
hr = IDWriteFontFileStream_ReadFileFragment(stream, data_ptr, 0, *data_size, &data_context);
if (FAILED(hr))
{
IDWriteFontFileStream_Release(stream);
return 1;
}
if (!(context = heap_alloc(sizeof(*context))))
{
IDWriteFontFileStream_Release(stream);
return 1;
}
context->stream = stream;
context->context = data_context;
*ret_context = context;
*index = IDWriteFontFace_GetIndex(fontface);
return 0;
}
static void CDECL release_font_data_cb(struct font_data_context *context)
{
if (!context) return;
IDWriteFontFileStream_ReleaseFileFragment(context->stream, context->context);
IDWriteFontFileStream_Release(context->stream);
heap_free(context);
}
struct font_callback_funcs callback_funcs =
{
get_font_data_cb,
release_font_data_cb,
};
void init_font_backend(void)
{
init_font_lib(dwrite_module, DLL_PROCESS_ATTACH, &callback_funcs, NULL);
}
void release_font_backend(void)
{
init_font_lib(dwrite_module, DLL_PROCESS_DETACH, &callback_funcs, NULL);
}

View file

@ -31,6 +31,8 @@
#include FT_TRUETYPE_TABLES_H
#endif /* HAVE_FT2BUILD_H */
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "wine/debug.h"
@ -60,6 +62,8 @@ typedef struct
FT_Int patch;
} FT_Version_t;
static const struct font_callback_funcs *callback_funcs;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
MAKE_FUNCPTR(FT_Done_FreeType);
MAKE_FUNCPTR(FT_Done_Glyph);
@ -92,86 +96,44 @@ MAKE_FUNCPTR(FTC_Manager_RemoveFaceID);
#undef MAKE_FUNCPTR
static FT_Error (*pFT_Outline_EmboldenXY)(FT_Outline *, FT_Pos, FT_Pos);
struct face_finalizer_data
{
IDWriteFontFileStream *stream;
void *context;
};
static void face_finalizer(void *object)
{
FT_Face face = object;
struct face_finalizer_data *data = (struct face_finalizer_data *)face->generic.data;
IDWriteFontFileStream_ReleaseFileFragment(data->stream, data->context);
IDWriteFontFileStream_Release(data->stream);
heap_free(data);
callback_funcs->release_font_data((struct font_data_context *)face->generic.data);
}
static FT_Error face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face)
{
IDWriteFontFace *fontface = (IDWriteFontFace*)face_id;
IDWriteFontFileStream *stream;
IDWriteFontFile *file;
struct font_data_context *context;
const void *data_ptr;
UINT32 index, count;
FT_Error fterror;
UINT64 data_size;
void *context;
HRESULT hr;
UINT32 index;
*face = NULL;
if (!fontface) {
if (!face_id)
{
WARN("NULL fontface requested.\n");
return FT_Err_Ok;
}
count = 1;
hr = IDWriteFontFace_GetFiles(fontface, &count, &file);
if (FAILED(hr))
if (callback_funcs->get_font_data(face_id, &data_ptr, &data_size, &index, &context))
return FT_Err_Ok;
hr = get_filestream_from_file(file, &stream);
IDWriteFontFile_Release(file);
if (FAILED(hr))
return FT_Err_Ok;
hr = IDWriteFontFileStream_GetFileSize(stream, &data_size);
if (FAILED(hr)) {
fterror = FT_Err_Invalid_Stream_Read;
goto fail;
}
hr = IDWriteFontFileStream_ReadFileFragment(stream, &data_ptr, 0, data_size, &context);
if (FAILED(hr)) {
fterror = FT_Err_Invalid_Stream_Read;
goto fail;
}
index = IDWriteFontFace_GetIndex(fontface);
fterror = pFT_New_Memory_Face(library, data_ptr, data_size, index, face);
if (fterror == FT_Err_Ok) {
struct face_finalizer_data *data;
data = heap_alloc(sizeof(*data));
data->stream = stream;
data->context = context;
(*face)->generic.data = data;
if (fterror == FT_Err_Ok)
{
(*face)->generic.data = context;
(*face)->generic.finalizer = face_finalizer;
return fterror;
}
else
IDWriteFontFileStream_ReleaseFileFragment(stream, context);
fail:
IDWriteFontFileStream_Release(stream);
callback_funcs->release_font_data(context);
return fterror;
}
BOOL init_freetype(void)
static BOOL init_freetype(void)
{
FT_Version_t FT_Version;
@ -243,12 +205,6 @@ sym_not_found:
return FALSE;
}
void release_freetype(void)
{
pFTC_Manager_Done(cache_manager);
pFT_Done_FreeType(library);
}
void freetype_notify_cacheremove(IDWriteFontFace5 *fontface)
{
EnterCriticalSection(&freetype_cs);
@ -790,17 +746,22 @@ INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emSize, UINT1
return advance;
}
static NTSTATUS init_freetype_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
{
callback_funcs = ptr_in;
if (!init_freetype()) return STATUS_DLL_NOT_FOUND;
return STATUS_SUCCESS;
}
static NTSTATUS release_freetype_lib(void)
{
pFTC_Manager_Done(cache_manager);
pFT_Done_FreeType(library);
return STATUS_SUCCESS;
}
#else /* HAVE_FREETYPE */
BOOL init_freetype(void)
{
return FALSE;
}
void release_freetype(void)
{
}
void freetype_notify_cacheremove(IDWriteFontFace5 *fontface)
{
}
@ -838,4 +799,23 @@ INT32 freetype_get_glyph_advance(IDWriteFontFace5 *fontface, FLOAT emSize, UINT1
return 0;
}
static NTSTATUS init_freetype_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
{
return STATUS_DLL_NOT_FOUND;
}
static NTSTATUS release_freetype_lib(void)
{
return STATUS_DLL_NOT_FOUND;
}
#endif /* HAVE_FREETYPE */
NTSTATUS CDECL init_font_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
{
if (reason == DLL_PROCESS_ATTACH)
return init_freetype_lib(module, reason, ptr_in, ptr_out);
else if (reason == DLL_PROCESS_DETACH)
return release_freetype_lib();
return STATUS_SUCCESS;
}

View file

@ -34,6 +34,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
HMODULE dwrite_module = 0;
static IDWriteFactory7 *shared_factory;
static void release_shared_factory(IDWriteFactory7 *factory);
@ -42,14 +43,15 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
switch (reason)
{
case DLL_PROCESS_ATTACH:
dwrite_module = hinstDLL;
DisableThreadLibraryCalls( hinstDLL );
init_freetype();
init_font_backend();
init_local_fontfile_loader();
break;
case DLL_PROCESS_DETACH:
if (reserved) break;
release_shared_factory(shared_factory);
release_freetype();
release_font_backend();
}
return TRUE;
}