diff options
| author | salmonik <salmonik@tuta.io> | 2026-10-26 20:13:07 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-10-26 20:13:07 +0100 |
| commit | 76b6485a33094b40e8f833c32dc84457055062ec (patch) | |
| tree | 667bffc5d38a800204656931ca3693ed3e801016 /src | |
| parent | Bones: head fallback for headcrab black/fast (diff) | |
| download | hl2h-76b6485a33094b40e8f833c32dc84457055062ec.tar.gz hl2h-76b6485a33094b40e8f833c32dc84457055062ec.zip | |
Fonts: bundle Liberation Sans and register it with fontconfig
- ship assets/LiberationSans-Regular.ttf (+ OFL license/README)
- at startup, resolve the .so path via dladdr, add assets/...ttf to the
current fontconfig config with FcConfigAppFontAddFile, and fall back to
the system Liberation path if the asset is missing
- font creation tries Liberation Sans, then DejaVu Sans/Noto/Tahoma/Verdana/
Arial, so the overlay still renders on installs without the bundled font
Diffstat (limited to '')
| -rw-r--r-- | src/menu.cpp | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/src/menu.cpp b/src/menu.cpp index 9537e05..1ef8638 100644 --- a/src/menu.cpp +++ b/src/menu.cpp | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | #include <cstdio> | 4 | #include <cstdio> |
| 5 | #include <cstdlib> | 5 | #include <cstdlib> |
| 6 | #include <cstring> | 6 | #include <cstring> |
| 7 | #include <dlfcn.h> | ||
| 7 | #include <sys/stat.h> | 8 | #include <sys/stat.h> |
| 9 | #include <unistd.h> | ||
| 8 | 10 | ||
| 9 | // --------------------------------------------------------------------------- | 11 | // --------------------------------------------------------------------------- |
| 10 | // ConMsg (tier0 console printer — prints to in-game console) | 12 | // ConMsg (tier0 console printer — prints to in-game console) |
| @@ -217,6 +219,63 @@ static std::string config_path() { | |||
| 217 | return dir + "/config"; | 219 | return dir + "/config"; |
| 218 | } | 220 | } |
| 219 | 221 | ||
| 222 | // Register the bundled Liberation Sans with fontconfig so the VGUI overlay | ||
| 223 | // does not depend on the host/game install having it. The font file lives in | ||
| 224 | // assets/ next to the .so (or the system path as a fallback). | ||
| 225 | void register_bundled_font() { | ||
| 226 | static bool done = false; | ||
| 227 | if (done) | ||
| 228 | return; | ||
| 229 | done = true; | ||
| 230 | |||
| 231 | std::string path; | ||
| 232 | Dl_info info; | ||
| 233 | if (dladdr((void *)®ister_bundled_font, &info) && info.dli_fname) { | ||
| 234 | char resolved[4096]; | ||
| 235 | const char *lib = realpath(info.dli_fname, resolved); | ||
| 236 | std::string p = lib ? resolved : info.dli_fname; | ||
| 237 | size_t slash = p.find_last_of('/'); | ||
| 238 | if (slash != std::string::npos) | ||
| 239 | p.resize(slash + 1); | ||
| 240 | else | ||
| 241 | p = "./"; | ||
| 242 | p += "assets/LiberationSans-Regular.ttf"; | ||
| 243 | if (access(p.c_str(), R_OK) == 0) | ||
| 244 | path = p; | ||
| 245 | } | ||
| 246 | if (path.empty()) { | ||
| 247 | const char *sys = "/usr/share/fonts/liberation/LiberationSans-Regular.ttf"; | ||
| 248 | if (access(sys, R_OK) == 0) | ||
| 249 | path = sys; | ||
| 250 | } | ||
| 251 | if (path.empty()) { | ||
| 252 | logf("font: bundled LiberationSans-Regular.ttf not found"); | ||
| 253 | return; | ||
| 254 | } | ||
| 255 | |||
| 256 | void *fc = dlopen("libfontconfig.so.1", RTLD_LAZY | RTLD_GLOBAL); | ||
| 257 | if (!fc) { | ||
| 258 | logf("font: libfontconfig.so.1 not available"); | ||
| 259 | return; | ||
| 260 | } | ||
| 261 | using InitFn = int (*)(); | ||
| 262 | using GetCurrentFn = void *(*)(); | ||
| 263 | using AddFileFn = int (*)(void *, const char *); | ||
| 264 | auto init = (InitFn)dlsym(fc, "FcInit"); | ||
| 265 | auto get = (GetCurrentFn)dlsym(fc, "FcConfigGetCurrent"); | ||
| 266 | auto add = (AddFileFn)dlsym(fc, "FcConfigAppFontAddFile"); | ||
| 267 | if (!init || !get || !add) { | ||
| 268 | logf("font: fontconfig symbols missing"); | ||
| 269 | return; | ||
| 270 | } | ||
| 271 | init(); | ||
| 272 | void *cfg = get(); | ||
| 273 | if (cfg && add(cfg, path.c_str())) | ||
| 274 | logf("font: registered %s", path.c_str()); | ||
| 275 | else | ||
| 276 | logf("font: failed to register %s", path.c_str()); | ||
| 277 | } | ||
| 278 | |||
| 220 | static void config_save() { | 279 | static void config_save() { |
| 221 | FILE *f = fopen(config_path().c_str(), "w"); | 280 | FILE *f = fopen(config_path().c_str(), "w"); |
| 222 | if (!f) | 281 | if (!f) |
| @@ -671,17 +730,24 @@ void outer_draw() { | |||
| 671 | if (!g_surface || (!g_menu_open && !draw_test && !esp_on)) | 730 | if (!g_surface || (!g_menu_open && !draw_test && !esp_on)) |
| 672 | return; | 731 | return; |
| 673 | if (!g_font) { | 732 | if (!g_font) { |
| 674 | g_font = surf_create_font(); | 733 | static const char *families[] = { |
| 675 | if (!g_font) { | 734 | "Liberation Sans", "DejaVu Sans", "Noto Sans", "Tahoma", |
| 676 | logf("outer_draw: CreateFont failed"); | 735 | "Verdana", "Arial", nullptr}; |
| 677 | return; | 736 | bool font_ok = false; |
| 737 | for (int fi = 0; families[fi] && !font_ok; fi++) { | ||
| 738 | g_font = surf_create_font(); | ||
| 739 | if (!g_font) | ||
| 740 | continue; | ||
| 741 | if (surf_set_font_glyph_set(g_font, families[fi], 16, 400, 0, 0, 0x400, | ||
| 742 | 0x20, 0xFF)) { | ||
| 743 | logf("outer_draw: font family %s", families[fi]); | ||
| 744 | font_ok = true; | ||
| 745 | } else { | ||
| 746 | g_font = 0; | ||
| 747 | } | ||
| 678 | } | 748 | } |
| 679 | // FONTFLAG_CUSTOM only; Liberation Sans is an installed real TTF (Verdana | 749 | if (!font_ok) { |
| 680 | // substitutes to Noto). Raw glyphs, ASCII range pinned. | 750 | logf("outer_draw: no usable font"); |
| 681 | if (!surf_set_font_glyph_set(g_font, "Liberation Sans", 16, 400, 0, 0, | ||
| 682 | 0x400, 0x20, 0xFF)) { | ||
| 683 | logf("outer_draw: SetFontGlyphSet failed"); | ||
| 684 | g_font = 0; | ||
| 685 | return; | 751 | return; |
| 686 | } | 752 | } |
| 687 | } | 753 | } |
| @@ -789,6 +855,7 @@ static ISurface *find_surface_interface() { | |||
| 789 | 855 | ||
| 790 | void install_menu() { | 856 | void install_menu() { |
| 791 | build_tree(); | 857 | build_tree(); |
| 858 | register_bundled_font(); | ||
| 792 | logf("config: %s", config_path().c_str()); | 859 | logf("config: %s", config_path().c_str()); |
| 793 | config_load(); | 860 | config_load(); |
| 794 | // resolve ISurface once (used by the DrawPrintText hook in hl2h.cpp and | 861 | // resolve ISurface once (used by the DrawPrintText hook in hl2h.cpp and |
