Nikolay Sivov : dwrite: Do not use freetype cache for design glyph metrics.

Alexandre Julliard julliard at winehq.org
Thu Dec 2 15:30:17 CST 2021


Module: wine
Branch: master
Commit: 6356717c47ee7c1aa5bc385fc91fd8e21cb7b040
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=6356717c47ee7c1aa5bc385fc91fd8e21cb7b040

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Thu Dec  2 15:37:17 2021 +0300

dwrite: Do not use freetype cache for design glyph metrics.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/dwrite_private.h |  3 +-
 dlls/dwrite/font.c           | 23 +++++++-----
 dlls/dwrite/freetype.c       | 89 ++++++++++++++++++++++++++++----------------
 3 files changed, 72 insertions(+), 43 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 75bc1be902a..3d445cddae2 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -260,6 +260,7 @@ struct dwrite_fontface
     font_object_handle font_object;
     void *data_context;
     p_dwrite_fontface_get_font_object get_font_object;
+    CRITICAL_SECTION cs;
 
     USHORT simulations;
     DWRITE_FONT_FACE_TYPE type;
@@ -748,7 +749,7 @@ struct font_backend_funcs
             BOOL *has_contours);
     void (CDECL *get_glyph_bbox)(struct dwrite_glyphbitmap *bitmap_desc);
     BOOL (CDECL *get_glyph_bitmap)(struct dwrite_glyphbitmap *bitmap_desc);
-    void (CDECL *get_design_glyph_metrics)(void *key, UINT16 upem, UINT16 ascent, unsigned int simulations,
+    void (CDECL *get_design_glyph_metrics)(font_object_handle object, UINT16 upem, UINT16 ascent, unsigned int simulations,
             UINT16 glyph, DWRITE_GLYPH_METRICS *metrics);
 };
 
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 5f4f5587a62..4b135b83d68 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -659,6 +659,7 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace5 *iface)
 
         dwrite_cmap_release(&fontface->cmap);
         IDWriteFactory7_Release(fontface->factory);
+        DeleteCriticalSection(&fontface->cs);
         heap_free(fontface);
     }
 
