(RGUI) Add Russian language support

This commit is contained in:
jdgleaver 2021-01-13 10:00:51 +00:00
parent ba01aa5334
commit 3a6558c2f1
3 changed files with 207 additions and 4 deletions

View File

@ -54,6 +54,11 @@
#define FONT_10X10_GLYPH_MIN_KOR 0xAC00
#define FONT_10X10_GLYPH_MAX_KOR 0xD7A3
#define FONT_10X10_FILE_RUS "bitmap10x10_rus.bin"
#define FONT_10X10_SIZE_RUS 1248
#define FONT_10X10_GLYPH_MIN_RUS 0x400
#define FONT_10X10_GLYPH_MAX_RUS 0x45F
#define FONT_10X10_OFFSET(x) ((x) * ((FONT_10X10_HEIGHT * FONT_10X10_WIDTH + 7) / 8))
/* Loads a font of the specified language
@ -107,6 +112,12 @@ bitmapfont_lut_t *bitmapfont_10x10_load(unsigned language)
glyph_min = FONT_10X10_GLYPH_MIN_KOR;
glyph_max = FONT_10X10_GLYPH_MAX_KOR;
break;
case RETRO_LANGUAGE_RUSSIAN:
font_file = FONT_10X10_FILE_RUS;
font_size = FONT_10X10_SIZE_RUS;
glyph_min = FONT_10X10_GLYPH_MIN_RUS;
glyph_max = FONT_10X10_GLYPH_MAX_RUS;
break;
default:
break;
}

View File

@ -12,10 +12,15 @@
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <compat/strl.h>
#include <string/stdstring.h>
#include "../msg_hash.h"
#include "../verbosity.h"
#if defined(_MSC_VER) && !defined(_XBOX) && (_MSC_VER >= 1500 && _MSC_VER < 1900)
#if (_MSC_VER >= 1700)
@ -40,12 +45,51 @@ int msg_hash_get_help_ru_enum(enum msg_hash_enums msg, char *s, size_t len)
return ret;
}
const char *msg_hash_to_str_ru(enum msg_hash_enums msg)
#ifdef HAVE_MENU
static const char *menu_hash_to_str_ru_label_enum(enum msg_hash_enums msg)
{
if (msg <= MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_END &&
msg >= MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN)
{
static char hotkey_lbl[128] = {0};
unsigned idx = msg - MENU_ENUM_LABEL_INPUT_HOTKEY_BIND_BEGIN;
snprintf(hotkey_lbl, sizeof(hotkey_lbl), "input_hotkey_binds_%d", idx);
return hotkey_lbl;
}
switch (msg)
{
#include "msg_hash_ru.h"
#include "msg_hash_lbl.h"
default:
#if 0
RARCH_LOG("Unimplemented: [%d]\n", msg);
#endif
break;
}
return "null";
}
#endif
const char *msg_hash_to_str_ru(enum msg_hash_enums msg)
{
#ifdef HAVE_MENU
const char *ret = menu_hash_to_str_ru_label_enum(msg);
if (ret && !string_is_equal(ret, "null"))
return ret;
#endif
switch (msg)
{
#include "msg_hash_ru.h"
default:
#if 0
RARCH_LOG("Unimplemented: [%d]\n", msg);
{
RARCH_LOG("[%d] : %s\n", msg - 1, msg_hash_to_str(((enum msg_hash_enums)(msg - 1))));
}
#endif
break;
}

View File

@ -602,6 +602,7 @@ typedef struct
bitmapfont_lut_t *chn_10x10;
bitmapfont_lut_t *jpn_10x10;
bitmapfont_lut_t *kor_10x10;
bitmapfont_lut_t *rus_10x10;
} fonts;
frame_buf_t frame_buf;
@ -1148,6 +1149,12 @@ static void rgui_fonts_free(rgui_t *rgui)
bitmapfont_free_lut(rgui->fonts.kor_10x10);
rgui->fonts.kor_10x10 = NULL;
}
if (rgui->fonts.rus_10x10)
{
bitmapfont_free_lut(rgui->fonts.rus_10x10);
rgui->fonts.rus_10x10 = NULL;
}
}
static bool rgui_fonts_init(rgui_t *rgui)
@ -1212,6 +1219,26 @@ static bool rgui_fonts_init(rgui_t *rgui)
rgui->language = language;
break;
case RETRO_LANGUAGE_RUSSIAN:
rgui->fonts.eng_10x10 = bitmapfont_10x10_load(RETRO_LANGUAGE_ENGLISH);
rgui->fonts.rus_10x10 = bitmapfont_10x10_load(RETRO_LANGUAGE_RUSSIAN);
if (!rgui->fonts.eng_10x10 ||
!rgui->fonts.rus_10x10)
{
rgui_fonts_free(rgui);
*msg_hash_get_uint(MSG_HASH_USER_LANGUAGE) = RETRO_LANGUAGE_ENGLISH;
runloop_msg_queue_push(
msg_hash_to_str(MSG_RGUI_MISSING_FONTS), 1, 256, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
goto english;
}
rgui->font_width = FONT_10X10_WIDTH;
rgui->font_height = FONT_10X10_HEIGHT;
rgui->font_width_stride = FONT_10X10_WIDTH_STRIDE;
rgui->font_height_stride = FONT_10X10_HEIGHT_STRIDE;
rgui->language = language;
break;
case RETRO_LANGUAGE_ARABIC:
case RETRO_LANGUAGE_GREEK:
case RETRO_LANGUAGE_PERSIAN:
@ -2975,7 +3002,7 @@ static void blit_line_cjk_shadow(
unsigned fb_width, int x, int y,
const char *message, uint16_t color, uint16_t shadow_color)
{
uint16_t *frame_buf_data = rgui->frame_buf.data;
uint16_t *frame_buf_data = rgui->frame_buf.data;
bitmapfont_lut_t *font_eng = rgui->fonts.eng_10x10;
bitmapfont_lut_t *font_chn = rgui->fonts.chn_10x10;
bitmapfont_lut_t *font_jpn = rgui->fonts.jpn_10x10;
@ -3041,6 +3068,121 @@ static void blit_line_cjk_shadow(
x += FONT_10X10_WIDTH_STRIDE;
}
}
static void blit_line_rus(
rgui_t *rgui,
unsigned fb_width, int x, int y,
const char *message, uint16_t color, uint16_t shadow_color)
{
uint16_t *frame_buf_data = rgui->frame_buf.data;
bitmapfont_lut_t *font_eng = rgui->fonts.eng_10x10;
bitmapfont_lut_t *font_rus = rgui->fonts.rus_10x10;
while (!string_is_empty(message))
{
/* Deal with spaces first, for efficiency */
if (*message == ' ')
message++;
else
{
unsigned i, j;
bool *symbol_lut;
uint32_t symbol = utf8_walk(&message);
if (symbol == 339) /* Latin small ligature oe */
symbol = 156;
if (symbol == 338) /* Latin capital ligature oe */
symbol = 140;
/* Find glyph LUT data */
if (symbol <= font_eng->glyph_max)
symbol_lut = font_eng->lut[symbol];
else if ((symbol >= font_rus->glyph_min) && (symbol <= font_rus->glyph_max))
symbol_lut = font_rus->lut[symbol - font_rus->glyph_min];
else
continue;
for (j = 0; j < FONT_10X10_HEIGHT; j++)
{
unsigned buff_offset = ((y + j) * fb_width) + x;
for (i = 0; i < FONT_10X10_WIDTH; i++)
{
if (*(symbol_lut + i + (j * FONT_10X10_WIDTH)))
*(frame_buf_data + buff_offset + i) = color;
}
}
}
x += FONT_10X10_WIDTH_STRIDE;
}
}
static void blit_line_rus_shadow(
rgui_t *rgui,
unsigned fb_width, int x, int y,
const char *message, uint16_t color, uint16_t shadow_color)
{
uint16_t *frame_buf_data = rgui->frame_buf.data;
bitmapfont_lut_t *font_eng = rgui->fonts.eng_10x10;
bitmapfont_lut_t *font_rus = rgui->fonts.rus_10x10;
uint16_t color_buf[2];
uint16_t shadow_color_buf[2];
color_buf[0] = color;
color_buf[1] = shadow_color;
shadow_color_buf[0] = shadow_color;
shadow_color_buf[1] = shadow_color;
while (!string_is_empty(message))
{
/* Deal with spaces first, for efficiency */
if (*message == ' ')
message++;
else
{
unsigned i, j;
bool *symbol_lut;
uint32_t symbol = utf8_walk(&message);
if (symbol == 339) /* Latin small ligature oe */
symbol = 156;
if (symbol == 338) /* Latin capital ligature oe */
symbol = 140;
/* Find glyph LUT data */
if (symbol <= font_eng->glyph_max)
symbol_lut = font_eng->lut[symbol];
else if ((symbol >= font_rus->glyph_min) && (symbol <= font_rus->glyph_max))
symbol_lut = font_rus->lut[symbol - font_rus->glyph_min];
else
continue;
for (j = 0; j < FONT_10X10_HEIGHT; j++)
{
unsigned buff_offset = ((y + j) * fb_width) + x;
for (i = 0; i < FONT_10X10_WIDTH; i++)
{
if (*(symbol_lut + i + (j * FONT_10X10_WIDTH)))
{
uint16_t *frame_buf_ptr = frame_buf_data + buff_offset + i;
/* Text pixel + right shadow */
memcpy(frame_buf_ptr, color_buf, sizeof(color_buf));
/* Bottom shadow */
frame_buf_ptr += fb_width;
memcpy(frame_buf_ptr, shadow_color_buf, sizeof(shadow_color_buf));
}
}
}
}
x += FONT_10X10_WIDTH_STRIDE;
}
}
#endif
static void (*blit_line)(rgui_t *rgui, unsigned fb_width, int x, int y,
@ -3175,6 +3317,9 @@ static void rgui_set_blit_functions(unsigned language,
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
blit_line = blit_line_cjk_shadow;
break;
case RETRO_LANGUAGE_RUSSIAN:
blit_line = blit_line_rus_shadow;
break;
default:
if (extended_ascii)
blit_line = blit_line_extended_shadow;
@ -3202,6 +3347,9 @@ static void rgui_set_blit_functions(unsigned language,
case RETRO_LANGUAGE_CHINESE_TRADITIONAL:
blit_line = blit_line_cjk;
break;
case RETRO_LANGUAGE_RUSSIAN:
blit_line = blit_line_rus;
break;
default:
if (extended_ascii)
blit_line = blit_line_extended;