RetroArch/gfx/font_driver.c

1239 lines
32 KiB
C
Raw Normal View History

2012-04-21 21:13:50 +00:00
/* RetroArch - A frontend for libretro.
2014-01-01 00:50:59 +00:00
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
2017-01-22 12:40:32 +00:00
* Copyright (C) 2011-2017 - Daniel De Matteis
*
2012-04-21 21:13:50 +00:00
* RetroArch is free software: you can redistribute it and/or modify it under the terms
2012-02-12 14:23:35 +00:00
* 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.
*
2012-04-21 21:13:50 +00:00
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
2012-02-12 14:23:35 +00:00
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
2012-04-21 21:31:57 +00:00
* You should have received a copy of the GNU General Public License along with RetroArch.
2012-02-12 14:23:35 +00:00
* If not, see <http://www.gnu.org/licenses/>.
*/
2018-01-04 13:42:13 +00:00
#include <stdlib.h>
#include <math.h>
2016-09-06 21:47:05 +00:00
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
2018-01-04 13:42:13 +00:00
#include "font_driver.h"
#include "video_thread_wrapper.h"
#include "../retroarch.h"
2018-01-04 13:42:13 +00:00
#include "../verbosity.h"
static const font_renderer_driver_t *font_backends[] = {
#ifdef HAVE_FREETYPE
&freetype_font_renderer,
#endif
#if defined(__APPLE__) && defined(HAVE_CORETEXT)
&coretext_font_renderer,
#endif
#ifdef HAVE_STB_FONT
#if defined(VITA) || defined(WIIU) || defined(ANDROID) || (defined(_WIN32) && !defined(_XBOX) && !defined(_MSC_VER) && _MSC_VER >= 1400) || (defined(_WIN32) && !defined(_XBOX) && defined(_MSC_VER)) || defined(__CELLOS_LV2__) || defined(HAVE_LIBNX) || defined(__linux__) || defined (HAVE_EMSCRIPTEN) || defined(__APPLE__) || defined(HAVE_ODROIDGO2)
2016-11-05 15:20:18 +00:00
&stb_unicode_font_renderer,
#else
&stb_font_renderer,
2016-11-05 15:20:18 +00:00
#endif
#endif
&bitmap_font_renderer,
NULL
};
2020-05-29 04:20:16 +00:00
/* TODO/FIXME - global */
static void *video_font_driver = NULL;
2018-07-13 22:54:14 +00:00
int font_renderer_create_default(
const font_renderer_driver_t **drv,
void **handle,
const char *font_path, unsigned font_size)
{
unsigned i;
for (i = 0; font_backends[i]; i++)
{
const char *path = font_path;
if (!path)
path = font_backends[i]->get_default_font();
if (!path)
continue;
*handle = font_backends[i]->init(path, font_size);
if (*handle)
{
2017-04-23 09:56:46 +00:00
RARCH_LOG("[Font]: Using font rendering backend: %s.\n",
font_backends[i]->ident);
*drv = font_backends[i];
return 1;
}
2020-08-14 04:45:36 +00:00
RARCH_ERR("[Font]: Failed to create rendering backend: %s.\n",
font_backends[i]->ident);
}
2018-07-13 22:54:14 +00:00
*drv = NULL;
*handle = NULL;
return 0;
}
2012-02-12 14:23:35 +00:00
#ifdef HAVE_D3D8
static const font_renderer_t *d3d8_font_backends[] = {
#if defined(_XBOX1)
&d3d_xdk1_font,
#endif
NULL
};
static bool d3d8_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(d3d8_font_backends); i++)
{
void *data = d3d8_font_backends[i] ? d3d8_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded) : NULL;
if (!data)
continue;
*font_driver = d3d8_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
#ifdef HAVE_D3D9
static const font_renderer_t *d3d9_font_backends[] = {
2019-10-19 14:42:39 +00:00
#if defined(_WIN32) && defined(HAVE_D3DX)
&d3d_win32_font,
2012-12-15 02:35:04 +00:00
#endif
2017-09-04 23:03:55 +00:00
NULL
2012-12-15 02:35:04 +00:00
};
static bool d3d9_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
2012-12-15 02:35:04 +00:00
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(d3d9_font_backends); i++)
2012-12-15 02:35:04 +00:00
{
void *data = d3d9_font_backends[i] ? d3d9_font_backends[i]->init(
video_data, font_path, font_size,
2018-01-04 13:42:13 +00:00
is_threaded) : NULL;
if (!data)
continue;
*font_driver = d3d9_font_backends[i];
*font_handle = data;
return true;
2012-12-15 02:35:04 +00:00
}
return false;
2012-12-15 02:35:04 +00:00
}
#endif
2019-04-22 21:30:24 +00:00
#ifdef HAVE_OPENGL1
static const font_renderer_t *gl1_font_backends[] = {
&gl1_raster_font,
NULL,
};
2019-04-22 21:30:24 +00:00
static bool gl1_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
2019-04-22 21:30:24 +00:00
for (i = 0; gl1_font_backends[i]; i++)
{
2019-04-22 21:30:24 +00:00
void *data = gl1_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
2019-04-22 21:30:24 +00:00
*font_driver = gl1_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
2019-04-22 21:30:24 +00:00
#endif
2019-04-22 21:30:24 +00:00
#if defined(HAVE_OPENGL)
static const font_renderer_t *gl_font_backends[] = {
&gl_raster_font,
NULL,
};
2019-04-22 21:30:24 +00:00
static bool gl_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
2019-04-22 21:30:24 +00:00
for (i = 0; gl_font_backends[i]; i++)
{
2019-04-22 21:30:24 +00:00
void *data = gl_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
2019-04-22 21:30:24 +00:00
*font_driver = gl_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
#ifdef HAVE_OPENGL_CORE
static const font_renderer_t *gl_core_font_backends[] = {
&gl_core_raster_font,
NULL,
};
static bool gl_core_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; gl_core_font_backends[i]; i++)
{
void *data = gl_core_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = gl_core_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2016-12-01 17:13:36 +00:00
#ifdef HAVE_CACA
static const font_renderer_t *caca_font_backends[] = {
&caca_font,
NULL,
};
static bool caca_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
2016-12-01 17:13:36 +00:00
{
unsigned i;
for (i = 0; caca_font_backends[i]; i++)
{
void *data = caca_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
2016-12-01 17:13:36 +00:00
if (!data)
continue;
*font_driver = caca_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2018-07-12 20:55:08 +00:00
#ifdef HAVE_SIXEL
static const font_renderer_t *sixel_font_backends[] = {
&sixel_font,
NULL,
};
static bool sixel_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; sixel_font_backends[i]; i++)
{
void *data = sixel_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = sixel_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2017-01-21 22:41:20 +00:00
#ifdef DJGPP
static const font_renderer_t *vga_font_backends[] = {
&vga_font,
NULL,
};
static bool vga_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
2017-01-21 22:41:20 +00:00
{
unsigned i;
for (i = 0; vga_font_backends[i]; i++)
{
void *data = vga_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
2017-01-21 22:41:20 +00:00
if (!data)
continue;
*font_driver = vga_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2019-07-11 11:18:38 +00:00
#ifdef HAVE_GDI
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
2017-01-04 07:07:19 +00:00
static const font_renderer_t *gdi_font_backends[] = {
&gdi_font,
NULL,
};
static bool gdi_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
2017-01-04 07:07:19 +00:00
{
unsigned i;
for (i = 0; gdi_font_backends[i]; i++)
{
void *data = gdi_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
2017-01-04 07:07:19 +00:00
if (!data)
continue;
*font_driver = gdi_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2019-07-11 11:18:38 +00:00
#endif
2017-01-04 07:07:19 +00:00
2016-02-16 19:24:00 +00:00
#ifdef HAVE_VULKAN
static const font_renderer_t *vulkan_font_backends[] = {
&vulkan_raster_font,
NULL,
};
static bool vulkan_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
2016-02-16 19:24:00 +00:00
{
unsigned i;
for (i = 0; vulkan_font_backends[i]; i++)
{
void *data = vulkan_font_backends[i]->init(video_data,
font_path, font_size,
is_threaded);
2016-02-16 19:24:00 +00:00
if (!data)
continue;
*font_driver = vulkan_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
#ifdef HAVE_METAL
static const font_renderer_t *metal_font_backends[] = {
&metal_raster_font,
NULL,
};
static bool metal_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; metal_font_backends[i]; i++)
{
void *data = metal_font_backends[i]->init(video_data,
font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = metal_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2018-04-21 01:27:41 +00:00
#ifdef HAVE_D3D10
static const font_renderer_t *d3d10_font_backends[] = {
&d3d10_font,
NULL,
};
static bool d3d10_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; d3d10_font_backends[i]; i++)
{
void *data = d3d10_font_backends[i]->init(video_data,
font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = d3d10_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2018-01-24 19:51:19 +00:00
#ifdef HAVE_D3D11
static const font_renderer_t *d3d11_font_backends[] = {
&d3d11_font,
NULL,
};
static bool d3d11_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; d3d11_font_backends[i]; i++)
{
void *data = d3d11_font_backends[i]->init(video_data,
font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = d3d11_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2018-02-07 20:59:18 +00:00
#ifdef HAVE_D3D12
static const font_renderer_t *d3d12_font_backends[] = {
&d3d12_font,
NULL,
};
static bool d3d12_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; d3d12_font_backends[i]; i++)
{
void *data = d3d12_font_backends[i]->init(video_data,
font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = d3d12_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2019-01-07 20:49:55 +00:00
#ifdef PS2
static const font_renderer_t *ps2_font_backends[] = {
&ps2_font
};
static bool ps2_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; ps2_font_backends[i]; i++)
{
void *data = ps2_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = ps2_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2015-10-01 22:11:54 +00:00
#ifdef HAVE_VITA2D
static const font_renderer_t *vita2d_font_backends[] = {
&vita2d_vita_font
};
static bool vita2d_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
2015-10-01 22:11:54 +00:00
{
unsigned i;
for (i = 0; vita2d_font_backends[i]; i++)
{
2016-02-06 20:51:37 +00:00
void *data = vita2d_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
2015-10-01 22:11:54 +00:00
if (!data)
continue;
*font_driver = vita2d_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
#ifdef _3DS
static const font_renderer_t *ctr_font_backends[] = {
&ctr_font
};
static bool ctr_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; ctr_font_backends[i]; i++)
{
void *data = ctr_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = ctr_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2019-02-03 23:49:35 +00:00
#ifdef HAVE_LIBNX
2018-09-26 23:18:07 +00:00
static const font_renderer_t *switch_font_backends[] = {
&switch_font,
NULL
};
static bool switch_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; switch_font_backends[i]; i++)
{
void *data = switch_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = switch_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2017-05-21 02:05:41 +00:00
#ifdef WIIU
static const font_renderer_t *wiiu_font_backends[] = {
&wiiu_font,
NULL
};
static bool wiiu_font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path,
float font_size, bool is_threaded)
{
unsigned i;
for (i = 0; wiiu_font_backends[i]; i++)
{
void *data = wiiu_font_backends[i]->init(
video_data, font_path, font_size,
is_threaded);
if (!data)
continue;
*font_driver = wiiu_font_backends[i];
*font_handle = data;
return true;
}
return false;
}
#endif
2016-02-06 20:51:37 +00:00
static bool font_init_first(
const void **font_driver, void **font_handle,
void *video_data, const char *font_path, float font_size,
enum font_driver_render_api api, bool is_threaded)
{
if (font_path && !font_path[0])
font_path = NULL;
switch (api)
{
#ifdef HAVE_OPENGL1
case FONT_DRIVER_RENDER_OPENGL1_API:
return gl1_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
2015-10-01 22:11:54 +00:00
#endif
2019-04-22 21:30:24 +00:00
#ifdef HAVE_OPENGL
case FONT_DRIVER_RENDER_OPENGL_API:
return gl_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
#ifdef HAVE_OPENGL_CORE
case FONT_DRIVER_RENDER_OPENGL_CORE_API:
return gl_core_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2016-02-16 19:24:00 +00:00
#ifdef HAVE_VULKAN
case FONT_DRIVER_RENDER_VULKAN_API:
return vulkan_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
2016-02-16 19:24:00 +00:00
#endif
#ifdef HAVE_METAL
case FONT_DRIVER_RENDER_METAL_API:
return metal_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
#ifdef HAVE_D3D8
case FONT_DRIVER_RENDER_D3D8_API:
return d3d8_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
#ifdef HAVE_D3D9
case FONT_DRIVER_RENDER_D3D9_API:
return d3d9_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2018-04-21 01:27:41 +00:00
#ifdef HAVE_D3D10
case FONT_DRIVER_RENDER_D3D10_API:
return d3d10_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2018-01-24 19:51:19 +00:00
#ifdef HAVE_D3D11
case FONT_DRIVER_RENDER_D3D11_API:
return d3d11_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2018-02-07 20:59:18 +00:00
#ifdef HAVE_D3D12
case FONT_DRIVER_RENDER_D3D12_API:
return d3d12_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2015-10-01 22:11:54 +00:00
#ifdef HAVE_VITA2D
case FONT_DRIVER_RENDER_VITA2D:
return vita2d_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2019-01-07 20:49:55 +00:00
#ifdef PS2
case FONT_DRIVER_RENDER_PS2:
return ps2_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
#ifdef _3DS
case FONT_DRIVER_RENDER_CTR:
return ctr_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
2016-12-01 17:13:36 +00:00
#endif
2017-05-21 02:05:41 +00:00
#ifdef WIIU
case FONT_DRIVER_RENDER_WIIU:
return wiiu_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2016-12-01 17:13:36 +00:00
#ifdef HAVE_CACA
case FONT_DRIVER_RENDER_CACA:
return caca_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
2017-01-04 07:07:19 +00:00
#endif
2018-07-12 20:55:08 +00:00
#ifdef HAVE_SIXEL
case FONT_DRIVER_RENDER_SIXEL:
return sixel_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2018-09-26 23:18:07 +00:00
#ifdef HAVE_LIBNX
case FONT_DRIVER_RENDER_SWITCH:
return switch_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
2019-07-11 11:18:38 +00:00
#ifdef HAVE_GDI
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
2017-01-04 07:07:19 +00:00
case FONT_DRIVER_RENDER_GDI:
return gdi_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
2017-01-21 22:41:20 +00:00
#endif
2019-07-11 11:18:38 +00:00
#endif
2017-01-21 22:41:20 +00:00
#ifdef DJGPP
case FONT_DRIVER_RENDER_VGA:
return vga_font_init_first(font_driver, font_handle,
video_data, font_path, font_size, is_threaded);
#endif
case FONT_DRIVER_RENDER_DONT_CARE:
/* TODO/FIXME - lookup graphics driver's 'API' */
break;
default:
break;
}
return false;
}
2018-02-05 19:54:55 +00:00
#ifdef HAVE_LANGEXTRA
/* ACII: 0xxxxxxx (c & 0x80) == 0x00
* other start: 11xxxxxx (c & 0xC0) == 0xC0
* other cont: 10xxxxxx (c & 0xC0) == 0x80
* Neutral :
* 0020 - 002F : 001xxxxx (c & 0xE0) == 0x20
* Arabic:
* 0600 - 07FF : 11011xxx (c & 0xF8) == 0xD8 (2 bytes)
* 0800 - 08FF : 11100000 101000xx c == 0xE0 && (c1 & 0xAC) == 0xA0 (3 bytes) */
/* clang-format off */
#define IS_ASCII(p) ((*(p)&0x80) == 0x00)
#define IS_MBSTART(p) ((*(p)&0xC0) == 0xC0)
#define IS_MBCONT(p) ((*(p)&0xC0) == 0x80)
#define IS_DIR_NEUTRAL(p) ((*(p)&0xE0) == 0x20)
#define IS_ARABIC0(p) ((*(p)&0xF8) == 0xD8)
#define IS_ARABIC1(p) ((*(p) == 0xE0) && ((*((p) + 1) & 0xAC) == 0xA0))
#define IS_ARABIC(p) (IS_ARABIC0(p) || IS_ARABIC1(p))
#define IS_RTL(p) IS_ARABIC(p)
/* 0x0620 to 0x064F */
static const unsigned arabic_shape_map[0x50 - 0x20][0x4] = {
{ 0 }, /* 0x0620 */
{ 0xFE80 },
{ 0xFE81, 0xFE82 },
{ 0xFE83, 0xFE84 },
{ 0xFE85, 0xFE86 },
{ 0xFE87, 0xFE88 },
{ 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C },
{ 0xFE8D, 0xFE8E },
{ 0xFE8F, 0xFE90, 0xFE91, 0xFE92 },
{ 0xFE93, 0xFE94 },
{ 0xFE95, 0xFE96, 0xFE97, 0xFE98 },
{ 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C },
{ 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0 },
{ 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4 },
{ 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8 },
{ 0xFEA9, 0xFEAA },
{ 0xFEAB, 0xFEAC }, /* 0x0630 */
{ 0xFEAD, 0xFEAE },
{ 0xFEAF, 0xFEB0 },
{ 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4 },
{ 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8 },
{ 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC },
{ 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0 },
{ 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4 },
{ 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8 },
{ 0xFEC9, 0xFECA, 0xFECB, 0xFECC },
{ 0xFECD, 0xFECE, 0xFECF, 0xFED0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0xFED1, 0xFED2, 0xFED3, 0xFED4 }, /* 0x0640 */
{ 0xFED5, 0xFED6, 0xFED7, 0xFED8 },
{ 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC },
{ 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0 },
{ 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4 },
{ 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8 },
{ 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC },
{ 0xFEED, 0xFEEE },
{ 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9 },
{ 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4 },
};
/* clang-format on */
static INLINE unsigned font_get_replacement(const char* src, const char* start)
{
if ((*src & 0xFC) == 0xD8) /* 0x0600 to 0x06FF */
{
2018-02-11 15:42:53 +00:00
unsigned result = 0;
2018-02-05 19:54:55 +00:00
bool prev_connected = false;
bool next_connected = false;
unsigned char id = ((unsigned char)src[0] << 6) | ((unsigned char)src[1] & 0x3F);
2018-02-05 19:54:55 +00:00
const char* prev1 = src - 2;
const char* prev2 = src - 4;
if (id < 0x21 || id > 0x4A)
return 0;
2018-02-11 15:42:53 +00:00
if (prev2 < start)
2018-02-05 19:54:55 +00:00
{
prev2 = NULL;
2018-02-11 15:42:53 +00:00
if (prev1 < start)
2018-02-05 19:54:55 +00:00
prev1 = NULL;
}
if (prev1 && (*prev1 & 0xFC) == 0xD8)
{
unsigned char prev1_id = 0;
if (prev1)
prev1_id = ((unsigned char)prev1[0] << 6) | ((unsigned char)prev1[1] & 0x3F);
2018-02-05 19:54:55 +00:00
if (prev1_id == 0x44)
{
unsigned char prev2_id = 0;
if (prev2)
prev2_id = (prev2[0] << 6) | (prev2[1] & 0x3F);
if (prev2_id > 0x20 || prev2_id < 0x50)
prev_connected = !!arabic_shape_map[prev2_id - 0x20][2];
switch (id)
{
case 0x22:
return 0xFEF5 + prev_connected;
case 0x23:
return 0xFEF7 + prev_connected;
case 0x25:
return 0xFEF9 + prev_connected;
case 0x27:
return 0xFEFB + prev_connected;
}
}
if (prev1_id > 0x20 || prev1_id < 0x50)
prev_connected = !!arabic_shape_map[prev1_id - 0x20][2];
}
if ((src[2] & 0xFC) == 0xD8)
{
unsigned char next_id = ((unsigned char)src[2] << 6) | ((unsigned char)src[3] & 0x3F);
2018-02-05 19:54:55 +00:00
if (next_id > 0x20 || next_id < 0x50)
next_connected = true;
}
result = arabic_shape_map[id - 0x20][prev_connected | (next_connected << 1)];
if (result)
return result;
return arabic_shape_map[id - 0x20][prev_connected];
}
return 0;
}
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
static char* font_driver_reshape_msg(const char* msg, unsigned char *buffer, size_t buffer_size)
2018-02-05 19:54:55 +00:00
{
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
unsigned char* dst_buffer = buffer;
const unsigned char* src = (const unsigned char*)msg;
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
unsigned char* dst;
bool reverse = false;
size_t msg_size = (strlen(msg) * 2) + 1;
2018-02-05 19:54:55 +00:00
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
/* fallback to heap allocated buffer if the buffer is too small */
/* worst case transformations are 2 bytes to 4 bytes -- aliaspider */
if (buffer_size < msg_size)
dst_buffer = (unsigned char*)malloc(msg_size);
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
dst = (unsigned char*)dst_buffer;
2018-02-05 19:54:55 +00:00
while (*src || reverse)
{
if (reverse)
{
src--;
while (IS_MBCONT(src))
{
2018-02-05 19:54:55 +00:00
src--;
if (src == (const unsigned char*)msg)
goto end;
}
2018-02-05 19:54:55 +00:00
if (IS_RTL(src) || IS_DIR_NEUTRAL(src))
{
unsigned replacement = font_get_replacement((const char*)src, msg);
2018-02-05 19:54:55 +00:00
if (replacement)
{
if (replacement < 0x80)
*dst++ = replacement;
else if (replacement < 0x8000)
{
*dst++ = 0xC0 | (replacement >> 6);
*dst++ = 0x80 | (replacement & 0x3F);
}
else if (replacement < 0x10000)
{
/* merged glyphs */
if ((replacement >= 0xFEF5) && (replacement <= 0xFEFC))
src -= 2;
*dst++ = 0xE0 | (replacement >> 12);
*dst++ = 0x80 | ((replacement >> 6) & 0x3F);
*dst++ = 0x80 | (replacement & 0x3F);
}
else
{
*dst++ = 0xF0 | (replacement >> 18);
*dst++ = 0x80 | ((replacement >> 12) & 0x3F);
*dst++ = 0x80 | ((replacement >> 6) & 0x3F);
*dst++ = 0x80 | (replacement & 0x3F);
}
continue;
}
*dst++ = *src++;
while (IS_MBCONT(src))
*dst++ = *src++;
src--;
while (IS_MBCONT(src))
src--;
}
else
{
reverse = false;
src++;
while (IS_MBCONT(src) || IS_RTL(src) || IS_DIR_NEUTRAL(src))
src++;
}
}
else
{
if (IS_RTL(src))
{
reverse = true;
while (IS_MBCONT(src) || IS_RTL(src) || IS_DIR_NEUTRAL(src))
src++;
}
else
*dst++ = *src++;
}
}
end:
2018-02-05 19:54:55 +00:00
*dst = '\0';
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
return (char*)dst_buffer;
2018-02-05 19:54:55 +00:00
}
#endif
void font_driver_render_msg(
void *data,
const char *msg,
const void *_params,
void *font_data)
{
const struct font_params *params = (const struct font_params*)_params;
font_data_t *font = (font_data_t*)(font_data
? font_data : video_font_driver);
2018-02-05 19:54:55 +00:00
if (msg && *msg && font && font->renderer && font->renderer->render_msg)
2018-02-05 19:54:55 +00:00
{
#ifdef HAVE_LANGEXTRA
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
unsigned char tmp_buffer[64];
char *new_msg = font_driver_reshape_msg(msg, tmp_buffer, sizeof(tmp_buffer));
2018-02-05 19:54:55 +00:00
#else
2018-05-12 17:03:39 +00:00
char *new_msg = (char*)msg;
#endif
2020-03-09 20:34:14 +00:00
font->renderer->render_msg(data,
font->renderer_data, new_msg, params);
#ifdef HAVE_LANGEXTRA
Implements small buffer optimization in font_driver_reshape_msg() Use a stack-allocated 64 bytes long buffer to avoid so many temp heap allocations when the menu is up. This size is more than enough store 75% of the return values from msg_hash_to_str and 50% of the returned values from msg_hash_get_help of any currently supported language (includes fallback to English). String size per type: count mean std ... 50% 75% max type ... msg_hash_get_help 83885.0 95.295476 106.331779 ... 54.0 103.0 842.0 msg_hash_to_str 83903.0 27.737959 33.389184 ... 19.0 31.0 440.0 string size per type and language: count mean std ... 50% 75% max type language ... msg_hash_get_help 0 4415.0 89.922310 96.873902 ... 55.0 101.0 590.0 1 4415.0 97.555606 118.031412 ... 55.0 101.0 842.0 2 4415.0 118.459570 127.811760 ... 75.0 131.0 774.0 3 4415.0 111.978256 112.702991 ... 68.0 125.0 651.0 4 4415.0 106.040544 111.360658 ... 62.0 124.0 776.0 5 4415.0 100.129105 114.437432 ... 62.0 103.0 688.0 6 4415.0 32.987769 31.047851 ... 28.0 28.0 595.0 7 4415.0 109.366025 124.717259 ... 71.0 121.0 720.0 8 4415.0 98.023783 105.149942 ... 62.0 105.0 610.0 9 4415.0 93.834428 104.433820 ... 55.0 101.0 637.0 10 4415.0 93.657984 96.884429 ... 55.0 101.0 594.0 11 4415.0 93.452775 104.040553 ... 48.0 100.0 583.0 12 4415.0 89.729558 104.062959 ... 50.0 100.0 550.0 13 4415.0 91.462514 95.968107 ... 55.0 101.0 590.0 14 4415.0 92.062741 97.959207 ... 55.0 101.0 611.0 15 4415.0 92.597055 97.190835 ... 56.0 101.0 600.0 16 4415.0 92.088109 98.110738 ... 55.0 101.0 608.0 17 4415.0 102.483126 106.379639 ... 65.0 110.0 652.0 18 4415.0 104.782786 114.025678 ... 65.0 112.0 646.0 msg_hash_to_str 0 4415.0 24.591619 29.148312 ... 18.0 28.0 346.0 1 4416.0 31.247736 36.302532 ... 21.0 36.0 352.0 2 4416.0 31.853714 39.332395 ... 21.0 36.0 418.0 3 4416.0 28.270833 33.300996 ... 21.0 32.0 429.0 4 4416.0 27.139040 31.905206 ... 19.0 31.0 346.0 5 4416.0 27.380435 32.314188 ... 19.0 31.0 346.0 6 4416.0 25.028080 29.188490 ... 19.0 28.0 346.0 7 4416.0 29.660553 35.283592 ... 21.0 33.0 393.0 8 4416.0 27.685915 32.707466 ... 20.0 31.0 346.0 9 4416.0 34.786685 43.587766 ... 21.0 39.0 414.0 10 4416.0 28.769928 34.428596 ... 20.0 32.0 440.0 11 4416.0 24.407609 28.690934 ... 18.0 27.0 346.0 12 4416.0 23.970788 27.075638 ... 18.0 28.0 346.0 13 4416.0 24.587636 29.146213 ... 18.0 28.0 346.0 14 4416.0 27.642889 33.300451 ... 20.0 31.0 346.0 15 4416.0 25.036005 29.159115 ... 18.0 28.0 346.0 16 4416.0 24.732111 29.134002 ... 18.0 28.0 346.0 17 4416.0 32.068161 38.807095 ... 21.0 36.0 407.0 18 4416.0 28.160779 34.013300 ... 20.0 31.0 432.0
2020-05-23 22:15:32 +00:00
if (new_msg != (char*)tmp_buffer)
free(new_msg);
2018-02-05 19:54:55 +00:00
#endif
}
}
2015-12-05 10:34:56 +00:00
void font_driver_bind_block(void *font_data, void *block)
2015-12-05 09:59:03 +00:00
{
2017-01-10 20:26:48 +00:00
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
2015-12-05 09:59:03 +00:00
2016-10-19 22:30:34 +00:00
if (font && font->renderer && font->renderer->bind_block)
font->renderer->bind_block(font->renderer_data, block);
2015-12-05 09:59:03 +00:00
}
void font_driver_flush(unsigned width, unsigned height, void *font_data)
2015-12-05 11:10:12 +00:00
{
2017-01-10 20:26:48 +00:00
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
2016-10-19 22:30:34 +00:00
if (font && font->renderer && font->renderer->flush)
font->renderer->flush(width, height, font->renderer_data);
2015-12-05 11:10:12 +00:00
}
int font_driver_get_message_width(void *font_data,
2016-02-06 20:51:37 +00:00
const char *msg, unsigned len, float scale)
2015-12-05 11:17:58 +00:00
{
2017-01-10 20:26:48 +00:00
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
if (len == 0 && msg)
len = (unsigned)strlen(msg);
2016-10-19 22:30:34 +00:00
if (font && font->renderer && font->renderer->get_message_width)
return font->renderer->get_message_width(font->renderer_data, msg, len, scale);
return -1;
2015-12-05 11:17:58 +00:00
}
2019-02-17 15:54:24 +00:00
int font_driver_get_line_height(void *font_data, float scale)
{
struct font_line_metrics *metrics = NULL;
2019-02-21 20:34:22 +00:00
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
2019-02-17 15:54:24 +00:00
/* First try the line metrics implementation */
if (font && font->renderer && font->renderer->get_line_metrics)
if ((font->renderer->get_line_metrics(font->renderer_data, &metrics)))
return (int)roundf(metrics->height * scale);
2019-02-17 15:54:24 +00:00
/* Else return an approximation
* (uses a fudge of standard font metrics - mostly garbage...)
* > font_size = (width of 'a') / 0.6
* > line_height = font_size * 1.7f */
return (int)roundf(1.7f * (float)font_driver_get_message_width(font_data, "a", 1, scale) / 0.6f);
}
int font_driver_get_line_ascender(void *font_data, float scale)
{
struct font_line_metrics *metrics = NULL;
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
/* First try the line metrics implementation */
if (font && font->renderer && font->renderer->get_line_metrics)
if ((font->renderer->get_line_metrics(font->renderer_data, &metrics)))
return (int)roundf(metrics->ascender * scale);
/* Else return an approximation
* (uses a fudge of standard font metrics - mostly garbage...)
* > font_size = (width of 'a') / 0.6
* > ascender = 1.58 * font_size * 0.75 */
return (int)roundf(1.58f * 0.75f * (float)font_driver_get_message_width(font_data, "a", 1, scale) / 0.6f);
}
int font_driver_get_line_descender(void *font_data, float scale)
{
struct font_line_metrics *metrics = NULL;
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
/* First try the line metrics implementation */
if (font && font->renderer && font->renderer->get_line_metrics)
if ((font->renderer->get_line_metrics(font->renderer_data, &metrics)))
return (int)roundf(metrics->descender * scale);
/* Else return an approximation
* (uses a fudge of standard font metrics - mostly garbage...)
* > font_size = (width of 'a') / 0.6
* > descender = 1.58 * font_size * 0.25 */
return (int)roundf(1.58f * 0.25f * (float)font_driver_get_message_width(font_data, "a", 1, scale) / 0.6f);
}
int font_driver_get_line_centre_offset(void *font_data, float scale)
{
struct font_line_metrics *metrics = NULL;
font_data_t *font = (font_data_t*)(font_data ? font_data : video_font_driver);
/* First try the line metrics implementation */
if (font && font->renderer && font->renderer->get_line_metrics)
if ((font->renderer->get_line_metrics(font->renderer_data, &metrics)))
return (int)roundf((metrics->ascender - metrics->descender) * 0.5f * scale);
/* Else return an approximation... */
return (int)roundf((1.58f * 0.5f * (float)font_driver_get_message_width(font_data, "a", 1, scale) / 0.6f) / 2.0f);
2019-02-17 15:54:24 +00:00
}
void font_driver_free(void *font_data)
{
font_data_t *font = (font_data_t*)font_data;
if (font)
{
bool is_threaded = false;
#ifdef HAVE_THREADS
2017-04-29 15:02:35 +00:00
bool *is_threaded_tmp = video_driver_get_threaded();
is_threaded = *is_threaded_tmp;
#endif
if (font->renderer && font->renderer->free)
font->renderer->free(font->renderer_data, is_threaded);
2015-12-05 09:54:53 +00:00
font->renderer = NULL;
font->renderer_data = NULL;
2015-12-05 09:54:53 +00:00
free(font);
}
}
font_data_t *font_driver_init_first(
void *video_data, const char *font_path, float font_size,
bool threading_hint, bool is_threaded,
enum font_driver_render_api api)
{
const void *font_driver = NULL;
void *font_handle = NULL;
bool ok = false;
2015-12-06 21:42:22 +00:00
#ifdef HAVE_THREADS
if ( threading_hint
&& is_threaded
2016-05-08 12:00:51 +00:00
&& !video_driver_is_hw_context())
ok = video_thread_font_init(&font_driver, &font_handle,
video_data, font_path, font_size, api, font_init_first,
is_threaded);
else
2015-12-06 21:42:22 +00:00
#endif
ok = font_init_first(&font_driver, &font_handle,
video_data, font_path, font_size, api, is_threaded);
if (ok)
{
2020-06-27 22:50:48 +00:00
font_data_t *font = (font_data_t*)malloc(sizeof(*font));
font->renderer = (const font_renderer_t*)font_driver;
font->renderer_data = font_handle;
font->size = font_size;
return font;
}
2015-12-05 10:29:06 +00:00
return NULL;
}
2015-12-05 11:10:12 +00:00
void font_driver_init_osd(
void *video_data,
const void *video_info_data,
bool threading_hint,
bool is_threaded,
enum font_driver_render_api api)
{
const video_info_t *video_info = (const video_info_t*)video_info_data;
if (video_font_driver || !video_info)
2017-01-10 20:26:48 +00:00
return;
2017-01-10 20:26:48 +00:00
video_font_driver = font_driver_init_first(video_data,
*video_info->path_font ? video_info->path_font : NULL,
video_info->font_size, threading_hint, is_threaded, api);
2017-01-10 20:26:48 +00:00
if (!video_font_driver)
2020-06-08 16:04:29 +00:00
RARCH_ERR("[Font]: Failed to initialize OSD font.\n");
}
void font_driver_free_osd(void)
{
2017-01-10 20:26:48 +00:00
if (video_font_driver)
font_driver_free(video_font_driver);
2017-01-10 20:26:48 +00:00
video_font_driver = NULL;
}