A UI font update: Rubik Bold as the default, a SETTINGS > FONT page with the built-in fonts, free look-alikes of game fonts, the player's own copies of the real game fonts and their own mods/fonts files. Network protocol unchanged (43): 1.18.10 plays with 1.18.7 and 1.18.9 games and servers, and demos are unchanged.
The default UI font: Rubik Bold (tools/make_font_atlas.py, src/client/font_ui.h)
- What: the UI text (menus, HUD, chat, scoreboard, editor) is Rubik at wght 700 (Bold), was Work Sans Bold. The console stays monospaced.
- Why Rubik: it's already the logo's, the launcher's and the website title's font (
assets/fonts/Rubik.ttf, SIL OFL 1.1), so the game's text now matches its branding. - How:
tools/make_font_atlas.pybakes it intosrc/client/font_ui.has before: raw R8 distance-field texels, uploaded at startup with no decoding, so startup costs the same.Rubik.ttfis a variable font whose default instance is Light; the tool sets wght 700 (Pillow). - Layouts: Rubik Bold's widths are within 0.1% of Work Sans Bold's at the same em, so every label fits as before. Capitals are 5.25 units (
kUiCapHeight), the height every other font is sized to. - Asset override:
fonts/Rubik.ttf/.otf(inassets/overrides/or the Asset Studio) now replaces the default font.fonts/WorkSans.*used to replace the UI font. It now replaces only the WORK SANS entry. The asset export listsfont/rubik(fonts/Rubik.ttf) as the default font, besidefont/worksans.
SETTINGS > FONT (src/client/uifonts.cpp, src/client/game.cpp)
- The page: a FONT button beside BACK on the settings page opens
settings/fonts, in the menus and in game. It lists the built-ins (kBuiltinFonts: RUBIK, WORK SANS, QUARK CLASSIC, then the game-styled entries), then every.ttf/.otfin the game folder'smods/fonts(OPEN FOLDER, REFRESH; the wheel scrolls a long list). The page rises over the logo when the list is long, so all 10 built-ins fit unscrolled at 1280x720 and 1024x768. - Picking: a click builds that font once (a baked PNG atlas about 3 ms, a TTF about 55 ms) and saves it as
ui_fontin quark.cfg (a built-in's id or the file's name). A font that can't be loaded changes nothing and shows a notice. One that's gone at startup falls back to Rubik with a notice, and the setting is kept, so the font comes back with its file. - Applied once, never per frame:
Game::frameappliesui_fontonly when it differs from the last one tried (a string compare), so the console'sui_font xand the UI test's settings reset work too.Renderer::setUiFontreplaces the font texture's texels in place (glTexSubImage2D, same layout) and swaps the advance / kerning tables every text call reads. Nothing changes in the per-frame text path, so frame times and the F3 1% / 0.1% lows are unaffected. - Sizing:
buildFontAtlassizes any font so its capitals are as tall as Rubik's (FontAtlasLayout::cap), so a picked font doesn't break layouts. Before, a fixed em made fonts with small capitals look tiny. - QUARK CLASSIC: the original 5x7 pixel font (the
kFonttable removed in 8678b00) with its original metrics, baked as a max-norm distance field so its edges and outline stay square (17 KB). - Built-ins are baked PNG atlases (new
src/client/font_builtin.h), not font files rasterised at run time:- Pillow can set a variable font's weight; stb_truetype only draws the default instance (Work Sans would come out Regular).
- The bake sizes every font to Rubik's capitals.
- A distance field compresses about 5:1 as a PNG: Work Sans Bold is 65 KB instead of 488 KB of raw texels or the 361 KB font file.
The game-styled fonts (assets/fonts, src/client/uifonts.cpp)
- Seven free look-alikes, bundled (owner-approved downloads, each with its licence beside it in
assets/fonts/):
| Entry | Bundled font | Licence |
|---|---|---|
| OVERWATCH | Bebas Neue | SIL OFL 1.1 |
| COCAINE DIESEL | Decalotype Bold (the font Cocaine Diesel itself uses) | SIL OFL 1.1 |
| QUAKE | LibreQuake's CONCHARS (a 16x16 sheet of 8x8 characters) | BSD-3-Clause |
| HALF-LIFE 2 | DejaVu Sans Bold | Bitstream Vera licence |
| TF2 | Lilita One | SIL OFL 1.1 |
| TF2 SECONDARY | Jost, baked at wght 600 (SemiBold) | SIL OFL 1.1 |
| APEX LEGENDS | Barlow Condensed Bold | SIL OFL 1.1 |
Why look-alikes: the real fonts can't be shipped. Big Noodle Titling's EULA forbids redistribution, the fan "Apex" family is personal use only, and the TF2, Quake and Verdana files belong to their games and Windows.
- The player's own real font comes first: each entry has a list of places the real font may be, and the first one found is used instead of the look-alike. Those places are
mods/fontsunder its known names, the system's Verdana Bold (Half-Life 2's menu font; Windows, macOS, Linux msttcorefonts), Steam'sTeam Fortress 2/tf/resource/tf2build.ttf/tf2secondary.ttf, and Quake'sgfx.wadorpak0.pak(CONCHARS read from the WAD2 or the PAK, palette index 0 as paper). These files are read only on the player's computer, when the menu opens, on REFRESH and when picked. They are never shipped, and the search never runs per frame. An entry with neither a bundled file nor a found real font isn't listed. - Tuning (from screenshots of each font on the main menu, settings and FONT pages, and the UI test's layout checks run in every font with
QUARK_UITEST_FONT):- Bebas Neue is baked 20% taller. It's capitals only and very condensed, and at Rubik's cap height its 1-pixel strokes broke up in small labels.
- The pixel fonts (QUARK CLASSIC, LibreQuake, a player's own CONCHARS) are 1 unit a pixel and may be drawn down to scale 1 (
FontAtlas/BakedFont::minScale,Renderer::minTextScale), where Rubik stops at 1.3. - Quake sheets are proportional (each glyph as wide as its ink): fixed 8-pixel cells clipped 6 settings labels at 1280x720.
- A sheet's dark drop shadow is treated as paper, because the UI draws its own outline.
- Quake sheets (
buildSheetAtlas,quakeConchars): a 16x16 pixel font sheet becomes a max-norm distance field sized by its H, from a PAK (its gfx.wad), a WAD2, the raw lump or a PNG / JPEG sheet. - Asset overrides: each look-alike can be replaced under its own file name (
fonts/BebasNeue-Regular.ttf,fonts/LibreQuake-CONCHARS.pnga 16x16 sheet, ...), and each is in the asset export (the Asset Studio lists them). A player's own copy of the real game font still comes first. - Text scale: the UI's shrink-to-fit (
Ui::fit,fitText, sliders, the reset hint) uses the font in use's smallest scale (Renderer::minTextScale()) instead of the fixed 1.3, so a pixel font can shrink to 1 pixel a pixel before clipping.
mods/fonts
- New
mods/fonts/README.txt: how to add a font, and the real fonts' file names the game-styled entries look for. - A variable font in
mods/fontsis drawn at its default instance (stb_truetype). A name inui_fontcan't leave that folder.
Size
- The nine baked atlases in
font_builtin.hadd about 440 KB (Work Sans 65 KB, QUARK CLASSIC 17 KB, LibreQuake 15 KB, the other six 53-65 KB each). quark.exe is about 0.5 MB bigger.
Asset provenance (assets/provenance, tools/provenance.py)
- The seven bundled look-alikes are registered in
fonts.jsonasthird-party(made by people, under their licences), like Rubik and Work Sans. Rubik's and Work Sans's descriptions now say which is the UI font. The new FONT page isui/settings/fonts(ai). tools/provenance.py syncnow finds a font's licence by its family (<family>-OFL.txt,-LICENSE.txtor-COPYING.txt, the font's file name starting with<family>), soDejaVuSans-Bold.ttf(DejaVu-LICENSE.txt, Bitstream Vera) andLibreQuake-CONCHARS.png(LibreQuake-COPYING.txt, BSD-3-Clause) are read as third-party too. Before, it only matched<file name>-OFL.txtand would have called themai. The fonts category now also lists a.pngsheet inassets/fonts.- Human-made assets: 18.1% (100 of 550), was 17.1% (93 of 542).
Tests
testUiFonts(assets tests):- every listed built-in loads;
- a font is sized to Rubik's capitals, and QUARK CLASSIC keeps its original metrics;
- a Quake-style sheet (raw, in a WAD2, in a PAK) becomes a pixel atlas, and a bad WAD or a sheet without an H fails;
- a
mods/fontsname can't leave that folder.
- The asset export test checks
fonts/Rubik.*is listed. - UI test: the FONT page is
settings/fonts:- each entry is
cfg("ui_font")with the font's name as a stable id (the one in use is inert); - REFRESH is
state("fontscan"), and OPEN FOLDER isurl(); --fontsand--settingsmenuopen the pages for screenshots;QUARK_UITEST_FONTruns the layout checks in another font.
- each entry is
Docs and credits
- README's Fonts section credits Rubik Bold as the UI font and every bundled font with its copyright and licence. The site footer and the Asset Studio's font hint name Rubik.
- docs/ASSETS.md: how each font is built and why the built-ins are baked,
mods/fonts, QUARK CLASSIC, the game-styled entries (look-alike, licence, where the real font is looked for), the sources of the bundled files, the tuning, and how to add a built-in. - docs/RELEASE_CHECKLIST.md: a FONT row. docs/UI_TEST.md: the fonts page and
QUARK_UITEST_FONT. docs/PROVENANCE.md: the font licence rule.