Add lib/lv_lib_freetype

This commit is contained in:
fvanroie 2021-11-13 03:16:11 +01:00
parent 7f7c2f08c1
commit c7a008dd1d
9 changed files with 860 additions and 5 deletions

View File

@ -357,10 +357,10 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
#define HASP_FONT_2 robotocondensed_regular_24_latin1 /* 5% Width */ #define HASP_FONT_2 robotocondensed_regular_24_latin1 /* 5% Width */
#endif #endif
#ifndef HASP_FONT_3 #ifndef HASP_FONT_3
#define HASP_FONT_3 robotocondensed_regular_32_latin1 /* 10% Width */ #define HASP_FONT_3 robotocondensed_regular_16_latin1 /* 10% Width */
#endif #endif
#ifndef HASP_FONT_4 #ifndef HASP_FONT_4
#define HASP_FONT_4 robotocondensed_regular_48_latin1 /* 10% Height */ #define HASP_FONT_4 robotocondensed_regular_16_latin1 /* 10% Height */
#endif #endif
#ifndef ROBOTOCONDENSED_REGULAR_16_LATIN1 #ifndef ROBOTOCONDENSED_REGULAR_16_LATIN1
@ -370,10 +370,10 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
#define ROBOTOCONDENSED_REGULAR_24_LATIN1 1 #define ROBOTOCONDENSED_REGULAR_24_LATIN1 1
#endif #endif
#ifndef ROBOTOCONDENSED_REGULAR_32_LATIN1 #ifndef ROBOTOCONDENSED_REGULAR_32_LATIN1
#define ROBOTOCONDENSED_REGULAR_32_LATIN1 1 #define ROBOTOCONDENSED_REGULAR_32_LATIN1 0
#endif #endif
#ifndef ROBOTOCONDENSED_REGULAR_48_LATIN1 #ifndef ROBOTOCONDENSED_REGULAR_48_LATIN1
#define ROBOTOCONDENSED_REGULAR_48_LATIN1 1 #define ROBOTOCONDENSED_REGULAR_48_LATIN1 0
#endif #endif
#ifndef HASP_FONT_SIZE_1 #ifndef HASP_FONT_SIZE_1

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 LittlevGL
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,44 @@
# FreeType integration with LVGL
Interface to FreeType to generate font bitmaps run time
## Install FreeType
- Download Freetype from [here](https://sourceforge.net/projects/freetype/files/)
- `make`
- `sudo make install`
## Add FreeType to your project
- Add include path: `/usr/include/freetype2` (for GCC: `-I/usr/include/freetype2 -L/usr/local/lib`)
- Add library: `freetype` (for GCC: `-L/usr/local/lib -lfreetype`)
## Usage in LVGL
To enable cache, set`LV_USE_FT_CACHE_MANAGER 1`in lv_freetype.h.
```c
/* init freetype library */
lv_freetype_init(64, 1, 0);
/*Create a font*/
lv_ft_info_t info;
info.name = "./lv_lib_freetype/arial.ttf"";
info.size = 16;
info.style = FT_FONT_STYLE_NORMAL;
lv_ft_font_init(&info);
/*Create style with the new font*/
static lv_style_t style;
lv_style_init(&style);
lv_style_set_text_font(&style, LV_STATE_DEFAULT, info.font);
/*Create a label with the new style*/
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
lv_obj_add_style(label, LV_LABEL_PART_MAIN, &style);
lv_label_set_text(label, "Hello world");
/* free font */
//lv_ft_font_destroy(info.font);
```
## Learn more
- FreeType [tutorial](https://www.freetype.org/freetype2/docs/tutorial/step1.html)
- LVGL's [font interface](https://docs.lvgl.io/v7/en/html/overview/font.html#add-a-new-font-engine)

Binary file not shown.

View File

@ -0,0 +1,469 @@
/**
* @file lv_freetype.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_freetype.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif
/*
* FreeType requires up to 32KB of stack to run, which overflows the stack of 8KB.
*
* We delegate to a FreeRTOS sub-task with a bigger stack.
*
* Parameters are passed via a RequestQueue, and response back via ResponseQueue
*
* The function that uses this scheme is `get_glyph_dsc_cb()``
*
*/
QueueHandle_t FTRequestQueue;
QueueHandle_t FTResponseQueue;
TaskHandle_t FTTaskHandle;
void FT_loop_task(void *pvParameters);
typedef struct FT_glyph_dsc_request {
const lv_font_t * font;
lv_font_glyph_dsc_t * dsc_out;
uint32_t unicode_letter;
uint32_t unicode_letter_next;
} FT_glyph_dsc_request;
typedef bool FT_glyph_dsc_response;
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static FT_Face face_find_in_list(lv_ft_info_t *info);
static void face_add_to_list(FT_Face face);
static void face_remove_from_list(FT_Face face);
static void face_generic_finalizer(void* object);
static bool get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out,
uint32_t unicode_letter, uint32_t unicode_letter_next);
static const uint8_t * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter);
#if LV_USE_FT_CACHE_MANAGER
static FT_Error font_face_requester(FTC_FaceID face_id,
FT_Library library_is,FT_Pointer req_data,FT_Face* aface);
#endif
/**********************
* STATIC VARIABLES
**********************/
static FT_Library library;
#if LV_USE_FT_CACHE_MANAGER
static FTC_Manager cache_manager;
static FTC_CMapCache cmap_cache;
static FTC_SBitCache sbit_cache;
static FTC_SBit sbit;
#endif
static lv_faces_control_t face_control;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes)
{
face_control.cnt = 0;
face_control.num = max_faces;
_lv_ll_init(&face_control.face_ll, sizeof(FT_Face *));
FT_Error error = FT_Init_FreeType(&library);
if (error) {
LV_LOG_ERROR("init freeType error(%d)", error);
return false;
}
#if LV_USE_FT_CACHE_MANAGER
error = FTC_Manager_New(library, max_faces, max_sizes,
max_bytes, font_face_requester, NULL, &cache_manager);
if (error) {
FT_Done_FreeType(library);
LV_LOG_ERROR("Failed to open cache manager");
return false;
}
error = FTC_CMapCache_New(cache_manager, &cmap_cache);
if(error) {
LV_LOG_ERROR("Failed to open Cmap Cache");
goto Fail;
}
error = FTC_SBitCache_New(cache_manager, &sbit_cache);
if(error){
LV_LOG_ERROR("Failed to open sbit cache");
goto Fail;
}
// initialize the queues to send request and receive response
FTRequestQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_request));
FTResponseQueue = xQueueCreate(1, sizeof(FT_glyph_dsc_response));
xTaskCreatePinnedToCore(FT_loop_task, "FreeType_task", LV_USE_FT_STACK_SIZE, NULL, 1, &FTTaskHandle, ARDUINO_RUNNING_CORE);
if (FTRequestQueue && FTResponseQueue) {
return true;
}
Fail:
FTC_Manager_Done(cache_manager);
FT_Done_FreeType(library);
return false;
#else
LV_UNUSED(max_sizes);
LV_UNUSED(max_bytes);
return true;
#endif/* LV_USE_FT_CACHE_MANAGER */
}
void lv_freetype_destroy(void)
{
#if LV_USE_FT_CACHE_MANAGER
FTC_Manager_Done(cache_manager);
#endif
FT_Done_FreeType(library);
}
bool lv_ft_font_init(lv_ft_info_t *info)
{
lv_font_fmt_ft_dsc_t * dsc = lv_mem_alloc(sizeof(lv_font_fmt_ft_dsc_t));
if(dsc == NULL) return false;
dsc->font = lv_mem_alloc(sizeof(lv_font_t));
if(dsc->font == NULL) {
lv_mem_free(dsc);
return false;
}
lv_face_info_t *face_info = NULL;
FT_Face face = face_find_in_list(info);
if (face == NULL) {
if (face_control.cnt == face_control.num - 1) {
LV_LOG_WARN("face full");
goto Fail;
}
face_info = lv_mem_alloc(sizeof(lv_face_info_t) + strlen(info->name) + 1);
if(face_info == NULL) {
goto Fail;
}
FT_Error error = FT_New_Face(library, info->name, 0, &face);
if(error){
lv_mem_free(face_info);
LV_LOG_WARN("create face error(%d)", error);
goto Fail;
}
face_info->name = ((char *)face_info) + sizeof(lv_face_info_t);
strcpy(face_info->name, info->name);
face_info->cnt = 1;
face->generic.data = face_info;
face->generic.finalizer = face_generic_finalizer;
face_add_to_list(face);
}
else {
#if LV_USE_FT_CACHE_MANAGER == 0
FT_Size size;
FT_Error error = FT_New_Size(face, &size);
if (error) {
goto Fail;
}
FT_Activate_Size(size);
FT_Reference_Face(face);
#else
face_info = (lv_face_info_t *)face->generic.data;
face_info->cnt++;
#endif
}
FT_Set_Pixel_Sizes(face, 0, info->weight);
dsc->face = face;
dsc->size = face->size;
dsc->weight = info->weight;
dsc->style = info->style;
lv_font_t *font = dsc->font;
font->user_data = dsc;
font->get_glyph_dsc = get_glyph_dsc_cb;
font->get_glyph_bitmap = get_glyph_bitmap_cb;
font->line_height = (dsc->face->size->metrics.height >> 6);
font->base_line = -(dsc->face->size->metrics.descender >> 6);
font->subpx = LV_FONT_SUBPX_NONE;
font->underline_position = dsc->face->underline_position;
font->underline_thickness = dsc->face->underline_thickness;
font->dsc = NULL;
info->font = font;
return true;
Fail:
lv_mem_free(dsc->font);
lv_mem_free(dsc);
return false;
}
void lv_ft_font_destroy(lv_font_t* font)
{
if (font == NULL) {
return;
}
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data);
if (dsc) {
#if LV_USE_FT_CACHE_MANAGER == 0
FT_Done_Size(dsc->size);
FT_Done_Face(dsc->face);
#else
lv_face_info_t *face_info = (lv_face_info_t *)dsc->face->generic.data;
face_info->cnt--;
if(face_info->cnt == 0){
FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc->face);
}
#endif
lv_mem_free(dsc->font);
lv_mem_free(dsc);
}
}
/**********************
* STATIC FUNCTIONS
**********************/
static void face_generic_finalizer(void* object)
{
FT_Face face = (FT_Face)object;
face_remove_from_list(face);
if(face->generic.data){
lv_face_info_t *face_info = (lv_face_info_t *)face->generic.data;
lv_mem_free(face_info);
}
LV_LOG_INFO("face finalizer(%p)\n", face);
}
static FT_Face face_find_in_list(lv_ft_info_t *info)
{
lv_face_info_t *face_info;
FT_Face *pface = _lv_ll_get_head(&face_control.face_ll);
while(pface) {
face_info = (lv_face_info_t *)(*pface)->generic.data;
if (strcmp(face_info->name, info->name) == 0) {
return *pface;
}
pface = _lv_ll_get_next(&face_control.face_ll, pface);
}
return NULL;
}
static void face_add_to_list(FT_Face face)
{
FT_Face *pface;
pface = (FT_Face *)_lv_ll_ins_tail(&face_control.face_ll);
*pface = face;
face_control.cnt++;
}
static void face_remove_from_list(FT_Face face)
{
FT_Face *pface = _lv_ll_get_head(&face_control.face_ll);
while(pface) {
if (*pface == face) {
_lv_ll_remove(&face_control.face_ll, pface);
lv_mem_free(pface);
face_control.cnt--;
break;
}
pface = _lv_ll_get_next(&face_control.face_ll, pface);
}
}
#if LV_USE_FT_CACHE_MANAGER
static FT_Error font_face_requester(FTC_FaceID face_id,
FT_Library library_is,FT_Pointer req_data,FT_Face* aface)
{
LV_UNUSED(library_is);
LV_UNUSED(req_data);
*aface = face_id;
return FT_Err_Ok;
}
static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
{
LV_UNUSED(unicode_letter_next);
if(unicode_letter < 0x20) {
dsc_out->adv_w = 0;
dsc_out->box_h = 0;
dsc_out->box_w = 0;
dsc_out->ofs_x = 0;
dsc_out->ofs_y = 0;
dsc_out->bpp = 0;
return true;
}
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data);
FT_Face face = dsc->face;
static FTC_ImageTypeRec desc_sbit_type;
desc_sbit_type.face_id = (FTC_FaceID)face;
desc_sbit_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
desc_sbit_type.height = dsc->weight;
desc_sbit_type.width = dsc->weight;
FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap);
FT_UInt glyph_index = FTC_CMapCache_Lookup(cmap_cache, (FTC_FaceID)face, charmap_index, unicode_letter);
FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_sbit_type, glyph_index, &sbit, NULL);
dsc_out->adv_w = sbit->xadvance;
dsc_out->box_h = sbit->height; /*Height of the bitmap in [px]*/
dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = sbit->left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = sbit->top - sbit->height; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
return true;
}
static const uint8_t * get_glyph_bitmap_cb_cache(const lv_font_t * font, uint32_t unicode_letter)
{
LV_UNUSED(font);
LV_UNUSED(unicode_letter);
return (const uint8_t *)sbit->buffer;
}
#else/* LV_USE_FT_CACHE_MANAGER */
// extern void berry_log_C(const char * berry_buf, ...);
static bool get_glyph_dsc_cb_nocache(const lv_font_t * font,
lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
{
// berry_log_C(">> get_glyph_dsc_cb_nocache %i %i", unicode_letter, unicode_letter_next);
LV_UNUSED(unicode_letter_next);
if(unicode_letter < 0x20) {
dsc_out->adv_w = 0;
dsc_out->box_h = 0;
dsc_out->box_w = 0;
dsc_out->ofs_x = 0;
dsc_out->ofs_y = 0;
dsc_out->bpp = 0;
return true;
}
FT_Error error;
FT_Face face;
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data);
face = dsc->face;
FT_UInt glyph_index = FT_Get_Char_Index( face, unicode_letter );
if (face->size != dsc->size) {
// berry_log_C(">> FT_Activate_Size %i", dsc->size);
FT_Activate_Size(dsc->size);
}
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT );
// berry_log_C(">> after FT_Load_Glyph error = %i", error);
if (error){
return false;
}
error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL);
// berry_log_C(">> after FT_Render_Glyph error = %i", error);
if (error){
return false;
}
dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6);
dsc_out->box_h = face->glyph->bitmap.rows; /*Height of the bitmap in [px]*/
dsc_out->box_w = face->glyph->bitmap.width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = face->glyph->bitmap_top - face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
// berry_log_C("+++ adv_w %i, h %i, w %i, x %i, y %i", dsc_out->adv_w, dsc_out->box_h, dsc_out->box_w, dsc_out->ofs_x, dsc_out->ofs_y);
return true;
}
static const uint8_t * get_glyph_bitmap_cb_nocache(const lv_font_t * font, uint32_t unicode_letter)
{
LV_UNUSED(unicode_letter);
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->user_data);
FT_Face face = dsc->face;
return (const uint8_t *)(face->glyph->bitmap.buffer);
}
#endif/* LV_USE_FT_CACHE_MANAGER */
static bool get_glyph_dsc_cb(const lv_font_t * font,
lv_font_glyph_dsc_t * dsc_out, uint32_t unicode_letter, uint32_t unicode_letter_next)
{
// #if LV_USE_FT_CACHE_MANAGER
// return get_glyph_dsc_cb_cache(font, dsc_out, unicode_letter, unicode_letter_next);
// #else
// return get_glyph_dsc_cb_nocache(font, dsc_out, unicode_letter, unicode_letter_next);
// #endif
static FT_glyph_dsc_request request;
static FT_glyph_dsc_response response;
request.font = font;
request.dsc_out = dsc_out;
request.unicode_letter = unicode_letter;
request.unicode_letter_next = unicode_letter_next;
xQueueSendToBack(FTRequestQueue, &request, portMAX_DELAY);
if (xQueueReceive(FTResponseQueue, &response, portMAX_DELAY)) {
return response;
} else {
return false; // should never happen
}
}
static const uint8_t * get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter)
{
#if LV_USE_FT_CACHE_MANAGER
return get_glyph_bitmap_cb_cache(font, unicode_letter);
#else
return get_glyph_bitmap_cb_nocache(font, unicode_letter);
#endif
}
void FT_loop_task(void *pvParameters) {
(void) pvParameters;
while (1) {
FT_glyph_dsc_request request;
FT_glyph_dsc_response response;
if (xQueueReceive(FTRequestQueue, &request, portMAX_DELAY)) {
#if LV_USE_FT_CACHE_MANAGER
response = get_glyph_dsc_cb_cache(request.font, request.dsc_out, request.unicode_letter, request.unicode_letter_next);
#else
response = get_glyph_dsc_cb_nocache(request.font, request.dsc_out, request.unicode_letter, request.unicode_letter_next);
#endif
xQueueSendToBack(FTResponseQueue, &response, portMAX_DELAY); // send back response
}
}
}

