diff --git a/gfx/drivers_font/vita2d_font.c b/gfx/drivers_font/vita2d_font.c index 402b1fa65b..0baaa86ec3 100644 --- a/gfx/drivers_font/vita2d_font.c +++ b/gfx/drivers_font/vita2d_font.c @@ -26,6 +26,7 @@ typedef struct vita2d_texture *texture; const font_renderer_driver_t *font_driver; void *font_data; + struct font_atlas *atlas; } vita_font_t; @@ -47,7 +48,8 @@ static void *vita2d_font_init_font(void *data, const char *font_path, float font &font->font_data, font_path, font_size)) goto error; - atlas = font->font_driver->get_atlas(font->font_data); + font->atlas = font->font_driver->get_atlas(font->font_data); + atlas = font->atlas; if (!atlas) goto error; @@ -72,6 +74,8 @@ static void *vita2d_font_init_font(void *data, const char *font_path, float font for (j = 0; j < atlas->height; j++) for (k = 0; k < atlas->width; k++) tex32[k + j*stride] = frame32[k + j*pitch]; + + font->atlas->dirty = false; return font; @@ -160,6 +164,9 @@ static void vita2d_font_render_line( for (i = 0; i < msg_len; i++) { int off_x, off_y, tex_x, tex_y, width, height; + unsigned int stride, pitch, j, k; + const uint8_t *frame32 = NULL; + uint8_t *tex32 = NULL; const char *msg_tmp = &msg[i]; unsigned code = utf8_walk(&msg_tmp); unsigned skip = msg_tmp - &msg[i]; @@ -181,6 +188,20 @@ static void vita2d_font_render_line( tex_y = glyph->atlas_offset_y; width = glyph->width; height = glyph->height; + + if (font->atlas->dirty) + { + stride = vita2d_texture_get_stride(font->texture); + tex32 = vita2d_texture_get_datap(font->texture); + frame32 = font->atlas->buffer; + pitch = font->atlas->width; + + for (j = 0; j < font->atlas->height; j++) + for (k = 0; k < font->atlas->width; k++) + tex32[k + j*stride] = frame32[k + j*pitch]; + + font->atlas->dirty = false; + } vita2d_draw_texture_tint_part_scale(font->texture, x + off_x + delta_x * scale, diff --git a/gfx/drivers_font_renderer/stb_unicode.c b/gfx/drivers_font_renderer/stb_unicode.c new file mode 100644 index 0000000000..2a51da7f17 --- /dev/null +++ b/gfx/drivers_font_renderer/stb_unicode.c @@ -0,0 +1,279 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2015-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2016 - 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 . + */ + +#include + +#include +#include +#include + +#include "../font_driver.h" +#include "../../verbosity.h" + +#define STB_TRUETYPE_IMPLEMENTATION +#define STB_RECT_PACK_IMPLEMENTATION +#define STBRP_STATIC +#define STBRP_STATIC +#define static static INLINE +#include "../../deps/stb/stb_rect_pack.h" +#include "../../deps/stb/stb_truetype.h" +#undef static + +typedef struct +{ + uint8_t *font_data; + stbtt_fontinfo info; + + int max_glyph_width; + int max_glyph_height; + int line_height; + float scale_factor; + struct font_atlas atlas; + struct font_glyph glyphs[256]; + uint8_t uc_to_id[0x10000]; + uint16_t id_to_uc[256]; + unsigned last_used[256]; + unsigned usage_counter; + +} stb_unicode_font_renderer_t; + +static struct font_atlas *font_renderer_stb_unicode_get_atlas(void *data) +{ + stb_unicode_font_renderer_t *self = (stb_unicode_font_renderer_t*)data; + return &self->atlas; +} + +static void font_renderer_stb_unicode_free(void *data) +{ + stb_unicode_font_renderer_t *self = (stb_unicode_font_renderer_t*)data; + + free(self->atlas.buffer); + free(self->font_data); + free(self); +} + +static unsigned font_renderer_stb_unicode_get_slot(stb_unicode_font_renderer_t *handle) +{ + int i; + unsigned oldest = 1; + + for (i = 2; i < 256; i++) + if(handle->last_used[i] < handle->last_used[oldest]) + oldest = i; + + handle->uc_to_id[handle->id_to_uc[oldest]] = 0; + handle->id_to_uc[oldest] = 0; + return oldest; +} + +static uint32_t font_renderer_stb_unicode_update_atlas(stb_unicode_font_renderer_t *self, uint32_t charcode) +{ + int id, glyph_index, offset_x, offset_y; + struct font_glyph *glyph; + uint8_t *dst; + + if(charcode > 0xFFFF) + return 0; + + if(self->uc_to_id[charcode]) + return self->uc_to_id[charcode]; + + id = font_renderer_stb_unicode_get_slot(self); + self->id_to_uc[id] = charcode; + self->uc_to_id[charcode] = id; + self->atlas.dirty = true; + + glyph = &self->glyphs[id]; + + glyph_index = stbtt_FindGlyphIndex(&self->info, charcode); + + offset_x = (id % 16) * self->max_glyph_width; + offset_y = (id / 16) * self->max_glyph_height; + + dst = self->atlas.buffer + offset_x + offset_y * self->atlas.width; + + stbtt_MakeGlyphBitmap(&self->info, dst, self->max_glyph_width, self->max_glyph_height, + self->atlas.width, self->scale_factor, self->scale_factor, glyph_index); + + int x0, y0, x1, y1, advance_width, left_side_bearing; + stbtt_GetGlyphHMetrics(&self->info, glyph_index, &advance_width, &left_side_bearing); + stbtt_GetGlyphBox(&self->info, glyph_index, &x0, &y0, &x1, &y1); + glyph->advance_x = advance_width * self->scale_factor; + glyph->atlas_offset_x = offset_x; + glyph->atlas_offset_y = offset_y; + glyph->draw_offset_x = x0 * self->scale_factor; + glyph->draw_offset_y = - y1 * self->scale_factor; + glyph->width = self->max_glyph_width; + glyph->height = self->max_glyph_height; +// glyph->width = (x1 + x0 ) * self->scale_factor; +// glyph->height = (y1 - y0 ) * self->scale_factor; + return id; +} + +static bool font_renderer_stb_unicode_create_atlas(stb_unicode_font_renderer_t *self, float font_size) +{ + int i, id; + + self->max_glyph_width = font_size < 0 ? -font_size : font_size; + self->max_glyph_height = font_size < 0 ? -font_size : font_size; + self->atlas.width = self->max_glyph_width * 16; + self->atlas.height = self->max_glyph_height * 16; + self->atlas.buffer = (uint8_t*)calloc(self->atlas.height, self->atlas.width); + + if (!self->atlas.buffer) + return false; + + self->usage_counter = 1; + + for (i = 0; i < 256; ++i) + { + id = font_renderer_stb_unicode_update_atlas(self, i); + if(id) + self->last_used[id] = self->usage_counter++; + + } + + return true; +} + +static const struct font_glyph *font_renderer_stb_unicode_get_glyph( + void *data, uint32_t code) +{ + unsigned id; + stb_unicode_font_renderer_t *self = (stb_unicode_font_renderer_t*)data; + + if (!self) + return NULL; + + if(code > 0xFFFF) + return NULL; + + id = self->uc_to_id[code]; + + if(!id) + id = font_renderer_stb_unicode_update_atlas(self, code); + + self->last_used[id] = self->usage_counter++; + + return &self->glyphs[id]; + +} + +static void *font_renderer_stb_unicode_init(const char *font_path, float font_size) +{ + int ascent, descent, line_gap; + stb_unicode_font_renderer_t *self = (stb_unicode_font_renderer_t*) calloc(1, sizeof(*self)); + + + if (!self) + goto error; + + if (font_size < 1.0) + goto error; + + /* See https://github.com/nothings/stb/blob/master/stb_truetype.h#L539 */ + font_size = STBTT_POINT_SIZE(font_size); + + if (!filestream_read_file(font_path, (void**)&self->font_data, NULL)) + goto error; + + if (!stbtt_InitFont(&self->info, self->font_data, stbtt_GetFontOffsetForIndex(self->font_data, 0))) + goto error; + + + + stbtt_GetFontVMetrics(&self->info, &ascent, &descent, &line_gap); + + + if (font_size < 0) + self->scale_factor = stbtt_ScaleForMappingEmToPixels(&self->info, -font_size); + else + self->scale_factor = stbtt_ScaleForPixelHeight(&self->info, font_size); + +// self->line_height = (ascent - descent + line_gap) * self->scale_factor; + self->line_height = (ascent - descent) * self->scale_factor; + + if (!font_renderer_stb_unicode_create_atlas(self, font_size)) + goto error; + + return self; + +error: + if (self) + font_renderer_stb_unicode_free(self); + return NULL; +} + +static const char *font_renderer_stb_unicode_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", + "/Library/Fonts/Andale Mono.ttf", + "/Library/Fonts/Courier New.ttf", +#elif defined(__ANDROID_API__) + "/system/fonts/DroidSansMono.ttf", + "/system/fonts/CutiveMono.ttf", + "/system/fonts/DroidSans.ttf", +#elif defined(VITA) + "vs0:data/external/font/pvf/c041056ts.ttf", + "vs0:data/external/font/pvf/d013013ds.ttf", + "vs0:data/external/font/pvf/e046323ms.ttf", + "vs0:data/external/font/pvf/e046323ts.ttf", + "vs0:data/external/font/pvf/k006004ds.ttf", + "vs0:data/external/font/pvf/n023055ms.ttf", + "vs0:data/external/font/pvf/n023055ts.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_unicode_get_line_height(void* data) +{ + stb_unicode_font_renderer_t *handle = (stb_unicode_font_renderer_t*)data; + return handle->line_height; +} + +font_renderer_driver_t stb_unicode_font_renderer = { + font_renderer_stb_unicode_init, + font_renderer_stb_unicode_get_atlas, + font_renderer_stb_unicode_get_glyph, + font_renderer_stb_unicode_free, + font_renderer_stb_unicode_get_default_font, + "stb-unicode", + font_renderer_stb_unicode_get_line_height, +}; diff --git a/gfx/font_driver.c b/gfx/font_driver.c index 22d19b76c7..fcedcc1d90 100644 --- a/gfx/font_driver.c +++ b/gfx/font_driver.c @@ -34,7 +34,11 @@ static const font_renderer_driver_t *font_backends[] = { &coretext_font_renderer, #endif #ifdef HAVE_STB_FONT +#ifdef VITA + &stb_unicode_font_renderer, +#else &stb_font_renderer, +#endif #endif &bitmap_font_renderer, NULL diff --git a/gfx/font_driver.h b/gfx/font_driver.h index 2b2044b695..a7f33b11c2 100644 --- a/gfx/font_driver.h +++ b/gfx/font_driver.h @@ -166,6 +166,7 @@ extern font_renderer_t ctr_font; extern font_renderer_t vulkan_raster_font; extern font_renderer_driver_t stb_font_renderer; +extern font_renderer_driver_t stb_unicode_font_renderer; extern font_renderer_driver_t freetype_font_renderer; extern font_renderer_driver_t coretext_font_renderer; extern font_renderer_driver_t bitmap_font_renderer;