A version of surface.CreateFont that solves some cross platform issues

On Linux (and maybe osx?) surface.CreateFont doesn’t work the same way it does on windows. This is a version of surface.CreateFont that attempts to solve some of the issues.

Windows notes:
► It’s based on ::CreateFont which handles weight, italic, strikeout and underline internally.
► The font field in surface.CreateFont can be a full font name or a font family name. (A font family would be “Roboto” while a full font name would be “Roboto Bold Italic”.)
► When using a font family name it will automatically pick the right font based on the weight and italic values. But if a weighed font cannot be found windows (i think?) tries to make the font bold with some internal method. This happens if the weight is above 550.
► Weight 550-650 is bolder than 700 and up on smaller fonts.
► There are just 3 levels of boldness with weight. 0-550 (none), 550-650 and 600-beyond
► Using font paths like “roboto-bold.ttf” does not work.
► When attempting to draw a unicode character that does not exist in the font there seems to be a fallback handled internally by windows.

Wine on Linux handles italic, bold, etc using freetype. You can see how it does that here https://github.com/wine-mirror/wine/blob/master/dlls/gdi32/freetype.c (ctrl-f fake_bold and fake_italic) But this is out of scope for glua and maybe even gmod. It’s something the source engine has to do.

Linux notes:
► Weight and italic doesn’t do anything. (because it’s a windows specific feature)
► Antialias is always on (this looks bad when using outline on very small fonts, ie the debug font).
► Outline affects the size of the font, it seems to just add 2 to the size, so subtracting 2 from size fixes this.
► Outline offsets the text x position by 1 pixel when drawing it.
► Using a font path like “roboto-bold.ttf” works, but only in resource/fonts/* and not resource/. In resource/ you have to use the full font name . (ie “roboto bold”)
► When using a unicode character that does not exist there is no fallback. (in console you’ll get m_face->glyph->bitmap.width is 0 for ch:54620 Nimbus Sans L)

So this version of surface.CreateFont attempts to fix these differences.

► It only allows using fonts in resource/fonts/* or resource/*. It will be marked as invalid if you try to use a system font like “Comic Sans MS”.
► It fixes outline size differences.
► You can use font family names as well.
► It attempts to solve the weight value, but it’s different from windows and it doesn’t do anything if there are no bold fonts. But when using weight it’s at least consistent on windows and Linux with fonts like Roboto.

It also includes some console commands:
dump_font_families – dump available fonts sorted as a family tree
dump_font_names – dump full font names
dump_fonts_created – dump valid fonts created through surface.CreateFont
dump_invalid_fonts – dump invalid fonts created through surface.CreateFont

You can search with all of these commands. Example:

Note that while fonts like “Tahoma” are valid in source engine on Linux it will just translate to resource/fonts/dejavusans.ttf. I think it’s better to just use “DejaVu Sans” as it’s available on windows and Linux so there’s no ambiguity.

Based on vgui_spew_fonts these windows fonts are translated on Linux:

??	=	DejaVu Sans
Courier	=	Nimbus Mono L
Courier New	=	Liberation Mono
Helvetica Bold	=	DejaVu Sans
Lucida Console	=	DejaVu Sans
Tahoma	=	DejaVu Sans
Trebuchet MS	=	DejaVu Sans
Verdana	=	DejaVu Sans
Verdana Bold	=	DejaVu Sans
Verdana Bold Italic	=	DejaVu Sans

(I can’t find the “liberation mono” font anywhere though, which are used by debug and possibly console. Maybe this explains why the console is not a mono font?)

One way to generate bold fonts is to use something like FontForge.
(ignore all warnings and just yes everything)

  1. Open your TTF font.
  2. Select all glyphs
  3. Element > Style > Change Weight >
  4. Change settings around (the default already makes it bold)
  5. Element > Font Info >
  6. Change the weight field to bold, black, semi bold, or whatever.
  7. File > Generate Fonts >
  8. Change the type to TrueType and save as somethingbold.ttf. Note that the file name can be anything as we’re using font names anyway.
  9. Save the font in garrysmod at resource/fonts/myboldfont.ttf, add it with resource.AddFile, etc

This could also hopefully motivate someone to fix these issues in the engine itself. I think being allowed to use full path names would be a good start to avoid ambiguity.

Facepunch needs to fix Gmod on linux in general :vs:. The community members shouldn’t have to fix it for them. Nice work though.