diff --git a/minuitwrp/truetype.cpp b/minuitwrp/truetype.cpp index 3dffbe41..de927156 100755 --- a/minuitwrp/truetype.cpp +++ b/minuitwrp/truetype.cpp @@ -163,19 +163,17 @@ static bool gr_ttf_freeFontCache(void *value, void *context __unused) { TrueTypeCacheEntry *e = (TrueTypeCacheEntry *)value; FT_Done_Glyph((FT_Glyph)e->glyph); - free(e); + delete e; return true; } -bool twrpTruetype::gr_ttf_freeStringCache(void *key, void *value, void *context __unused) { +void twrpTruetype::gr_ttf_freeStringCache(void *key, void *value, void *context __unused) { StringCacheKey *k = (StringCacheKey *)key; - delete k->text; delete k; StringCacheEntry *e = (StringCacheEntry *)value; - delete e->surface.data; + free(e->surface.data); delete e; - return true; } void twrpTruetype::gr_ttf_freeFont(void *font) { @@ -191,13 +189,13 @@ void twrpTruetype::gr_ttf_freeFont(void *font) { StringCacheMap::iterator stringCacheEntryIt = d->string_cache.begin(); while (stringCacheEntryIt != d->string_cache.end()) { - gr_ttf_freeStringCache(stringCacheEntryIt->second->key, stringCacheEntryIt->second, NULL); + gr_ttf_freeStringCache(stringCacheEntryIt->second->key, stringCacheEntryIt->second, nullptr); stringCacheEntryIt = d->string_cache.erase(stringCacheEntryIt); } TrueTypeCacheEntryMap::iterator ttcIt = d->glyph_cache.begin(); while(ttcIt != d->glyph_cache.end()) { - gr_ttf_freeFontCache(ttcIt->second, NULL); + gr_ttf_freeFontCache(ttcIt->second, nullptr); ttcIt = d->glyph_cache.erase(ttcIt); } @@ -230,7 +228,7 @@ TrueTypeCacheEntry* twrpTruetype::gr_ttf_glyph_cache_get(TrueTypeFont *font, int if(error) { fprintf(stderr, "Failed to load glyph idx %d: %d\n", char_index, error); - return NULL; + return nullptr; } FT_BitmapGlyph glyph; @@ -238,7 +236,7 @@ TrueTypeCacheEntry* twrpTruetype::gr_ttf_glyph_cache_get(TrueTypeFont *font, int if(error) { fprintf(stderr, "Failed to copy glyph %d: %d\n", char_index, error); - return NULL; + return nullptr; } res = new TrueTypeCacheEntry; @@ -332,7 +330,7 @@ void twrpTruetype::gr_ttf_calcMaxFontHeight(TrueTypeFont *f) { } // returns number of bytes from const char *text rendered to fit max_width, not number of UTF8 characters! -int twrpTruetype::gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const char *text, int max_width) { +int twrpTruetype::gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const std::string text, int max_width) { TrueTypeFont *f = font; TrueTypeCacheEntry *ent; int bytes_rendered = 0, total_w = 0; @@ -342,11 +340,11 @@ int twrpTruetype::gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, co int height; FT_Vector delta; uint8_t *data = NULL; - const char *text_itr = text; + const char *text_itr = text.c_str(); int *char_idxs; int char_idxs_len = 0; - char_idxs = new int[strlen(text)]; + char_idxs = new int[text.length()]; while(*text_itr) { @@ -387,8 +385,8 @@ int twrpTruetype::gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, co height = font->max_height; - data = new uint8_t[total_w * height]; - x = 0; + data = (uint8_t *)malloc(total_w*height); + memset(data, 0, total_w*height); x = 0; prev_idx = 0; surface->version = sizeof(*surface); @@ -422,10 +420,10 @@ int twrpTruetype::gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, co } StringCacheEntry* twrpTruetype::gr_ttf_string_cache_peek(TrueTypeFont *font, - const char *text, + const std::string text, __attribute__((unused)) int max_width) { StringCacheKey k = { - .text = (char*)text, + .text = text, .max_width = max_width }; StringCacheMap::iterator stringCacheItr = font->string_cache.find(k); @@ -437,50 +435,49 @@ StringCacheEntry* twrpTruetype::gr_ttf_string_cache_peek(TrueTypeFont *font, } } -StringCacheEntry* twrpTruetype::gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width) { +void twrpTruetype::gr_ttf_string_cache_truncate(TrueTypeFont *font) { + StringCacheMap::iterator stringCacheItr; + + if (font->string_cache.size() == STRING_CACHE_MAX_ENTRIES) { + StringCacheEntry *truncateEntry = nullptr; + stringCacheItr = font->string_cache.begin(); + int deleteCtr = 0; + while (stringCacheItr != font->string_cache.end() || deleteCtr == (STRING_CACHE_MAX_ENTRIES - 1)) { + truncateEntry = stringCacheItr->second; + gr_ttf_freeStringCache(truncateEntry->key, truncateEntry, nullptr); + stringCacheItr = font->string_cache.erase(stringCacheItr); + deleteCtr++; + } + } +} + +StringCacheEntry* twrpTruetype::gr_ttf_string_cache_get(TrueTypeFont *font, const std::string text, int max_width) { StringCacheEntry *res = nullptr; + StringCacheMap::iterator stringCacheItr; StringCacheKey k = { - .text = (char*)text, + .text = text, .max_width = max_width }; - StringCacheMap::iterator stringCacheItr = font->string_cache.find(k); - if (stringCacheItr == font->string_cache.end()) - { + stringCacheItr = font->string_cache.find(k); + if (stringCacheItr == font->string_cache.end()) { res = new StringCacheEntry; res->rendered_bytes = gr_ttf_render_text(font, &res->surface, text, max_width); - if(res->rendered_bytes < 0) - { + if(res->rendered_bytes < 0) { delete res; return nullptr; } StringCacheKey *new_key = new StringCacheKey; new_key->max_width = max_width; - new_key->text = strdup(text); + new_key->text = text; res->key = new_key; - font->string_cache[k] = res; + font->string_cache[*new_key] = res; } else { res = stringCacheItr->second; - - // truncate old entries - if (font->string_cache.size() >= STRING_CACHE_MAX_ENTRIES) - { - StringCacheEntry *ent; - for(int i = 0; i < STRING_CACHE_TRUNCATE_ENTRIES; ++i) - { - StringCacheMap::iterator stringTruncCacheItr = font->string_cache.find(k); - - if (stringTruncCacheItr != font->string_cache.end()) { - ent = stringTruncCacheItr->second; - gr_ttf_freeStringCache(ent->key, ent, nullptr); - font->string_cache.erase(stringTruncCacheItr); - } - } - } } return res; } @@ -490,6 +487,7 @@ int twrpTruetype::gr_ttf_measureEx(const char *s, void *font) { int res = -1; pthread_mutex_lock(&f->mutex); + gr_ttf_string_cache_truncate(f); StringCacheEntry *e = gr_ttf_string_cache_get(f, s, -1); if(e) res = e->surface.width; @@ -511,15 +509,13 @@ int twrpTruetype::gr_ttf_maxExW(const char *s, void *font, int max_width) { pthread_mutex_lock(&f->mutex); e = gr_ttf_string_cache_peek(f, s, max_width); - if(e) - { + if (e) { max_bytes = e->rendered_bytes; pthread_mutex_unlock(&f->mutex); return max_bytes; } - while(*s) - { + while(*s) { utf_bytes = utf8_to_unicode(s, &unicode); s += utf_bytes; @@ -567,8 +563,7 @@ int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y, pthread_mutex_lock(&font->mutex); StringCacheEntry *e = gr_ttf_string_cache_get(font, s, max_width); - if(!e) - { + if (!e) { pthread_mutex_unlock(&font->mutex); return -1; } @@ -584,8 +579,8 @@ int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y, string_surface_rotated.stride = string_surface_rotated.width; string_surface_rotated.format = e->surface.format; // e->surface.format is GGL_PIXEL_FORMAT_A_8 (grayscale) - string_surface_rotated.data = new GGLubyte[string_surface_rotated.stride * string_surface_rotated.height * 1]; - surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1); + string_surface_rotated.data = (GGLubyte*) malloc(string_surface_rotated.stride * string_surface_rotated.height * 1); + surface_ROTATION_transform((gr_surface) &string_surface_rotated, (const gr_surface) &e->surface, 1); #endif int y_bottom = y + e->surface.height; @@ -631,10 +626,9 @@ int twrpTruetype::gr_ttf_textExWH(void *context, int x, int y, gl->disable(gl, GGL_TEXTURE_2D); #if TW_ROTATION != 0 - delete [] string_surface_rotated.data; + free(string_surface_rotated.data); #endif - - pthread_mutex_unlock(&font->mutex); + pthread_mutex_unlock(&font->mutex);; return res; } diff --git a/minuitwrp/truetype.hpp b/minuitwrp/truetype.hpp index e0d7a2f1..3ae20905 100755 --- a/minuitwrp/truetype.hpp +++ b/minuitwrp/truetype.hpp @@ -1,121 +1,118 @@ -/* - Copyright 2013 to 2020 TeamWin - TWRP 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 Foundation, either version 3 of the License, or - (at your option) any later version. - - TWRP 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 TWRP. If not, see . -*/ - -#ifndef _TWRP_TRUETYPE_HPP -#define _TWRP_TRUETYPE_HPP - -#include -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include -#include "minui.h" - -struct TrueTypeFontKey { - int size; - int dpi; - char *path; - - bool operator<(const TrueTypeFontKey &ttfk) const { - return size < ttfk.size || (size == ttfk.size && dpi < ttfk.dpi) || (size == ttfk.size && dpi == ttfk.dpi - && std::strcmp(path, ttfk.path) < 0) || (size == ttfk.size && std::strcmp(path, ttfk.path) > 0); - } -}; - -typedef struct TrueTypeFontKey TrueTypeFontKey; - -typedef struct { - FT_BBox bbox; - FT_BitmapGlyph glyph; -} TrueTypeCacheEntry; - -struct StringCacheKey { - char *text; - int max_width; - - bool operator<(const StringCacheKey &sck) const { - return max_width < sck.max_width || (max_width == sck.max_width - && std::strcmp(text, sck.text) < 0) || (max_width == sck.max_width && std::strcmp(text, sck.text) > 0); - } -}; - -typedef struct StringCacheKey StringCacheKey; - -typedef struct StringCacheEntry { - GGLSurface surface; - int rendered_bytes; // number of bytes from C string rendered, not number of UTF8 characters! - StringCacheKey *key; -} StringCacheEntry; - -typedef struct { - int type; - int refcount; - int size; - int dpi; - int max_height; - int base; - FT_Face face; - std::map glyph_cache; - std::map string_cache; - pthread_mutex_t mutex; - TrueTypeFontKey *key; -} TrueTypeFont; - -typedef struct { - FT_Library ft_library; - std::map fonts; - pthread_mutex_t mutex; -} FontData; - -typedef std::map StringCacheMap; -typedef std::map TrueTypeCacheEntryMap; -typedef std::map TrueTypeFontMap; - -#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) -#define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) - -// 32bit FNV-1a hash algorithm -// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a -static const uint32_t FNV_prime = 16777619U; -static const uint32_t offset_basis = 2166136261U; - -#define STRING_CACHE_MAX_ENTRIES 400 -#define STRING_CACHE_TRUNCATE_ENTRIES 150 - -class twrpTruetype { -public: - twrpTruetype(); - static int utf8_to_unicode(const char* pIn, unsigned int *pOut); - static void* gr_ttf_loadFont(const char *filename, int size, int dpi); - static void* gr_ttf_scaleFont(void *font, int max_width, int measured_width); - static bool gr_ttf_freeStringCache(void *key, void *value, void *context __unused); - static void gr_ttf_freeFont(void *font); - static TrueTypeCacheEntry* gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index); - static TrueTypeCacheEntry* gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index); - static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base); - static void gr_ttf_calcMaxFontHeight(TrueTypeFont *f); - static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const char *text, int max_width); - static StringCacheEntry* gr_ttf_string_cache_peek(TrueTypeFont *font, const char *text, __attribute__((unused)) int max_width); - static StringCacheEntry* gr_ttf_string_cache_get(TrueTypeFont *font, const char *text, int max_width); - static int gr_ttf_measureEx(const char *s, void *font); - static int gr_ttf_maxExW(const char *s, void *font, int max_width); - static int gr_ttf_textExWH(void *context, int x, int y, - const char *s, void *pFont, - int max_width, int max_height, - const gr_surface gr_draw_surface); - static int gr_ttf_getMaxFontHeight(void *font); -}; -#endif // _TWRP_TRUETYPE_HPP +/* + Copyright 2013 to 2020 TeamWin + TWRP 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 Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP 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 TWRP. If not, see . +*/ + +#ifndef _TWRP_TRUETYPE_HPP +#define _TWRP_TRUETYPE_HPP + +#include +#include +#include +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include +#include "minui.h" + +typedef struct TrueTypeFontKey { + int size; + int dpi; + char *path; +} TrueTypeFontKey; + +inline bool operator<(const TrueTypeFontKey &ttfkLeft, const TrueTypeFontKey &ttfkRight) { + return std::tie(ttfkLeft.size, ttfkLeft.dpi, *ttfkLeft.path) < std::tie(ttfkRight.size, ttfkRight.dpi, *ttfkRight.path); +} + +typedef struct { + FT_BBox bbox; + FT_BitmapGlyph glyph; +} TrueTypeCacheEntry; + +typedef struct StringCacheKey { + int max_width; + std::string text; +} StringCacheKey; + +inline bool operator<(const StringCacheKey &sckLeft, const StringCacheKey &sckRight) { + return std::tie(sckLeft.text, sckLeft.max_width) < std::tie(sckRight.text, sckRight.max_width); +} + +typedef struct StringCacheEntry { + GGLSurface surface; + int rendered_bytes; // number of bytes from C string rendered, not number of UTF8 characters! + StringCacheKey *key; +} StringCacheEntry; + +typedef struct { + int type; + int refcount; + int size; + int dpi; + int max_height; + int base; + FT_Face face; + std::map glyph_cache; + std::map string_cache; + pthread_mutex_t mutex; + TrueTypeFontKey *key; +} TrueTypeFont; + +typedef struct { + FT_Library ft_library; + std::map fonts; + pthread_mutex_t mutex; +} FontData; + +typedef std::map StringCacheMap; +typedef std::map TrueTypeCacheEntryMap; +typedef std::map TrueTypeFontMap; + +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) +#define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) + +// 32bit FNV-1a hash algorithm +// http://isthe.com/chongo/tech/comp/fnv/#FNV-1a +static const uint32_t FNV_prime = 16777619U; +static const uint32_t offset_basis = 2166136261U; + +#define STRING_CACHE_MAX_ENTRIES 400 +#define STRING_CACHE_TRUNCATE_ENTRIES 150 + +class twrpTruetype { +public: + twrpTruetype(); + static int utf8_to_unicode(const char* pIn, unsigned int *pOut); + static void* gr_ttf_loadFont(const char *filename, int size, int dpi); + static void* gr_ttf_scaleFont(void *font, int max_width, int measured_width); + static void gr_ttf_freeStringCache(void *key, void *value, void *context __unused); + static void gr_ttf_freeFont(void *font); + static TrueTypeCacheEntry* gr_ttf_glyph_cache_peek(TrueTypeFont *font, int char_index); + static TrueTypeCacheEntry* gr_ttf_glyph_cache_get(TrueTypeFont *font, int char_index); + static int gr_ttf_copy_glyph_to_surface(GGLSurface *dest, FT_BitmapGlyph glyph, int offX, int offY, int base); + static void gr_ttf_calcMaxFontHeight(TrueTypeFont *f); + static int gr_ttf_render_text(TrueTypeFont *font, GGLSurface *surface, const std::string text, int max_width); + static StringCacheEntry* gr_ttf_string_cache_peek(TrueTypeFont *font, const std::string text, __attribute__((unused)) int max_width); + static StringCacheEntry* gr_ttf_string_cache_get(TrueTypeFont *font, const std::string text, int max_width); + static int gr_ttf_measureEx(const char *s, void *font); + static int gr_ttf_maxExW(const char *s, void *font, int max_width); + static int gr_ttf_textExWH(void *context, int x, int y, + const char *s, void *pFont, + int max_width, int max_height, + const gr_surface gr_draw_surface); + static int gr_ttf_getMaxFontHeight(void *font); + static void gr_ttf_string_cache_truncate(TrueTypeFont *font); +}; +#endif // _TWRP_TRUETYPE_HPP