diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 423a56a2b5..ae11c8b0c9 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3899,7 +3899,7 @@ STR_5557 :Stay connected after desynchronisation (Multiplayer) STR_5558 :A restart is required for this setting to take effect STR_5559 :10 min. inspections STR_5560 :{SMALLFONT}{BLACK}Sets the inspection time to 'Every 10 minutes' on all rides -STR_5561 :Failed to load language file +STR_5561 :Failed to load language STR_5562 :WARNING! STR_5563 :This feature is currently unstable, take extra caution. STR_5564 :Insert Corrupt Element @@ -3918,6 +3918,7 @@ STR_5576 :Port: STR_5577 :South Korean Won (W) STR_5578 :Russian Rouble (R) STR_5579 :Window scale factor: +STR_5580 :Czech koruna (Kc) ##################### # Rides/attractions # diff --git a/src/drawing/font.c b/src/drawing/font.c index eaadbd1901..d4b3b08090 100644 --- a/src/drawing/font.c +++ b/src/drawing/font.c @@ -126,3 +126,61 @@ int font_get_line_height_small(int fontSpriteBase) { return font_get_line_height(fontSpriteBase) / 2; } + +bool font_supports_string(const utf8 *text, int fontSize) +{ + const utf8 *src = text; + + uint32 codepoint; + while ((codepoint = utf8_get_next(src, &src)) != 0) { + if (gUseTrueTypeFont) { + bool supported = TTF_GlyphIsProvided(gCurrentTTFFontSet->size[fontSize].font, (uint16)codepoint); + if (!supported) { + return false; + } + } else { + bool supported = false; + switch (codepoint) { + case FORMAT_ENDQUOTES: + case FORMAT_AMINUSCULE: + case FORMAT_UP: + case FORMAT_SYMBOL_i: + case FORMAT_CENT: + case FORMAT_POUND: + case FORMAT_YEN: + case FORMAT_COPYRIGHT: + case FORMAT_DOWN: + case FORMAT_LEFTGUILLEMET: + case FORMAT_TICK: + case FORMAT_CROSS: + case FORMAT_RIGHT: + case FORMAT_DEGREE: + case FORMAT_SYMBOL_RAILWAY: + case FORMAT_SQUARED: + case FORMAT_OPENQUOTES: + case FORMAT_EURO: + case FORMAT_SYMBOL_ROAD: + case FORMAT_SYMBOL_FLAG: + case FORMAT_APPROX: + case FORMAT_POWERNEGATIVEONE: + case FORMAT_BULLET: + case FORMAT_RIGHTGUILLEMET: + case FORMAT_SMALLUP: + case FORMAT_SMALLDOWN: + case FORMAT_LEFT: + case FORMAT_INVERTEDQUESTION: + supported = true; + break; + default: + if (codepoint >= 32 && codepoint < 256) { + supported = true; + } + break; + } + if (!supported) { + return false; + } + } + } + return true; +} diff --git a/src/drawing/font.h b/src/drawing/font.h index 8d6868e12e..9290a0ee6e 100644 --- a/src/drawing/font.h +++ b/src/drawing/font.h @@ -43,5 +43,6 @@ int font_sprite_get_codepoint_sprite(int fontSpriteBase, int codepoint); int font_get_size_from_sprite_base(uint16 spriteBase); int font_get_line_height(int fontSpriteBase); int font_get_line_height_small(int fontSpriteBase); +bool font_supports_string(const utf8 *text, int fontSize); #endif diff --git a/src/drawing/string.c b/src/drawing/string.c index 1472f4ca90..e1416ddf1b 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -881,8 +881,9 @@ static uint32 _ttf_getwidth_cache_get_or_add(TTF_Font *font, const utf8 *text) bool ttf_initialise() { if (!_ttfInitialised) { - if (TTF_Init() != 0) + if (TTF_Init() != 0) { return false; + } for (int i = 0; i < 4; i++) { TTFFontDescriptor *fontDesc = &(gCurrentTTFFontSet->size[i]); @@ -893,6 +894,7 @@ bool ttf_initialise() fontDesc->font = TTF_OpenFont(fontPath, fontDesc->ptSize); if (fontDesc->font == NULL) { log_error("Unable to load '%s'", fontPath); + return false; } } diff --git a/src/localisation/currency.c b/src/localisation/currency.c index 1411e21491..1dbd267e8b 100644 --- a/src/localisation/currency.c +++ b/src/localisation/currency.c @@ -21,17 +21,18 @@ #include "currency.h" #include "string_ids.h" -const rct_currency_spec g_currency_specs[CURRENCY_END] = { - { 10 , "\xC2\xA3" , CURRENCY_PREFIX, STR_POUNDS }, // British Pound - { 10 , "$" , CURRENCY_PREFIX, STR_DOLLARS}, // US Dollar - { 10 , "F" , CURRENCY_SUFFIX, STR_FRANC }, // French Franc - { 10 , "DM" , CURRENCY_PREFIX, STR_DEUTSCHMARK }, // Deutschmark - { 1000 , "\xC2\xA5" , CURRENCY_PREFIX, STR_YEN }, // Japanese Yen - { 10 , "Pts" , CURRENCY_SUFFIX, STR_PESETA }, // Spanish Peseta - { 1000 , "L" , CURRENCY_PREFIX, STR_LIRA }, // Italian Lira - { 10 , "fl. " , CURRENCY_PREFIX, STR_GUILDERS }, // Dutch Guilder - { 10 , "kr." , CURRENCY_SUFFIX, STR_KRONA }, // Swedish Krona - { 10 , "\xE2\x82\xAC" , CURRENCY_PREFIX, STR_EUROS }, // Euro - { 10000 , "W" , CURRENCY_PREFIX, STR_WON }, // South Korean Won - { 1000 , "R " , CURRENCY_PREFIX, STR_ROUBLE }, // Russian Rouble +const currency_descriptor CurrencyDescriptors[CURRENCY_END] = { + { 10 , CURRENCY_PREFIX, "\xC2\xA3" , CURRENCY_SUFFIX, "GBP" , STR_POUNDS }, // British Pound + { 10 , CURRENCY_PREFIX, "$" , CURRENCY_PREFIX, "$" , STR_DOLLARS }, // US Dollar + { 10 , CURRENCY_SUFFIX, "F" , CURRENCY_SUFFIX, "F" , STR_FRANC }, // French Franc + { 10 , CURRENCY_PREFIX, "DM" , CURRENCY_PREFIX, "DM" , STR_DEUTSCHMARK }, // Deutschmark + { 1000 , CURRENCY_PREFIX, "\xC2\xA5" , CURRENCY_SUFFIX, "YEN" , STR_YEN }, // Japanese Yen + { 10 , CURRENCY_SUFFIX, "Pts" , CURRENCY_SUFFIX, "Pts" , STR_PESETA }, // Spanish Peseta + { 1000 , CURRENCY_PREFIX, "L" , CURRENCY_PREFIX, "L" , STR_LIRA }, // Italian Lira + { 10 , CURRENCY_PREFIX, "\xC6\x92" , CURRENCY_PREFIX, "fl." , STR_GUILDERS }, // Dutch Guilder + { 10 , CURRENCY_SUFFIX, "kr." , CURRENCY_SUFFIX, "kr." , STR_KRONA }, // Swedish Krona + { 10 , CURRENCY_PREFIX, "\xE2\x82\xAC" , CURRENCY_SUFFIX, "EUR" , STR_EUROS }, // Euro + { 10000 , CURRENCY_PREFIX, "\xE2\x82\xA9" , CURRENCY_PREFIX, "W" , STR_WON }, // South Korean Won + { 1000 , CURRENCY_PREFIX, "R " , CURRENCY_PREFIX, "R " , STR_ROUBLE }, // Russian Rouble + { 100 , CURRENCY_SUFFIX, " K\xC4\x8D" , CURRENCY_SUFFIX, " Kc" , STR_CZECH_KORUNA }, // Czech koruna }; diff --git a/src/localisation/currency.h b/src/localisation/currency.h index 4cba80c1c6..ffa400828b 100644 --- a/src/localisation/currency.h +++ b/src/localisation/currency.h @@ -37,6 +37,7 @@ typedef enum { CURRENCY_EUROS, // Euro CURRENCY_WON, // South Korean Won CURRENCY_ROUBLE, // Russian Rouble + CURRENCY_CZECH_KORUNA, // Czech koruna CURRENCY_END // Last item } CURRENCY_TYPE; @@ -50,14 +51,16 @@ typedef enum { // Currency format specification - inspired by OpenTTD typedef struct { - // Rate is relative to 0.1 GBP + // Rate is relative to 0.10 GBP int rate; - utf8 symbol[CURRENCY_SYMBOL_MAX_SIZE]; - int affix; - int stringId; -} rct_currency_spec; + uint8 affix_unicode; + utf8 symbol_unicode[CURRENCY_SYMBOL_MAX_SIZE]; + uint8 affix_ascii; + char symbol_ascii[CURRENCY_SYMBOL_MAX_SIZE]; + rct_string_id stringId; +} currency_descriptor; // List of currency formats -extern const rct_currency_spec g_currency_specs[CURRENCY_END]; +extern const currency_descriptor CurrencyDescriptors[CURRENCY_END]; #endif diff --git a/src/localisation/language.cpp b/src/localisation/language.cpp index 5c1bacd1b9..7e22900aa5 100644 --- a/src/localisation/language.cpp +++ b/src/localisation/language.cpp @@ -173,6 +173,11 @@ int language_open(int id) gCurrentTTFFontSet = LanguagesDescriptors[id].font; if (!ttf_initialise()) { log_warning("Unable to initialise TrueType fonts."); + + // Fall back to sprite font + gUseTrueTypeFont = false; + gCurrentTTFFontSet = nullptr; + return 0; } } diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index 7e131093b0..237f22f36c 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -345,9 +345,9 @@ void format_comma_separated_fixed_2dp(char **dest, long long value) void format_currency(char **dest, long long value) { - const rct_currency_spec *currencySpec = &g_currency_specs[gConfigGeneral.currency_format]; + const currency_descriptor *currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format]; - int rate = currencySpec->rate; + int rate = currencyDesc->rate; value *= rate; // Negative sign @@ -363,10 +363,15 @@ void format_currency(char **dest, long long value) } // Currency symbol - const utf8 *symbol = currencySpec->symbol; + const utf8 *symbol = currencyDesc->symbol_unicode; + uint8 affix = currencyDesc->affix_unicode; + if (!font_supports_string(symbol, FONT_SIZE_MEDIUM)) { + symbol = currencyDesc->symbol_ascii; + affix = currencyDesc->affix_ascii; + } // Prefix - if (currencySpec->affix == CURRENCY_PREFIX) { + if (affix == CURRENCY_PREFIX) { safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -374,7 +379,7 @@ void format_currency(char **dest, long long value) format_comma_separated_integer(dest, value); // Currency symbol suffix - if (currencySpec->affix == CURRENCY_SUFFIX) { + if (affix == CURRENCY_SUFFIX) { safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -382,9 +387,9 @@ void format_currency(char **dest, long long value) void format_currency_2dp(char **dest, long long value) { - const rct_currency_spec *currencySpec = &g_currency_specs[gConfigGeneral.currency_format]; + const currency_descriptor *currencyDesc = &CurrencyDescriptors[gConfigGeneral.currency_format]; - int rate = currencySpec->rate; + int rate = currencyDesc->rate; value *= rate; // Negative sign @@ -394,10 +399,15 @@ void format_currency_2dp(char **dest, long long value) } // Currency symbol - const utf8 *symbol = currencySpec->symbol; + const utf8 *symbol = currencyDesc->symbol_unicode; + uint8 affix = currencyDesc->affix_unicode; + if (!font_supports_string(symbol, FONT_SIZE_MEDIUM)) { + symbol = currencyDesc->symbol_ascii; + affix = currencyDesc->affix_ascii; + } // Prefix - if (currencySpec->affix == CURRENCY_PREFIX) { + if (affix == CURRENCY_PREFIX) { safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -410,7 +420,7 @@ void format_currency_2dp(char **dest, long long value) } // Currency symbol suffix - if (currencySpec->affix == CURRENCY_SUFFIX) { + if (affix == CURRENCY_SUFFIX) { safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 5b7ed3167a..bc2bb1b397 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -2174,6 +2174,8 @@ enum { STR_UI_SCALING_DESC = 5579, + STR_CZECH_KORUNA = 5580, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 }; diff --git a/src/openrct2.c b/src/openrct2.c index 31167ee178..b3c97eda7c 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -251,10 +251,13 @@ bool openrct2_initialise() audio_init(); audio_populate_devices(); } - if (!language_open(gConfigGeneral.language)) - { - log_fatal("Failed to open language, exiting."); - return false; + if (!language_open(gConfigGeneral.language)) { + log_error("Failed to open configured language..."); + + if (!language_open(LANGUAGE_ENGLISH_UK)) { + log_fatal("Failed to open fallback language..."); + return false; + } } http_init(); diff --git a/src/windows/options.c b/src/windows/options.c index 6fcb3a819b..14f072530a 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -803,7 +803,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* for (i = 0; i < num_items; i++) { gDropdownItemsFormat[i] = 1142; - gDropdownItemsArgs[i] = g_currency_specs[i].stringId; + gDropdownItemsArgs[i] = CurrencyDescriptors[i].stringId; } window_options_show_dropdown(w, widget, num_items); @@ -1204,7 +1204,7 @@ static void window_options_invalidate(rct_window *w) case WINDOW_OPTIONS_PAGE_CULTURE: // currency: pounds, dollars, etc. (10 total) - RCT2_GLOBAL(0x013CE952 + 12, uint16) = g_currency_specs[gConfigGeneral.currency_format].stringId; + RCT2_GLOBAL(0x013CE952 + 12, uint16) = CurrencyDescriptors[gConfigGeneral.currency_format].stringId; // distance: metric/imperial RCT2_GLOBAL(0x013CE952 + 14, uint16) = STR_IMPERIAL + gConfigGeneral.measurement_format;