Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57076
I don't know if this is how native does it, but it makes intuitive sense to me that if we have a glyph in the requested font, we should use it, and this fixes the bug in question. This should avoid the possibility of regression in cases where font linking isn't needed. There is a possibility of regression in corner cases handled better by the earlier version of font linking.
-- v3: gdiplus: Use font linking only for missing glyphs.
From: Esme Povirk esme@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57076 --- dlls/gdiplus/graphics.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 4699f8c21d3..28f11d75091 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -5359,29 +5359,42 @@ static void generate_font_link_info(struct gdip_format_string_info *info, DWORD HFONT map_hfont, hfont, old_font; LONG processed, progress = 0; struct gdip_font_link_section *section; - DWORD font_codepages, string_codepages; + DWORD string_codepages; + WORD *glyph_indices;
list_init(&info->font_link_info.sections); info->font_link_info.base_font = base_font;
+ glyph_indices = calloc(length, sizeof(*glyph_indices)); + GetGlyphIndicesW(info->hdc, info->string, length, glyph_indices, GGI_MARK_NONEXISTING_GLYPHS); + + /* Newlines won't have a glyph but don't need a fallback */ + for (progress = 0; progress < length; progress++) + if (info->string[progress] == '\r' || info->string[progress] == '\n') + glyph_indices[progress] = 0; + GetGlobalFontLinkObject(&iMLFL);
get_font_hfont(info->graphics, base_font, NULL, &hfont, NULL, NULL); - IMLangFontLink_GetFontCodePages(iMLFL, info->hdc, hfont, &font_codepages);
+ progress = 0; while (progress < length) { section = calloc(1, sizeof(*section)); section->start = progress; - IMLangFontLink_GetStrCodePages(iMLFL, &info->string[progress], length - progress, - font_codepages, &string_codepages, &processed);
- if (font_codepages & string_codepages) + if (glyph_indices[progress] != 0xffff) { section->font = (GpFont *)base_font; + + processed = 0; + while (progress + processed < length && glyph_indices[progress + processed] != 0xffff) + processed++; } else { + IMLangFontLink_GetStrCodePages(iMLFL, &info->string[progress], length - progress, + 0, &string_codepages, &processed); IMLangFontLink_MapFont(iMLFL, info->hdc, string_codepages, hfont, &map_hfont); old_font = SelectObject(info->hdc, map_hfont); GdipCreateFontFromDC(info->hdc, &gpfont); @@ -5397,6 +5410,7 @@ static void generate_font_link_info(struct gdip_format_string_info *info, DWORD
DeleteObject(hfont); IMLangFontLink_Release(iMLFL); + free(glyph_indices); }
static void font_link_get_text_extent_point(struct gdip_format_string_info *info,
Updated to make the logic closer to the original font linking object, while fixing the regression (which should make this less likely to introduce another regression, whether the logic is correct or not). Tested both Harmony Assistant and the gdiplus tests (including the interactive test case for font linking).
Running the gdiplus tests required Remi's patch from !7107, so the pipeline will most likely fail until that's merged.
I'm reading https://gitlab.winehq.org/wine/wine/-/merge_requests/7054#note_91586 as "I don't know enough to approve this change but I'm not opposed", and as such removing Nikolay as reviewer.