mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
(Font) One copy of the language-to-font decision
The same switch existed five times - twice in ozone, once each in materialui, gfx_widgets and file_path_special - mapping Arabic and Persian to fallback-font.ttf, Chinese to chinese-fallback-font.ttf, Korean to korean-fallback-font.ttf, and everything else to the caller's own default. Character for character the same, differing only in which variable held the assets directory. font_driver_language_font_file() returns the file name, or NULL when the language has no special requirement. The name rather than a full path, because the callers do genuinely differ on the directory: ozone and materialui build it from directory_assets, widgets keep assets_pkg_dir already, file_path_special has its own. The default branch stays with the caller too - bold.ttf, regular.ttf, FILE_PATH_TTF_FONT and the xmb theme directory are all different. Adding a language was five edits and is now one. That matters immediately: Thai renders as tofu today because it is not in the switch, and neither shipped fallback font contains Thai - checking the cmap tables, fallback-font.ttf covers Arabic but not U+0E01. So Thai needs a font as well as a case, and when one arrives there is now a single place to put it. This is also the piece the language switch was missing. font_driver_reload_fonts() rebuilds each font from the path it was created with, which re-reads the same face; making a language change take effect without a restart needs the path re-resolved, and that needs one function to ask. It exists now. samples/gfx/font_lifecycle grows a msg_hash_get_uint() stub, since font_driver.c now asks which language is selected. English there - the tests are about the lifecycle, not the mapping. Clean under ASan, UBSan, LeakSanitizer and TSan.
This commit is contained in:
1 parent
588c1c8ecb
commit
f7bb668669
7 files changed
+83
-95
No files matched your search
+14
-28
@@ -381,35 +381,21 @@ size_t fill_pathname_application_special(char *s,
|
||||
{
|
||||
char tmp_dir[DIR_MAX_LENGTH];
|
||||
|
||||
switch (*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE))
|
||||
const char *lang_font = font_driver_language_font_file();
|
||||
|
||||
if (lang_font)
|
||||
{
|
||||
case RETRO_LANGUAGE_ARABIC:
|
||||
case RETRO_LANGUAGE_PERSIAN:
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
_len = fill_pathname_join_special(s, tmp_dir, "fallback-font.ttf", len);
|
||||
break;
|
||||
case RETRO_LANGUAGE_CHINESE_SIMPLIFIED:
|
||||
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
_len = fill_pathname_join_special(s, tmp_dir, "chinese-fallback-font.ttf", len);
|
||||
break;
|
||||
case RETRO_LANGUAGE_KOREAN:
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
_len = fill_pathname_join_special(s, tmp_dir, "korean-fallback-font.ttf", len);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char tmp_dir2[DIR_MAX_LENGTH];
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *dir_assets = settings->paths.directory_assets;
|
||||
fill_pathname_join_special(tmp_dir2, dir_assets, "xmb", sizeof(tmp_dir2));
|
||||
fill_pathname_join_special(tmp_dir, tmp_dir2, xmb_theme_ident(), sizeof(tmp_dir));
|
||||
_len = fill_pathname_join_special(s, tmp_dir, FILE_PATH_TTF_FONT, len);
|
||||
}
|
||||
break;
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
_len = fill_pathname_join_special(s, tmp_dir, lang_font, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp_dir2[DIR_MAX_LENGTH];
|
||||
const char *dir_assets = settings->paths.directory_assets;
|
||||
fill_pathname_join_special(tmp_dir2, dir_assets, "xmb", sizeof(tmp_dir2));
|
||||
fill_pathname_join_special(tmp_dir, tmp_dir2, xmb_theme_ident(), sizeof(tmp_dir));
|
||||
_len = fill_pathname_join_special(s, tmp_dir, FILE_PATH_TTF_FONT, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "../msg_hash.h"
|
||||
#include "font_driver.h"
|
||||
#include "video_thread_wrapper.h"
|
||||
|
||||
@@ -68,6 +69,25 @@ static void font_driver_cache_metrics(font_data_t *font)
|
||||
}
|
||||
}
|
||||
|
||||
const char *font_driver_language_font_file(void)
|
||||
{
|
||||
switch (*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE))
|
||||
{
|
||||
case RETRO_LANGUAGE_ARABIC:
|
||||
case RETRO_LANGUAGE_PERSIAN:
|
||||
return "fallback-font.ttf";
|
||||
case RETRO_LANGUAGE_CHINESE_SIMPLIFIED:
|
||||
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
|
||||
return "chinese-fallback-font.ttf";
|
||||
case RETRO_LANGUAGE_KOREAN:
|
||||
return "korean-fallback-font.ttf";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned font_driver_reload_fonts(void)
|
||||
{
|
||||
font_data_t *font;
|
||||
|
||||
@@ -150,6 +150,15 @@ void font_driver_free(font_data_t *font);
|
||||
* left alone. Returns the number rebuilt. */
|
||||
unsigned font_driver_reload_fonts(void);
|
||||
|
||||
/* The font file the current menu language needs, relative to the
|
||||
* assets pkg directory, or NULL when it has no special requirement
|
||||
* and the caller's own default should be used.
|
||||
*
|
||||
* One copy of this decision. It was four - ozone, materialui,
|
||||
* gfx_widgets and file_path_special each carried the same switch -
|
||||
* which is three places to forget when a language is added. */
|
||||
const char *font_driver_language_font_file(void);
|
||||
|
||||
/* Returns a monotonic counter incremented on every font free;
|
||||
* see font_driver.c for rationale. Used to validate externally
|
||||
* cached per-font derived data */
|
||||
|
||||
+8
-15
@@ -1015,22 +1015,15 @@ static void gfx_widgets_layout(
|
||||
is_threaded, p_dispwidget->ozone_bold_font_path, BASE_FONT_SIZE);
|
||||
|
||||
/* Create msg_queue font */
|
||||
switch (*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE))
|
||||
{
|
||||
case RETRO_LANGUAGE_ARABIC:
|
||||
case RETRO_LANGUAGE_PERSIAN:
|
||||
fill_pathname_join_special(font_file, p_dispwidget->assets_pkg_dir, "fallback-font.ttf", sizeof(font_file));
|
||||
break;
|
||||
case RETRO_LANGUAGE_CHINESE_SIMPLIFIED:
|
||||
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
|
||||
fill_pathname_join_special(font_file, p_dispwidget->assets_pkg_dir, "chinese-fallback-font.ttf", sizeof(font_file));
|
||||
break;
|
||||
case RETRO_LANGUAGE_KOREAN:
|
||||
fill_pathname_join_special(font_file, p_dispwidget->assets_pkg_dir, "korean-fallback-font.ttf", sizeof(font_file));
|
||||
break;
|
||||
default:
|
||||
strlcpy(font_file, p_dispwidget->ozone_regular_font_path, sizeof(font_file));
|
||||
break;
|
||||
const char *lang_font = font_driver_language_font_file();
|
||||
|
||||
if (lang_font)
|
||||
fill_pathname_join_special(font_file,
|
||||
p_dispwidget->assets_pkg_dir, lang_font, sizeof(font_file));
|
||||
else
|
||||
strlcpy(font_file, p_dispwidget->ozone_regular_font_path,
|
||||
sizeof(font_file));
|
||||
}
|
||||
gfx_widgets_font_init(p_disp, p_dispwidget,
|
||||
&p_dispwidget->gfx_widget_fonts.msg_queue,
|
||||
|
||||
@@ -9327,33 +9327,22 @@ static void materialui_init_font(gfx_display_t *p_disp,
|
||||
font_data->font = NULL;
|
||||
}
|
||||
|
||||
switch (*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE))
|
||||
{
|
||||
case RETRO_LANGUAGE_ARABIC:
|
||||
case RETRO_LANGUAGE_PERSIAN:
|
||||
const char *lang_font = font_driver_language_font_file();
|
||||
|
||||
if (lang_font)
|
||||
{
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(fontpath, tmp_dir, "fallback-font.ttf",
|
||||
fill_pathname_join_special(fontpath, tmp_dir, lang_font,
|
||||
sizeof(fontpath));
|
||||
break;
|
||||
case RETRO_LANGUAGE_CHINESE_SIMPLIFIED:
|
||||
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(fontpath, tmp_dir, "chinese-fallback-font.ttf",
|
||||
sizeof(fontpath));
|
||||
break;
|
||||
case RETRO_LANGUAGE_KOREAN:
|
||||
fill_pathname_join_special(tmp_dir,
|
||||
settings->paths.directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(fontpath, tmp_dir, "korean-fallback-font.ttf",
|
||||
sizeof(fontpath));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_pathname_join_special(tmp_dir, dir_assets, "glui", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(fontpath, tmp_dir, FILE_PATH_TTF_FONT,
|
||||
sizeof(fontpath));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
font_data->font = gfx_display_font_file(p_disp,
|
||||
|
||||
+14
-32
@@ -10114,25 +10114,16 @@ static void ozone_set_layout(
|
||||
ozone->pointer_active_delta = CURSOR_ACTIVE_DELTA * scale_factor;
|
||||
|
||||
/* Initialise fonts */
|
||||
switch (*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE))
|
||||
{
|
||||
case RETRO_LANGUAGE_ARABIC:
|
||||
case RETRO_LANGUAGE_PERSIAN:
|
||||
const char *lang_font = font_driver_language_font_file();
|
||||
|
||||
if (lang_font)
|
||||
{
|
||||
fill_pathname_join_special(tmp_dir, path_directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(font_path, tmp_dir, "fallback-font.ttf", sizeof(font_path));
|
||||
break;
|
||||
case RETRO_LANGUAGE_CHINESE_SIMPLIFIED:
|
||||
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
|
||||
fill_pathname_join_special(tmp_dir, path_directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(font_path, tmp_dir, "chinese-fallback-font.ttf", sizeof(font_path));
|
||||
break;
|
||||
case RETRO_LANGUAGE_KOREAN:
|
||||
fill_pathname_join_special(tmp_dir, path_directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(font_path, tmp_dir, "korean-fallback-font.ttf", sizeof(font_path));
|
||||
break;
|
||||
default:
|
||||
fill_pathname_join_special(font_path, tmp_dir, lang_font, sizeof(font_path));
|
||||
}
|
||||
else
|
||||
fill_pathname_join_special(font_path, ozone->assets_path, "bold.ttf", sizeof(font_path));
|
||||
break;
|
||||
}
|
||||
|
||||
if (path_menu_font && *path_menu_font)
|
||||
@@ -10143,25 +10134,16 @@ static void ozone_set_layout(
|
||||
if (!(((ozone->flags & OZONE_FLAG_HAS_ALL_ASSETS) > 0) && font_inited))
|
||||
ozone->flags &= ~OZONE_FLAG_HAS_ALL_ASSETS;
|
||||
|
||||
switch (*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE))
|
||||
{
|
||||
case RETRO_LANGUAGE_ARABIC:
|
||||
case RETRO_LANGUAGE_PERSIAN:
|
||||
const char *lang_font = font_driver_language_font_file();
|
||||
|
||||
if (lang_font)
|
||||
{
|
||||
fill_pathname_join_special(tmp_dir, path_directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(font_path, tmp_dir, "fallback-font.ttf", sizeof(font_path));
|
||||
break;
|
||||
case RETRO_LANGUAGE_CHINESE_SIMPLIFIED:
|
||||
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
|
||||
fill_pathname_join_special(tmp_dir, path_directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(font_path, tmp_dir, "chinese-fallback-font.ttf", sizeof(font_path));
|
||||
break;
|
||||
case RETRO_LANGUAGE_KOREAN:
|
||||
fill_pathname_join_special(tmp_dir, path_directory_assets, "pkg", sizeof(tmp_dir));
|
||||
fill_pathname_join_special(font_path, tmp_dir, "korean-fallback-font.ttf", sizeof(font_path));
|
||||
break;
|
||||
default:
|
||||
fill_pathname_join_special(font_path, tmp_dir, lang_font, sizeof(font_path));
|
||||
}
|
||||
else
|
||||
fill_pathname_join_special(font_path, ozone->assets_path, "regular.ttf", sizeof(font_path));
|
||||
break;
|
||||
}
|
||||
|
||||
if (path_menu_font && *path_menu_font)
|
||||
|
||||
@@ -26,6 +26,15 @@ bool filestream_read_file(const char *path, void **buf, int64_t *len)
|
||||
return *buf != NULL;
|
||||
}
|
||||
|
||||
/* font_driver_language_font_file() asks which language is selected.
|
||||
* English here: the tests are about the lifecycle, not the mapping. */
|
||||
unsigned *msg_hash_get_uint(enum msg_hash_action type)
|
||||
{
|
||||
static unsigned lang = 0; /* RETRO_LANGUAGE_ENGLISH */
|
||||
(void)type;
|
||||
return ⟨
|
||||
}
|
||||
|
||||
static video_driver_state_t vst;
|
||||
video_driver_state_t *video_state_get_ptr(void) { return &vst; }
|
||||
|
||||
|
||||
Reference in new issue
Block a user