1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01:00

Add language-specific font configuration

meta.xml can now have a <font> tag, which gives the name of the font
that the language needs. This will directly control the interface font
when the language is active, and will soon also control the font used
for each option on the language screen.
This commit is contained in:
Dav999-v 2023-01-15 01:31:02 +01:00 committed by Misa Elizabeth Kai
parent dadb7f2623
commit 5dad6b38be
12 changed files with 94 additions and 23 deletions

View file

@ -26,4 +26,7 @@
<!-- The indication that a certain menu option or button is selected --> <!-- The indication that a certain menu option or button is selected -->
<menu_select>[ {label} ]</menu_select> <menu_select>[ {label} ]</menu_select>
<menu_select_tight>[{label}]</menu_select_tight> <menu_select_tight>[{label}]</menu_select_tight>
<!-- The filename of the font to use. For example, "font_cn" means font_cn.png and font_cn.fontmeta. -->
<font>font</font>
</langmeta> </langmeta>

View file

@ -26,4 +26,7 @@
<!-- The indication that a certain menu option or button is selected --> <!-- The indication that a certain menu option or button is selected -->
<menu_select>[ {label} ]</menu_select> <menu_select>[ {label} ]</menu_select>
<menu_select_tight>[{label}]</menu_select_tight> <menu_select_tight>[{label}]</menu_select_tight>
<!-- The filename of the font to use. For example, "font_cn" means font_cn.png and font_cn.fontmeta. -->
<font>font</font>
</langmeta> </langmeta>

View file

@ -26,4 +26,7 @@
<!-- The indication that a certain menu option or button is selected --> <!-- The indication that a certain menu option or button is selected -->
<menu_select>[ {label} ]</menu_select> <menu_select>[ {label} ]</menu_select>
<menu_select_tight>[{label}]</menu_select_tight> <menu_select_tight>[{label}]</menu_select_tight>
<!-- The filename of the font to use. For example, "font_cn" means font_cn.png and font_cn.fontmeta. -->
<font>font</font>
</langmeta> </langmeta>

View file

@ -26,4 +26,7 @@
<!-- The indication that a certain menu option or button is selected --> <!-- The indication that a certain menu option or button is selected -->
<menu_select>[ {label} ]</menu_select> <menu_select>[ {label} ]</menu_select>
<menu_select_tight>[{label}]</menu_select_tight> <menu_select_tight>[{label}]</menu_select_tight>
<!-- The filename of the font to use. For example, "font_cn" means font_cn.png and font_cn.fontmeta. -->
<font>font</font>
</langmeta> </langmeta>

View file

@ -26,4 +26,7 @@
<!-- The indication that a certain menu option or button is selected --> <!-- The indication that a certain menu option or button is selected -->
<menu_select>[ {label} ]</menu_select> <menu_select>[ {label} ]</menu_select>
<menu_select_tight>[{label}]</menu_select_tight> <menu_select_tight>[{label}]</menu_select_tight>
<!-- The filename of the font to use. For example, "font_cn" means font_cn.png and font_cn.fontmeta. -->
<font>font</font>
</langmeta> </langmeta>

View file

