diff --git a/src/font/lv_font.h b/src/font/lv_font.h index b6be57aa34..e6dbc89a31 100644 --- a/src/font/lv_font.h +++ b/src/font/lv_font.h @@ -50,7 +50,8 @@ typedef struct { uint8_t bpp: 4; /**< Bit-per-pixel: 1, 2, 4, 8*/ uint8_t is_placeholder: 1; /** Glyph is missing. But placeholder will still be displayed */ - lv_cache_entry_t * entry; + uint32_t glyph_index; /**< The index of the glyph in the font file. Used by the font cache*/ + lv_cache_entry_t * entry; /**< The cache entry of the glyph draw data. Used by the font cache*/ } lv_font_glyph_dsc_t; /** The bitmaps might be upscaled by 3 to achieve subpixel rendering.*/ diff --git a/src/libs/freetype/lv_freetype_glyph.c b/src/libs/freetype/lv_freetype_glyph.c new file mode 100644 index 0000000000..8c6dda29f1 --- /dev/null +++ b/src/libs/freetype/lv_freetype_glyph.c @@ -0,0 +1,196 @@ +/** + * @file lv_freetype_glyph.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_freetype_private.h" + +/********************* + * DEFINES + *********************/ +#if LV_USE_FREETYPE + +#define LV_FREETYPE_GLYPH_DSC_CACHE_SIZE (LV_FREETYPE_CACHE_FT_OUTLINES * 2) +/********************** + * TYPEDEFS + **********************/ +typedef struct _lv_freetype_glyph_cache_data_t { + uint32_t unicode; + uint32_t size; + + lv_font_glyph_dsc_t glyph_dsc; +} lv_freetype_glyph_cache_data_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, + uint32_t unicode_letter_next); + +static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data); +static void freetype_glyph_free_cb(lv_freetype_glyph_cache_data_t * data, void * user_data); +static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_cache_data_t * lhs, + const lv_freetype_glyph_cache_data_t * rhs); +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ +lv_cache_t * lv_freetype_glyph_cache_create(lv_freetype_font_dsc_t * dsc) +{ + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + + lv_cache_ops_t ops = { + .create_cb = (lv_cache_create_cb_t)freetype_glyph_create_cb, + .free_cb = (lv_cache_free_cb_t)freetype_glyph_free_cb, + .compare_cb = (lv_cache_compare_cb_t)freetype_glyph_compare_cb, + }; + + lv_cache_t * cache = lv_cache_create(&lv_cache_class_lru_rb_count + , sizeof(lv_freetype_glyph_cache_data_t), + LV_FREETYPE_GLYPH_DSC_CACHE_SIZE, + ops + ); + if(cache == NULL) { + LV_LOG_ERROR("lv_cache_create failed"); + return NULL; + } + + dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb; + return cache; +} + +void lv_freetype_glyph_cache_delete(lv_cache_t * cache) +{ + lv_cache_destroy(cache, NULL); +} + +static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, + uint32_t unicode_letter_next) +{ + LV_ASSERT_NULL(font); + LV_ASSERT_NULL(g_dsc); + + if(unicode_letter < 0x20) { + g_dsc->adv_w = 0; + g_dsc->box_h = 0; + g_dsc->box_w = 0; + g_dsc->ofs_x = 0; + g_dsc->ofs_y = 0; + g_dsc->bpp = 0; + return true; + } + + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + + lv_freetype_glyph_cache_data_t search_key = { + .unicode = unicode_letter, + .size = dsc->size, + }; + + lv_cache_t * glyph_cache = lv_freetype_get_glyph_cache(dsc); + + lv_cache_entry_t * entry = lv_cache_acquire_or_create(glyph_cache, &search_key, dsc); + if(entry == NULL) { + LV_LOG_ERROR("glyph lookup failed for unicode = %u", unicode_letter); + return false; + } + lv_freetype_glyph_cache_data_t * data = lv_cache_entry_get_data(entry); + *g_dsc = data->glyph_dsc; + + if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { + g_dsc->adv_w = g_dsc->box_w + g_dsc->ofs_x; + } + + g_dsc->entry = NULL; + + lv_cache_release(glyph_cache, entry, NULL); + return true; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/*----------------- + * Cache Callbacks + *----------------*/ + +static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data) +{ + lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data; + + FT_Error error; + + FT_Size ft_size = lv_freetype_lookup_size(dsc); + if(!ft_size) { + return false; + } + + lv_font_glyph_dsc_t * dsc_out = &data->glyph_dsc; + + FT_Face face = ft_size->face; + FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); + FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, data->unicode); + + FT_Set_Pixel_Sizes(face, 0, dsc->size); + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_COMPUTE_METRICS | FT_LOAD_NO_BITMAP); + if(error) { + FT_ERROR_MSG("FT_Load_Glyph", error); + return false; + } + + FT_GlyphSlot glyph = ft_size->face->glyph; + +#if LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE + dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->metrics.horiAdvance); + dsc_out->box_h = FT_F26DOT6_TO_INT(glyph->metrics.height); /*Height of the bitmap in [px]*/ + dsc_out->box_w = FT_F26DOT6_TO_INT(glyph->metrics.width); /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingX); /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingY - + glyph->metrics.height); /*Y offset of the bitmap measured from the as line*/ +#elif LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_BITMAP + FT_Bitmap * glyph_bitmap = &ft_size->face->glyph->bitmap; + + dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->advance.x); /*Width of the glyph in [pf]*/ + dsc_out->box_h = glyph_bitmap->rows; /*Height of the bitmap in [px]*/ + dsc_out->box_w = glyph_bitmap->width; /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = glyph->bitmap_top - + dsc_out->box_h; /*Y offset of the bitmap measured from the as line*/ +#endif + + dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + dsc_out->is_placeholder = glyph_index == 0; + dsc_out->glyph_index = glyph_index; + + return true; +} +static void freetype_glyph_free_cb(lv_freetype_glyph_cache_data_t * data, void * user_data) +{ + LV_UNUSED(data); + LV_UNUSED(user_data); +} +static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_cache_data_t * lhs, + const lv_freetype_glyph_cache_data_t * rhs) +{ + if(lhs->unicode != rhs->unicode) { + return lhs->unicode > rhs->unicode ? 1 : -1; + } + if(lhs->size != rhs->size) { + return lhs->size > rhs->size ? 1 : -1; + } + return 0; +} +#endif diff --git a/src/libs/freetype/lv_freetype_image.c b/src/libs/freetype/lv_freetype_image.c index 4cfe1d1c84..2c2dc9b234 100755 --- a/src/libs/freetype/lv_freetype_image.c +++ b/src/libs/freetype/lv_freetype_image.c @@ -20,36 +20,32 @@ **********************/ struct _lv_freetype_cache_context_t { - lv_cache_t * cache; - - FT_Face face; }; struct _lv_freetype_cache_node_t { + FT_Face face; + lv_cache_t * image_cache; + lv_cache_t * glyph_cache; +}; + +typedef struct _lv_freetype_image_cache_data_t { FT_UInt glyph_index; uint32_t size; - lv_font_glyph_dsc_t glyph_dsc; lv_draw_buf_t * draw_buf; -}; +} lv_freetype_image_cache_data_t; /********************** * STATIC PROTOTYPES **********************/ - -static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, - uint32_t unicode_letter, - uint32_t unicode_letter_next); - static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, uint8_t * bitmap_out); -static bool freetype_image_create_cb(lv_freetype_cache_node_t * data, void * user_data); -static void freetype_image_free_cb(lv_freetype_cache_node_t * node, void * user_data); -static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_cache_node_t * lhs, - const lv_freetype_cache_node_t * rhs); +static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void * user_data); +static void freetype_image_free_cb(lv_freetype_image_cache_data_t * node, void * user_data); +static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_cache_data_t * lhs, + const lv_freetype_image_cache_data_t * rhs); static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc); /********************** @@ -72,34 +68,18 @@ lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_conte LV_ASSERT_MALLOC(cache_ctx); lv_memzero(cache_ctx, sizeof(lv_freetype_cache_context_t)); - lv_cache_ops_t ops = { - .compare_cb = (lv_cache_compare_cb_t)freetype_image_compare_cb, - .create_cb = (lv_cache_create_cb_t)freetype_image_create_cb, - .free_cb = (lv_cache_free_cb_t)freetype_image_free_cb, - }; - - cache_ctx->cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_cache_node_t), - LV_FREETYPE_CACHE_FT_OUTLINES, ops); - if(cache_ctx->cache == NULL) { - LV_LOG_ERROR("lv_cache_create failed"); - lv_free(cache_ctx); - return NULL; - } - return cache_ctx; } void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_ctx) { LV_ASSERT_NULL(cache_ctx); - lv_cache_destroy(cache_ctx->cache, NULL); lv_free(cache_ctx); } bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc) { LV_ASSERT_FREETYPE_FONT_DSC(dsc); - dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb; dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb; dsc->font.release_glyph = freetype_image_release_cb; @@ -113,70 +93,50 @@ bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc) if(dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) { lv_freetype_italic_transform(face); } + + lv_freetype_cache_node_t * cache_node = lv_malloc_zeroed(sizeof(lv_freetype_cache_node_t)); + if(cache_node == NULL) { + LV_LOG_ERROR("cache_node alloc failed"); + return false; + } + + lv_cache_ops_t ops = { + .compare_cb = (lv_cache_compare_cb_t)freetype_image_compare_cb, + .create_cb = (lv_cache_create_cb_t)freetype_image_create_cb, + .free_cb = (lv_cache_free_cb_t)freetype_image_free_cb, + }; + + cache_node->image_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_image_cache_data_t), + LV_FREETYPE_CACHE_FT_OUTLINES, ops); + cache_node->glyph_cache = lv_freetype_glyph_cache_create(dsc); + if(cache_node->image_cache == NULL || cache_node->glyph_cache == NULL) { + LV_LOG_ERROR("lv_cache_create failed"); + return NULL; + } + + dsc->cache_node = cache_node; + return true; } void lv_freetype_on_font_delete(lv_freetype_font_dsc_t * dsc) { LV_ASSERT_FREETYPE_FONT_DSC(dsc); + lv_cache_destroy(dsc->cache_node->image_cache, NULL); + lv_freetype_glyph_cache_delete(dsc->cache_node->glyph_cache); + lv_free(dsc->cache_node); +} + +lv_cache_t * lv_freetype_get_glyph_cache(const lv_freetype_font_dsc_t * dsc) +{ + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + return dsc->cache_node->glyph_cache; } /********************** * STATIC FUNCTIONS **********************/ -static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, - uint32_t unicode_letter, - uint32_t unicode_letter_next) -{ - if(unicode_letter < 0x20) { - dsc_out->adv_w = 0; - dsc_out->box_h = 0; - dsc_out->box_w = 0; - dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; - dsc_out->bpp = 0; - return true; - } - - lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; - LV_ASSERT_FREETYPE_FONT_DSC(dsc); - - FT_Size ft_size = lv_freetype_lookup_size(dsc); - if(!ft_size) { - return false; - } - - FT_Face face = ft_size->face; - FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); - FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter); - dsc_out->is_placeholder = glyph_index == 0; - dsc->context->cache_context->face = face; - - lv_freetype_cache_node_t search_key = { - .glyph_index = glyph_index, - .size = dsc->size, - }; - - lv_cache_entry_t * entry = lv_cache_acquire_or_create(dsc->context->cache_context->cache, &search_key, dsc); - if(entry == NULL) { - LV_LOG_ERROR("glyph lookup failed for glyph_index = %u", glyph_index); - return false; - } - lv_freetype_cache_node_t * data = lv_cache_entry_get_data(entry); - *dsc_out = data->glyph_dsc; - - if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { - dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x; - } - - dsc_out->entry = NULL; - - lv_cache_release(dsc->context->cache_context->cache, entry, NULL); - return true; -} - static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, uint8_t * bitmap_out) @@ -195,19 +155,19 @@ static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_f FT_Face face = ft_size->face; FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter); - dsc->context->cache_context->face = face; + dsc->cache_node->face = face; - lv_cache_t * cache = dsc->context->cache_context->cache; + lv_cache_t * cache = dsc->cache_node->image_cache; - lv_freetype_cache_node_t search_key = { + lv_freetype_image_cache_data_t search_key = { .glyph_index = glyph_index, - .size = dsc->size + .size = dsc->size, }; lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache, &search_key, dsc); g_dsc->entry = entry; - lv_freetype_cache_node_t * cache_node = lv_cache_entry_get_data(entry); + lv_freetype_image_cache_data_t * cache_node = lv_cache_entry_get_data(entry); return cache_node->draw_buf->data; } @@ -216,7 +176,7 @@ static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_ { LV_ASSERT_NULL(font); lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; - lv_cache_release(dsc->context->cache_context->cache, g_dsc->entry, NULL); + lv_cache_release(dsc->cache_node->image_cache, g_dsc->entry, NULL); g_dsc->entry = NULL; } @@ -224,13 +184,13 @@ static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_ * Cache Callbacks *----------------*/ -static bool freetype_image_create_cb(lv_freetype_cache_node_t * data, void * user_data) +static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void * user_data) { lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data; FT_Error error; - FT_Face face = dsc->context->cache_context->face; + FT_Face face = dsc->cache_node->face; FT_Set_Pixel_Sizes(face, 0, dsc->size); error = FT_Load_Glyph(face, data->glyph_index, FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL); if(error) { @@ -252,33 +212,26 @@ static bool freetype_image_create_cb(lv_freetype_cache_node_t * data, void * use FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)glyph; - lv_font_glyph_dsc_t * dsc_out = &data->glyph_dsc; + uint16_t box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/ + uint16_t box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->adv_w = FT_F16DOT16_TO_INT(glyph_bitmap->root.advance.x); - dsc_out->box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/ - dsc_out->box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = glyph_bitmap->left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = glyph_bitmap->top - - glyph_bitmap->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + uint32_t stride = lv_draw_buf_width_to_stride(box_w, LV_COLOR_FORMAT_A8); + data->draw_buf = lv_draw_buf_create(box_w, box_h, LV_COLOR_FORMAT_A8, stride); - uint32_t stride = lv_draw_buf_width_to_stride(dsc_out->box_w, LV_COLOR_FORMAT_A8); - data->draw_buf = lv_draw_buf_create(dsc_out->box_w, dsc_out->box_h, LV_COLOR_FORMAT_A8, stride); - - for(int y = 0; y < dsc_out->box_h; ++y) { - lv_memcpy((uint8_t *)(data->draw_buf->data) + y * stride, glyph_bitmap->bitmap.buffer + y * dsc_out->box_w, - dsc_out->box_w); + for(int y = 0; y < box_h; ++y) { + lv_memcpy((uint8_t *)(data->draw_buf->data) + y * stride, glyph_bitmap->bitmap.buffer + y * box_w, + box_w); } return true; } -static void freetype_image_free_cb(lv_freetype_cache_node_t * data, void * user_data) +static void freetype_image_free_cb(lv_freetype_image_cache_data_t * data, void * user_data) { LV_UNUSED(user_data); lv_draw_buf_destroy(data->draw_buf); } -static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_cache_node_t * lhs, - const lv_freetype_cache_node_t * rhs) +static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_cache_data_t * lhs, + const lv_freetype_image_cache_data_t * rhs) { if(lhs->glyph_index != rhs->glyph_index) { return lhs->glyph_index > rhs->glyph_index ? 1 : -1; diff --git a/src/libs/freetype/lv_freetype_outline.c b/src/libs/freetype/lv_freetype_outline.c index 1fe494d78f..fb42fcc63f 100755 --- a/src/libs/freetype/lv_freetype_outline.c +++ b/src/libs/freetype/lv_freetype_outline.c @@ -17,8 +17,6 @@ #define LV_FREETYPE_OUTLINE_REF_SIZE_DEF 128 -#define LV_FREETYPE_GLYPH_DSC_CACHE_SIZE (LV_FREETYPE_CACHE_FT_OUTLINES * 2) - #if LV_FREETYPE_CACHE_FT_OUTLINES <= 0 #error "LV_FREETYPE_CACHE_FT_OUTLINES must be greater than 0" #endif @@ -34,12 +32,6 @@ struct _lv_freetype_cache_context_t { void * user_data; }; -typedef struct _lv_freetype_glyph_dsc_node_t { - FT_UInt glyph_index; - uint32_t size; - lv_font_glyph_dsc_t glyph_dsc; -} lv_freetype_glyph_dsc_node_t; - struct _lv_freetype_cache_node_t { lv_freetype_cache_context_t * cache_context; @@ -48,13 +40,12 @@ struct _lv_freetype_cache_node_t { lv_freetype_font_style_t style; FT_Face face; + /*glyph cache*/ + lv_cache_t * glyph_cache; + /*glyph outline cache*/ lv_cache_t * glyph_outline_cache; int outline_cnt; - - /*glyph size cache*/ - lv_cache_t * glyph_dsc_cache; - int dsc_cnt; }; typedef struct _lv_freetype_outline_node_t { @@ -69,15 +60,12 @@ typedef struct _lv_freetype_outline_node_t { static lv_freetype_outline_t outline_create(lv_freetype_context_t * ctx, FT_Face face, FT_UInt glyph_index, uint32_t size, uint32_t strength); static lv_result_t outline_delete(lv_freetype_cache_context_t * cache_context, lv_freetype_outline_t outline); -static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, - uint32_t unicode_letter_next); static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter, uint8_t * bitmap_out); static void freetype_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc); -static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_context_t * ctx, const char * pathname, - lv_freetype_font_style_t style); +static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_font_dsc_t * dsc, const char * pathname); static void lv_freetype_cache_node_drop(lv_freetype_font_dsc_t * dsc); static lv_cache_entry_t * lv_freetype_outline_lookup(lv_freetype_font_dsc_t * dsc, uint32_t unicode_letter); @@ -87,12 +75,6 @@ static void freetype_glyph_outline_free_cb(lv_freetype_outline_node_t * node, lv static lv_cache_compare_res_t freetype_glyph_outline_cmp_cb(const lv_freetype_outline_node_t * node_a, const lv_freetype_outline_node_t * node_b); -/*glyph dsc cache lru callbacks*/ -static bool freetype_glyph_dsc_create_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc); -static void freetype_glyph_dsc_free_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc); -static lv_cache_compare_res_t freetype_glyph_dsc_cmp_cb(const lv_freetype_glyph_dsc_node_t * node_a, - const lv_freetype_glyph_dsc_node_t * node_b); - /********************** * STATIC VARIABLES **********************/ @@ -142,8 +124,7 @@ void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_contex bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc) { LV_ASSERT_FREETYPE_FONT_DSC(dsc); - dsc->cache_node = lv_freetype_cache_node_lookup(dsc->context, lv_freetype_get_pathname(dsc->face_id), dsc->style); - dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb; + dsc->cache_node = lv_freetype_cache_node_lookup(dsc, lv_freetype_get_pathname(dsc->face_id)); dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb; dsc->font.release_glyph = freetype_release_glyph_cb; return true; @@ -206,6 +187,12 @@ bool lv_freetype_is_outline_font(const lv_font_t * font) return true; } +lv_cache_t * lv_freetype_get_glyph_cache(const lv_freetype_font_dsc_t * dsc) +{ + LV_ASSERT_FREETYPE_FONT_DSC(dsc); + return dsc->cache_node->glyph_cache; +} + /********************** * STATIC FUNCTIONS **********************/ @@ -214,12 +201,13 @@ bool lv_freetype_is_outline_font(const lv_font_t * font) * FACE CACHE *------------------*/ -static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_context_t * ctx, - const char * pathname, lv_freetype_font_style_t style) +static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_font_dsc_t * dsc, const char * pathname) { - LV_ASSERT_NULL(ctx); LV_ASSERT_NULL(pathname); + lv_freetype_context_t * ctx = dsc->context; + lv_freetype_font_style_t style = dsc->style; + lv_freetype_cache_context_t * cache_context = ctx->cache_context; lv_freetype_cache_node_t * cache; @@ -269,20 +257,13 @@ static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_cont cache->ref_cnt = 1; cache->cache_context = cache_context; - lv_cache_ops_t glyph_dsc_cache_ops = { - .create_cb = (lv_cache_create_cb_t)freetype_glyph_dsc_create_cb, - .free_cb = (lv_cache_free_cb_t)freetype_glyph_dsc_free_cb, - .compare_cb = (lv_cache_compare_cb_t)freetype_glyph_dsc_cmp_cb, - }; lv_cache_ops_t glyph_outline_cache_ops = { .create_cb = (lv_cache_create_cb_t)freetype_glyph_outline_create_cb, .free_cb = (lv_cache_free_cb_t)freetype_glyph_outline_free_cb, .compare_cb = (lv_cache_compare_cb_t)freetype_glyph_outline_cmp_cb, }; - cache->glyph_dsc_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_glyph_dsc_node_t), - LV_FREETYPE_GLYPH_DSC_CACHE_SIZE, - glyph_dsc_cache_ops); + cache->glyph_cache = lv_freetype_glyph_cache_create(dsc); cache->glyph_outline_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_outline_node_t), LV_FREETYPE_CACHE_FT_OUTLINES, glyph_outline_cache_ops); @@ -315,112 +296,11 @@ static void lv_freetype_cache_node_drop(lv_freetype_font_dsc_t * dsc) lv_ll_t * cache_ll = &cache_node->cache_context->cache_ll; _lv_ll_remove(cache_ll, cache_node); - lv_cache_destroy(cache_node->glyph_dsc_cache, dsc); lv_cache_destroy(cache_node->glyph_outline_cache, dsc); + lv_freetype_glyph_cache_delete(cache_node->glyph_cache); lv_free(cache_node); } -/*------------------- - * GLYPH DSC CACHE - *------------------*/ - -static bool freetype_glyph_dsc_create_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc) -{ - lv_font_glyph_dsc_t * dsc_out = &glyph_dsc_node->glyph_dsc; - - FT_UInt glyph_index = glyph_dsc_node->glyph_index; - /* cache miss, load dsc */ - FT_Size ft_size = lv_freetype_lookup_size(dsc); - if(!ft_size) { - return false; - } - - FT_Error error = FT_Load_Glyph(ft_size->face, glyph_index, FT_LOAD_COMPUTE_METRICS | FT_LOAD_NO_BITMAP); - if(error) { - FT_ERROR_MSG("FT_Load_Glyph", error); - return false; - } - - LV_LOG_INFO("glyph_index = %u, cnt = %d", glyph_index, ++dsc->cache_node->dsc_cnt); - - FT_GlyphSlot glyph = ft_size->face->glyph; - - dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->metrics.horiAdvance); - dsc_out->box_h = FT_F26DOT6_TO_INT(glyph->metrics.height); /*Height of the bitmap in [px]*/ - dsc_out->box_w = FT_F26DOT6_TO_INT(glyph->metrics.width); /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingX); /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingY - - glyph->metrics.height); /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - dsc_out->is_placeholder = glyph_index == 0; - - return true; -} - -static void freetype_glyph_dsc_free_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc) -{ - LV_UNUSED(glyph_dsc_node); - LV_UNUSED(dsc); - LV_LOG_INFO("cnt = %d", --dsc->cache_node->dsc_cnt); -} - -static lv_cache_compare_res_t freetype_glyph_dsc_cmp_cb(const lv_freetype_glyph_dsc_node_t * node_a, - const lv_freetype_glyph_dsc_node_t * node_b) -{ - if(node_a->glyph_index != node_b->glyph_index) - return (node_a->glyph_index > node_b->glyph_index) ? 1 : -1; - - if(node_a->size != node_b->size) - return (node_a->size > node_b->size) ? 1 : -1; - - return 0; -} - -static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, - uint32_t unicode_letter, - uint32_t unicode_letter_next) -{ - LV_ASSERT_NULL(font); - LV_ASSERT_NULL(dsc_out); - - if(unicode_letter < 0x20) { - dsc_out->adv_w = 0; - dsc_out->box_h = 0; - dsc_out->box_w = 0; - dsc_out->ofs_x = 0; - dsc_out->ofs_y = 0; - dsc_out->bpp = 0; - return true; - } - - lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc; - LV_ASSERT_FREETYPE_FONT_DSC(dsc); - - lv_freetype_cache_node_t * cache_node = dsc->cache_node; - - FT_UInt charmap_index = FT_Get_Charmap_Index(cache_node->face->charmap); - FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter); - - lv_freetype_glyph_dsc_node_t tmp_node; - tmp_node.glyph_index = glyph_index; - tmp_node.size = dsc->size; - - lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache_node->glyph_dsc_cache, &tmp_node, dsc); - if(entry == NULL) { - return false; - } - lv_freetype_glyph_dsc_node_t * new_node = lv_cache_entry_get_data(entry); - *dsc_out = new_node->glyph_dsc; - - if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { - dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x; - } - lv_cache_release(cache_node->glyph_dsc_cache, entry, NULL); - - return true; -} - /*------------------- * OUTLINE CACHE *------------------*/ diff --git a/src/libs/freetype/lv_freetype_private.h b/src/libs/freetype/lv_freetype_private.h index 0763d6cdae..d2b6d4d40b 100755 --- a/src/libs/freetype/lv_freetype_private.h +++ b/src/libs/freetype/lv_freetype_private.h @@ -105,6 +105,10 @@ lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_conte void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_ctx); +lv_cache_t * lv_freetype_glyph_cache_create(lv_freetype_font_dsc_t * dsc); + +void lv_freetype_glyph_cache_delete(lv_cache_t * cache); + bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc); void lv_freetype_on_font_delete(lv_freetype_font_dsc_t * dsc); @@ -113,6 +117,8 @@ void lv_freetype_italic_transform(FT_Face face); const char * lv_freetype_get_pathname(FTC_FaceID face_id); +lv_cache_t * lv_freetype_get_glyph_cache(const lv_freetype_font_dsc_t * dsc); + /********************** * MACROS **********************/