Open WatchTheFort opened 2 years ago
This is somewhat complicated...
Fonts substitution library is set up and configured even before spring hits the main menu, therefore the engine knows nothing about a game a user is about to launch nor about the fonts it might carry. I doubt even VFS exists at that stage of the engine loading.
Therefore the only way is to make it game specific is to expose fonts substitution to Lua, with that however there are certain concerns too:
smallFont
and font
) it's not possible to recall fonts created from Lua.Is the current way of doing substitution not good enough? Can I have screenshots where it fails spectacularly?
If you mean option 2 from above, it results in the user experiencing an undesirable long freeze while LuaUI reloads, and it changes all glyphs displayed using that font, even if we don't want their appearance to change (e.g. numbers).
Nope, didn't mean that. Both options above are implementation possibilities.
Right now all fonts in engine's fonts
and system wide fonts directory are matched for substitution.
undesirable long freeze while LuaUI reloads
yes, it's not great but it's one time off operation, people don't change their language every minute
it changes all glyphs displayed using that font, even if we don't want their appearance to change (e.g. numbers).
This is something I'd like to hear more about. Screenshot or short video or reproduction steps are needed
See the code here
When an Asian language is used, it's switching the value of the config strings bar_font
and bar_font2
Resource bar with English (default fonts):
Resource bar with Chinese (SourceHanSans-Regular):
This is not what fontconfig/fonts substitution does. Here you just change one font to another and no surprise they're looking differently.
What fonts substitution does instead it keeps the original font and draws all glyphs found in this font from that font file and only tries to replace glyphs NOT found in that font file from some other font file. For that fontconfig
lib builds a database and tries its best to match the style of original fonts with replacement fonts. Things like font family, font make, slant, style, etc are used to select the best font candidate. After that the bitmap of particular "replaced" glyph is added into per-font texture atlas and kept there until the font is destroyed.
In short I can say i don't minde the LuaUI reload/freeze. This is a one-time operation and i think people likely understand or even expect a 'reload' (or even a restart).
Regarding different font-styles - yes, this can be a big thing, since fonts do a LOT in design. Primarily it's of course about readability, so if a substitute is super readable and has support for exotic glyphs/whatnot AND we can still say which font-substitute this will be, then i think we should be able to find the most fitting font, that hurts the design the least.
It's worth trying to see how things look if you keep the original (mostly English-only) fonts and rely on fontconfig to do substitution of non-English glyphs.
But are we able to specify which fallback fonts fontconfig is using? If not, different players will see different things, and from a professional presentation standpoint, we want the game to have a single, standard appearance.
Yes I understand what you mean, but I estimate it's not going to be an easy thing to do. First it's worth doing an experiment with keeping the original font in place and seeing how bad or good the substitution will be.
This is what my game looks like using the original font substitution, ignore the English parts, that's due to widget bugs. Some parts are good, some parts are completely illegible.
Note that there is a missing glyph in the ready button, where the empty space is should be a !
character (U+FF01 : FULLWIDTH EXCLAMATION MARK). I don't know why font substitution is failing for this particular character.
Note that even if it was completely fine for me, that doesn't mean it will appear the same way to other players, and control over that is what we want.
Drop me a code to run this, there's a lot to check here.
I just commented out these lines: https://github.com/beyond-all-reason/Beyond-All-Reason/blob/904742cdaf8e67a7e38c0c9a966671d07e6045ae/modules/i18n/i18n.lua#L38-L46
Language can be switched in game from Settings -> Dev -> Language (first column near the bottom)
Looks like fontconfig and engine support allows a lot of possibilities.
I think we can approach this in different ways:
with our provided fontconfig xml (fontconfig way)
I tried the following next to where we have <cachedir>fontcache</cachedir>
in cacheDirFmt:
<match>
<test name="family"><string>FreeSans</string></test>
<edit name="family" mode="prepend" binding="strong">
<string>Noto Sans</string>
<string>Noto Emoji</string>
<string>Noto Emoji Regular</string>
</edit>
</match>
With that I managed to make fontconfig prefer NotoEmoji-VariableFont_wght.ttf inside spring/fonts instead of my os preferred one FreeSerif.otf to render 🔥.
I also tried <alias>
with <accept>
, <prefer>
or <default>
but could not get that to work.
in-code by always checking our fonts first (the override way)
Instead of always delegating to fontconfig to search for font alternatives, due to how the engine support is written, it wouldn't be hard to always manually search first in some preffered set of fonts, before delegating to fontconfig.
general remarks
With both approaches, we could provide some lua api (didn't check to see if we have one already), to allow games to add folders/fonts to the preferred lists. Didn't think much about this yet, but wanted to hear what others think about both approaches, they look feasible, I think the first one can be better but maybe in the end the last one is easier to control.
The tricky part with the first approach can actually be making fontconfig include VFS memory fonts from games into its search db I looked a bit and doesn't seem to be a direct way to do that, but will investigate and try to find a way. update: looks like it can be done
At the end of the day, games need complete control of how text appears, so that every player sees the same thing.
Issue https://github.com/beyond-all-reason/spring/issues/87 was raised regarding automatic font substitution, which is something handled at the OS level.
Unfortunately, this means the font that is substituted is dependent on which fonts the user has installed on their system. We want to maintain control over the appearance of all aspects of the game, which includes how text is displayed.
What alternatives do we have to OS level font substitution?