[PATCH v6 0/1] MR2850: gdiplus: Fix GdipGetGenericFontFamily functions according to native gdiplus.dll
I have investigated `GdipGetGenericFontFamily*` functions from native gdiplus.dll. The result of investigation * GdipGetGenericFontFamilySansSerif: is taking first `"Microsoft Sans Serif"` font, then `Arial` [(here is the comparison)](http://www.identifont.com/differences?first=Microsoft+Sans+Serif&second=Aria...). The replacement for Arial is `"Liberation Sans"`. [(here is the comparison)](http://www.identifont.com/differences?first=Liberation+Sans&second=Arial&q=G...). If these fonts are not found then [`Tahoma` is taken.](http://www.identifont.com/differences?first=Liberation+Sans&second=Tahoma&q=...) * GdipGetGenericFontFamilySerif: If `"Times New Roman"` is not found, then the fonts from `FamilySansSerif` is taken. * GdipGetGenericFontFamilyMonospace: If `"Courier New"` is not found, then the fonts from `FamilySansSerif` is taken. It seems that most risky was previous implementation of `GdipGetGenericFontFamilySansSerif`, as it used only priopritary fonts. With proposed solution all `GdipGetGenericFontFamily*` functions have free replacement from Liberation fonts. More information about Liberation Fonts: https://en.wikipedia.org/wiki/Liberation_fonts -- v6: gdiplus: Fix GdipGetGenericFontFamily functions according to native gdiplus.dll https://gitlab.winehq.org/wine/wine/-/merge_requests/2850
From: Bartosz Kosiorek <gang65(a)poczta.onet.pl> --- dlls/gdiplus/font.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c index bcf36a60090..8b85f567aab 100644 --- a/dlls/gdiplus/font.c +++ b/dlls/gdiplus/font.c @@ -969,19 +969,22 @@ GpStatus WINGDIPAPI GdipIsStyleAvailable(GDIPCONST GpFontFamily* family, /***************************************************************************** * GdipGetGenericFontFamilyMonospace [GDIPLUS.@] * - * Obtains a serif family (Courier New on Windows) + * Obtains a monospace family (Courier New on Windows) * * PARAMS - * **nativeFamily [I] Where the font will be stored + * **nativeFamily [O] Where the font will be stored * * RETURNS * InvalidParameter if nativeFamily is NULL. + * FontFamilyNotFound if unable to get font. * Ok otherwise. */ GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily **nativeFamily) { GpStatus stat; + TRACE("(%p)\n", nativeFamily); + if (nativeFamily == NULL) return InvalidParameter; stat = GdipCreateFontFamilyFromName(L"Courier New", NULL, nativeFamily); @@ -990,7 +993,7 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily **nativeFamil stat = GdipCreateFontFamilyFromName(L"Liberation Mono", NULL, nativeFamily); if (stat == FontFamilyNotFound) - ERR("Missing 'Courier New' font\n"); + stat = GdipCreateFontFamilyFromName(L"Courier", NULL, nativeFamily); return stat; } @@ -1001,10 +1004,11 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily **nativeFamil * Obtains a serif family (Times New Roman on Windows) * * PARAMS - * **nativeFamily [I] Where the font will be stored + * **nativeFamily [O] Where the font will be stored * * RETURNS * InvalidParameter if nativeFamily is NULL. + * FontFamilyNotFound if unable to get font. * Ok otherwise. */ GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily **nativeFamily) @@ -1021,7 +1025,7 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily **nativeFamily) stat = GdipCreateFontFamilyFromName(L"Liberation Serif", NULL, nativeFamily); if (stat == FontFamilyNotFound) - ERR("Missing 'Times New Roman' font\n"); + stat = GdipGetGenericFontFamilySansSerif(nativeFamily); return stat; } @@ -1029,13 +1033,14 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily **nativeFamily) /***************************************************************************** * GdipGetGenericFontFamilySansSerif [GDIPLUS.@] * - * Obtains a serif family (Microsoft Sans Serif on Windows) + * Obtains a sans serif family (Microsoft Sans Serif or Arial on Windows) * * PARAMS - * **nativeFamily [I] Where the font will be stored + * **nativeFamily [O] Where the font will be stored * * RETURNS * InvalidParameter if nativeFamily is NULL. + * FontFamilyNotFound if unable to get font. * Ok otherwise. */ GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily **nativeFamily) @@ -1049,7 +1054,12 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily **nativeFamil stat = GdipCreateFontFamilyFromName(L"Microsoft Sans Serif", NULL, nativeFamily); if (stat == FontFamilyNotFound) - /* FIXME: Microsoft Sans Serif is not installed on Wine. */ + stat = GdipCreateFontFamilyFromName(L"Arial", NULL, nativeFamily); + + if (stat == FontFamilyNotFound) + stat = GdipCreateFontFamilyFromName(L"Liberation Sans", NULL, nativeFamily); + + if (stat == FontFamilyNotFound) stat = GdipCreateFontFamilyFromName(L"Tahoma", NULL, nativeFamily); return stat; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/2850
How about using font fallback mechanism inside GDI? That is creating a logical font (`LOGFONT`) with a certain `lfPitchAndFamily` value (e.g. `FF_ROMAN`). Then, you can make `GdipFamily` from `LOGFONT` via `GdipCreateFromLogfont` and `GdipGetFamily`. Win32u.dll has some fallback lists including Liberation fonts. See around https://gitlab.winehq.org/wine/wine/-/blob/wine-8.8/dlls/win32u/font.c#L997 for the implementation. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2850#note_33340
GDI fallback sounds complicated, and I don't really trust it. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2850#note_33408
I see Wine doesn't ship with a serif font, so I guess we either have to use GDI to find one or not give the app a serif font. But, if we don't have any on the list, the one we get is essentially random. Between those choices, I think I prefer the sans fallback. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2850#note_33409
This merge request was approved by Esme Povirk. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/2850
participants (4)
-
Akihiro Sagawa (@sgwaki) -
Bartosz Kosiorek -
Bartosz Kosiorek (@gang65) -
Esme Povirk (@madewokherd)