@@ -745,8 +746,8 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa
     UINT16 const *glyphs, UINT32 glyph_count, DWRITE_GLYPH_METRICS *ret, BOOL is_sideways)
 {
     struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
+    HRESULT hr = S_OK;
     unsigned int i;
-    HRESULT hr;
 
     TRACE("%p, %p, %u, %p, %d.\n", iface, glyphs, glyph_count, ret, is_sideways);
 
@@ -756,22 +757,23 @@ static HRESULT WINAPI dwritefontface_GetDesignGlyphMetrics(IDWriteFontFace5 *ifa
     if (is_sideways)
         FIXME("sideways metrics are not supported.\n");
 
-    for (i = 0; i < glyph_count; i++) {
+    EnterCriticalSection(&fontface->cs);
+    for (i = 0; i < glyph_count; ++i)
+    {
         DWRITE_GLYPH_METRICS metrics;
 
-        hr = get_cached_glyph_metrics(fontface, glyphs[i], &metrics);
-        if (hr != S_OK)
+        if (get_cached_glyph_metrics(fontface, glyphs[i], &metrics) != S_OK)
         {
-            font_funcs->get_design_glyph_metrics(iface, fontface->metrics.designUnitsPerEm,
-                    fontface->typo_metrics.ascent, fontface->simulations, glyphs[i], &metrics);
-            hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics);
-            if (FAILED(hr))
-                return hr;
+            font_funcs->get_design_glyph_metrics(fontface->get_font_object(fontface),
+                    fontface->metrics.designUnitsPerEm, fontface->typo_metrics.ascent,
+                    fontface->simulations, glyphs[i], &metrics);
+            if (FAILED(hr = set_cached_glyph_metrics(fontface, glyphs[i], &metrics))) break;
         }
         ret[i] = metrics;
     }
+    LeaveCriticalSection(&fontface->cs);
 
-    return S_OK;
+    return hr;
 }
 
 static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace5 *iface, UINT32 const *codepoints,
@@ -5076,6 +5078,7 @@ HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_li
     IDWriteFontFile_AddRef(fontface->file);
     fontface->stream = desc->stream;
     IDWriteFontFileStream_AddRef(fontface->stream);
+    InitializeCriticalSection(&fontface->cs);
 
     stream_desc.stream = fontface->stream;
     stream_desc.face_type = desc->face_type;
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index 6b566649edc..b19ae3616bc 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -33,6 +33,7 @@
 #include FT_FREETYPE_H
 #include FT_OUTLINE_H
 #include FT_TRUETYPE_TABLES_H
+#include FT_SIZES_H
 #endif /* HAVE_FT2BUILD_H */
 
 #include "ntstatus.h"
@@ -69,9 +70,11 @@ typedef struct
 static const struct font_callback_funcs *callback_funcs;
 
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f = NULL
+MAKE_FUNCPTR(FT_Activate_Size);
 MAKE_FUNCPTR(FT_Done_Face);
 MAKE_FUNCPTR(FT_Done_FreeType);
 MAKE_FUNCPTR(FT_Done_Glyph);
+MAKE_FUNCPTR(FT_Done_Size);
 MAKE_FUNCPTR(FT_Get_First_Char);
 MAKE_FUNCPTR(FT_Get_Kerning);
 MAKE_FUNCPTR(FT_Get_Sfnt_Table);
@@ -84,6 +87,7 @@ MAKE_FUNCPTR(FT_Load_Glyph);
 MAKE_FUNCPTR(FT_Matrix_Multiply);
 MAKE_FUNCPTR(FT_MulDiv);
 MAKE_FUNCPTR(FT_New_Memory_Face);
+MAKE_FUNCPTR(FT_New_Size);
 MAKE_FUNCPTR(FT_Outline_Copy);
 MAKE_FUNCPTR(FT_Outline_Decompose);
 MAKE_FUNCPTR(FT_Outline_Done);
@@ -92,6 +96,7 @@ MAKE_FUNCPTR(FT_Outline_Get_Bitmap);
 MAKE_FUNCPTR(FT_Outline_New);
 MAKE_FUNCPTR(FT_Outline_Transform);
 MAKE_FUNCPTR(FT_Outline_Translate);
+MAKE_FUNCPTR(FT_Set_Pixel_Sizes);
 MAKE_FUNCPTR(FTC_ImageCache_Lookup);
 MAKE_FUNCPTR(FTC_ImageCache_New);
 MAKE_FUNCPTR(FTC_Manager_New);
@@ -139,6 +144,28 @@ static FT_Error face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointe
     return fterror;
 }
 
+static FT_Size freetype_set_face_size(FT_Face face, FT_UInt emsize)
+{
+    FT_Size size;
+
+    if (pFT_New_Size(face, &size)) return NULL;
+
+    pFT_Activate_Size(size);
+
+    if (pFT_Set_Pixel_Sizes(face, emsize, emsize))
+    {
+        pFT_Done_Size(size);
+        return NULL;
+    }
+
+    return size;
+}
+
+static BOOL freetype_glyph_has_contours(FT_Face face)
+{
+    return face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && face->glyph->outline.n_contours;
+}
+
 static BOOL init_freetype(void)
 {
     FT_Version_t FT_Version;
@@ -151,9 +178,11 @@ static BOOL init_freetype(void)
     }
 
 #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_Activate_Size)
     LOAD_FUNCPTR(FT_Done_Face)
     LOAD_FUNCPTR(FT_Done_FreeType)
     LOAD_FUNCPTR(FT_Done_Glyph)
+    LOAD_FUNCPTR(FT_Done_Size)
     LOAD_FUNCPTR(FT_Get_First_Char)
     LOAD_FUNCPTR(FT_Get_Kerning)
     LOAD_FUNCPTR(FT_Get_Sfnt_Table)
@@ -166,6 +195,7 @@ static BOOL init_freetype(void)
     LOAD_FUNCPTR(FT_Matrix_Multiply)
     LOAD_FUNCPTR(FT_MulDiv)
     LOAD_FUNCPTR(FT_New_Memory_Face)
+    LOAD_FUNCPTR(FT_New_Size)
     LOAD_FUNCPTR(FT_Outline_Copy)
     LOAD_FUNCPTR(FT_Outline_Decompose)
     LOAD_FUNCPTR(FT_Outline_Done)
