mirror of https://github.com/arendst/Tasmota.git
LVGL moved Freetype embedded in LVGL8
This commit is contained in:
parent
4e62d9bbac
commit
9958be83a8
|
@ -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.
|
|
|
@ -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)
|
|
|
@ -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" ]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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*/
|
|
@ -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,37 +12,16 @@ extern "C" {
|
||||||
/*********************
|
/*********************
|
||||||
* INCLUDES
|
* INCLUDES
|
||||||
*********************/
|
*********************/
|
||||||
// #include "lvgl/lvgl.h" // TODO
|
#include "../../../lvgl.h"
|
||||||
#include "lvgl.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
|
* 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 {
|
|
||||||
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 {
|
typedef enum {
|
||||||
FT_FONT_STYLE_NORMAL = 0,
|
FT_FONT_STYLE_NORMAL = 0,
|
||||||
FT_FONT_STYLE_ITALIC = 1 << 0,
|
FT_FONT_STYLE_ITALIC = 1 << 0,
|
||||||
|
@ -50,22 +29,12 @@ typedef enum {
|
||||||
} LV_FT_FONT_STYLE;
|
} LV_FT_FONT_STYLE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* name; /* The name of the font file */
|
const char * name; /* The name of the font file */
|
||||||
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 {
|
|
||||||
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
|
* 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.
|
* 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
|
||||||
|
@ -91,20 +60,22 @@ void lv_freetype_destroy(void);
|
||||||
* when success, lv_ft_info_t->font point to the font you created.
|
* when success, lv_ft_info_t->font point to the font you created.
|
||||||
* @return true on success, otherwise false.
|
* @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.
|
* Destroy a font that has been created.
|
||||||
* @param font pointer to font.
|
* @param font pointer to font.
|
||||||
*/
|
*/
|
||||||
void lv_ft_font_destroy(lv_font_t* font);
|
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 */
|
|
@ -20,7 +20,7 @@ extern "C" {
|
||||||
// #include "gif/lv_gif.h"
|
// #include "gif/lv_gif.h"
|
||||||
// #include "qrcode/lv_qrcode.h"
|
// #include "qrcode/lv_qrcode.h"
|
||||||
// #include "sjpg/lv_sjpg.h"
|
// #include "sjpg/lv_sjpg.h"
|
||||||
// #include "freetype/lv_freetype.h"
|
#include "freetype/lv_freetype.h"
|
||||||
// #include "rlottie/lv_rlottie.h"
|
// #include "rlottie/lv_rlottie.h"
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
|
|
|
@ -571,7 +571,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
|
||||||
#define LV_USE_QRCODE 0
|
#define LV_USE_QRCODE 0
|
||||||
|
|
||||||
/*FreeType library*/
|
/*FreeType library*/
|
||||||
#define LV_USE_FREETYPE 0
|
#define LV_USE_FREETYPE 1
|
||||||
#if LV_USE_FREETYPE
|
#if LV_USE_FREETYPE
|
||||||
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
||||||
# define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
# define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||||
|
|
|
@ -1131,4 +1131,15 @@
|
||||||
#include "user_config_override.h" // Configuration overrides for my_user_config.h
|
#include "user_config_override.h" // Configuration overrides for my_user_config.h
|
||||||
#endif
|
#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_
|
#endif // _MY_USER_CONFIG_H_
|
||||||
|
|
|
@ -28,11 +28,6 @@
|
||||||
#include "lv_berry.h"
|
#include "lv_berry.h"
|
||||||
#include "Adafruit_LvGL_Glue.h"
|
#include "Adafruit_LvGL_Glue.h"
|
||||||
|
|
||||||
#ifdef USE_LVGL_FREETYPE
|
|
||||||
#include "esp_task_wdt.h"
|
|
||||||
#include "lv_freetype.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Berry easy logging
|
// Berry easy logging
|
||||||
extern "C" {
|
extern "C" {
|
||||||
extern void berry_log_C(const char * berry_buf, ...);
|
extern void berry_log_C(const char * berry_buf, ...);
|
||||||
|
@ -126,7 +121,7 @@ extern "C" {
|
||||||
#ifdef USE_LVGL_FREETYPE
|
#ifdef USE_LVGL_FREETYPE
|
||||||
int argc = be_top(vm);
|
int argc = be_top(vm);
|
||||||
if (argc == 3 && be_isstring(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3)) {
|
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.name = be_tostring(vm, 1);
|
||||||
info.weight = be_toint(vm, 2);
|
info.weight = be_toint(vm, 2);
|
||||||
info.style = be_toint(vm, 3);
|
info.style = be_toint(vm, 3);
|
||||||
|
|
|
@ -214,6 +214,9 @@ extern "C" {
|
||||||
be_map_insert_int(vm, "program_free", ESP.getFreeSketchSpace() / 1024);
|
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, "heap_free", ESP_getFreeHeap() / 1024);
|
||||||
be_map_insert_int(vm, "frag", ESP_getHeapFragmentation());
|
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()) {
|
if (UsePSRAM()) {
|
||||||
be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024);
|
be_map_insert_int(vm, "psram", ESP.getPsramSize() / 1024);
|
||||||
be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024);
|
be_map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024);
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
|
|
||||||
#include "Adafruit_LvGL_Glue.h"
|
#include "Adafruit_LvGL_Glue.h"
|
||||||
|
|
||||||
#ifdef USE_LVGL_FREETYPE
|
|
||||||
#include "lv_freetype.h"
|
|
||||||
#endif // USE_LVGL_FREETYPE
|
|
||||||
|
|
||||||
Adafruit_LvGL_Glue * glue;
|
Adafruit_LvGL_Glue * glue;
|
||||||
|
|
||||||
// **************************************************
|
// **************************************************
|
||||||
|
|
Loading…
Reference in New Issue