From 9958be83a8b3fbad3c0c2bd287a2e6116259944e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Thu, 13 Jan 2022 19:32:16 +0100 Subject: [PATCH] LVGL moved Freetype embedded in LVGL8 --- lib/libesp32_lvgl/lv_lib_freetype/LICENSE | 21 - lib/libesp32_lvgl/lv_lib_freetype/README.md | 44 -- .../lv_lib_freetype/library.json | 15 - .../lv_lib_freetype/lv_freetype.c | 469 ----------------- .../src/extra/libs/freetype}/arial.ttf | Bin .../src/extra/libs/freetype/lv_freetype.c | 486 ++++++++++++++++++ .../src/extra/libs/freetype}/lv_freetype.h | 53 +- .../lvgl/src/extra/libs/lv_libs.h | 2 +- tasmota/lvgl_berry/tasmota_lv_conf.h | 2 +- tasmota/my_user_config.h | 11 + tasmota/xdrv_52_3_berry_lvgl.ino | 7 +- tasmota/xdrv_52_3_berry_tasmota.ino | 3 + tasmota/xdrv_54_lvgl.ino | 4 - 13 files changed, 515 insertions(+), 602 deletions(-) delete mode 100644 lib/libesp32_lvgl/lv_lib_freetype/LICENSE delete mode 100644 lib/libesp32_lvgl/lv_lib_freetype/README.md delete mode 100644 lib/libesp32_lvgl/lv_lib_freetype/library.json delete mode 100644 lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c rename lib/libesp32_lvgl/{lv_lib_freetype => lvgl/src/extra/libs/freetype}/arial.ttf (100%) create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c rename lib/libesp32_lvgl/{lv_lib_freetype => lvgl/src/extra/libs/freetype}/lv_freetype.h (60%) diff --git a/lib/libesp32_lvgl/lv_lib_freetype/LICENSE b/lib/libesp32_lvgl/lv_lib_freetype/LICENSE deleted file mode 100644 index cc227abed..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 LittlevGL - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/lib/libesp32_lvgl/lv_lib_freetype/README.md b/lib/libesp32_lvgl/lv_lib_freetype/README.md deleted file mode 100644 index 2bfbddb4e..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# FreeType integration with LVGL -Interface to FreeType to generate font bitmaps run time - -## Install FreeType -- Download Freetype from [here](https://sourceforge.net/projects/freetype/files/) -- `make` -- `sudo make install` - -## Add FreeType to your project -- Add include path: `/usr/include/freetype2` (for GCC: `-I/usr/include/freetype2 -L/usr/local/lib`) -- Add library: `freetype` (for GCC: `-L/usr/local/lib -lfreetype`) - -## Usage in LVGL - -To enable cache, set`LV_USE_FT_CACHE_MANAGER 1`in lv_freetype.h. - -```c -/* init freetype library */ -lv_freetype_init(64, 1, 0); - -/*Create a font*/ -lv_ft_info_t info; -info.name = "./lv_lib_freetype/arial.ttf""; -info.size = 16; -info.style = FT_FONT_STYLE_NORMAL; -lv_ft_font_init(&info); - -/*Create style with the new font*/ -static lv_style_t style; -lv_style_init(&style); -lv_style_set_text_font(&style, LV_STATE_DEFAULT, info.font); - -/*Create a label with the new style*/ -lv_obj_t * label = lv_label_create(lv_scr_act(), NULL); -lv_obj_add_style(label, LV_LABEL_PART_MAIN, &style); -lv_label_set_text(label, "Hello world"); - -/* free font */ -//lv_ft_font_destroy(info.font); -``` - -## Learn more -- FreeType [tutorial](https://www.freetype.org/freetype2/docs/tutorial/step1.html) -- LVGL's [font interface](https://docs.lvgl.io/v7/en/html/overview/font.html#add-a-new-font-engine) diff --git a/lib/libesp32_lvgl/lv_lib_freetype/library.json b/lib/libesp32_lvgl/lv_lib_freetype/library.json deleted file mode 100644 index f4269fb70..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/library.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name":"lv_lib_freetype", - "description":"Interface to FreeType to generate font bitmaps run time", - "keywords":"lvgl, freetype", - "license": "MIT License", - "repository": { - "type": "git", - "url": "https://github.com/lvgl/lv_lib_freetype" - }, - "frameworks": "arduino", - "platforms": "espressif32", - "build": { - "flags": [ "-DLV_LVGL_H_INCLUDE_SIMPLE", "-I$PROJECT_DIR/include", "-includetasmota_options.h" ] - } -} \ No newline at end of file diff --git a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c b/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c deleted file mode 100644 index 3c00d8b65..000000000 --- a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.c +++ /dev/null @@ -1,469 +0,0 @@ -/** - * @file lv_freetype.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_freetype.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" - -#if CONFIG_FREERTOS_UNICORE -#define ARDUINO_RUNNING_CORE 0 -#else -#define ARDUINO_RUNNING_CORE 1 -#endif - -/* - * FreeType requires up to 32KB of stack to run, which overflows the stack of 8KB. - * - * We delegate to a FreeRTOS sub-task with a bigger stack. - * - * Parameters are passed via a RequestQueue, and response back via ResponseQueue - * - * The function that uses this scheme is `get_glyph_dsc_cb()`` - * - */ - -QueueHandle_t FTRequestQueue; -QueueHandle_t FTResponseQueue; -TaskHandle_t FTTaskHandle; -void FT_loop_task(void *pvParameters); - -typedef struct FT_glyph_dsc_request { - const lv_font_t * font; - lv_font_glyph_dsc_t * dsc_out; - uint32_t unicode_letter; - uint32_t unicode_letter_next; -} FT_glyph_dsc_request; - -typedef bool FT_glyph_dsc_response; - - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ -static FT_Face face_find_in_list(lv_ft_info_t *info); -static void face_add_to_list(FT_Face face); -static void face_remove_from_list(FT_Face face); - -static void face_generic_finalizer(void* object); -static bool 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 * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter); - -#if LV_USE_FT_CACHE_MANAGER -static FT_Error font_face_requester(FTC_FaceID face_id, - FT_Library library_is,FT_Pointer req_data,FT_Face* aface); -#endif - - /********************** - * STATIC VARIABLES - **********************/ -static FT_Library library; - -#if LV_USE_FT_CACHE_MANAGER -static FTC_Manager cache_manager; -static FTC_CMapCache cmap_cache; -static FTC_SBitCache sbit_cache; -static FTC_SBit sbit; -#endif - -static lv_faces_control_t face_control; - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ -bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes) -{ - face_control.cnt = 0; - face_control.num = max_faces; - _lv_ll_init(&face_control.face_ll, sizeof(FT_Face *)); - - FT_Error error = FT_Init_FreeType(&library); - if (error) { - LV_LOG_ERROR("init freeType error(%d)", error); - return false; - } - -#if LV_USE_FT_CACHE_MANAGER - error = FTC_Manager_New(library, max_faces, max_sizes, - max_bytes, font_face_requester, NULL, &cache_manager); - if (error) { - FT_Done_FreeType(library); - LV_LOG_ERROR("Failed to open cache manager"); - return false; - } - - error = FTC_CMapCache_New(cache_manager, &cmap_cache); - if(error) { - LV_LOG_ERROR("Failed to open Cmap Cache"); - goto Fail; - } - - error = FTC_SBitCache_New(cache_manager, &sbit_cache); - if(error){ - LV_LOG_ERROR("Failed to open sbit cache"); - goto Fail; - } - - // initialize the queues to send request and receive response - FTRequestQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_request)); - FTResponseQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_response)); - - xTaskCreatePinnedToCore(FT_loop_task, "FreeType_task", LV_USE_FT_STACK_SIZE, NULL, 1, &FTTaskHandle, ARDUINO_RUNNING_CORE); - - if (FTRequestQueue && FTResponseQueue) { - return true; - } -Fail: - FTC_Manager_Done(cache_manager); - FT_Done_FreeType(library); - return false; -#else - LV_UNUSED(max_sizes); - LV_UNUSED(max_bytes); - return true; -#endif/* LV_USE_FT_CACHE_MANAGER */ -} - -void lv_freetype_destroy(void) -{ -#if LV_USE_FT_CACHE_MANAGER - FTC_Manager_Done(cache_manager); -#endif - FT_Done_FreeType(library); -} - -bool lv_ft_font_init(lv_ft_info_t *info) -{ - lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t)); - if(dsc == NULL) return false; - - dsc->font = lv_mem_alloc(sizeof(lv_font_t)); - if(dsc->font == NULL) { - lv_mem_free(dsc); - return false; - } - - lv_face_info_t *face_info = NULL; - FT_Face face = face_find_in_list(info); - if (face == NULL) { - if (face_control.cnt == face_control.num - 1) { - LV_LOG_WARN("face full"); - goto Fail; - } - face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1); - if(face_info == NULL) { - goto Fail; - } - FT_Error error = FT_New_Face(library, info->name, 0, &face); - if(error){ - lv_mem_free(face_info); - LV_LOG_WARN("create face error(%d)", error); - goto Fail; - } - - face_info->name = ((char *)face_info) + sizeof(lv_face_info_t); - strcpy(face_info->name, info->name); - face_info->cnt = 1; - face->generic.data = face_info; - face->generic.finalizer = face_generic_finalizer; - face_add_to_list(face); - } - else { -#if LV_USE_FT_CACHE_MANAGER == 0 - FT_Size size; - FT_Error error = FT_New_Size(face, &size); - if (error) { - goto Fail; - } - FT_Activate_Size(size); - FT_Reference_Face(face); -#else - face_info = (lv_face_info_t *)face->generic.data; - face_info->cnt++; -#endif - } - FT_Set_Pixel_Sizes(face, 0, info->weight); - - dsc->face = face; - dsc->size = face->size; - dsc->weight = info->weight; - dsc->style = info->style; - lv_font_t *font = dsc->font; - font->user_data = dsc; - font->get_glyph_dsc = get_glyph_dsc_cb; - font->get_glyph_bitmap = get_glyph_bitmap_cb; - font->line_height = (dsc->face->size->metrics.height >> 6); - font->base_line = -(dsc->face->size->metrics.descender >> 6); - font->subpx = LV_FONT_SUBPX_NONE; - font->underline_position = dsc->face->underline_position; - font->underline_thickness = dsc->face->underline_thickness; - font->dsc = NULL; - info->font = font; - return true; - -Fail: - lv_mem_free(dsc->font); - lv_mem_free(dsc); - return false; -} - -void lv_ft_font_destroy(lv_font_t* font) -{ - if (font == NULL) { - return; - } - - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - if (dsc) { -#if LV_USE_FT_CACHE_MANAGER == 0 - FT_Done_Size(dsc->size); - FT_Done_Face(dsc->face); -#else - lv_face_info_t *face_info = (lv_face_info_t *)dsc->face->generic.data; - face_info->cnt--; - if(face_info->cnt == 0){ - FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc->face); - } -#endif - lv_mem_free(dsc->font); - lv_mem_free(dsc); - } -} - -/********************** - * STATIC FUNCTIONS - **********************/ -static void face_generic_finalizer(void* object) -{ - FT_Face face = (FT_Face)object; - face_remove_from_list(face); - if(face->generic.data){ - lv_face_info_t *face_info = (lv_face_info_t *)face->generic.data; - lv_mem_free(face_info); - } - LV_LOG_INFO("face finalizer(%p)\n", face); -} - -static FT_Face face_find_in_list(lv_ft_info_t *info) -{ - lv_face_info_t *face_info; - FT_Face *pface = _lv_ll_get_head(&face_control.face_ll); - while(pface) { - face_info = (lv_face_info_t *)(*pface)->generic.data; - if (strcmp(face_info->name, info->name) == 0) { - return *pface; - } - pface = _lv_ll_get_next(&face_control.face_ll, pface); - } - - return NULL; -} - -static void face_add_to_list(FT_Face face) -{ - FT_Face *pface; - pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll); - *pface = face; - face_control.cnt++; -} - -static void face_remove_from_list(FT_Face face) -{ - FT_Face *pface = _lv_ll_get_head(&face_control.face_ll); - while(pface) { - if (*pface == face) { - _lv_ll_remove(&face_control.face_ll, pface); - lv_mem_free(pface); - face_control.cnt--; - break; - } - pface = _lv_ll_get_next(&face_control.face_ll, pface); - } -} - -#if LV_USE_FT_CACHE_MANAGER - -static FT_Error font_face_requester(FTC_FaceID face_id, - FT_Library library_is,FT_Pointer req_data,FT_Face* aface) -{ - LV_UNUSED(library_is); - LV_UNUSED(req_data); - *aface = face_id; - return FT_Err_Ok; -} - -static bool get_glyph_dsc_cb_cache(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ - LV_UNUSED(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_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - FT_Face face = dsc->face; - - static FTC_ImageTypeRec desc_sbit_type; - desc_sbit_type.face_id = (FTC_FaceID)face; - desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; - desc_sbit_type.height = dsc->weight; - desc_sbit_type.width = dsc->weight; - FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); - FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, (FTC_FaceID)face, charmap_index, unicode_letter); - FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_sbit_type, glyph_index, &sbit, NULL); - - dsc_out->adv_w = sbit->xadvance; - dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/ - dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - - return true; -} - -static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter) -{ - LV_UNUSED(font); - LV_UNUSED(unicode_letter); - return (const uint8_t *)sbit->buffer; -} - -#else/* LV_USE_FT_CACHE_MANAGER */ -// extern void berry_log_C(const char * berry_buf, ...); - -static bool get_glyph_dsc_cb_nocache(const lv_font_t * font, - lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) -{ - // berry_log_C(">> get_glyph_dsc_cb_nocache %i %i", unicode_letter, unicode_letter_next); - LV_UNUSED(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; - } - - FT_Error error; - FT_Face face; - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - face = dsc->face; - - FT_UInt glyph_index = FT_Get_Char_Index( face, unicode_letter ); - - if (face->size != dsc->size) { - // berry_log_C(">> FT_Activate_Size %i", dsc->size); - FT_Activate_Size(dsc->size); - } - - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT ); - // berry_log_C(">> after FT_Load_Glyph error = %i", error); - if (error){ - return false; - } - - error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL); - // berry_log_C(">> after FT_Render_Glyph error = %i", error); - if (error){ - return false; - } - - dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); - dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/ - dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/ - dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ - dsc_out->ofs_y = face->glyph->bitmap_top - face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ - dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ - - // berry_log_C("+++ adv_w %i, h %i, w %i, x %i, y %i", dsc_out->adv_w, dsc_out->box_h, dsc_out->box_w, dsc_out->ofs_x, dsc_out->ofs_y); - - return true; -} - -static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter) -{ - LV_UNUSED(unicode_letter); - lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data); - FT_Face face = dsc->face; - return (const uint8_t *)(face->glyph->bitmap.buffer); -} - -#endif/* LV_USE_FT_CACHE_MANAGER */ - -static bool 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 LV_USE_FT_CACHE_MANAGER -// return get_glyph_dsc_cb_cache(font, dsc_out, unicode_letter, unicode_letter_next); -// #else -// return get_glyph_dsc_cb_nocache(font, dsc_out, unicode_letter, unicode_letter_next); -// #endif - static FT_glyph_dsc_request request; - static FT_glyph_dsc_response response; - - request.font = font; - request.dsc_out = dsc_out; - request.unicode_letter = unicode_letter; - request.unicode_letter_next = unicode_letter_next; - xQueueSendToBack(FTRequestQueue, &request, portMAX_DELAY); - if (xQueueReceive(FTResponseQueue, &response, portMAX_DELAY)) { - return response; - } else { - return false; // should never happen - } -} - -static const uint8_t * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter) -{ -#if LV_USE_FT_CACHE_MANAGER - return get_glyph_bitmap_cb_cache(font, unicode_letter); -#else - return get_glyph_bitmap_cb_nocache(font, unicode_letter); -#endif -} - -void FT_loop_task(void *pvParameters) { - (void) pvParameters; - - while (1) { - FT_glyph_dsc_request request; - FT_glyph_dsc_response response; - - if (xQueueReceive(FTRequestQueue, &request, portMAX_DELAY)) { - #if LV_USE_FT_CACHE_MANAGER - response = get_glyph_dsc_cb_cache(request.font, request.dsc_out, request.unicode_letter, request.unicode_letter_next); - #else - response = get_glyph_dsc_cb_nocache(request.font, request.dsc_out, request.unicode_letter, request.unicode_letter_next); - #endif - xQueueSendToBack(FTResponseQueue, &response, portMAX_DELAY); // send back response - } - } -} \ No newline at end of file diff --git a/lib/libesp32_lvgl/lv_lib_freetype/arial.ttf b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/arial.ttf similarity index 100% rename from lib/libesp32_lvgl/lv_lib_freetype/arial.ttf rename to lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/arial.ttf diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c new file mode 100644 index 000000000..96f68af21 --- /dev/null +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.c @@ -0,0 +1,486 @@ +/** + * @file lv_freetype.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_freetype.h" +#if LV_USE_FREETYPE + +#include "ft2build.h" +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_CACHE_H +#include FT_SIZES_H + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + char * name; +} lv_face_info_t; + +typedef struct { + lv_ll_t face_ll; +} lv_faces_control_t; + +typedef struct { +#if LV_FREETYPE_CACHE_SIZE >= 0 + void * face_id; +#else + FT_Size size; +#endif + lv_font_t * font; + uint16_t style; + uint16_t height; +} lv_font_fmt_ft_dsc_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +#if LV_FREETYPE_CACHE_SIZE >= 0 +static FT_Error font_face_requester(FTC_FaceID face_id, + FT_Library library_is, FT_Pointer req_data, FT_Face * aface); +static bool lv_ft_font_init_cache(lv_ft_info_t * info); +static void lv_ft_font_destroy_cache(lv_font_t * font); +static bool lv_ft_font_init_cache(lv_ft_info_t * info); +static void lv_ft_font_destroy_cache(lv_font_t * font); +#else +static FT_Face face_find_in_list(lv_ft_info_t * info); +static void face_add_to_list(FT_Face face); +static void face_remove_from_list(FT_Face face); +static void face_generic_finalizer(void * object); +static bool lv_ft_font_init_nocache(lv_ft_info_t * info); +static void lv_ft_font_destroy_nocache(lv_font_t * font); +#endif + +/********************** +* STATIC VARIABLES +**********************/ +static FT_Library library; + +#if LV_FREETYPE_CACHE_SIZE >= 0 + static FTC_Manager cache_manager; + static FTC_CMapCache cmap_cache; + static FTC_SBitCache sbit_cache; + static FTC_SBit sbit; +#else + static lv_faces_control_t face_control; +#endif + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes) +{ + FT_Error error = FT_Init_FreeType(&library); + if(error) { + LV_LOG_ERROR("init freeType error(%d)", error); + return false; + } + +#if LV_FREETYPE_CACHE_SIZE >= 0 + error = FTC_Manager_New(library, max_faces, max_sizes, + max_bytes, font_face_requester, NULL, &cache_manager); + if(error) { + FT_Done_FreeType(library); + LV_LOG_ERROR("Failed to open cache manager"); + return false; + } + + error = FTC_CMapCache_New(cache_manager, &cmap_cache); + if(error) { + LV_LOG_ERROR("Failed to open Cmap Cache"); + goto Fail; + } + + error = FTC_SBitCache_New(cache_manager, &sbit_cache); + if(error) { + LV_LOG_ERROR("Failed to open sbit cache"); + goto Fail; + } + + return true; +Fail: + FTC_Manager_Done(cache_manager); + FT_Done_FreeType(library); + return false; +#else + LV_UNUSED(max_faces); + LV_UNUSED(max_sizes); + LV_UNUSED(max_bytes); + _lv_ll_init(&face_control.face_ll, sizeof(FT_Face *)); + return true; +#endif/* LV_FREETYPE_CACHE_SIZE */ +} + +void lv_freetype_destroy(void) +{ +#if LV_FREETYPE_CACHE_SIZE >= 0 + FTC_Manager_Done(cache_manager); +#endif + FT_Done_FreeType(library); +} + +bool lv_ft_font_init(lv_ft_info_t * info) +{ +#if LV_FREETYPE_CACHE_SIZE >= 0 + return lv_ft_font_init_cache(info); +#else + return lv_ft_font_init_nocache(info); +#endif +} + +void lv_ft_font_destroy(lv_font_t * font) +{ +#if LV_FREETYPE_CACHE_SIZE >= 0 + lv_ft_font_destroy_cache(font); +#else + lv_ft_font_destroy_nocache(font); +#endif +} + +/********************** + * STATIC FUNCTIONS + **********************/ +#if LV_FREETYPE_CACHE_SIZE >= 0 + +static FT_Error font_face_requester(FTC_FaceID face_id, + FT_Library library_is, FT_Pointer req_data, FT_Face * aface) +{ + LV_UNUSED(library_is); + LV_UNUSED(req_data); + + lv_face_info_t * info = (lv_face_info_t *)face_id; + FT_Error error = FT_New_Face(library, info->name, 0, aface); + if(error) { + LV_LOG_ERROR("FT_New_Face error:%d\n", error); + return error; + } + return FT_Err_Ok; +} + +static bool get_glyph_dsc_cb_cache(const lv_font_t * font, + lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) +{ + LV_UNUSED(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_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + + FT_Face face; + FTC_ImageTypeRec desc_sbit_type; + FTC_FaceID face_id = (FTC_FaceID)dsc->face_id; + FTC_Manager_LookupFace(cache_manager, face_id, &face); + + desc_sbit_type.face_id = face_id; + desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; + desc_sbit_type.height = dsc->height; + desc_sbit_type.width = dsc->height; + FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap); + FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, face_id, charmap_index, unicode_letter); + FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_sbit_type, glyph_index, &sbit, NULL); + if(error) { + LV_LOG_ERROR("SBitCache_Lookup error"); + } + + dsc_out->adv_w = sbit->xadvance; + dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/ + dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + + return true; +} + +static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter) +{ + LV_UNUSED(font); + LV_UNUSED(unicode_letter); + return (const uint8_t *)sbit->buffer; +} + +static bool lv_ft_font_init_cache(lv_ft_info_t * info) +{ + lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t)); + if(dsc == NULL) return false; + + dsc->font = lv_mem_alloc(sizeof(lv_font_t)); + if(dsc->font == NULL) { + lv_mem_free(dsc); + return false; + } + + lv_face_info_t * face_info = NULL; + face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1); + if(face_info == NULL) { + goto Fail; + } + face_info->name = ((char *)face_info) + sizeof(lv_face_info_t); + strcpy(face_info->name, info->name); + + dsc->face_id = face_info; + dsc->height = info->weight; + dsc->style = info->style; + + /* use to get font info */ + FT_Size face_size; + struct FTC_ScalerRec_ scaler; + scaler.face_id = (FTC_FaceID)dsc->face_id; + scaler.width = info->weight; + scaler.height = info->weight; + scaler.pixel = 1; + FT_Error error = FTC_Manager_LookupSize(cache_manager, &scaler, &face_size); + if(error) { + lv_mem_free(face_info); + LV_LOG_ERROR("Failed to LookupSize"); + goto Fail; + } + + lv_font_t * font = dsc->font; + font->dsc = dsc; + font->get_glyph_dsc = get_glyph_dsc_cb_cache; + font->get_glyph_bitmap = get_glyph_bitmap_cb_cache; + font->subpx = LV_FONT_SUBPX_NONE; + font->line_height = (face_size->face->size->metrics.height >> 6); + font->base_line = -(face_size->face->size->metrics.descender >> 6); + + FT_Fixed scale = face_size->face->size->metrics.y_scale; + int8_t thickness = FT_MulFix(scale, face_size->face->underline_thickness) >> 6; + font->underline_position = FT_MulFix(scale, face_size->face->underline_position) >> 6; + font->underline_thickness = thickness < 1 ? 1 : thickness; + + /* return to user */ + info->font = font; + + return true; + +Fail: + lv_mem_free(dsc->font); + lv_mem_free(dsc); + return false; +} + +void lv_ft_font_destroy_cache(lv_font_t * font) +{ + if(font == NULL) { + return; + } + + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + if(dsc) { + lv_mem_free(dsc->face_id); + lv_mem_free(dsc->font); + lv_mem_free(dsc); + } +} + +#else/* LV_FREETYPE_CACHE_SIZE */ + +static FT_Face face_find_in_list(lv_ft_info_t * info) +{ + lv_face_info_t * face_info; + FT_Face * pface = _lv_ll_get_head(&face_control.face_ll); + while(pface) { + face_info = (lv_face_info_t *)(*pface)->generic.data; + if(strcmp(face_info->name, info->name) == 0) { + return *pface; + } + pface = _lv_ll_get_next(&face_control.face_ll, pface); + } + + return NULL; +} + +static void face_add_to_list(FT_Face face) +{ + FT_Face * pface; + pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll); + *pface = face; +} + +static void face_remove_from_list(FT_Face face) +{ + FT_Face * pface = _lv_ll_get_head(&face_control.face_ll); + while(pface) { + if(*pface == face) { + _lv_ll_remove(&face_control.face_ll, pface); + lv_mem_free(pface); + break; + } + pface = _lv_ll_get_next(&face_control.face_ll, pface); + } +} + +static void face_generic_finalizer(void * object) +{ + FT_Face face = (FT_Face)object; + face_remove_from_list(face); + if(face->generic.data) { + lv_face_info_t * face_info = (lv_face_info_t *)face->generic.data; + lv_mem_free(face_info); + } + LV_LOG_INFO("face finalizer(%p)\n", face); +} + +static bool get_glyph_dsc_cb_nocache(const lv_font_t * font, + lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next) +{ + LV_UNUSED(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; + } + + FT_Error error; + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + FT_Face face = dsc->size->face; + + FT_UInt glyph_index = FT_Get_Char_Index(face, unicode_letter); + + if(face->size != dsc->size) { + FT_Activate_Size(dsc->size); + } + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { + return false; + } + + error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + if(error) { + return false; + } + + dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); + dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/ + dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/ + dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/ + dsc_out->ofs_y = face->glyph->bitmap_top - + face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ + dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/ + + return true; +} + +static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter) +{ + LV_UNUSED(unicode_letter); + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + FT_Face face = dsc->size->face; + return (const uint8_t *)(face->glyph->bitmap.buffer); +} + +static bool lv_ft_font_init_nocache(lv_ft_info_t * info) +{ + lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t)); + if(dsc == NULL) return false; + + dsc->font = lv_mem_alloc(sizeof(lv_font_t)); + if(dsc->font == NULL) { + lv_mem_free(dsc); + return false; + } + + lv_face_info_t * face_info = NULL; + FT_Face face = face_find_in_list(info); + if(face == NULL) { + face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1); + if(face_info == NULL) { + goto Fail; + } + FT_Error error = FT_New_Face(library, info->name, 0, &face); + if(error) { + lv_mem_free(face_info); + LV_LOG_WARN("create face error(%d)", error); + goto Fail; + } + + /* link face and face info */ + face_info->name = ((char *)face_info) + sizeof(lv_face_info_t); + strcpy(face_info->name, info->name); + face->generic.data = face_info; + face->generic.finalizer = face_generic_finalizer; + face_add_to_list(face); + } + else { + FT_Size size; + FT_Error error = FT_New_Size(face, &size); + if(error) { + goto Fail; + } + FT_Activate_Size(size); + FT_Reference_Face(face); + } + + FT_Set_Pixel_Sizes(face, 0, info->weight); + dsc->size = face->size; + dsc->height = info->weight; + dsc->style = info->style; + + lv_font_t * font = dsc->font; + font->dsc = dsc; + font->get_glyph_dsc = get_glyph_dsc_cb_nocache; + font->get_glyph_bitmap = get_glyph_bitmap_cb_nocache; + font->line_height = (face->size->metrics.height >> 6); + font->base_line = -(face->size->metrics.descender >> 6); + font->subpx = LV_FONT_SUBPX_NONE; + + FT_Fixed scale = face->size->metrics.y_scale; + int8_t thickness = FT_MulFix(scale, face->underline_thickness) >> 6; + font->underline_position = FT_MulFix(scale, face->underline_position) >> 6; + font->underline_thickness = thickness < 1 ? 1 : thickness; + + info->font = font; + return true; + +Fail: + lv_mem_free(dsc->font); + lv_mem_free(dsc); + return false; +} + +static void lv_ft_font_destroy_nocache(lv_font_t * font) +{ + if(font == NULL) { + return; + } + + lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); + if(dsc) { + FT_Face face = dsc->size->face; + FT_Done_Size(dsc->size); + FT_Done_Face(face); + lv_mem_free(dsc->font); + lv_mem_free(dsc); + } +} + +#endif/* LV_FREETYPE_CACHE_SIZE */ + +#endif /*LV_USE_FREETYPE*/ diff --git a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h similarity index 60% rename from lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.h rename to lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h index 1b419b99a..3f1fe7076 100644 --- a/lib/libesp32_lvgl/lv_lib_freetype/lv_freetype.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/freetype/lv_freetype.h @@ -2,8 +2,8 @@ * @file lv_freetype.h * */ -#ifndef _LV_FONT_TTF_H -#define _LV_FONT_TTF_H +#ifndef LV_FREETYPE_H +#define LV_FREETYPE_H #ifdef __cplusplus extern "C" { @@ -12,37 +12,16 @@ extern "C" { /********************* * INCLUDES *********************/ -// #include "lvgl/lvgl.h" // TODO -#include "lvgl.h" -#include "ft2build.h" -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include FT_CACHE_H -#include FT_SIZES_H +#include "../../../lvgl.h" +#if LV_USE_FREETYPE /********************* * DEFINES *********************/ -#ifndef LV_USE_FT_CACHE_MANAGER -#define LV_USE_FT_CACHE_MANAGER 0 -#endif - -#define LV_USE_FT_STACK_SIZE 24*1024 // FreeType consumes a large amount of stack /********************** * TYPEDEFS **********************/ -typedef struct { - uint16_t cnt; - char* name; -} lv_face_info_t; - -typedef struct { - uint16_t num; - uint16_t cnt; - lv_ll_t face_ll; -} lv_faces_control_t; - typedef enum { FT_FONT_STYLE_NORMAL = 0, FT_FONT_STYLE_ITALIC = 1 << 0, @@ -50,22 +29,12 @@ typedef enum { } LV_FT_FONT_STYLE; typedef struct { - const char* name; /* The name of the font file */ - lv_font_t* font; /* point to lvgl font */ + const char * name; /* The name of the font file */ + lv_font_t * font; /* point to lvgl font */ uint16_t weight; /* font size */ uint16_t style; /* font style */ } lv_ft_info_t; -typedef struct { - FT_Face face; - FT_Size size; - lv_font_t* font; - uint16_t style; - uint16_t weight; -} lv_font_fmt_freetype_dsc_t; - -typedef lv_font_fmt_freetype_dsc_t lv_font_fmt_ft_dsc_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -78,7 +47,7 @@ typedef lv_font_fmt_freetype_dsc_t lv_font_fmt_ft_dsc_t; * Note that this value does not account for managed FT_Face and FT_Size objects. * @return true on success, otherwise false. */ -bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes); +bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes); /** * Destroy freetype library @@ -91,20 +60,22 @@ void lv_freetype_destroy(void); * when success, lv_ft_info_t->font point to the font you created. * @return true on success, otherwise false. */ -bool lv_ft_font_init(lv_ft_info_t *info); +bool lv_ft_font_init(lv_ft_info_t * info); /** * Destroy a font that has been created. * @param font pointer to font. */ -void lv_ft_font_destroy(lv_font_t* font); +void lv_ft_font_destroy(lv_font_t * font); /********************** * MACROS **********************/ +#endif /*LV_USE_FREETYPE*/ + #ifdef __cplusplus } /* extern "C" */ #endif -#endif +#endif /* LV_FREETYPE_H */ diff --git a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h b/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h index c8e4fbb91..eb2d03532 100644 --- a/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h +++ b/lib/libesp32_lvgl/lvgl/src/extra/libs/lv_libs.h @@ -20,7 +20,7 @@ extern "C" { // #include "gif/lv_gif.h" // #include "qrcode/lv_qrcode.h" // #include "sjpg/lv_sjpg.h" -// #include "freetype/lv_freetype.h" +#include "freetype/lv_freetype.h" // #include "rlottie/lv_rlottie.h" /********************* diff --git a/tasmota/lvgl_berry/tasmota_lv_conf.h b/tasmota/lvgl_berry/tasmota_lv_conf.h index 63afa7ec9..92640e85c 100644 --- a/tasmota/lvgl_berry/tasmota_lv_conf.h +++ b/tasmota/lvgl_berry/tasmota_lv_conf.h @@ -571,7 +571,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/ #define LV_USE_QRCODE 0 /*FreeType library*/ -#define LV_USE_FREETYPE 0 +#define LV_USE_FREETYPE 1 #if LV_USE_FREETYPE /*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/ # define LV_FREETYPE_CACHE_SIZE (16 * 1024) diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 77cdacb54..7e4afb25d 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -1131,4 +1131,15 @@ #include "user_config_override.h" // Configuration overrides for my_user_config.h #endif +/*********************************************************************************************\ + * Post-process stack size adjustment +\*********************************************************************************************/ + +#if defined(USE_LVGL) && defined(USE_LVGL_FREETYPE) // Freetype requires a stack of at least 24KB + #if SET_ESP32_STACK_SIZE < (24 * 1024) + #undef SET_ESP32_STACK_SIZE + #define SET_ESP32_STACK_SIZE (24 * 1024) + #endif +#endif // USE_LVGL && USE_LVGL_FREETYPE + #endif // _MY_USER_CONFIG_H_ diff --git a/tasmota/xdrv_52_3_berry_lvgl.ino b/tasmota/xdrv_52_3_berry_lvgl.ino index 5571917a4..0f4ac4262 100644 --- a/tasmota/xdrv_52_3_berry_lvgl.ino +++ b/tasmota/xdrv_52_3_berry_lvgl.ino @@ -28,11 +28,6 @@ #include "lv_berry.h" #include "Adafruit_LvGL_Glue.h" -#ifdef USE_LVGL_FREETYPE -#include "esp_task_wdt.h" -#include "lv_freetype.h" -#endif - // Berry easy logging extern "C" { extern void berry_log_C(const char * berry_buf, ...); @@ -126,7 +121,7 @@ extern "C" { #ifdef USE_LVGL_FREETYPE int argc = be_top(vm); if (argc == 3 && be_isstring(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) { - lv_ft_info_t info; + lv_ft_info_t info = {}; info.name = be_tostring(vm, 1); info.weight = be_toint(vm, 2); info.style = be_toint(vm, 3); diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index db8ab31d9..c7c13c007 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -214,6 +214,9 @@ extern "C" { be_map_insert_int(vm, "program_free", ESP.getFreeSketchSpace() / 1024); be_map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); be_map_insert_int(vm, "frag", ESP_getHeapFragmentation()); + // give info about stack size + be_map_insert_int(vm, "stack_size", SET_ESP32_STACK_SIZE / 1024); + be_map_insert_int(vm, "stack_low", uxTaskGetStackHighWaterMark(nullptr) / 1024); if (UsePSRAM()) { be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index 763c55b54..dd4089b0c 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -32,10 +32,6 @@ #include "Adafruit_LvGL_Glue.h" -#ifdef USE_LVGL_FREETYPE - #include "lv_freetype.h" -#endif // USE_LVGL_FREETYPE - Adafruit_LvGL_Glue * glue; // **************************************************