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.
-- v2: 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 +++++++++++++++++++----- dlls/gdiplus/tests/graphics.c | 4 ++-- 2 files changed, 21 insertions(+), 7 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, diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c index dd25dd54fb2..1293e05f810 100644 --- a/dlls/gdiplus/tests/graphics.c +++ b/dlls/gdiplus/tests/graphics.c @@ -2360,7 +2360,7 @@ static void test_GdipDrawString(void) status = GdipCreateStringFormat(0,0,&format); expect(Ok, status);
- if (winetest_interactive) + if (1) { status = GdipCreateSolidFill(0xFF000000, (GpSolidFill**)&brush); expect(Ok, status); @@ -2374,7 +2374,7 @@ static void test_GdipDrawString(void) status = GdipDrawString(graphics, L"\u8336Hola\u8336", 6, fnt, &rect, format, brush); expect(Ok, status); RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); /* FIXME: In Windows this test works without this line. */ - Sleep(4000); + Sleep(40000); GdipDeleteBrush(brush); GdipResetWorldTransform(graphics); }