mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49: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:
parent
dadb7f2623
commit
5dad6b38be
12 changed files with 94 additions and 23 deletions
|
@ -26,4 +26,7 @@
|
|||
<!-- The indication that a certain menu option or button is selected -->
|
||||
<menu_select>[ {label} ]</menu_select>
|
||||
<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>
|
||||
|
|
|
@ -26,4 +26,7 @@
|
|||
<!-- The indication that a certain menu option or button is selected -->
|
||||
<menu_select>[ {label} ]</menu_select>
|
||||
<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>
|
||||
|
|
|
@ -26,4 +26,7 @@
|
|||
<!-- The indication that a certain menu option or button is selected -->
|
||||
<menu_select>[ {label} ]</menu_select>
|
||||
<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>
|
||||
|
|
|
@ -26,4 +26,7 @@
|
|||
<!-- The indication that a certain menu option or button is selected -->
|
||||
<menu_select>[ {label} ]</menu_select>
|
||||
<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>
|
||||
|
|
|
@ -26,4 +26,7 @@
|
|||
<!-- The indication that a certain menu option or button is selected -->
|
||||
<menu_select>[ {label} ]</menu_select>
|
||||
<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>
|
||||
|
|
|
@ -21,11 +21,10 @@ namespace font
|
|||
static FontContainer fonts_main = {};
|
||||
static FontContainer fonts_custom = {};
|
||||
|
||||
static size_t font_idx_interface = 0;
|
||||
static size_t font_idx_8x8 = 0;
|
||||
static uint8_t font_idx_8x8 = 0;
|
||||
|
||||
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(
|
||||
const uint32_t codepoint,
|
||||
|
@ -147,15 +146,19 @@ static bool decode_xml_range(tinyxml2::XMLElement* elem, unsigned* start, unsign
|
|||
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));
|
||||
if (new_fonts == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
container->fonts = new_fonts;
|
||||
size_t f_idx = container->count++;
|
||||
uint8_t f_idx = container->count++;
|
||||
Font* f = &container->fonts[f_idx];
|
||||
|
||||
vlog_info("Loading font \"%s\"...", name);
|
||||
|
@ -329,11 +332,11 @@ static size_t load_font(FontContainer* container, const char* name)
|
|||
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
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -344,6 +347,16 @@ static bool find_font_by_name(FontContainer* container, const char* name, size_t
|
|||
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)
|
||||
{
|
||||
/* 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));
|
||||
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)
|
||||
{
|
||||
|
@ -400,9 +413,6 @@ void load_main(void)
|
|||
load_font_filename(false, item);
|
||||
}
|
||||
FILESYSTEM_freeEnumerate(&handle);
|
||||
|
||||
//font_idx_interface = 1; // TODO TEMP
|
||||
//font_idx_custom = 1;
|
||||
}
|
||||
|
||||
void load_custom(void)
|
||||
|
@ -433,7 +443,7 @@ void unload_font(Font* f)
|
|||
|
||||
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]);
|
||||
}
|
||||
|
@ -702,7 +712,7 @@ static int print_char(
|
|||
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).
|
||||
* Does its best to return at least something,
|
||||
|
@ -727,6 +737,37 @@ static Font* container_get(FontContainer* container, size_t idx)
|
|||
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)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
case 0:
|
||||
return container_get(&fonts_main, font_idx_interface);
|
||||
return container_get(&fonts_main, loc::get_langmeta()->font_idx);
|
||||
case 1:
|
||||
if (font_idx_custom_is_custom)
|
||||
{
|
||||
|
|
|
@ -64,7 +64,7 @@ struct Font
|
|||
|
||||
struct FontContainer
|
||||
{
|
||||
size_t count;
|
||||
uint8_t count;
|
||||
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_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_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_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 height(const uint32_t flags);
|
||||
|
||||
|
|
|
@ -28,8 +28,7 @@ struct LangMeta
|
|||
bool toupper_lower_escape_char; // = false; enable ~ to mark lowercase letters for uppercasing
|
||||
std::string menu_select;
|
||||
std::string menu_select_tight;
|
||||
unsigned char font_w;
|
||||
unsigned char font_h;
|
||||
uint8_t font_idx;
|
||||
};
|
||||
|
||||
struct TextboxFormat
|
||||
|
|
|
@ -57,6 +57,8 @@ static void sync_lang_file(const std::string& langcode)
|
|||
pElem->SetText(langmeta.menu_select.c_str());
|
||||
else if (SDL_strcmp(pKey, "menu_select_tight") == 0)
|
||||
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
|
||||
|
|
|
@ -65,8 +65,7 @@ static void loadmeta(LangMeta& meta, const std::string& langcode = lang)
|
|||
meta.toupper_lower_escape_char = false;
|
||||
meta.menu_select = "[ {label} ]";
|
||||
meta.menu_select_tight = "[{label}]";
|
||||
meta.font_w = 8;
|
||||
meta.font_h = 8;
|
||||
meta.font_idx = font::get_font_idx_8x8();
|
||||
|
||||
tinyxml2::XMLDocument 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);
|
||||
else if (SDL_strcmp(pKey, "menu_select_tight") == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned short max_w_px = max_w * get_langmeta()->font_w;
|
||||
unsigned short max_h_px = max_h * SDL_max(10, get_langmeta()->font_h);
|
||||
uint8_t font_w = 8;
|
||||
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;
|
||||
|
||||
|
|
|
@ -712,8 +712,11 @@ static void menurender(void)
|
|||
);
|
||||
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_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);
|
||||
|
||||
int wraplimit;
|
||||
|
|
|
@ -105,7 +105,7 @@ void textboxclass::resize(void)
|
|||
for (size_t iter = 0; iter < lines.size(); 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
|
||||
|
|
Loading…
Reference in a new issue