/* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * Copyright (C) 2011-2020 - Daniel De Matteis * Copyright (C) 2019-2020 - James Leaver * Copyright (C) 2020-2022 - trngaje * Copyright (C) 2022 - Michael Burgardt * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with RetroArch. * If not, see . */ #include #include #include #include #include #include #include #include #include #include "../../file_path_special.h" #include "bitmapfont_6x10.h" /* MACROS */ /* extended ASCII: Basic Latin + Latin-1 Supplement */ #define FONT_6X10_FILE_ENG "bitmap6x10_eng.bin" #define FONT_6X10_SIZE_ENG 2048 #define FONT_6X10_GLYPH_MIN_ENG 0x0 #define FONT_6X10_GLYPH_MAX_ENG 0xFF /* Latin Supplement Extended: Latin Extended A + B */ #define FONT_6X10_FILE_LSE "bitmap6x10_lse.bin" #define FONT_6X10_SIZE_LSE 2688 #define FONT_6X10_GLYPH_MIN_LSE 0x100 #define FONT_6X10_GLYPH_MAX_LSE 0x24F /* Loads a font of the specified language * Returns NULL if language is invalid or * font file is missing */ bitmapfont_lut_t *bitmapfont_6x10_load(unsigned language) { char font_dir[PATH_MAX_LENGTH]; char font_path[PATH_MAX_LENGTH]; const char *font_file = NULL; void *bitmap_raw = NULL; unsigned char *bitmap_char = NULL; bitmapfont_lut_t *font = NULL; int64_t font_size = 0; int64_t len = 0; size_t glyph_min = 0; size_t glyph_max = 0; size_t num_glyphs = 0; size_t symbol_index; size_t i, j; /* Get font file associated with * specified language */ switch (language) { /* Needed individually for any non-Latin languages */ case RETRO_LANGUAGE_ENGLISH: font_file = FONT_6X10_FILE_ENG; font_size = FONT_6X10_SIZE_ENG; glyph_min = FONT_6X10_GLYPH_MIN_ENG; glyph_max = FONT_6X10_GLYPH_MAX_ENG; break; /* All Latin alphabet languages go here */ case RETRO_LANGUAGE_FRENCH: case RETRO_LANGUAGE_SPANISH: case RETRO_LANGUAGE_GERMAN: case RETRO_LANGUAGE_ITALIAN: case RETRO_LANGUAGE_DUTCH: case RETRO_LANGUAGE_PORTUGUESE_BRAZIL: case RETRO_LANGUAGE_PORTUGUESE_PORTUGAL: case RETRO_LANGUAGE_ESPERANTO: case RETRO_LANGUAGE_POLISH: case RETRO_LANGUAGE_VIETNAMESE: case RETRO_LANGUAGE_TURKISH: case RETRO_LANGUAGE_SLOVAK: case RETRO_LANGUAGE_ASTURIAN: case RETRO_LANGUAGE_FINNISH: case RETRO_LANGUAGE_INDONESIAN: case RETRO_LANGUAGE_SWEDISH: case RETRO_LANGUAGE_CZECH: case RETRO_LANGUAGE_HUNGARIAN: #if 0 /* These languages are not yet added */ case RETRO_LANGUAGE_ROMANIAN: case RETRO_LANGUAGE_CROATIAN: case RETRO_LANGUAGE_SERBIAN: case RETRO_LANGUAGE_WELSH: #endif font_file = FONT_6X10_FILE_LSE; font_size = FONT_6X10_SIZE_LSE; glyph_min = FONT_6X10_GLYPH_MIN_LSE; glyph_max = FONT_6X10_GLYPH_MAX_LSE; break; default: break; } /* Sanity check: should only trigger on bug */ if (string_is_empty(font_file)) goto error; /* Get font path */ fill_pathname_application_special(font_dir, sizeof(font_dir), APPLICATION_SPECIAL_DIRECTORY_ASSETS_RGUI_FONT); fill_pathname_join_special(font_path, font_dir, font_file, sizeof(font_path)); /* Attempt to read bitmap file */ if (!rzipstream_read_file(font_path, &bitmap_raw, &len)) goto error; /* Ensure that we have the correct number * of bytes */ if (len != font_size) goto error; bitmap_char = (unsigned char *)bitmap_raw; num_glyphs = (glyph_max - glyph_min) + 1; /* Initialise font struct */ if (!(font = (bitmapfont_lut_t*)calloc(1, sizeof(bitmapfont_lut_t)))) goto error; font->glyph_min = glyph_min; font->glyph_max = glyph_max; /* Note: Need to use a calloc() here, otherwise * we'll get undefined behaviour when calling * bitmapfont_free_lut() if the following loop fails */ if (!(font->lut = (bool**)calloc(1, num_glyphs * sizeof(bool*)))) goto error; /* Loop over all possible characters */ for (symbol_index = 0; symbol_index < num_glyphs; symbol_index++) { /* Allocate memory for current symbol */ font->lut[symbol_index] = (bool*)malloc(FONT_6X10_WIDTH * FONT_6X10_HEIGHT * sizeof(bool)); if (!font->lut[symbol_index]) goto error; for (j = 0; j < FONT_6X10_HEIGHT; j++) { for (i = 0; i < FONT_6X10_WIDTH; i++) { uint8_t rem = 1 << ((i + j * FONT_6X10_WIDTH) & 7); size_t offset = (i + j * FONT_6X10_WIDTH) >> 3; /* LUT value is 'true' if specified glyph * position contains a pixel */ font->lut[symbol_index][i + (j * FONT_6X10_WIDTH)] = (bitmap_char[FONT_6X10_OFFSET(symbol_index) + offset] & rem) > 0; } } } /* Clean up */ free(bitmap_raw); return font; error: if (bitmap_raw) free(bitmap_raw); if (font) bitmapfont_free_lut(font); return NULL; }