diff --git a/include/lv_conf_v7.h b/include/lv_conf_v7.h index 1a702541..31db8745 100644 --- a/include/lv_conf_v7.h +++ b/include/lv_conf_v7.h @@ -357,10 +357,10 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in #define HASP_FONT_2 robotocondensed_regular_24_latin1 /* 5% Width */ #endif #ifndef HASP_FONT_3 -#define HASP_FONT_3 robotocondensed_regular_32_latin1 /* 10% Width */ +#define HASP_FONT_3 robotocondensed_regular_16_latin1 /* 10% Width */ #endif #ifndef HASP_FONT_4 -#define HASP_FONT_4 robotocondensed_regular_48_latin1 /* 10% Height */ +#define HASP_FONT_4 robotocondensed_regular_16_latin1 /* 10% Height */ #endif #ifndef ROBOTOCONDENSED_REGULAR_16_LATIN1 @@ -370,10 +370,10 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in #define ROBOTOCONDENSED_REGULAR_24_LATIN1 1 #endif #ifndef ROBOTOCONDENSED_REGULAR_32_LATIN1 -#define ROBOTOCONDENSED_REGULAR_32_LATIN1 1 +#define ROBOTOCONDENSED_REGULAR_32_LATIN1 0 #endif #ifndef ROBOTOCONDENSED_REGULAR_48_LATIN1 -#define ROBOTOCONDENSED_REGULAR_48_LATIN1 1 +#define ROBOTOCONDENSED_REGULAR_48_LATIN1 0 #endif #ifndef HASP_FONT_SIZE_1 diff --git a/lib/lv_lib_freetype/LICENSE b/lib/lv_lib_freetype/LICENSE new file mode 100644 index 00000000..cc227abe --- /dev/null +++ b/lib/lv_lib_freetype/LICENSE @@ -0,0 +1,21 @@ +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/lv_lib_freetype/README.md b/lib/lv_lib_freetype/README.md new file mode 100644 index 00000000..2bfbddb4 --- /dev/null +++ b/lib/lv_lib_freetype/README.md @@ -0,0 +1,44 @@ +# 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/lv_lib_freetype/arial.ttf b/lib/lv_lib_freetype/arial.ttf new file mode 100644 index 00000000..886789b8 Binary files /dev/null and b/lib/lv_lib_freetype/arial.ttf differ diff --git a/lib/lv_lib_freetype/lv_freetype.c b/lib/lv_lib_freetype/lv_freetype.c new file mode 100644 index 00000000..3c00d8b6 --- /dev/null +++ b/lib/lv_lib_freetype/lv_freetype.c @@ -0,0 +1,469 @@ +/** + * @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/lv_lib_freetype/lv_freetype.h b/lib/lv_lib_freetype/lv_freetype.h new file mode 100644 index 00000000..1b419b99 --- /dev/null +++ b/lib/lv_lib_freetype/lv_freetype.h @@ -0,0 +1,110 @@ +/** + * @file lv_freetype.h + * + */ +#ifndef _LV_FONT_TTF_H +#define _LV_FONT_TTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * 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 + +/********************* + * 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, + FT_FONT_STYLE_BOLD = 1 << 1 +} LV_FT_FONT_STYLE; + +typedef struct { + 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 + **********************/ + +/** + * init freetype library + * @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults. + * @param max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults. + * @param max_bytes Maximum number of bytes to use for cached data nodes. Use 0 for defaults. + * 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); + +/** + * Destroy freetype library + */ +void lv_freetype_destroy(void); + +/** + * Creates a font with info parameter specified. + * @param info See lv_ft_info_t for details. + * 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); + +/** + * Destroy a font that has been created. + * @param font pointer to font. + */ +void lv_ft_font_destroy(lv_font_t* font); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/lib/lv_lib_freetype/lv_fs_freetype.c b/lib/lv_lib_freetype/lv_fs_freetype.c new file mode 100644 index 00000000..967195ff --- /dev/null +++ b/lib/lv_lib_freetype/lv_fs_freetype.c @@ -0,0 +1,134 @@ +/** + * @file lv_fs_freetype.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include +#include "lv_fs_freetype.h" + +/********************* + * DEFINES + *********************/ +#if LV_USE_FS_IF +#include "lv_fs_if.h" + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +// FILE * fopen ( const char * filename, const char * mode ); +lv_ft_stream_t* lv_ft_fopen(const char* filename, const char* mode) +{ + lv_fs_file_t* file_p = malloc(sizeof(lv_fs_file_t)); // reserve memory + + if(file_p) { + lv_fs_mode_t rw = mode[0] == 'r' ? LV_FS_MODE_RD : LV_FS_MODE_WR; + lv_fs_res_t res = lv_fs_open(file_p, filename, rw); + + if(res == LV_FS_RES_OK) { // success + return (lv_ft_stream_t*)file_p; + } else { // error + free(file_p); // release memory + } + } + + return NULL; +} + +// int fclose ( FILE * stream ); +int lv_ft_fclose(lv_ft_stream_t* stream) +{ + lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream; + + lv_fs_close(f_ptr); + free(f_ptr); // release memory + + return 0; +} + +// size_t fread ( void * ptr, size_t size, size_t count, FILE * stream ); +size_t lv_ft_fread(void* ptr, size_t size, size_t count, lv_ft_stream_t* stream) +{ + lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream; + uint32_t bytes_read; + + lv_fs_res_t res = lv_fs_read(f_ptr, ptr, size * count, &bytes_read); + if(res != LV_FS_RES_OK) { // error + bytes_read = 0; + } + + return bytes_read; +} + +// long int ftell ( FILE * stream ); +int lv_ft_ftell(lv_ft_stream_t* stream) +{ + lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream; + uint32_t pos; + + lv_fs_res_t res = lv_fs_tell(f_ptr, &pos); + if(res == LV_FS_RES_OK) return pos; + + return -1; +} + +// int fseek ( FILE * stream, long int offset, int origin ); +int lv_ft_fseek(lv_ft_stream_t* stream, long int offset, int origin) +{ + lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream; + uint32_t start = 0; + + switch(origin) { + case SEEK_SET: + start = 0; + break; + + case SEEK_CUR: { + int pos = lv_ft_ftell(f_ptr); + if(pos < 0) { // error + return -1; + } + start = pos; + } break; + + case SEEK_END: { + lv_fs_res_t res = lv_fs_size(f_ptr, &start); + if(res != LV_FS_RES_OK) { // error + return -1; + } + break; + } + + default: + return -1; // Unknown origin + } + + if(start + offset < 0) { // underflow, go to beginning of the file + start = 0; + offset = 0; + } + + lv_fs_res_t res = lv_fs_seek(f_ptr, start + offset); + return res == LV_FS_RES_OK ? 0 : -1; +} + +#endif // LV_USE_FS_IF \ No newline at end of file diff --git a/lib/lv_lib_freetype/lv_fs_freetype.h b/lib/lv_lib_freetype/lv_fs_freetype.h new file mode 100644 index 00000000..bf7d131c --- /dev/null +++ b/lib/lv_lib_freetype/lv_fs_freetype.h @@ -0,0 +1,77 @@ +/** + * @file lv_fs_freetype.h + * + */ +#ifndef LV_FS_FREETYPE_H +#define LV_FS_FREETYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "lv_fs_if.h" + +/********************* + * DEFINES + *********************/ +#if LV_USE_FILESYSTEM + +/********************** + * TYPEDEFS + **********************/ +typedef void lv_ft_stream_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ +/** + * fopen glue for freetype library to access lv_fs api + * @param filename The full path to the file including lv_fs drive letter + * @param mode "r" for read, "w" fro write. + * @return A file stream pointer on success, NULL on error. + */ +lv_ft_stream_t* lv_ft_fopen(const char* filename, const char* mode); + +/** + * fclose glue for freetype library to access lv_fs api + * @param stream The file stream to close. + * @return Always 0. + */ +int lv_ft_fclose(lv_ft_stream_t* stream); + +/** + * fread glue for freetype library to access lv_fs api + * @param ptr The buffer read to. + * @param size Size of the read buffer. + * @param count The number of bytes to read. + * @param stream The file stream to read. + * @return The number of bytes read on success, otherwise 0. + */ +size_t lv_ft_fread(void* ptr, size_t size, size_t count, lv_ft_stream_t* stream); + +/** + * fseek glue for freetype library to access lv_fs api + * @param stream The file stream to seek. + * @param offset The offset from the origin position. + * @param origin The start position within the file, either SEEK_SET, SEEK_CUR or SEEK_END. + * @return 1 on success, otherwise 0. + */ +int lv_ft_fseek(lv_ft_stream_t* stream, long int offset, int origin); + +/** + * ftell glue for freetype library to access lv_fs api + * @param stream The file stream to tell. + * @return The current file cursor position on success, otherwise -1. + */ +int lv_ft_ftell(lv_ft_stream_t* stream); + +#endif // LV_USE_FILESYSTEM + +#ifdef __cplusplus +} +#endif + +#endif // LV_FS_FREETYPE_H diff --git a/user_setups/esp32/freetouchdeck.ini b/user_setups/esp32/freetouchdeck.ini index d962174f..85761453 100644 --- a/user_setups/esp32/freetouchdeck.ini +++ b/user_setups/esp32/freetouchdeck.ini @@ -5,7 +5,7 @@ ;***************************************************; [env:freetouchdeck] -extends = esp32_4mb +extends = esp32_8mb board = esp32dev build_flags =