[PATCH 1/5] dwrite: Create backend font objects for faces.

Nikolay Sivov nsivov at codeweavers.com
Thu Dec 2 06:37:15 CST 2021


Signed-off-by: Nikolay Sivov <nsivov at 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,
-- 
2.33.0




More information about the wine-devel mailing list