From 1a8d6f55f245aca47d233607419012f5fcd55b71 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 2 Dec 2021 15:37:18 +0300 Subject: [PATCH] dwrite: Allocate outline buffers on PE side. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- 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;