mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-25 00:49:47 +00:00
183 lines
5.0 KiB
C
183 lines
5.0 KiB
C
|
/* RetroArch - A frontend for libretro.
|
||
|
* Copyright (C) 2015-2014 - Hans-Kristian Arntzen
|
||
|
* Copyright (C) 2011-2015 - Daniel De Matteis
|
||
|
*
|
||
|
* 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "../font_renderer_driver.h"
|
||
|
#include <file/file_path.h>
|
||
|
#include "../../general.h"
|
||
|
#include "../../file_ops.h"
|
||
|
|
||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||
|
#include "../../deps/stb/stb_rect_pack.h"
|
||
|
#include "../../deps/stb/stb_truetype.h"
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
int line_height;
|
||
|
struct font_atlas atlas;
|
||
|
struct font_glyph glyphs[256];
|
||
|
} stb_font_renderer_t;
|
||
|
|
||
|
static const struct font_atlas *font_renderer_stb_get_atlas(void *data)
|
||
|
{
|
||
|
stb_font_renderer_t *self = (stb_font_renderer_t*)data;
|
||
|
return &self->atlas;
|
||
|
}
|
||
|
|
||
|
static const struct font_glyph *font_renderer_stb_get_glyph(
|
||
|
void *data, uint32_t code)
|
||
|
{
|
||
|
stb_font_renderer_t *self = (stb_font_renderer_t*)data;
|
||
|
return code < 256 ? &self->glyphs[code] : NULL;
|
||
|
}
|
||
|
|
||
|
static void font_renderer_stb_free(void *data)
|
||
|
{
|
||
|
stb_font_renderer_t *self = (stb_font_renderer_t*)data;
|
||
|
|
||
|
free(self->atlas.buffer);
|
||
|
free(self);
|
||
|
}
|
||
|
|
||
|
static bool font_renderer_stb_create_atlas(stb_font_renderer_t *self,
|
||
|
uint8_t *font_data, float font_size)
|
||
|
{
|
||
|
int i;
|
||
|
stbtt_pack_context pc;
|
||
|
stbtt_packedchar chardata[256];
|
||
|
|
||
|
self->atlas.width = self->atlas.height = 512;
|
||
|
self->atlas.buffer = (uint8_t*)calloc(self->atlas.height, self->atlas.width);
|
||
|
|
||
|
if (!self->atlas.buffer)
|
||
|
return false;
|
||
|
|
||
|
stbtt_PackBegin(&pc, self->atlas.buffer,
|
||
|
self->atlas.width, self->atlas.height,
|
||
|
self->atlas.width, 1, NULL);
|
||
|
|
||
|
stbtt_PackFontRange(&pc, font_data, 0, font_size, 0, 256, chardata);
|
||
|
stbtt_PackEnd(&pc);
|
||
|
|
||
|
for (i = 0; i < 256; ++i)
|
||
|
{
|
||
|
struct font_glyph *g = &self->glyphs[i];
|
||
|
stbtt_packedchar *c = &chardata[i];
|
||
|
|
||
|
g->advance_x = c->xadvance;
|
||
|
g->atlas_offset_x = c->x0;
|
||
|
g->atlas_offset_y = c->y0;
|
||
|
g->draw_offset_x = c->xoff;
|
||
|
g->draw_offset_y = c->yoff;
|
||
|
g->width = c->x1 - c->x0;
|
||
|
g->height = c->y1 - c->y0;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static void *font_renderer_stb_init(const char *font_path, float font_size)
|
||
|
{
|
||
|
uint8_t *font_data = NULL;
|
||
|
int ascent, descent, line_gap;
|
||
|
stbtt_fontinfo info;
|
||
|
stb_font_renderer_t *self = (stb_font_renderer_t*) calloc(1, sizeof(*self));
|
||
|
|
||
|
/* prevent warnings */
|
||
|
(void)rect_width_compare;
|
||
|
|
||
|
if (!self)
|
||
|
goto error;
|
||
|
|
||
|
if (!read_file(font_path, (void**)&font_data, NULL))
|
||
|
goto error;
|
||
|
|
||
|
if (!font_renderer_stb_create_atlas(self, font_data, font_size))
|
||
|
goto error;
|
||
|
|
||
|
if (!stbtt_InitFont(&info, font_data, stbtt_GetFontOffsetForIndex(font_data, 0)))
|
||
|
goto error;
|
||
|
|
||
|
stbtt_GetFontVMetrics(&info, &ascent, &descent, &line_gap);
|
||
|
self->line_height = ascent - descent;// + line_gap;
|
||
|
|
||
|
if (font_size < 0)
|
||
|
self->line_height *= stbtt_ScaleForMappingEmToPixels(&info, -font_size);
|
||
|
else
|
||
|
self->line_height *= stbtt_ScaleForPixelHeight(&info, font_size);
|
||
|
|
||
|
free(font_data);
|
||
|
|
||
|
return self;
|
||
|
|
||
|
error:
|
||
|
if (font_data)
|
||
|
free(font_data);
|
||
|
|
||
|
font_renderer_stb_free(self);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static const char *font_renderer_stb_get_default_font(void)
|
||
|
{
|
||
|
static const char *paths[] = {
|
||
|
#if defined(_WIN32)
|
||
|
"C:\\Windows\\Fonts\\consola.ttf",
|
||
|
"C:\\Windows\\Fonts\\verdana.ttf",
|
||
|
#elif defined(__APPLE__)
|
||
|
"/Library/Fonts/Microsoft/Candara.ttf",
|
||
|
"/Library/Fonts/Verdana.ttf",
|
||
|
"/Library/Fonts/Tahoma.ttf",
|
||
|
#elif defined(__ANDROID_API__)
|
||
|
"/system/fonts/DroidSansMono.ttf",
|
||
|
"/system/fonts/DroidSansFallback.ttf",
|
||
|
#else
|
||
|
"/usr/share/fonts/TTF/DejaVuSansMono.ttf",
|
||
|
"/usr/share/fonts/TTF/DejaVuSans.ttf",
|
||
|
"/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf",
|
||
|
"/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
|
||
|
"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf",
|
||
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
||
|
#endif
|
||
|
"osd-font.ttf",
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
const char **p;
|
||
|
|
||
|
for (p = paths; *p; ++p)
|
||
|
if (path_file_exists(*p))
|
||
|
return *p;
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static int font_renderer_stb_get_line_height(void* data)
|
||
|
{
|
||
|
stb_font_renderer_t *handle = (stb_font_renderer_t*)data;
|
||
|
return handle->line_height;
|
||
|
}
|
||
|
|
||
|
font_renderer_driver_t stb_font_renderer = {
|
||
|
font_renderer_stb_init,
|
||
|
font_renderer_stb_get_atlas,
|
||
|
font_renderer_stb_get_glyph,
|
||
|
font_renderer_stb_free,
|
||
|
font_renderer_stb_get_default_font,
|
||
|
"stb",
|
||
|
font_renderer_stb_get_line_height,
|
||
|
};
|