diff options
Diffstat (limited to '')
| -rw-r--r-- | src/gui.cpp | 106 |
1 files changed, 82 insertions, 24 deletions
diff --git a/src/gui.cpp b/src/gui.cpp index b512ef3..417860f 100644 --- a/src/gui.cpp +++ b/src/gui.cpp | |||
| @@ -39,6 +39,8 @@ static unsigned long g_font_title = 0; | |||
| 39 | static int g_body_h = 15; | 39 | static int g_body_h = 15; |
| 40 | static int g_title_h = 20; | 40 | static int g_title_h = 20; |
| 41 | static float g_font_scale = 0.0f; | 41 | static float g_font_scale = 0.0f; |
| 42 | static void *g_font_local = (void *)-1; | ||
| 43 | static bool g_font_fail_logged = false; | ||
| 42 | static int g_scr_w = 0, g_scr_h = 0; | 44 | static int g_scr_w = 0, g_scr_h = 0; |
| 43 | 45 | ||
| 44 | static void s_color(int r, int g, int b, int a) { | 46 | static void s_color(int r, int g, int b, int a) { |
| @@ -485,41 +487,97 @@ bool gui_toasts_active() { | |||
| 485 | return active; | 487 | return active; |
| 486 | } | 488 | } |
| 487 | 489 | ||
| 488 | static void ensure_fonts() { | 490 | static bool font_valid(unsigned long f) { |
| 489 | if (g_font_body && fabsf(g_font_scale - g_scale) < 0.001f) | 491 | if (!f || !g_surface) |
| 490 | return; | 492 | return false; |
| 491 | g_font_scale = g_scale; | 493 | int w = 0, h = 0; |
| 492 | g_body_h = (int)(15.0f * g_scale + 0.5f); | 494 | s_text_size(f, L"M", w, h); |
| 493 | g_title_h = (int)(20.0f * g_scale + 0.5f); | 495 | return w > 0 && h > 0; |
| 494 | if (g_body_h < 11) g_body_h = 11; | 496 | } |
| 495 | if (g_title_h < 15) g_title_h = 15; | 497 | |
| 498 | static void gui_reset_fonts() { | ||
| 499 | g_font_body = 0; | ||
| 500 | g_font_title = 0; | ||
| 501 | g_font_scale = 0.0f; | ||
| 502 | } | ||
| 503 | |||
| 504 | static unsigned long create_gui_font(int tall) { | ||
| 496 | static const char *families[] = {"Liberation Sans", "DejaVu Sans", | 505 | static const char *families[] = {"Liberation Sans", "DejaVu Sans", |
| 497 | "Noto Sans", "Tahoma", "Verdana", "Arial", | 506 | "Noto Sans", "Tahoma", "Verdana", "Arial", |
| 498 | nullptr}; | 507 | nullptr}; |
| 508 | for (int i = 0; families[i]; i++) { | ||
| 509 | unsigned long f = s_create_font(); | ||
| 510 | if (!f) | ||
| 511 | break; | ||
| 512 | if (s_set_font(f, families[i], tall, 400, 0x400, 0x20, 0xFF) && | ||
| 513 | font_valid(f)) | ||
| 514 | return f; | ||
| 515 | } | ||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | static void ensure_fonts() { | ||
| 520 | void *le = nullptr; | ||
| 521 | if (g_iface.engine && g_iface.entitylist) { | ||
| 522 | int local = engine_get_local_player(); | ||
| 523 | if (local > 0) | ||
| 524 | le = entitylist_get(local); | ||
| 525 | } | ||
| 526 | if (le != g_font_local) { | ||
| 527 | g_font_local = le; | ||
| 528 | gui_reset_fonts(); | ||
| 529 | } | ||
| 530 | |||
| 531 | bool scale_changed = fabsf(g_font_scale - g_scale) >= 0.001f; | ||
| 532 | if (g_font_body && g_font_title && !scale_changed && | ||
| 533 | font_valid(g_font_body) && font_valid(g_font_title)) | ||
| 534 | return; | ||
| 535 | // Level transitions can silently invalidate VGUI font handles. Recreate | ||
| 536 | // them instead of drawing invisible text. | ||
| 537 | if ((g_font_body && !font_valid(g_font_body)) || | ||
| 538 | (g_font_title && !font_valid(g_font_title))) | ||
| 539 | gui_reset_fonts(); | ||
| 540 | if (scale_changed) | ||
| 541 | gui_reset_fonts(); | ||
| 542 | |||
| 543 | g_font_scale = g_scale; | ||
| 544 | int req_body = (int)(15.0f * g_scale + 0.5f); | ||
| 545 | int req_title = (int)(20.0f * g_scale + 0.5f); | ||
| 546 | if (req_body < 11) req_body = 11; | ||
| 547 | if (req_title < 15) req_title = 15; | ||
| 548 | g_body_h = req_body; | ||
| 549 | g_title_h = req_title; | ||
| 550 | |||
| 551 | if (!g_font_body) | ||
| 552 | g_font_body = create_gui_font(g_body_h); | ||
| 553 | if (!g_font_title) | ||
| 554 | g_font_title = create_gui_font(g_title_h); | ||
| 555 | |||
| 556 | // Small scaled sizes can fail in the font manager; 16 px is the proven ESP | ||
| 557 | // size, so use it as a readable fallback. | ||
| 499 | if (!g_font_body) { | 558 | if (!g_font_body) { |
| 500 | for (int i = 0; families[i] && !g_font_body; i++) { | 559 | g_body_h = 16; |
| 501 | unsigned long f = s_create_font(); | 560 | g_font_body = create_gui_font(g_body_h); |
| 502 | if (!f) | ||
| 503 | break; | ||
| 504 | if (s_set_font(f, families[i], g_body_h, 400, 0x400, 0x20, 0xFF)) | ||
| 505 | g_font_body = f; | ||
| 506 | } | ||
| 507 | } | 561 | } |
| 508 | if (!g_font_title) { | 562 | if (!g_font_title) { |
| 509 | for (int i = 0; families[i] && !g_font_title; i++) { | 563 | g_title_h = 16; |
| 510 | unsigned long f = s_create_font(); | 564 | g_font_title = create_gui_font(g_title_h); |
| 511 | if (!f) | ||
| 512 | break; | ||
| 513 | if (s_set_font(f, families[i], g_title_h, 400, 0x400, 0x20, 0xFF)) | ||
| 514 | g_font_title = f; | ||
| 515 | } | ||
| 516 | } | 565 | } |
| 517 | if (!g_font_title) | 566 | if (!g_font_title) |
| 518 | g_font_title = g_font_body; | 567 | g_font_title = g_font_body; |
| 568 | |||
| 519 | if (!g_font_body) { | 569 | if (!g_font_body) { |
| 520 | logf("gui: no usable body font"); | 570 | if (!g_font_fail_logged) { |
| 521 | toastf(TOAST_ERROR, "No usable GUI font"); | 571 | g_font_fail_logged = true; |
| 572 | logf("gui: no usable body font"); | ||
| 573 | toastf(TOAST_ERROR, "No usable GUI font"); | ||
| 574 | } | ||
| 575 | return; | ||
| 522 | } | 576 | } |
| 577 | g_font_fail_logged = false; | ||
| 578 | if (g_body_h != req_body || g_title_h != req_title) | ||
| 579 | logd("gui: font fallback body=%d title=%d (requested %d/%d)", g_body_h, | ||
| 580 | g_title_h, req_body, req_title); | ||
| 523 | } | 581 | } |
| 524 | 582 | ||
| 525 | static int text_w(const char *s, int tall) { | 583 | static int text_w(const char *s, int tall) { |