View File

@ -0,0 +1,110 @@
/**
* @file lv_freetype.h
*
*/
#ifndef _LV_FONT_TTF_H
#define _LV_FONT_TTF_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
// #include "lvgl/lvgl.h" // TODO
#include "lvgl.h"
#include "ft2build.h"
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_CACHE_H
#include FT_SIZES_H
/*********************
* DEFINES
*********************/
#ifndef LV_USE_FT_CACHE_MANAGER
#define LV_USE_FT_CACHE_MANAGER 0
#endif
#define LV_USE_FT_STACK_SIZE 24*1024 // FreeType consumes a large amount of stack
/**********************
* TYPEDEFS
**********************/
typedef struct {
uint16_t cnt;
char* name;
} lv_face_info_t;
typedef struct {
uint16_t num;
uint16_t cnt;
lv_ll_t face_ll;
} lv_faces_control_t;
typedef enum {
FT_FONT_STYLE_NORMAL = 0,
FT_FONT_STYLE_ITALIC = 1 << 0,
FT_FONT_STYLE_BOLD = 1 << 1
} LV_FT_FONT_STYLE;
typedef struct {
const char* name; /* The name of the font file */
lv_font_t* font; /* point to lvgl font */
uint16_t weight; /* font size */
uint16_t style; /* font style */
} lv_ft_info_t;
typedef struct {
FT_Face face;
FT_Size size;
lv_font_t* font;
uint16_t style;
uint16_t weight;
} lv_font_fmt_freetype_dsc_t;
typedef lv_font_fmt_freetype_dsc_t lv_font_fmt_ft_dsc_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* init freetype library
* @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults.
* @param max_sizes Maximum number of opened FT_Size objects managed by this cache instance. Use 0 for defaults.
* @param max_bytes Maximum number of bytes to use for cached data nodes. Use 0 for defaults.
* Note that this value does not account for managed FT_Face and FT_Size objects.
* @return true on success, otherwise false.
*/
bool lv_freetype_init(FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes);
/**
* Destroy freetype library
*/
void lv_freetype_destroy(void);
/**
* Creates a font with info parameter specified.
* @param info See lv_ft_info_t for details.
* when success, lv_ft_info_t->font point to the font you created.
* @return true on success, otherwise false.
*/
bool lv_ft_font_init(lv_ft_info_t *info);
/**
* Destroy a font that has been created.
* @param font pointer to font.
*/
void lv_ft_font_destroy(lv_font_t* font);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@ -0,0 +1,134 @@
/**
* @file lv_fs_freetype.c
*
*/
/*********************
* INCLUDES
*********************/
#include <stdlib.h>
#include "lv_fs_freetype.h"
/*********************
* DEFINES
*********************/
#if LV_USE_FS_IF
#include "lv_fs_if.h"
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
// FILE * fopen ( const char * filename, const char * mode );
lv_ft_stream_t* lv_ft_fopen(const char* filename, const char* mode)
{
lv_fs_file_t* file_p = malloc(sizeof(lv_fs_file_t)); // reserve memory
if(file_p) {
lv_fs_mode_t rw = mode[0] == 'r' ? LV_FS_MODE_RD : LV_FS_MODE_WR;
lv_fs_res_t res = lv_fs_open(file_p, filename, rw);
if(res == LV_FS_RES_OK) { // success
return (lv_ft_stream_t*)file_p;
} else { // error
free(file_p); // release memory
}
}
return NULL;
}
// int fclose ( FILE * stream );
int lv_ft_fclose(lv_ft_stream_t* stream)
{
lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream;
lv_fs_close(f_ptr);
free(f_ptr); // release memory
return 0;
}
// size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
size_t lv_ft_fread(void* ptr, size_t size, size_t count, lv_ft_stream_t* stream)
{
lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream;
uint32_t bytes_read;
lv_fs_res_t res = lv_fs_read(f_ptr, ptr, size * count, &bytes_read);
if(res != LV_FS_RES_OK) { // error
bytes_read = 0;
}
return bytes_read;
}
// long int ftell ( FILE * stream );
int lv_ft_ftell(lv_ft_stream_t* stream)
{
lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream;
uint32_t pos;
lv_fs_res_t res = lv_fs_tell(f_ptr, &pos);
if(res == LV_FS_RES_OK) return pos;
return -1;
}
// int fseek ( FILE * stream, long int offset, int origin );
int lv_ft_fseek(lv_ft_stream_t* stream, long int offset, int origin)
{
lv_fs_file_t* f_ptr = (lv_fs_file_t*)stream;
uint32_t start = 0;
switch(origin) {
case SEEK_SET:
start = 0;
break;
case SEEK_CUR: {
int pos = lv_ft_ftell(f_ptr);
if(pos < 0) { // error
return -1;
}
start = pos;
} break;
case SEEK_END: {
lv_fs_res_t res = lv_fs_size(f_ptr, &start);
if(res != LV_FS_RES_OK) { // error
return -1;
}
break;
}
default:
return -1; // Unknown origin
}
if(start + offset < 0) { // underflow, go to beginning of the file
start = 0;
offset = 0;
}
lv_fs_res_t res = lv_fs_seek(f_ptr, start + offset);
return res == LV_FS_RES_OK ? 0 : -1;
}
#endif // LV_USE_FS_IF

