From 6356717c47ee7c1aa5bc385fc91fd8e21cb7b040 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 2 Dec 2021 15:37:17 +0300 Subject: [PATCH] dwrite: Do not use freetype cache for design glyph metrics. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 3 +- dlls/dwrite/font.c | 23 +++++----- dlls/dwrite/freetype.c | 83 +++++++++++++++++++++++------------- 3 files changed, 69 insertions(+), 40 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; + 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->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; + 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; - } - } + /* 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) { }