mirror of
https://github.com/HASwitchPlate/openHASP.git
synced 2025-07-09 12:26:35 +00:00
Backport lv_lib_freetype from LVGL v8.x #249
This commit is contained in:
parent
a9859e7338
commit
651be6acb1
@ -3,11 +3,19 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
|
#include "lv_freetype.h"
|
||||||
|
#if HASP_USE_FREETYPE
|
||||||
|
|
||||||
|
#include "ft2build.h"
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_GLYPH_H
|
||||||
|
#include FT_CACHE_H
|
||||||
|
#include FT_SIZES_H
|
||||||
|
#include FT_IMAGE_H
|
||||||
|
#include FT_OUTLINE_H
|
||||||
|
|
||||||
#include "lv_freetype.h"
|
#include "lv_freetype.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -20,6 +28,8 @@
|
|||||||
#define ARDUINO_RUNNING_CORE 1
|
#define ARDUINO_RUNNING_CORE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define LV_USE_FT_STACK_SIZE 24 * 1024 // FreeType consumes a large amount of stack
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FreeType requires up to 32KB of stack to run, which overflows the stack of 8KB.
|
* FreeType requires up to 32KB of stack to run, which overflows the stack of 8KB.
|
||||||
*
|
*
|
||||||
@ -53,36 +63,60 @@ typedef bool FT_glyph_dsc_response;
|
|||||||
/**********************
|
/**********************
|
||||||
* TYPEDEFS
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
lv_ll_t face_ll;
|
||||||
|
} lv_faces_control_t;
|
||||||
|
|
||||||
|
typedef struct name_refer_t
|
||||||
|
{
|
||||||
|
const char* name; /* point to font name string */
|
||||||
|
int32_t cnt; /* reference count */
|
||||||
|
} name_refer_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
|
static void face_generic_finalizer_cache(void* object);
|
||||||
|
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);
|
||||||
|
#else
|
||||||
static FT_Face face_find_in_list(lv_ft_info_t* info);
|
static FT_Face face_find_in_list(lv_ft_info_t* info);
|
||||||
static void face_add_to_list(FT_Face face);
|
static void face_add_to_list(FT_Face face);
|
||||||
static void face_remove_from_list(FT_Face face);
|
static void face_remove_from_list(FT_Face face);
|
||||||
|
|
||||||
static void face_generic_finalizer(void* object);
|
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,
|
static bool lv_ft_font_init_nocache(lv_ft_info_t* info);
|
||||||
uint32_t unicode_letter_next);
|
static void lv_ft_font_destroy_nocache(lv_font_t* font);
|
||||||
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
|
#endif
|
||||||
|
|
||||||
|
static const char* name_refer_save(const char* name);
|
||||||
|
static void name_refer_del(const char* name);
|
||||||
|
static const char* name_refer_find(const char* name);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
**********************/
|
**********************/
|
||||||
static FT_Library library;
|
static FT_Library library;
|
||||||
|
static lv_ll_t names_ll;
|
||||||
|
|
||||||
#if LV_USE_FT_CACHE_MANAGER
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
static FTC_Manager cache_manager;
|
static FTC_Manager cache_manager;
|
||||||
static FTC_CMapCache cmap_cache;
|
static FTC_CMapCache cmap_cache;
|
||||||
|
static FT_Face current_face = NULL;
|
||||||
|
|
||||||
|
#if LV_FREETYPE_SBIT_CACHE
|
||||||
static FTC_SBitCache sbit_cache;
|
static FTC_SBitCache sbit_cache;
|
||||||
static FTC_SBit sbit;
|
static FTC_SBit sbit;
|
||||||
|
#else
|
||||||
|
static FTC_ImageCache image_cache;
|
||||||
|
static FT_Glyph image_glyph;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
static lv_faces_control_t face_control;
|
static lv_faces_control_t face_control;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* MACROS
|
* MACROS
|
||||||
@ -91,19 +125,20 @@ static lv_faces_control_t face_control;
|
|||||||
/**********************
|
/**********************
|
||||||
* GLOBAL FUNCTIONS
|
* 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*));
|
|
||||||
|
|
||||||
|
/*********************************************************************************************************************/
|
||||||
|
|
||||||
|
bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes)
|
||||||
|
{
|
||||||
FT_Error error = FT_Init_FreeType(&library);
|
FT_Error error = FT_Init_FreeType(&library);
|
||||||
if(error) {
|
if(error) {
|
||||||
LV_LOG_ERROR("init freeType error(%d)", error);
|
LV_LOG_ERROR("init freeType error(%d)", error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LV_USE_FT_CACHE_MANAGER
|
_lv_ll_init(&names_ll, sizeof(name_refer_t));
|
||||||
|
|
||||||
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
error = FTC_Manager_New(library, max_faces, max_sizes, max_bytes, font_face_requester, NULL, &cache_manager);
|
error = FTC_Manager_New(library, max_faces, max_sizes, max_bytes, font_face_requester, NULL, &cache_manager);
|
||||||
if(error) {
|
if(error) {
|
||||||
FT_Done_FreeType(library);
|
FT_Done_FreeType(library);
|
||||||
@ -117,11 +152,19 @@ bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes)
|
|||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LV_FREETYPE_SBIT_CACHE
|
||||||
error = FTC_SBitCache_New(cache_manager, &sbit_cache);
|
error = FTC_SBitCache_New(cache_manager, &sbit_cache);
|
||||||
if(error) {
|
if(error) {
|
||||||
LV_LOG_ERROR("Failed to open sbit cache");
|
LV_LOG_ERROR("Failed to open sbit cache");
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
error = FTC_ImageCache_New(cache_manager, &image_cache);
|
||||||
|
if(error) {
|
||||||
|
LV_LOG_ERROR("Failed to open image cache");
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// initialize the queues to send request and receive response
|
// initialize the queues to send request and receive response
|
||||||
FTRequestQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_request));
|
FTRequestQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_request));
|
||||||
@ -138,15 +181,17 @@ Fail:
|
|||||||
FT_Done_FreeType(library);
|
FT_Done_FreeType(library);
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
|
LV_UNUSED(max_faces);
|
||||||
LV_UNUSED(max_sizes);
|
LV_UNUSED(max_sizes);
|
||||||
LV_UNUSED(max_bytes);
|
LV_UNUSED(max_bytes);
|
||||||
|
_lv_ll_init(&face_control.face_ll, sizeof(FT_Face*));
|
||||||
return true;
|
return true;
|
||||||
#endif /* LV_USE_FT_CACHE_MANAGER */
|
#endif /* LV_FREETYPE_CACHE_SIZE */
|
||||||
}
|
}
|
||||||
|
|
||||||
void lv_freetype_destroy(void)
|
void lv_freetype_destroy(void)
|
||||||
{
|
{
|
||||||
#if LV_USE_FT_CACHE_MANAGER
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
FTC_Manager_Done(cache_manager);
|
FTC_Manager_Done(cache_manager);
|
||||||
#endif
|
#endif
|
||||||
FT_Done_FreeType(library);
|
FT_Done_FreeType(library);
|
||||||
@ -154,170 +199,82 @@ void lv_freetype_destroy(void)
|
|||||||
|
|
||||||
bool lv_ft_font_init(lv_ft_info_t* info)
|
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 LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
if(dsc == NULL) return false;
|
return lv_ft_font_init_cache(info);
|
||||||
|
|
||||||
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(1 || 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
|
#else
|
||||||
face_info = (lv_face_info_t*)face->generic.data;
|
return lv_ft_font_init_nocache(info);
|
||||||
face_info->cnt++;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Error error = FT_Set_Char_Size(face, 0, info->weight * 64, 0, 0);
|
|
||||||
if(error) {
|
|
||||||
lv_mem_free(face_info);
|
|
||||||
LV_LOG_WARN("set char size error(%d)", error);
|
|
||||||
goto Fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.ascender - dsc->face->size->metrics.descender ) >> 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)
|
void lv_ft_font_destroy(lv_font_t* font)
|
||||||
{
|
{
|
||||||
if(font == NULL) {
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
return;
|
lv_ft_font_destroy_cache(font);
|
||||||
}
|
|
||||||
|
|
||||||
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
|
#else
|
||||||
lv_face_info_t* face_info = (lv_face_info_t*)dsc->face->generic.data;
|
lv_ft_font_destroy_nocache(font);
|
||||||
face_info->cnt--;
|
|
||||||
if(face_info->cnt == 0) {
|
|
||||||
FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc->face);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
lv_mem_free(dsc->font);
|
|
||||||
lv_mem_free(dsc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC FUNCTIONS
|
* STATIC FUNCTIONS
|
||||||
**********************/
|
**********************/
|
||||||
static void face_generic_finalizer(void* object)
|
#if LV_FREETYPE_CACHE_SIZE >= 0
|
||||||
|
|
||||||
|
static void face_generic_finalizer_cache(void* object)
|
||||||
{
|
{
|
||||||
FT_Face face = (FT_Face)object;
|
FT_Face face = (FT_Face)object;
|
||||||
face_remove_from_list(face);
|
LV_LOG_WARN("face finalizer(%p)\n", 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)
|
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(library_is);
|
||||||
LV_UNUSED(req_data);
|
LV_UNUSED(req_data);
|
||||||
*aface = face_id;
|
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc = (lv_font_fmt_ft_dsc_t*)face_id;
|
||||||
|
FT_Error error;
|
||||||
|
if(dsc->mem) {
|
||||||
|
error = FT_New_Memory_Face(library, dsc->mem, dsc->mem_size, 0, aface);
|
||||||
|
} else {
|
||||||
|
error = FT_New_Face(library, dsc->name, 0, aface);
|
||||||
|
}
|
||||||
|
if(error) {
|
||||||
|
LV_LOG_ERROR("FT_New_Face error:%d\n", error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
(*aface)->generic.finalizer = face_generic_finalizer_cache;
|
||||||
return FT_Err_Ok;
|
return FT_Err_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_bold_glyph(const lv_font_t* font, FT_Face face, FT_UInt glyph_index, lv_font_glyph_dsc_t* dsc_out)
|
||||||
|
{
|
||||||
|
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc = (lv_font_fmt_ft_dsc_t*)(font->dsc);
|
||||||
|
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||||
|
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||||
|
int strength = 1 << 6;
|
||||||
|
FT_Outline_Embolden(&face->glyph->outline, strength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) {
|
||||||
|
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 bool get_glyph_dsc_cb_cache(const lv_font_t* font, lv_font_glyph_dsc_t* dsc_out, uint32_t unicode_letter,
|
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)
|
uint32_t unicode_letter_next)
|
||||||
{
|
{
|
||||||
@ -332,17 +289,54 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t* font, lv_font_glyph_dsc_t* d
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_font_fmt_ft_dsc_t* dsc = (lv_font_fmt_ft_dsc_t*)(font->user_data);
|
lv_font_fmt_ft_dsc_t* dsc = (lv_font_fmt_ft_dsc_t*)(font->dsc);
|
||||||
FT_Face face = dsc->face;
|
|
||||||
|
|
||||||
static FTC_ImageTypeRec desc_sbit_type;
|
FTC_FaceID face_id = (FTC_FaceID)dsc;
|
||||||
desc_sbit_type.face_id = (FTC_FaceID)face;
|
FT_Size face_size;
|
||||||
desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
struct FTC_ScalerRec_ scaler;
|
||||||
desc_sbit_type.height = dsc->weight;
|
scaler.face_id = face_id;
|
||||||
desc_sbit_type.width = dsc->weight;
|
scaler.width = dsc->height;
|
||||||
|
scaler.height = dsc->height;
|
||||||
|
scaler.pixel = 1;
|
||||||
|
if(FTC_Manager_LookupSize(cache_manager, &scaler, &face_size) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Face face = face_size->face;
|
||||||
FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap);
|
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_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);
|
// dsc_out->is_placeholder = glyph_index == 0;
|
||||||
|
|
||||||
|
if(dsc->style & FT_FONT_STYLE_ITALIC) {
|
||||||
|
FT_Matrix italic_matrix;
|
||||||
|
italic_matrix.xx = 1 << 16;
|
||||||
|
italic_matrix.xy = 0x5800;
|
||||||
|
italic_matrix.yx = 0;
|
||||||
|
italic_matrix.yy = 1 << 16;
|
||||||
|
FT_Set_Transform(face, &italic_matrix, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||||
|
current_face = face;
|
||||||
|
if(!get_bold_glyph(font, face, glyph_index, dsc_out)) {
|
||||||
|
current_face = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
FTC_ImageTypeRec desc_type;
|
||||||
|
desc_type.face_id = face_id;
|
||||||
|
desc_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||||
|
desc_type.height = dsc->height;
|
||||||
|
desc_type.width = dsc->height;
|
||||||
|
|
||||||
|
#if LV_FREETYPE_SBIT_CACHE
|
||||||
|
FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_type, glyph_index, &sbit, NULL);
|
||||||
|
if(error) {
|
||||||
|
LV_LOG_ERROR("SBitCache_Lookup error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
dsc_out->adv_w = sbit->xadvance;
|
dsc_out->adv_w = sbit->xadvance;
|
||||||
dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/
|
dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/
|
||||||
@ -350,91 +344,57 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t* font, lv_font_glyph_dsc_t* d
|
|||||||
dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/
|
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->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*/
|
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
|
||||||
|
#else
|
||||||
|
FT_Error error = FTC_ImageCache_Lookup(image_cache, &desc_type, glyph_index, &image_glyph, NULL);
|
||||||
|
if(error) {
|
||||||
|
LV_LOG_ERROR("ImageCache_Lookup error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(image_glyph->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||||
|
LV_LOG_ERROR("Glyph_To_Bitmap error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph;
|
||||||
|
dsc_out->adv_w = (glyph_bitmap->root.advance.x >> 16);
|
||||||
|
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*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
end:
|
||||||
|
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
|
||||||
|
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t* get_glyph_bitmap_cb_cache(const lv_font_t* font, uint32_t unicode_letter)
|
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);
|
LV_UNUSED(unicode_letter);
|
||||||
|
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc = (lv_font_fmt_ft_dsc_t*)(font->dsc);
|
||||||
|
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||||
|
if(current_face && current_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
|
||||||
|
return (const uint8_t*)(current_face->glyph->bitmap.buffer);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LV_FREETYPE_SBIT_CACHE
|
||||||
return (const uint8_t*)sbit->buffer;
|
return (const uint8_t*)sbit->buffer;
|
||||||
|
#else
|
||||||
|
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph;
|
||||||
|
return (const uint8_t*)glyph_bitmap->bitmap.buffer;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#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,
|
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)
|
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_request request;
|
||||||
static FT_glyph_dsc_response response;
|
static FT_glyph_dsc_response response;
|
||||||
|
|
||||||
@ -450,15 +410,6 @@ static bool get_glyph_dsc_cb(const lv_font_t* font, lv_font_glyph_dsc_t* dsc_out
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 FT_loop_task(void* pvParameters)
|
||||||
{
|
{
|
||||||
(void)pvParameters;
|
(void)pvParameters;
|
||||||
@ -480,4 +431,343 @@ void FT_loop_task(void* pvParameters)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
static bool lv_ft_font_init_cache(lv_ft_info_t* info)
|
||||||
|
{
|
||||||
|
size_t need_size = sizeof(lv_font_fmt_ft_dsc_t) + sizeof(lv_font_t);
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc = lv_mem_alloc(need_size);
|
||||||
|
if(dsc == NULL) return false;
|
||||||
|
_lv_memset_00(dsc, need_size);
|
||||||
|
|
||||||
|
dsc->font = (lv_font_t*)(((char*)dsc) + sizeof(lv_font_fmt_ft_dsc_t));
|
||||||
|
dsc->mem = info->mem;
|
||||||
|
dsc->mem_size = info->mem_size;
|
||||||
|
dsc->name = name_refer_save(info->name);
|
||||||
|
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;
|
||||||
|
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_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_dsc = get_glyph_dsc_cb;
|
||||||
|
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);
|
||||||
|
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_LOG_WARN("RemoveFaceID : %s %u", dsc->name, dsc->height);
|
||||||
|
|
||||||
|
FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc);
|
||||||
|
name_refer_del(dsc->name);
|
||||||
|
lv_mem_free(dsc);
|
||||||
|
font->dsc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* LV_FREETYPE_CACHE_SIZE */
|
||||||
|
|
||||||
|
static FT_Face face_find_in_list(lv_ft_info_t* info)
|
||||||
|
{
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc;
|
||||||
|
FT_Face* pface = _lv_ll_get_head(&face_control.face_ll);
|
||||||
|
while(pface) {
|
||||||
|
dsc = (lv_font_fmt_ft_dsc_t*)(*pface)->generic.data;
|
||||||
|
if(strcmp(dsc->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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// dsc_out->is_placeholder = glyph_index == 0;
|
||||||
|
|
||||||
|
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||||
|
if(error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
|
||||||
|
if(dsc->style & FT_FONT_STYLE_BOLD) {
|
||||||
|
int strength = 1 << 6;
|
||||||
|
FT_Outline_Embolden(&face->glyph->outline, strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dsc->style & FT_FONT_STYLE_ITALIC) {
|
||||||
|
FT_Matrix italic_matrix;
|
||||||
|
italic_matrix.xx = 1 << 16;
|
||||||
|
italic_matrix.xy = 0x5800;
|
||||||
|
italic_matrix.yx = 0;
|
||||||
|
italic_matrix.yy = 1 << 16;
|
||||||
|
FT_Outline_Transform(&face->glyph->outline, &italic_matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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*/
|
||||||
|
|
||||||
|
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
|
||||||
|
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
size_t need_size = sizeof(lv_font_fmt_ft_dsc_t) + sizeof(lv_font_t);
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc = lv_mem_alloc(need_size);
|
||||||
|
if(dsc == NULL) return false;
|
||||||
|
_lv_memset_00(dsc, need_size);
|
||||||
|
|
||||||
|
dsc->font = (lv_font_t*)(((char*)dsc) + sizeof(lv_font_fmt_ft_dsc_t));
|
||||||
|
dsc->mem = info->mem;
|
||||||
|
dsc->mem_size = info->mem_size;
|
||||||
|
dsc->name = name_refer_save(info->name);
|
||||||
|
dsc->height = info->weight;
|
||||||
|
dsc->style = info->style;
|
||||||
|
|
||||||
|
FT_Face face = face_find_in_list(info);
|
||||||
|
if(face == NULL) {
|
||||||
|
FT_Error error;
|
||||||
|
if(dsc->mem) {
|
||||||
|
error = FT_New_Memory_Face(library, dsc->mem, (FT_Long)dsc->mem_size, 0, &face);
|
||||||
|
} else {
|
||||||
|
error = FT_New_Face(library, dsc->name, 0, &face);
|
||||||
|
}
|
||||||
|
if(error) {
|
||||||
|
LV_LOG_WARN("create face error(%d)", error);
|
||||||
|
goto Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* link face and face info */
|
||||||
|
face->generic.data = dsc;
|
||||||
|
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;
|
||||||
|
|
||||||
|
lv_font_t* font = dsc->font;
|
||||||
|
font->dsc = dsc;
|
||||||
|
// font->get_glyph_dsc = get_glyph_dsc_cb_nocache;
|
||||||
|
font->get_glyph_dsc = get_glyph_dsc_cb;
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
name_refer_del(dsc->name);
|
||||||
|
lv_mem_free(dsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LV_FREETYPE_CACHE_SIZE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find name string in names list.name string cnt += 1 if find.
|
||||||
|
* @param name name string
|
||||||
|
* @return the string pointer of name.
|
||||||
|
*/
|
||||||
|
static const char* name_refer_find(const char* name)
|
||||||
|
{
|
||||||
|
name_refer_t* refer = _lv_ll_get_head(&names_ll);
|
||||||
|
while(refer) {
|
||||||
|
if(strcmp(refer->name, name) == 0) {
|
||||||
|
refer->cnt += 1;
|
||||||
|
return refer->name;
|
||||||
|
}
|
||||||
|
refer = _lv_ll_get_next(&names_ll, refer);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* del name string from list.
|
||||||
|
*/
|
||||||
|
static void name_refer_del(const char* name)
|
||||||
|
{
|
||||||
|
name_refer_t* refer = _lv_ll_get_head(&names_ll);
|
||||||
|
while(refer) {
|
||||||
|
if(strcmp(refer->name, name) == 0) {
|
||||||
|
refer->cnt -= 1;
|
||||||
|
if(refer->cnt <= 0) {
|
||||||
|
LV_LOG_WARN("Release String : %s", refer->name);
|
||||||
|
|
||||||
|
_lv_ll_remove(&names_ll, refer);
|
||||||
|
lv_mem_free((void*)refer->name);
|
||||||
|
lv_mem_free(refer);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
refer = _lv_ll_get_next(&names_ll, refer);
|
||||||
|
}
|
||||||
|
|
||||||
|
LV_LOG_WARN("name_in_names_del error(not find:%p).", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save name string to list.
|
||||||
|
* @param name name string
|
||||||
|
* @return Saved string pointer
|
||||||
|
*/
|
||||||
|
static const char* name_refer_save(const char* name)
|
||||||
|
{
|
||||||
|
const char* pos = name_refer_find(name);
|
||||||
|
if(pos) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_refer_t* refer = _lv_ll_ins_tail(&names_ll);
|
||||||
|
if(refer) {
|
||||||
|
uint32_t len = strlen(name) + 1;
|
||||||
|
refer->name = lv_mem_alloc(len);
|
||||||
|
if(refer->name) {
|
||||||
|
_lv_memcpy((void*)refer->name, name, len);
|
||||||
|
refer->cnt = 1;
|
||||||
|
return refer->name;
|
||||||
|
}
|
||||||
|
_lv_ll_remove(&names_ll, refer);
|
||||||
|
lv_mem_free(refer);
|
||||||
|
}
|
||||||
|
LV_LOG_WARN("save_name_to_names error(not memory).");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*LV_USE_FREETYPE*/
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
* @file lv_freetype.h
|
* @file lv_freetype.h
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef _LV_FONT_TTF_H
|
#ifndef LV_FREETYPE_H
|
||||||
#define _LV_FONT_TTF_H
|
#define LV_FREETYPE_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -12,59 +12,40 @@ extern "C" {
|
|||||||
/*********************
|
/*********************
|
||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
// #include "lvgl/lvgl.h" // TODO
|
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
#include "ft2build.h"
|
#if LV_USE_FREETYPE
|
||||||
#include FT_FREETYPE_H
|
|
||||||
#include FT_GLYPH_H
|
|
||||||
#include FT_CACHE_H
|
|
||||||
#include FT_SIZES_H
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
* DEFINES
|
* 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
|
* TYPEDEFS
|
||||||
**********************/
|
**********************/
|
||||||
typedef struct {
|
typedef enum { FT_FONT_STYLE_NORMAL = 0, FT_FONT_STYLE_ITALIC = 1 << 0, FT_FONT_STYLE_BOLD = 1 << 1 } LV_FT_FONT_STYLE;
|
||||||
uint16_t cnt;
|
|
||||||
char* name;
|
|
||||||
} lv_face_info_t;
|
|
||||||
|
|
||||||
typedef struct {
|
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 */
|
const char* name; /* The name of the font file */
|
||||||
|
const void* mem; /* The pointer of the font file */
|
||||||
|
size_t mem_size; /* The size of the memory */
|
||||||
lv_font_t* font; /* point to lvgl font */
|
lv_font_t* font; /* point to lvgl font */
|
||||||
uint16_t weight; /* font size */
|
uint16_t weight; /* font size */
|
||||||
uint16_t style; /* font style */
|
uint16_t style; /* font style */
|
||||||
} lv_ft_info_t;
|
} lv_ft_info_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
FT_Face face;
|
{
|
||||||
|
const void* mem;
|
||||||
|
const char* name;
|
||||||
|
size_t mem_size;
|
||||||
|
#if LV_FREETYPE_CACHE_SIZE < 0
|
||||||
FT_Size size;
|
FT_Size size;
|
||||||
|
#endif
|
||||||
lv_font_t* font;
|
lv_font_t* font;
|
||||||
uint16_t style;
|
uint16_t style;
|
||||||
uint16_t weight;
|
uint16_t height;
|
||||||
} lv_font_fmt_freetype_dsc_t;
|
} lv_font_fmt_ft_dsc_t;
|
||||||
|
|
||||||
typedef lv_font_fmt_freetype_dsc_t lv_font_fmt_ft_dsc_t;
|
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
@ -78,7 +59,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.
|
* Note that this value does not account for managed FT_Face and FT_Size objects.
|
||||||
* @return true on success, otherwise false.
|
* @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
|
* Destroy freetype library
|
||||||
@ -103,8 +84,10 @@ void lv_ft_font_destroy(lv_font_t* font);
|
|||||||
* MACROS
|
* MACROS
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
#endif /*LV_USE_FREETYPE*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif /* LV_FREETYPE_H */
|
||||||
|
@ -2,7 +2,14 @@
|
|||||||
|
|
||||||
#include "hasplib.h"
|
#include "hasplib.h"
|
||||||
#if HASP_USE_FREETYPE > 0
|
#if HASP_USE_FREETYPE > 0
|
||||||
|
|
||||||
|
#ifndef LV_USE_FREETYPE
|
||||||
|
#define LV_USE_FREETYPE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lv_freetype.h"
|
#include "lv_freetype.h"
|
||||||
|
#include "ft2build.h" // for FT_FREETYPE_H macro
|
||||||
|
#include FT_FREETYPE_H // for FREETYPE_VERSION macros
|
||||||
#else
|
#else
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -22,8 +29,19 @@ typedef struct
|
|||||||
{
|
{
|
||||||
char* payload; /* The payload with name and size */
|
char* payload; /* The payload with name and size */
|
||||||
lv_font_t* font; /* point to lvgl font */
|
lv_font_t* font; /* point to lvgl font */
|
||||||
|
uint8_t type;
|
||||||
} hasp_font_info_t;
|
} hasp_font_info_t;
|
||||||
|
|
||||||
|
bool font_dummy_glyph_dsc(const struct _lv_font_struct*, lv_font_glyph_dsc_t*, uint32_t letter, uint32_t letter_next)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* font_dummy_glyph_bitmap(const struct _lv_font_struct*, uint32_t)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void font_setup()
|
void font_setup()
|
||||||
{
|
{
|
||||||
_lv_ll_init(&hasp_fonts_ll, sizeof(hasp_font_info_t));
|
_lv_ll_init(&hasp_fonts_ll, sizeof(hasp_font_info_t));
|
||||||
@ -57,20 +75,15 @@ size_t font_split_payload(const char* payload)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void font_clear_list()
|
static void font_release(void* node)
|
||||||
{
|
{
|
||||||
if(_lv_ll_is_empty(&hasp_fonts_ll)) return;
|
|
||||||
|
|
||||||
void* node = _lv_ll_get_head(&hasp_fonts_ll);
|
|
||||||
while(node) {
|
|
||||||
|
|
||||||
hasp_font_info_t* font_p = (hasp_font_info_t*)node;
|
hasp_font_info_t* font_p = (hasp_font_info_t*)node;
|
||||||
if(font_p->font) {
|
if(font_p->font) {
|
||||||
if(font_p->font->user_data) { // It's a FreeType font
|
if(font_p->type = 1) { // It's a FreeType font
|
||||||
#if(HASP_USE_FREETYPE > 0)
|
#if(HASP_USE_FREETYPE > 0)
|
||||||
lv_ft_font_destroy(font_p->font);
|
lv_ft_font_destroy(font_p->font);
|
||||||
#endif
|
#endif
|
||||||
} else { // It's a binary font
|
} else if(font_p->type = 0) { // It's a binary font
|
||||||
hasp_font_free(font_p->font);
|
hasp_font_free(font_p->font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,10 +93,38 @@ void font_clear_list()
|
|||||||
LOG_DEBUG(TAG_FONT, F("Released font %s"), font_p->payload);
|
LOG_DEBUG(TAG_FONT, F("Released font %s"), font_p->payload);
|
||||||
hasp_free(font_p->payload);
|
hasp_free(font_p->payload);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_clear_list(const char* payload)
|
||||||
|
{
|
||||||
|
if(_lv_ll_is_empty(&hasp_fonts_ll)) return;
|
||||||
|
|
||||||
|
while(void* node = _lv_ll_get_head(&hasp_fonts_ll)) {
|
||||||
|
font_release(node);
|
||||||
_lv_ll_remove(&hasp_fonts_ll, node);
|
_lv_ll_remove(&hasp_fonts_ll, node);
|
||||||
lv_mem_free(node);
|
lv_mem_free(node);
|
||||||
node = _lv_ll_get_head(&hasp_fonts_ll);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void font_clear_list2(const char* payload)
|
||||||
|
{
|
||||||
|
hasp_font_info_t* font_p = (hasp_font_info_t*)_lv_ll_get_head(&hasp_fonts_ll);
|
||||||
|
while(font_p) {
|
||||||
|
if(font_p->type == 1) {
|
||||||
|
lv_font_fmt_ft_dsc_t* dsc = (lv_font_fmt_ft_dsc_t*)font_p->font->dsc;
|
||||||
|
if(strcmp(dsc->name, payload) == 0) { // name and size
|
||||||
|
lv_ft_font_destroy(font_p->font);
|
||||||
|
*font_p->font = HASP_FONT_1;
|
||||||
|
font_p->type = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if(strcmp(font_p->payload, payload) == 0) { // name and size
|
||||||
|
// LOG_DEBUG(TAG_FONT, F("Payload %s found => line height = %d - base_line = %d"), payload,
|
||||||
|
// font_p->font->line_height, font_p->font->base_line);
|
||||||
|
// return font_p->font;
|
||||||
|
// }
|
||||||
|
|
||||||
|
font_p = (hasp_font_info_t*)_lv_ll_get_next(&hasp_fonts_ll, font_p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +151,7 @@ static lv_font_t* font_add_to_list(const char* payload)
|
|||||||
snprintf_P(filename, sizeof(filename), PSTR("L:\\%s.bin"), payload);
|
snprintf_P(filename, sizeof(filename), PSTR("L:\\%s.bin"), payload);
|
||||||
lv_font_t* font = hasp_font_load(filename);
|
lv_font_t* font = hasp_font_load(filename);
|
||||||
char* name_p = NULL;
|
char* name_p = NULL;
|
||||||
|
uint8_t font_type = 0;
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32) && (HASP_USE_FREETYPE > 0)
|
#if defined(ARDUINO_ARCH_ESP32) && (HASP_USE_FREETYPE > 0)
|
||||||
char* ext[] = {"ttf", "otf"};
|
char* ext[] = {"ttf", "otf"};
|
||||||
@ -140,9 +182,12 @@ static lv_font_t* font_add_to_list(const char* payload)
|
|||||||
lv_ft_info_t info;
|
lv_ft_info_t info;
|
||||||
info.name = filename;
|
info.name = filename;
|
||||||
info.weight = size;
|
info.weight = size;
|
||||||
|
info.mem = NULL;
|
||||||
info.style = FT_FONT_STYLE_NORMAL;
|
info.style = FT_FONT_STYLE_NORMAL;
|
||||||
|
LOG_VERBOSE(TAG_FONT, F("Loading font %s size %d"), filename, size);
|
||||||
if(lv_ft_font_init(&info)) {
|
if(lv_ft_font_init(&info)) {
|
||||||
font = info.font;
|
font = info.font;
|
||||||
|
font_type = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +195,7 @@ static lv_font_t* font_add_to_list(const char* payload)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!font) return NULL;
|
if(!font) return NULL;
|
||||||
LOG_VERBOSE(TAG_FONT, F("Loaded font %s size %d"), filename, font->line_height);
|
LOG_VERBOSE(TAG_FONT, F("Loaded font %s line_height %d"), filename, font->line_height);
|
||||||
|
|
||||||
/* alloc payload str */
|
/* alloc payload str */
|
||||||
size_t len = strlen(payload);
|
size_t len = strlen(payload);
|
||||||
@ -164,6 +209,7 @@ static lv_font_t* font_add_to_list(const char* payload)
|
|||||||
|
|
||||||
new_font_item->payload = name_p;
|
new_font_item->payload = name_p;
|
||||||
new_font_item->font = font;
|
new_font_item->font = font;
|
||||||
|
new_font_item->type = font_type;
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
|
|
||||||
void font_setup();
|
void font_setup();
|
||||||
lv_font_t* get_font(const char* payload);
|
lv_font_t* get_font(const char* payload);
|
||||||
void font_clear_list();
|
void font_clear_list(const char* payload);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -41,6 +41,9 @@ build_flags =
|
|||||||
;-D CONFIG_LITTLEFS_FOR_IDF_3_2 ; obsolete in IDF 3.3
|
;-D CONFIG_LITTLEFS_FOR_IDF_3_2 ; obsolete in IDF 3.3
|
||||||
; -- FreeType build options ------------------------
|
; -- FreeType build options ------------------------
|
||||||
-D HASP_USE_FREETYPE=1
|
-D HASP_USE_FREETYPE=1
|
||||||
|
-D LV_USE_FREETYPE=1
|
||||||
|
-D LV_FREETYPE_SBIT_CACHE=1 ; use small bitmap cache
|
||||||
|
-D LV_FREETYPE_CACHE_SIZE=1 ; cache freetype font sizes
|
||||||
-D LV_USE_FT_CACHE_MANAGER=1 ; crashes without cache
|
-D LV_USE_FT_CACHE_MANAGER=1 ; crashes without cache
|
||||||
-D LVGL_FREETYPE_MAX_FACES=16 ; max number of FreeType faces in cache
|
-D LVGL_FREETYPE_MAX_FACES=16 ; max number of FreeType faces in cache
|
||||||
-D LVGL_FREETYPE_MAX_SIZES=16 ; max number of sizes in cache
|
-D LVGL_FREETYPE_MAX_SIZES=16 ; max number of sizes in cache
|
||||||
|
@ -48,6 +48,9 @@ build_flags =
|
|||||||
;-D CONFIG_LITTLEFS_FOR_IDF_3_2 ; obsolete in IDF 3.3
|
;-D CONFIG_LITTLEFS_FOR_IDF_3_2 ; obsolete in IDF 3.3
|
||||||
; -- FreeType build options ------------------------
|
; -- FreeType build options ------------------------
|
||||||
-D HASP_USE_FREETYPE=1
|
-D HASP_USE_FREETYPE=1
|
||||||
|
-D LV_USE_FREETYPE=1
|
||||||
|
-D LV_FREETYPE_SBIT_CACHE=1 ; use small bitmap cache
|
||||||
|
-D LV_FREETYPE_CACHE_SIZE=1 ; cache freetype font sizes
|
||||||
-D LV_USE_FT_CACHE_MANAGER=1 ; crashes without cache
|
-D LV_USE_FT_CACHE_MANAGER=1 ; crashes without cache
|
||||||
-D LVGL_FREETYPE_MAX_FACES=8 ; max number of FreeType faces in cache
|
-D LVGL_FREETYPE_MAX_FACES=8 ; max number of FreeType faces in cache
|
||||||
-D LVGL_FREETYPE_MAX_SIZES=8 ; max number of sizes in cache
|
-D LVGL_FREETYPE_MAX_SIZES=8 ; max number of sizes in cache
|
||||||
|
Loading…
x
Reference in New Issue
Block a user