View File

@ -0,0 +1,77 @@
/**
* @file lv_fs_freetype.h
*
*/
#ifndef LV_FS_FREETYPE_H
#define LV_FS_FREETYPE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "lv_fs_if.h"
/*********************
* DEFINES
*********************/
#if LV_USE_FILESYSTEM
/**********************
* TYPEDEFS
**********************/
typedef void lv_ft_stream_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* fopen glue for freetype library to access lv_fs api
* @param filename The full path to the file including lv_fs drive letter
* @param mode "r" for read, "w" fro write.
* @return A file stream pointer on success, NULL on error.
*/
lv_ft_stream_t* lv_ft_fopen(const char* filename, const char* mode);
/**
* fclose glue for freetype library to access lv_fs api
* @param stream The file stream to close.
* @return Always 0.
*/
int lv_ft_fclose(lv_ft_stream_t* stream);
/**
* fread glue for freetype library to access lv_fs api
* @param ptr The buffer read to.
* @param size Size of the read buffer.
* @param count The number of bytes to read.
* @param stream The file stream to read.
* @return The number of bytes read on success, otherwise 0.
*/
size_t lv_ft_fread(void* ptr, size_t size, size_t count, lv_ft_stream_t* stream);
/**
* fseek glue for freetype library to access lv_fs api
* @param stream The file stream to seek.
* @param offset The offset from the origin position.
* @param origin The start position within the file, either SEEK_SET, SEEK_CUR or SEEK_END.
* @return 1 on success, otherwise 0.
*/
int lv_ft_fseek(lv_ft_stream_t* stream, long int offset, int origin);
/**
* ftell glue for freetype library to access lv_fs api
* @param stream The file stream to tell.
* @return The current file cursor position on success, otherwise -1.
*/
int lv_ft_ftell(lv_ft_stream_t* stream);
#endif // LV_USE_FILESYSTEM
#ifdef __cplusplus
}
#endif
#endif // LV_FS_FREETYPE_H

View File

@ -5,7 +5,7 @@
;***************************************************; ;***************************************************;
[env:freetouchdeck] [env:freetouchdeck]
extends = esp32_4mb extends = esp32_8mb
board = esp32dev board = esp32dev
build_flags = build_flags =