[PATCH 4/5] dwrite: Allocate outline buffers on PE side..

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


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |  2 +-
 dlls/dwrite/font.c           | 27 +++++++++++++++++---
 dlls/dwrite/freetype.c       | 48 +++++++++++++++++-------------------
 3 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 3d445cddae2..2b9651a906c 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -742,7 +742,7 @@ 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,
+    int (CDECL *get_glyph_outline)(font_object_handle object, float emsize, unsigned int simulations, UINT16 glyph,
             struct dwrite_outline *outline);
     UINT16 (CDECL *get_glyph_count)(font_object_handle object);
     INT32 (CDECL *get_glyph_advance)(void *key, float em_size, UINT16 index, DWRITE_MEASURING_MODE measuring_mode,
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 4b135b83d68..20bb6b3159f 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -835,12 +835,13 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface,
 {
     struct dwrite_fontface *fontface = impl_from_IDWriteFontFace5(iface);
     D2D1_POINT_2F *origins, baseline_origin = { 0 };
-    struct dwrite_outline outline = {{ 0 }};
+    struct dwrite_outline outline, outline_size;
     D2D1_BEZIER_SEGMENT segment;
     D2D1_POINT_2F point;
     DWRITE_GLYPH_RUN run;
     unsigned int i, j, p;
     HRESULT hr;
+    int ret;
 
     TRACE("%p, %.8e, %p, %p, %p, %u, %d, %d, %p.\n", iface, emSize, glyphs, advances, offsets,
         count, is_sideways, is_rtl, sink);
@@ -871,14 +872,32 @@ static HRESULT WINAPI dwritefontface_GetGlyphRunOutline(IDWriteFontFace5 *iface,
 
     ID2D1SimplifiedGeometrySink_SetFillMode(sink, D2D1_FILL_MODE_WINDING);
 
+    memset(&outline_size, 0, sizeof(outline_size));
+    memset(&outline, 0, sizeof(outline));
+
     for (i = 0; i < count; ++i)
     {
         outline.tags.count = outline.points.count = 0;
-        if (font_funcs->get_glyph_outline(iface, emSize, fontface->simulations, glyphs[i], &outline))
+
+        EnterCriticalSection(&fontface->cs);
+        if (!(ret = font_funcs->get_glyph_outline(fontface->get_font_object(fontface), emSize, fontface->simulations,
+                glyphs[i], &outline_size)))
         {
-            WARN("Failed to get glyph outline for glyph %u.\n", glyphs[i]);
-            continue;
+            dwrite_array_reserve((void **)&outline.tags.values, &outline.tags.size, outline_size.tags.count,
+                    sizeof(*outline.tags.values));
+            dwrite_array_reserve((void **)&outline.points.values, &outline.points.size, outline_size.points.count,
+                    sizeof(*outline.points.values));
+
+            if ((ret = font_funcs->get_glyph_outline(fontface->get_font_object(fontface), emSize, fontface->simulations,
+                    glyphs[i], &outline)))
+            {
+                WARN("Failed to get glyph outline for glyph %u.\n", glyphs[i]);
+            }
         }
+        LeaveCriticalSection(&fontface->cs);
+
+        if (ret)
+            continue;
 
         for (j = 0, p = 0; j < outline.tags.count; ++j)
         {
diff --git a/dlls/dwrite/freetype.c b/dlls/dwrite/freetype.c
index b19ae3616bc..503f8b04496 100644
--- a/dlls/dwrite/freetype.c
+++ b/dlls/dwrite/freetype.c
@@ -318,11 +318,8 @@ static inline void ft_vector_to_d2d_point(const FT_Vector *v, D2D1_POINT_2F *p)
 
 static int dwrite_outline_push_tag(struct dwrite_outline *outline, unsigned char tag)
 {
-    if (!dwrite_array_reserve((void **)&outline->tags.values, &outline->tags.size, outline->tags.count + 1,
-            sizeof(*outline->tags.values)))
-    {
+    if (outline->tags.size < outline->tags.count + 1)
         return 1;
-    }
 
     outline->tags.values[outline->tags.count++] = tag;
 
@@ -331,11 +328,8 @@ static int dwrite_outline_push_tag(struct dwrite_outline *outline, unsigned char
 
 static int dwrite_outline_push_points(struct dwrite_outline *outline, const D2D1_POINT_2F *points, unsigned int count)
 {
-    if (!dwrite_array_reserve((void **)&outline->points.values, &outline->points.size, outline->points.count + count,
-            sizeof(*outline->points.values)))
-    {
+    if (outline->points.size < outline->points.count + count)
         return 1;
-    }
 
     memcpy(&outline->points.values[outline->points.count], points, sizeof(*points) * count);
     outline->points.count += count;
@@ -512,30 +506,25 @@ static void embolden_glyph(FT_Glyph glyph, FLOAT emsize)
     embolden_glyph_outline(&outline_glyph->outline, emsize);
 }
 
-static int CDECL freetype_get_glyph_outline(void *key, float emSize, unsigned int simulations,
+static int CDECL freetype_get_glyph_outline(font_object_handle object, float emsize, unsigned int simulations,
         UINT16 glyph, struct dwrite_outline *outline)
 {
-    FTC_ScalerRec scaler;
+    FT_Face face = object;
     FT_Size size;
-    int ret;
+    int ret = 0;
 
-    scaler.face_id = key;
-    scaler.width  = emSize;
-    scaler.height = emSize;
-    scaler.pixel = 1;
-    scaler.x_res = 0;
-    scaler.y_res = 0;
+    if (!(size = freetype_set_face_size(face, emsize)))
+        return 0;
 
-    RtlEnterCriticalSection(&freetype_cs);
-    if (!(ret = pFTC_Manager_LookupSize(cache_manager, &scaler, &size)))
+    if (!pFT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP))
     {
-        if (pFT_Load_Glyph(size->face, glyph, FT_LOAD_NO_BITMAP) == 0)
-        {
-            FT_Outline *ft_outline = &size->face->glyph->outline;
-            FT_Matrix m;
+        FT_Outline *ft_outline = &face->glyph->outline;
+        FT_Matrix m;
 
+        if (outline->points.values)
+        {
             if (simulations & DWRITE_FONT_SIMULATIONS_BOLD)
-                embolden_glyph_outline(ft_outline, emSize);
+                embolden_glyph_outline(ft_outline, emsize);
 
             m.xx = 1 << 16;
             m.xy = simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE ? (1 << 16) / 3 : 0;
@@ -546,8 +535,15 @@ static int CDECL freetype_get_glyph_outline(void *key, float emSize, unsigned in
 
             ret = decompose_outline(ft_outline, outline);
         }
+        else
+        {
+            /* Intentionally overestimate numbers to keep it simple. */
+            outline->points.count = ft_outline->n_points * 3;
+            outline->tags.count = ft_outline->n_points + ft_outline->n_contours * 2;
+        }
     }
-    RtlLeaveCriticalSection(&freetype_cs);
+
+    pFT_Done_Size(size);
 
     return ret;
 }
@@ -856,7 +852,7 @@ static void CDECL null_notify_release(void *key)
 {
 }
 
-static int CDECL null_get_glyph_outline(void *key, float emSize, unsigned int simulations,
+static int CDECL null_get_glyph_outline(font_object_handle object, float emSize, unsigned int simulations,
         UINT16 glyph, struct dwrite_outline *outline)
 {
     return 1;
-- 
2.33.0




More information about the wine-devel mailing list