@ -21,11 +21,10 @@ namespace font
static FontContainer fonts_main = {}; static FontContainer fonts_main = {};
static FontContainer fonts_custom = {}; static FontContainer fonts_custom = {};
static size_t font_idx_interface = 0; static uint8_t font_idx_8x8 = 0;
static size_t font_idx_8x8 = 0;
static bool font_idx_custom_is_custom = false; static bool font_idx_custom_is_custom = false;
static size_t font_idx_custom = 0; static uint8_t font_idx_custom = 0;
static void codepoint_split( static void codepoint_split(
const uint32_t codepoint, const uint32_t codepoint,
@ -147,15 +146,19 @@ static bool decode_xml_range(tinyxml2::XMLElement* elem, unsigned* start, unsign
return true; return true;
} }
static size_t load_font(FontContainer* container, const char* name) static uint8_t load_font(FontContainer* container, const char* name)
{ {
if (container->count >= 254)
{
return 0;
}
Font* new_fonts = (Font*) SDL_realloc(container->fonts, sizeof(Font)*(container->count+1)); Font* new_fonts = (Font*) SDL_realloc(container->fonts, sizeof(Font)*(container->count+1));
if (new_fonts == NULL) if (new_fonts == NULL)
{ {
return 0; return 0;
} }
container->fonts = new_fonts; container->fonts = new_fonts;
size_t f_idx = container->count++; uint8_t f_idx = container->count++;
Font* f = &container->fonts[f_idx]; Font* f = &container->fonts[f_idx];
vlog_info("Loading font \"%s\"...", name); vlog_info("Loading font \"%s\"...", name);
@ -329,11 +332,11 @@ static size_t load_font(FontContainer* container, const char* name)
return f_idx; return f_idx;
} }
static bool find_font_by_name(FontContainer* container, const char* name, size_t* idx) static bool find_font_by_name(FontContainer* container, const char* name, uint8_t* idx)
{ {
// Returns true if font found (and idx is set), false if not found // Returns true if font found (and idx is set), false if not found
for (size_t i = 0; i < container->count; i++) for (uint8_t i = 0; i < container->count; i++)
{ {
if (SDL_strcmp(name, container->fonts[i].name) == 0) if (SDL_strcmp(name, container->fonts[i].name) == 0)
{ {
@ -344,6 +347,16 @@ static bool find_font_by_name(FontContainer* container, const char* name, size_t
return false; return false;
} }
bool find_main_font_by_name(const char* name, uint8_t* idx)
{
return find_font_by_name(&fonts_main, name, idx);
}
uint8_t get_font_idx_8x8(void)
{
return font_idx_8x8;
}
static void set_custom_font(const char* name) static void set_custom_font(const char* name)
{ {
/* Apply the choice for a certain level-specific font. */ /* Apply the choice for a certain level-specific font. */
@ -381,7 +394,7 @@ static void load_font_filename(bool is_custom, const char* filename)
SDL_strlcpy(font_name, filename, sizeof(font_name)); SDL_strlcpy(font_name, filename, sizeof(font_name));
font_name[SDL_min(63, expected_ext_start)] = '\0'; font_name[SDL_min(63, expected_ext_start)] = '\0';
size_t f_idx = load_font(is_custom ? &fonts_custom : &fonts_main, font_name); uint8_t f_idx = load_font(is_custom ? &fonts_custom : &fonts_main, font_name);
if (is_fontpng && !is_custom) if (is_fontpng && !is_custom)
{ {
@ -400,9 +413,6 @@ void load_main(void)
load_font_filename(false, item); load_font_filename(false, item);
} }
FILESYSTEM_freeEnumerate(&handle); FILESYSTEM_freeEnumerate(&handle);
//font_idx_interface = 1; // TODO TEMP
//font_idx_custom = 1;
} }
void load_custom(void) void load_custom(void)
@ -433,7 +443,7 @@ void unload_font(Font* f)
void unload_font_container(FontContainer* container) void unload_font_container(FontContainer* container)
{ {
for (size_t i = 0; i < container->count; i++) for (uint8_t i = 0; i < container->count; i++)
{ {
unload_font(&container->fonts[i]); unload_font(&container->fonts[i]);
} }
@ -702,7 +712,7 @@ static int print_char(
return glyph->advance * scale; return glyph->advance * scale;
} }
static Font* container_get(FontContainer* container, size_t idx) static Font* container_get(FontContainer* container, uint8_t idx)
{ {
/* Get a certain font from the given container (with bounds checking). /* Get a certain font from the given container (with bounds checking).
* Does its best to return at least something, * Does its best to return at least something,
@ -727,6 +737,37 @@ static Font* container_get(FontContainer* container, size_t idx)
return NULL; return NULL;
} }
bool glyph_dimensions_main(uint8_t idx, uint8_t* glyph_w, uint8_t* glyph_h)
{
/* Gets the dimensions (glyph_w and glyph_h) of fonts_main[idx].
* Returns true if the font is valid (glyph_w and/or glyph_h were written to if not NULL), false if not. */
Font* f = container_get(&fonts_main, idx);
if (f == NULL)
{
return false;
}
if (glyph_w != NULL)
{
*glyph_w = f->glyph_w;
}
if (glyph_h != NULL)
{
*glyph_h = f->glyph_h;
}
return true;
}
const char* get_main_font_name(uint8_t idx)
{
Font* f = container_get(&fonts_main, idx);
if (f == NULL)
{
return "";
}
return f->name;
}
static Font* fontsel_to_font(int sel) static Font* fontsel_to_font(int sel)
{ {
/* Take font selection integer (0-31) and turn it into the correct Font /* Take font selection integer (0-31) and turn it into the correct Font
@ -744,7 +785,7 @@ static Font* fontsel_to_font(int sel)
switch (sel) switch (sel)
{ {
case 0: case 0:
return container_get(&fonts_main, font_idx_interface); return container_get(&fonts_main, loc::get_langmeta()->font_idx);
case 1: case 1:
if (font_idx_custom_is_custom) if (font_idx_custom_is_custom)
{ {

View file

@ -64,7 +64,7 @@ struct Font
struct FontContainer struct FontContainer
{ {
size_t count; uint8_t count;
Font* fonts; Font* fonts;
}; };
@ -105,6 +105,10 @@ struct PrintFlags
#define PR_CJK_LOW (1 << 20) /* larger fonts should stick out fully on the bottom (draw at Y) */ #define PR_CJK_LOW (1 << 20) /* larger fonts should stick out fully on the bottom (draw at Y) */
#define PR_CJK_HIGH (2 << 20) /* larger fonts should stick out fully on the top */ #define PR_CJK_HIGH (2 << 20) /* larger fonts should stick out fully on the top */
bool find_main_font_by_name(const char* name, uint8_t* idx);
const char* get_main_font_name(uint8_t idx);
uint8_t get_font_idx_8x8(void);
void load_main(void); void load_main(void);
void load_custom(void); void load_custom(void);
void unload_custom(void); void unload_custom(void);
@ -114,6 +118,8 @@ std::string string_wordwrap(const std::string& s, int maxwidth, short *lines = N
std::string string_wordwrap_balanced(const std::string& s, int maxwidth); std::string string_wordwrap_balanced(const std::string& s, int maxwidth);
std::string string_unwordwrap(const std::string& s); std::string string_unwordwrap(const std::string& s);
bool glyph_dimensions_main(uint8_t idx, uint8_t* glyph_w, uint8_t* glyph_h);
int len(uint32_t flags, const std::string& t); int len(uint32_t flags, const std::string& t);
int height(const uint32_t flags); int height(const uint32_t flags);

View file

@ -28,8 +28,7 @@ struct LangMeta
bool toupper_lower_escape_char; // = false; enable ~ to mark lowercase letters for uppercasing bool toupper_lower_escape_char; // = false; enable ~ to mark lowercase letters for uppercasing
std::string menu_select; std::string menu_select;
std::string menu_select_tight; std::string menu_select_tight;
unsigned char font_w; uint8_t font_idx;
unsigned char font_h;
}; };
struct TextboxFormat struct TextboxFormat

View file

@ -57,6 +57,8 @@ static void sync_lang_file(const std::string& langcode)
pElem->SetText(langmeta.menu_select.c_str()); pElem->SetText(langmeta.menu_select.c_str());
else if (SDL_strcmp(pKey, "menu_select_tight") == 0) else if (SDL_strcmp(pKey, "menu_select_tight") == 0)
pElem->SetText(langmeta.menu_select_tight.c_str()); pElem->SetText(langmeta.menu_select_tight.c_str());
else if (SDL_strcmp(pKey, "font") == 0)
pElem->SetText(font::get_main_font_name(langmeta.font_idx));
} }
/* This part exists because we want to preserve blank lines between the commented /* This part exists because we want to preserve blank lines between the commented

View file

@ -65,8 +65,7 @@ static void loadmeta(LangMeta& meta, const std::string& langcode = lang)
meta.toupper_lower_escape_char = false; meta.toupper_lower_escape_char = false;
meta.menu_select = "[ {label} ]"; meta.menu_select = "[ {label} ]";
meta.menu_select_tight = "[{label}]"; meta.menu_select_tight = "[{label}]";
meta.font_w = 8; meta.font_idx = font::get_font_idx_8x8();
meta.font_h = 8;
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
tinyxml2::XMLHandle hDoc(&doc); tinyxml2::XMLHandle hDoc(&doc);
@ -106,6 +105,8 @@ static void loadmeta(LangMeta& meta, const std::string& langcode = lang)
meta.menu_select = std::string(pText); meta.menu_select = std::string(pText);
else if (SDL_strcmp(pKey, "menu_select_tight") == 0) else if (SDL_strcmp(pKey, "menu_select_tight") == 0)
meta.menu_select_tight = std::string(pText); meta.menu_select_tight = std::string(pText);
else if (SDL_strcmp(pKey, "font") == 0)
font::find_main_font_by_name(pText, &meta.font_idx);
} }
} }
@ -298,8 +299,12 @@ static bool max_check_string(const char* str, const char* max)
max_h = 2; max_h = 2;
} }
unsigned short max_w_px = max_w * get_langmeta()->font_w; uint8_t font_w = 8;
unsigned short max_h_px = max_h * SDL_max(10, get_langmeta()->font_h); uint8_t font_h = 8;
font::glyph_dimensions_main(get_langmeta()->font_idx, &font_w, &font_h);
unsigned short max_w_px = max_w * font_w;
unsigned short max_h_px = max_h * SDL_max(10, font_h);
bool does_overflow = false; bool does_overflow = false;

View file

@ -712,8 +712,11 @@ static void menurender(void)
); );
graphics.Print(10, 10, buffer, tr/2, tg/2, tb/2); graphics.Print(10, 10, buffer, tr/2, tg/2, tb/2);
uint8_t font_h = 8;
font::glyph_dimensions_main(loc::get_langmeta()->font_idx, NULL, &font_h);
int box_x = SDL_min(10, (320-overflow.max_w_px)/2); int box_x = SDL_min(10, (320-overflow.max_w_px)/2);
int box_h = overflow.max_h_px - SDL_max(0, 10-loc::get_langmeta()->font_h); int box_h = overflow.max_h_px - SDL_max(0, 10-font_h);
graphics.fill_rect(box_x-1, 30-1, overflow.max_w_px+2, box_h+2, tr/3, tg/3, tb/3); graphics.fill_rect(box_x-1, 30-1, overflow.max_w_px+2, box_h+2, tr/3, tg/3, tb/3);
int wraplimit; int wraplimit;

View file

@ -105,7 +105,7 @@ void textboxclass::resize(void)
for (size_t iter = 0; iter < lines.size(); iter++) for (size_t iter = 0; iter < lines.size(); iter++)
{ {
int len = font::len(print_flags, lines[iter]); int len = font::len(print_flags, lines[iter]);
if (len > (unsigned int)max) max = len; if (len > max) max = len;
} }
// 16 for the borders // 16 for the borders