@@ -174,6 +204,7 @@ static BOOL init_freetype(void)
     LOAD_FUNCPTR(FT_Outline_New)
     LOAD_FUNCPTR(FT_Outline_Transform)
     LOAD_FUNCPTR(FT_Outline_Translate)
+    LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
     LOAD_FUNCPTR(FTC_ImageCache_Lookup)
     LOAD_FUNCPTR(FTC_ImageCache_New)
     LOAD_FUNCPTR(FTC_Manager_New)
@@ -238,43 +269,37 @@ static void CDECL freetype_notify_release(void *key)
     RtlLeaveCriticalSection(&freetype_cs);
 }
 
-static void CDECL freetype_get_design_glyph_metrics(void *key, UINT16 upem, UINT16 ascent,
+static void CDECL freetype_get_design_glyph_metrics(font_object_handle object, UINT16 upem, UINT16 ascent,
         unsigned int simulations, UINT16 glyph, DWRITE_GLYPH_METRICS *ret)
 {
-    FTC_ScalerRec scaler;
+    FT_Face face = object;
     FT_Size size;
 
-    scaler.face_id = key;
-    scaler.width = upem;
-    scaler.height = upem;
-    scaler.pixel = 1;
-    scaler.x_res = 0;
-    scaler.y_res = 0;
+    if (!(size = freetype_set_face_size(face, upem)))
+        return;
 
-    RtlEnterCriticalSection(&freetype_cs);
-    if (pFTC_Manager_LookupSize(cache_manager, &scaler, &size) == 0) {
-         if (pFT_Load_Glyph(size->face, glyph, FT_LOAD_NO_SCALE) == 0) {
-             FT_Glyph_Metrics *metrics = &size->face->glyph->metrics;
-
-             ret->leftSideBearing = metrics->horiBearingX;
-             ret->advanceWidth = metrics->horiAdvance;
-             ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width;
-
-             ret->advanceHeight = metrics->vertAdvance;
-             ret->verticalOriginY = ascent;
-             ret->topSideBearing = ascent - metrics->horiBearingY;
-             ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing;
-
-             /* Adjust in case of bold simulation, glyphs without contours are ignored. */
-             if (simulations & DWRITE_FONT_SIMULATIONS_BOLD &&
-                     size->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE && size->face->glyph->outline.n_contours)
-             {
-                 if (ret->advanceWidth)
-                     ret->advanceWidth += (upem + 49) / 50;
-             }
-         }
+    if (!pFT_Load_Glyph(face, glyph, FT_LOAD_NO_SCALE))
+    {
+        FT_Glyph_Metrics *metrics = &face->glyph->metrics;
+
+        ret->leftSideBearing = metrics->horiBearingX;
+        ret->advanceWidth = metrics->horiAdvance;
+        ret->rightSideBearing = metrics->horiAdvance - metrics->horiBearingX - metrics->width;
+
+        ret->advanceHeight = metrics->vertAdvance;
+        ret->verticalOriginY = ascent;
+        ret->topSideBearing = ascent - metrics->horiBearingY;
+        ret->bottomSideBearing = metrics->vertAdvance - metrics->height - ret->topSideBearing;
+
+        /* Adjust in case of bold simulation, glyphs without contours are ignored. */
+        if (simulations & DWRITE_FONT_SIMULATIONS_BOLD && freetype_glyph_has_contours(face))
+        {
+            if (ret->advanceWidth)
+                ret->advanceWidth += (upem + 49) / 50;
+        }
     }
-    RtlLeaveCriticalSection(&freetype_cs);
+
+    pFT_Done_Size(size);
 }
 
 struct decompose_context
@@ -859,7 +884,7 @@ static BOOL CDECL null_get_glyph_bitmap(struct dwrite_glyphbitmap *bitmap)
     return FALSE;
 }
 
-static void CDECL null_get_design_glyph_metrics(void *key, UINT16 upem, UINT16 ascent, unsigned int simulations,
+static void CDECL null_get_design_glyph_metrics(font_object_handle object, UINT16 upem, UINT16 ascent, unsigned int simulations,
         UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
 {
 }




More information about the wine-cvs mailing list