diff --git a/Kconfig b/Kconfig index f71ffc5d1..eda178a69 100644 --- a/Kconfig +++ b/Kconfig @@ -1241,6 +1241,10 @@ menu "LVGL configuration" bool "Enable loading Tiny TTF data from files" default n depends on LV_USE_TINY_TTF + config LV_TINY_TTF_CACHE_GLYPH_CNT + bool "Tiny ttf cache entries count" + default 256 + depends on LV_USE_TINY_TTF config LV_USE_RLOTTIE bool "Lottie library" diff --git a/demos/benchmark/assets/img_benchmark_cogwheel_alpha256.c b/demos/benchmark/assets/img_benchmark_cogwheel_alpha256.c index 155652b53..393a116c7 100644 --- a/demos/benchmark/assets/img_benchmark_cogwheel_alpha256.c +++ b/demos/benchmark/assets/img_benchmark_cogwheel_alpha256.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_BENCHMARK diff --git a/demos/benchmark/assets/img_benchmark_cogwheel_argb.c b/demos/benchmark/assets/img_benchmark_cogwheel_argb.c index 929b532b3..1b38b02e9 100644 --- a/demos/benchmark/assets/img_benchmark_cogwheel_argb.c +++ b/demos/benchmark/assets/img_benchmark_cogwheel_argb.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_BENCHMARK diff --git a/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.c b/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.c index 80aa26e38..8c37c5c93 100644 --- a/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.c +++ b/demos/benchmark/assets/img_benchmark_cogwheel_indexed16.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_BENCHMARK diff --git a/demos/benchmark/assets/img_benchmark_cogwheel_rgb.c b/demos/benchmark/assets/img_benchmark_cogwheel_rgb.c index 7e4b0d61a..2109d695a 100644 --- a/demos/benchmark/assets/img_benchmark_cogwheel_rgb.c +++ b/demos/benchmark/assets/img_benchmark_cogwheel_rgb.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_BENCHMARK diff --git a/demos/transform/assets/img_transform_avatar_15.c b/demos/transform/assets/img_transform_avatar_15.c index e2910d2ef..85c41361f 100644 --- a/demos/transform/assets/img_transform_avatar_15.c +++ b/demos/transform/assets/img_transform_avatar_15.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #ifndef LV_ATTRIBUTE_MEM_ALIGN diff --git a/demos/widgets/assets/img_clothes.c b/demos/widgets/assets/img_clothes.c index db172a976..874b8ca96 100644 --- a/demos/widgets/assets/img_clothes.c +++ b/demos/widgets/assets/img_clothes.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_WIDGETS diff --git a/demos/widgets/assets/img_demo_widgets_avatar.c b/demos/widgets/assets/img_demo_widgets_avatar.c index 490cf893e..3fdd56e97 100644 --- a/demos/widgets/assets/img_demo_widgets_avatar.c +++ b/demos/widgets/assets/img_demo_widgets_avatar.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_WIDGETS diff --git a/demos/widgets/assets/img_lvgl_logo.c b/demos/widgets/assets/img_lvgl_logo.c index f9e764341..5a1e39edd 100644 --- a/demos/widgets/assets/img_lvgl_logo.c +++ b/demos/widgets/assets/img_lvgl_logo.c @@ -1,9 +1,15 @@ +#ifdef __has_include + #if __has_include("lvgl.h") + #ifndef LV_LVGL_H_INCLUDE_SIMPLE + #define LV_LVGL_H_INCLUDE_SIMPLE + #endif + #endif +#endif + #if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../../../lvgl.h" + #include "lvgl.h" #else -#include "lvgl/lvgl.h" + #include "lvgl/lvgl.h" #endif #if LV_USE_DEMO_WIDGETS diff --git a/docs/libs/tiny_ttf.rst b/docs/libs/tiny_ttf.rst index ce3222ae4..69f801b4d 100644 --- a/docs/libs/tiny_ttf.rst +++ b/docs/libs/tiny_ttf.rst @@ -29,11 +29,14 @@ entire time the font is being used. After a font is created, you can change the font size in pixels by using :cpp:expr:`lv_tiny_ttf_set_size(font, font_size)`. -By default, a font will use up to 4KB of cache to speed up rendering -glyphs. This maximum can be changed by using -:cpp:expr:`lv_tiny_ttf_create_data_ex(data, data_size, font_size, cache_size)` -or :cpp:expr:`lv_tiny_ttf_create_file_ex(path, font_size, cache_size)` (when -available). The cache size is indicated in bytes. +By default, a font will cache data for upto 256 glyphs elements to speed up rendering. +This maximum can be changed by using +:cpp:expr:`lv_tiny_ttf_create_data_ex(data, data_size, font_size, kerning, cache_size, )` +or :cpp:expr:`lv_tiny_ttf_create_file_ex(path, font_size, kerning, cache_size)` (when +available). The cache size is indicated in number of entries. Kerning is whether to allow +if supported, or disable. + + .. _tiny_ttf_example: diff --git a/lv_conf_template.h b/lv_conf_template.h index 901170f85..cf425d17c 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -780,6 +780,7 @@ #if LV_USE_TINY_TTF /* Enable loading TTF data from files */ #define LV_TINY_TTF_FILE_SUPPORT 0 + #define LV_TINY_TTF_CACHE_GLYPH_CNT 256 #endif /*Rlottie library*/ diff --git a/src/core/lv_global.h b/src/core/lv_global.h index d64b14e7a..b720e70d9 100644 --- a/src/core/lv_global.h +++ b/src/core/lv_global.h @@ -174,10 +174,6 @@ typedef struct _lv_global_t { struct _lv_freetype_context_t * ft_context; #endif -#if LV_USE_TINY_TTF - lv_cache_t * tiny_ttf_cache; -#endif - #if LV_USE_FONT_COMPRESSED lv_font_fmt_rle_t font_fmt_rle; #endif diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.c b/src/libs/tiny_ttf/lv_tiny_ttf.c index 10afa6f09..0170607cf 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.c +++ b/src/libs/tiny_ttf/lv_tiny_ttf.c @@ -8,9 +8,7 @@ *********************/ #include "../../lvgl.h" -#if LV_USE_TINY_TTF - -#include "../../core/lv_global.h" +#if LV_USE_TINY_TTF != 0 #define font_draw_buf_handlers &(LV_GLOBAL_DEFAULT()->font_draw_buf_handlers) @@ -18,8 +16,6 @@ * DEFINES *********************/ -#define CACHE_NAME "TINY_TTF" - #define STB_RECT_PACK_IMPLEMENTATION #define STBRP_STATIC #define STBTT_STATIC @@ -55,6 +51,7 @@ static void ttf_cb_stream_seek(ttf_cb_stream_t * stream, size_t position); /********************** * TYPEDEFS **********************/ + typedef struct ttf_font_desc { lv_fs_file_t file; #if LV_TINY_TTF_FILE_SUPPORT != 0 @@ -66,10 +63,21 @@ typedef struct ttf_font_desc { float scale; int ascent; int descent; + + lv_font_kerning_t kerning; + + int cache_size; + lv_cache_t * glyph_cache; + lv_cache_t * draw_data_cache; } ttf_font_desc_t; -typedef struct _tiny_ttf_cache_data_t { - lv_font_t * font; +typedef struct _tiny_ttf_glyph_cache_data_t { + uint32_t unicode; + int adv_w; + lv_font_glyph_dsc_t glyph_dsc; +} tiny_ttf_glyph_cache_data_t; + +typedef struct _lv_tiny_ttf_cache_data_t { uint32_t glyph_index; uint32_t size; lv_draw_buf_t * draw_buf; @@ -82,13 +90,20 @@ static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * d static const void * ttf_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf); static void ttf_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc); static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, - int32_t font_size, + int32_t font_size, lv_font_kerning_t kerning, size_t cache_size); -static bool tiny_ttf_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_data); -static void tiny_ttf_cache_free_cb(tiny_ttf_cache_data_t * node, void * user_data); -static lv_cache_compare_res_t tiny_ttf_cache_compare_cb(const tiny_ttf_cache_data_t * lhs, - const tiny_ttf_cache_data_t * rhs); +static bool tiny_ttf_glyph_cache_create_cb(tiny_ttf_glyph_cache_data_t * node, void * user_data); +static void tiny_ttf_glyph_cache_free_cb(tiny_ttf_glyph_cache_data_t * node, void * user_data); +static lv_cache_compare_res_t tiny_ttf_glyph_cache_compare_cb(const tiny_ttf_glyph_cache_data_t * lhs, + const tiny_ttf_glyph_cache_data_t * rhs); + +static bool tiny_ttf_draw_data_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_data); +static void tiny_ttf_draw_data_cache_free_cb(tiny_ttf_cache_data_t * node, void * user_data); +static lv_cache_compare_res_t tiny_ttf_draw_data_cache_compare_cb(const tiny_ttf_cache_data_t * lhs, + const tiny_ttf_cache_data_t * rhs); + +static void lv_tiny_ttf_cache_create(ttf_font_desc_t * dsc); /********************** * GLOBAL VARIABLES **********************/ @@ -117,6 +132,20 @@ void lv_tiny_ttf_set_size(lv_font_t * font, int32_t font_size) stbtt_GetFontVMetrics(&dsc->info, &dsc->ascent, &dsc->descent, &line_gap); font->line_height = (int32_t)(dsc->scale * (dsc->ascent - dsc->descent + line_gap)); font->base_line = (int32_t)(dsc->scale * (line_gap - dsc->descent)); + + /* size change means cache needs to be invalidated. */ + + if(dsc->glyph_cache) { + lv_cache_destroy(dsc->glyph_cache, NULL); + dsc->glyph_cache = NULL; + } + + if(dsc->draw_data_cache) { + lv_cache_destroy(dsc->draw_data_cache, NULL); + dsc->draw_data_cache = NULL; + } + + lv_tiny_ttf_cache_create(dsc); } void lv_tiny_ttf_destroy(lv_font_t * font) @@ -130,7 +159,8 @@ void lv_tiny_ttf_destroy(lv_font_t * font) lv_fs_close(&ttf->file); } #endif - lv_cache_drop_all(tiny_ttf_cache, (void *)font->dsc); + lv_cache_destroy(ttf->glyph_cache, NULL); + lv_cache_destroy(ttf->draw_data_cache, NULL); lv_free(ttf); font->dsc = NULL; } @@ -138,23 +168,6 @@ void lv_tiny_ttf_destroy(lv_font_t * font) lv_free(font); } -void lv_tiny_ttf_init(void) -{ - lv_cache_ops_t ops = { - .compare_cb = (lv_cache_compare_cb_t)tiny_ttf_cache_compare_cb, - .create_cb = (lv_cache_create_cb_t)tiny_ttf_cache_create_cb, - .free_cb = (lv_cache_free_cb_t)tiny_ttf_cache_free_cb, - }; - - tiny_ttf_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(tiny_ttf_cache_data_t), 128, ops); - lv_cache_set_name(tiny_ttf_cache, CACHE_NAME); -} - -void lv_tiny_ttf_deinit(void) -{ - lv_cache_destroy(tiny_ttf_cache, NULL); -} - /********************** * STATIC FUNCTIONS **********************/ @@ -205,31 +218,51 @@ static bool ttf_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * d dsc_out->is_placeholder = false; return true; } + ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; - int g1 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter); - if(g1 == 0) { - /* Glyph not found */ + + tiny_ttf_glyph_cache_data_t search_key = { + .unicode = unicode_letter, + }; + + lv_cache_entry_t * entry = lv_cache_acquire_or_create(dsc->glyph_cache, &search_key, (void *)dsc); + + if(entry == NULL) { + LV_LOG_ERROR("cache not allocated"); return false; } - int x1, y1, x2, y2; - stbtt_GetGlyphBitmapBox(&dsc->info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2); - int g2 = 0; - if(unicode_letter_next != 0) { - g2 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter_next); + tiny_ttf_glyph_cache_data_t * data = lv_cache_entry_get_data(entry); + *dsc_out = data->glyph_dsc; + + /*Kerning correction*/ + if(font->kerning == LV_FONT_KERNING_NORMAL && + unicode_letter_next != 0) { // check if we need to do any kerning calculations + uint32_t g1 = data->glyph_dsc.gid.index; + + int g2 = 0; + search_key.unicode = unicode_letter_next; // reuse search key + lv_cache_entry_t * entry_next = lv_cache_acquire_or_create(dsc->glyph_cache, &search_key, (void *)dsc); + + if(entry_next == NULL) + g2 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter_next); + else { + tiny_ttf_glyph_cache_data_t * data_next = lv_cache_entry_get_data(entry_next); + g2 = data_next->glyph_dsc.gid.index; + lv_cache_release(dsc->glyph_cache, entry_next, NULL); + } + + if(g2) { + int k = stbtt_GetGlyphKernAdvance(&dsc->info, g1, g2); + dsc_out->adv_w = (uint16_t)floor((((float)data->adv_w + (float)k) * dsc->scale) + + 0.5f); /*Horizontal space required by the glyph in [px]*/ + } } - int advw, lsb; - stbtt_GetGlyphHMetrics(&dsc->info, g1, &advw, &lsb); - int k = stbtt_GetGlyphKernAdvance(&dsc->info, g1, g2); - dsc_out->adv_w = (uint16_t)floor((((float)advw + (float)k) * dsc->scale) + - 0.5f); /*Horizontal space required by the glyph in [px]*/ - dsc_out->box_w = (x2 - x1 + 1); /*width of the bitmap in [px]*/ - dsc_out->box_h = (y2 - y1 + 1); /*height of the bitmap in [px]*/ - dsc_out->ofs_x = x1; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = -y2; /*Y offset of the bitmap measured from the as line*/ - dsc_out->format = LV_FONT_GLYPH_FORMAT_A8; - dsc_out->is_placeholder = false; - dsc_out->gid.index = (uint32_t)g1; + + dsc_out->entry = NULL; + + lv_cache_release(dsc->glyph_cache, entry, NULL); + return true; /*true: glyph found; false: glyph was not found*/ } @@ -238,13 +271,13 @@ static const void * ttf_get_glyph_bitmap_cb(lv_font_glyph_dsc_t * g_dsc, lv_draw LV_UNUSED(draw_buf); uint32_t glyph_index = g_dsc->gid.index; const lv_font_t * font = g_dsc->resolved_font; + ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; tiny_ttf_cache_data_t search_key = { - .font = (lv_font_t *)font, .glyph_index = glyph_index, .size = font->line_height, }; - lv_cache_entry_t * entry = lv_cache_acquire_or_create(tiny_ttf_cache, &search_key, (void *)font->dsc); + lv_cache_entry_t * entry = lv_cache_acquire_or_create(dsc->draw_data_cache, &search_key, (void *)font->dsc); if(entry == NULL) { LV_LOG_ERROR("cache not allocated"); @@ -262,15 +295,35 @@ static void ttf_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g if(g_dsc->entry == NULL) { return; } - lv_cache_release(tiny_ttf_cache, g_dsc->entry, NULL); + ttf_font_desc_t * dsc = (ttf_font_desc_t *)font->dsc; + lv_cache_release(dsc->draw_data_cache, g_dsc->entry, NULL); g_dsc->entry = NULL; } +static void lv_tiny_ttf_cache_create(ttf_font_desc_t * dsc) +{ + /*Init cache*/ + dsc->glyph_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(tiny_ttf_glyph_cache_data_t), dsc->cache_size, + (lv_cache_ops_t) { + .compare_cb = (lv_cache_compare_cb_t)tiny_ttf_glyph_cache_compare_cb, + .create_cb = (lv_cache_create_cb_t)tiny_ttf_glyph_cache_create_cb, + .free_cb = (lv_cache_free_cb_t)tiny_ttf_glyph_cache_free_cb + }); + lv_cache_set_name(dsc->glyph_cache, "TINY_TTF_GLYPH"); + + dsc->draw_data_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(tiny_ttf_cache_data_t), dsc->cache_size, + (lv_cache_ops_t) { + .compare_cb = (lv_cache_compare_cb_t)tiny_ttf_draw_data_cache_compare_cb, + .create_cb = (lv_cache_create_cb_t)tiny_ttf_draw_data_cache_create_cb, + .free_cb = (lv_cache_free_cb_t)tiny_ttf_draw_data_cache_free_cb, + }); + lv_cache_set_name(dsc->draw_data_cache, "TINY_TTF_DRAW_DATA"); +} + static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size_t data_size, int32_t font_size, - size_t cache_size) + lv_font_kerning_t kerning, size_t cache_size) { LV_UNUSED(data_size); - LV_UNUSED(cache_size); if((path == NULL && data == NULL) || 0 >= font_size) { LV_LOG_ERROR("tiny_ttf: invalid argument"); return NULL; @@ -308,12 +361,23 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size } #endif + dsc->cache_size = cache_size; + lv_font_t * out_font = lv_malloc_zeroed(sizeof(lv_font_t)); if(out_font == NULL) { lv_free(dsc); LV_LOG_ERROR("tiny_ttf: out of memory"); return NULL; } + + // check if font has kerning tables to use, else disable kerning automatically. + if(stbtt_KernTableCheck(&dsc->info) == 0) { + kerning = LV_FONT_KERNING_NONE; // disable kerning if font has no tables. + } + + dsc->kerning = kerning; + out_font->kerning = kerning; + out_font->get_glyph_dsc = ttf_get_glyph_dsc_cb; out_font->get_glyph_bitmap = ttf_get_glyph_bitmap_cb; out_font->release_glyph = ttf_release_glyph_cb; @@ -322,31 +386,89 @@ static lv_font_t * lv_tiny_ttf_create(const char * path, const void * data, size return out_font; } #if LV_TINY_TTF_FILE_SUPPORT != 0 -lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, int32_t font_size, size_t cache_size) +lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, int32_t font_size, lv_font_kerning_t kerning, + size_t cache_size) { - return lv_tiny_ttf_create(path, NULL, 0, font_size, cache_size); + return lv_tiny_ttf_create(path, NULL, 0, font_size, kerning, cache_size); } lv_font_t * lv_tiny_ttf_create_file(const char * path, int32_t font_size) { - return lv_tiny_ttf_create(path, NULL, 0, font_size, 0); + return lv_tiny_ttf_create(path, NULL, 0, font_size, LV_FONT_KERNING_NORMAL, LV_TINY_TTF_CACHE_GLYPH_CNT); } #endif -lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, int32_t font_size, size_t cache_size) + +lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, int32_t font_size, + lv_font_kerning_t kerning, size_t cache_size) { - return lv_tiny_ttf_create(NULL, data, data_size, font_size, cache_size); + return lv_tiny_ttf_create(NULL, data, data_size, font_size, kerning, cache_size); } lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, int32_t font_size) { - return lv_tiny_ttf_create(NULL, data, data_size, font_size, 0); + return lv_tiny_ttf_create(NULL, data, data_size, font_size, LV_FONT_KERNING_NORMAL, LV_TINY_TTF_CACHE_GLYPH_CNT); } /*----------------- * Cache Callbacks *----------------*/ -static bool tiny_ttf_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_data) +static bool tiny_ttf_glyph_cache_create_cb(tiny_ttf_glyph_cache_data_t * node, void * user_data) { + ttf_font_desc_t * dsc = (ttf_font_desc_t *)user_data; + lv_font_glyph_dsc_t * dsc_out = &node->glyph_dsc; + uint32_t unicode_letter = node->unicode; + + int g1 = stbtt_FindGlyphIndex(&dsc->info, (int)unicode_letter); + if(g1 == 0) { + /* Glyph not found */ + return false; + } + int x1, y1, x2, y2; + + stbtt_GetGlyphBitmapBox(&dsc->info, g1, dsc->scale, dsc->scale, &x1, &y1, &x2, &y2); + + int advw, lsb; + stbtt_GetGlyphHMetrics(&dsc->info, g1, &advw, &lsb); + if(dsc->kerning != LV_FONT_KERNING_NORMAL) { // calculate default advance + int k = stbtt_GetGlyphKernAdvance(&dsc->info, g1, 0); + dsc_out->adv_w = (uint16_t)floor((((float)advw + (float)k) * dsc->scale) + + 0.5f); /*Horizontal space required by the glyph in [px]*/ + } + else { + dsc_out->adv_w = (uint16_t)floor(((float)advw * dsc->scale) + + 0.5f); /*Horizontal space required by the glyph in [px]*/; + } + // precalculate no kerning value + node->adv_w = advw; + dsc_out->box_w = (x2 - x1 + 1); /*width of the bitmap in [px]*/ + dsc_out->box_h = (y2 - y1 + 1); /*height of the bitmap in [px]*/ + dsc_out->ofs_x = x1; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = -y2; /*Y offset of the bitmap measured from the as line*/ + dsc_out->format = LV_FONT_GLYPH_FORMAT_A8; + dsc_out->is_placeholder = false; + dsc_out->gid.index = (uint32_t)g1; + + return true; +} + +static void tiny_ttf_glyph_cache_free_cb(tiny_ttf_glyph_cache_data_t * node, void * user_data) +{ + LV_UNUSED(node); + LV_UNUSED(user_data); +} + +static lv_cache_compare_res_t tiny_ttf_glyph_cache_compare_cb(const tiny_ttf_glyph_cache_data_t * lhs, + const tiny_ttf_glyph_cache_data_t * rhs) +{ + if(lhs->unicode != rhs->unicode) { + return lhs->unicode > rhs->unicode ? 1 : -1; + } + + return 0; +} + +static bool tiny_ttf_draw_data_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_data) +{ ttf_font_desc_t * dsc = (ttf_font_desc_t *)user_data; const stbtt_fontinfo * info = (const stbtt_fontinfo *)&dsc->info; @@ -375,20 +497,16 @@ static bool tiny_ttf_cache_create_cb(tiny_ttf_cache_data_t * node, void * user_d return true; } -static void tiny_ttf_cache_free_cb(tiny_ttf_cache_data_t * node, void * user_data) +static void tiny_ttf_draw_data_cache_free_cb(tiny_ttf_cache_data_t * node, void * user_data) { LV_UNUSED(user_data); lv_draw_buf_destroy_user(font_draw_buf_handlers, node->draw_buf); } -static lv_cache_compare_res_t tiny_ttf_cache_compare_cb(const tiny_ttf_cache_data_t * lhs, - const tiny_ttf_cache_data_t * rhs) +static lv_cache_compare_res_t tiny_ttf_draw_data_cache_compare_cb(const tiny_ttf_cache_data_t * lhs, + const tiny_ttf_cache_data_t * rhs) { - if(lhs->font != rhs->font) { - return lhs->font > rhs->font ? 1 : -1; - } - if(lhs->glyph_index != rhs->glyph_index) { return lhs->glyph_index > rhs->glyph_index ? 1 : -1; } diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.h b/src/libs/tiny_ttf/lv_tiny_ttf.h index 2966ade76..b1bfd11b4 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.h +++ b/src/libs/tiny_ttf/lv_tiny_ttf.h @@ -34,18 +34,16 @@ extern "C" { lv_font_t * lv_tiny_ttf_create_file(const char * path, int32_t font_size); /* create a font from the specified file or path with the specified line height with the specified cache size.*/ -lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, int32_t font_size, size_t cache_size); +lv_font_t * lv_tiny_ttf_create_file_ex(const char * path, int32_t font_size, lv_font_kerning_t kerning, + size_t cache_size); #endif -void lv_tiny_ttf_init(void); - -void lv_tiny_ttf_deinit(void); - /* create a font from the specified data pointer with the specified line height.*/ lv_font_t * lv_tiny_ttf_create_data(const void * data, size_t data_size, int32_t font_size); /* create a font from the specified data pointer with the specified line height and the specified cache size.*/ -lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, int32_t font_size, size_t cache_size); +lv_font_t * lv_tiny_ttf_create_data_ex(const void * data, size_t data_size, int32_t font_size, + lv_font_kerning_t kerning, size_t cache_size); /* set the size of the font to a new font_size*/ void lv_tiny_ttf_set_size(lv_font_t * font, int32_t font_size); diff --git a/src/libs/tiny_ttf/stb_truetype_htcw.h b/src/libs/tiny_ttf/stb_truetype_htcw.h index 9efa0240b..1cd3e2abe 100644 --- a/src/libs/tiny_ttf/stb_truetype_htcw.h +++ b/src/libs/tiny_ttf/stb_truetype_htcw.h @@ -2854,7 +2854,47 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo * info, i } } } + return 0; +} +STBTT_DEF int stbtt_KernTableCheck(const stbtt_fontinfo * info) +{ + if(info->gpos) { + stbtt_uint16 lookupListOffset; + stbtt_uint32 lookupList; + stbtt_uint16 lookupCount; +#ifdef STBTT_STREAM_TYPE + STBTT_STREAM_TYPE data = info->data; +#else + const stbtt_uint8 * data = info->data; +#endif + stbtt_int32 i; + + if(!info->gpos) return 0; + + if(ttUSHORT(data, 0 + info->gpos) != 1) return 0; // Major version 1 + if(ttUSHORT(data, 2 + info->gpos) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data, 8 + info->gpos); + lookupList = lookupListOffset; + lookupCount = ttUSHORT(data, lookupList); + + for(i = 0; i < lookupCount; ++i) { + stbtt_uint16 lookupOffset = ttUSHORT(data, lookupList + 2 + 2 * i); + stbtt_uint32 lookupTable = lookupList + lookupOffset; + + stbtt_uint16 lookupType = ttUSHORT(data, lookupTable); + + if(lookupType != 2) // Pair Adjustment Positioning Subtable + continue; + + return 1; // we have a usable lookup table. + } + return 0; + } + else if(info->kern) { + return 1; + } return 0; } diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index bf1a6d340..8f3dfc9fb 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -2597,6 +2597,13 @@ #define LV_TINY_TTF_FILE_SUPPORT 0 #endif #endif + #ifndef LV_TINY_TTF_CACHE_GLYPH_CNT + #ifdef CONFIG_LV_TINY_TTF_CACHE_GLYPH_CNT + #define LV_TINY_TTF_CACHE_GLYPH_CNT CONFIG_LV_TINY_TTF_CACHE_GLYPH_CNT + #else + #define LV_TINY_TTF_CACHE_GLYPH_CNT 256 + #endif + #endif #endif /*Rlottie library*/ diff --git a/src/lv_init.c b/src/lv_init.c index 35a068342..53e090245 100644 --- a/src/lv_init.c +++ b/src/lv_init.c @@ -316,10 +316,6 @@ void lv_init(void) lv_freetype_init(LV_FREETYPE_CACHE_FT_GLYPH_CNT); #endif -#if LV_USE_TINY_TTF - lv_tiny_ttf_init(); -#endif - lv_initialized = true; LV_LOG_TRACE("finished"); @@ -357,10 +353,6 @@ void lv_deinit(void) lv_freetype_uninit(); #endif -#if LV_USE_TINY_TTF - lv_tiny_ttf_deinit(); -#endif - #if LV_USE_THEME_DEFAULT lv_theme_default_deinit(); #endif