refact(freetype): clean up global variables and infrequent functions (#3782)

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
_VIFEXTech
2022-11-24 19:27:38 +08:00
committed by GitHub
parent ac763346c8
commit e7da3b247e
11 changed files with 1732 additions and 603 deletions

27
Kconfig
View File

@@ -956,19 +956,20 @@ menu "LVGL configuration"
if LV_USE_FREETYPE if LV_USE_FREETYPE
menu "FreeType cache config" menu "FreeType cache config"
config LV_FREETYPE_CACHE_SIZE config LV_FREETYPE_CACHE_SIZE
int "Memory used by FreeType to cache characters [bytes] (-1: no caching)" int "Memory used by FreeType to cache characters [bytes]"
default 16384 default 65535
if LV_FREETYPE_CACHE_SIZE >= 0 config LV_FREETYPE_USE_LVGL_PORT
config LV_FREETYPE_SBIT_CACHE bool "Let FreeType to use LVGL memory and file porting"
bool "enable sbit cache" default n
default n config LV_FREETYPE_SBIT_CACHE
config LV_FREETYPE_CACHE_FT_FACES bool "enable sbit cache"
int "The maximum number of FT_Face(0: use defaults)" default n
default 0 config LV_FREETYPE_CACHE_FT_FACES
config LV_FREETYPE_CACHE_FT_SIZES int "The maximum number of FT_Face(0: use defaults)"
int "The maximum number of FT_Size(0: use defaults)" default 4
default 0 config LV_FREETYPE_CACHE_FT_SIZES
endif int "The maximum number of FT_Size(0: use defaults)"
default 4
endmenu endmenu
endif endif

View File

@@ -2,37 +2,72 @@
# FreeType support # FreeType support
Interface to [FreeType](https://www.freetype.org/) to generate font bitmaps run time. Interface to [FreeType](https://www.freetype.org/) to generate font bitmaps run time.
## Install FreeType ## Add FreeType to your project
- Download Freetype from [here](https://sourceforge.net/projects/freetype/files/)
First, Download FreeType from [here](https://sourceforge.net/projects/freetype/files/).
There are two ways to use FreeType:
### For UNIX
For UNIX systems, it is recommended to use the way of compiling and installing libraries.
- Enter the FreeType source code directory.
- `make` - `make`
- `sudo make install` - `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 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`) - Link library: `freetype` (for GCC: `-L/usr/local/lib -lfreetype`)
### For Embedded Devices
For embedded devices, it is more recommended to use the FreeType configuration file provided by LVGL, which only includes the most commonly used functions, which is very meaningful for saving limited FLASH space.
- Copy the FreeType source code to your project directory.
- Refer to the following `Makefile` for configuration:
```make
# FreeType custom configuration header file
CFLAGS += -DFT2_BUILD_LIBRARY
CFLAGS += -DFT_CONFIG_MODULES_H=<lvgl/src/libs/freetype/ftmodule.h>
CFLAGS += -DFT_CONFIG_OPTIONS_H=<lvgl/src/libs/freetype/ftoption.h>
# FreeType include path
CFLAGS += -Ifreetype/include
# FreeType C source file
FT_CSRCS += freetype/src/base/ftbase.c
FT_CSRCS += freetype/src/base/ftbitmap.c
FT_CSRCS += freetype/src/base/ftdebug.c
FT_CSRCS += freetype/src/base/ftglyph.c
FT_CSRCS += freetype/src/base/ftinit.c
FT_CSRCS += freetype/src/cache/ftcache.c
FT_CSRCS += freetype/src/gzip/ftgzip.c
FT_CSRCS += freetype/src/sfnt/sfnt.c
FT_CSRCS += freetype/src/smooth/smooth.c
FT_CSRCS += freetype/src/truetype/truetype.c
CSRCS += $(FT_CSRCS)
```
## Usage ## Usage
Enable `LV_USE_FREETYPE` in `lv_conf.h`. Enable `LV_USE_FREETYPE` in `lv_conf.h`.
To cache the glyphs from the opened fonts, set `LV_FREETYPE_CACHE_SIZE >= 0` and then use the following macros for detailed configuration: Cache configuration:
1. `LV_FREETYPE_CACHE_SIZE`:maximum memory(bytes) used to cache font bitmap, outline, character maps, etc. 0 means use the system default value, less than 0 means disable cache. Note: that this value does not account for managed FT_Face and FT_Size objects. - `LV_FREETYPE_CACHE_SIZE` - Maximum memory(Bytes) used to cache font bitmap, outline, character maps, etc. **Note:** This value does not include the memory used by 'FT_Face' and 'FT_Size' objects
1. `LV_FREETYPE_CACHE_FT_FACES`:maximum number of opened FT_Face objects managed by this cache instance.0 means use the system default value. Only useful when LV_FREETYPE_CACHE_SIZE >= 0. - `LV_FREETYPE_CACHE_FT_FACES` - Maximum open number of `FT_Face` objects.
1. `LV_FREETYPE_CACHE_FT_SIZES`:maximum number of opened FT_Size objects managed by this cache instance. 0 means use the system default value. Only useful when LV_FREETYPE_CACHE_SIZE >= 0. - `LV_FREETYPE_CACHE_FT_SIZES` - Maximum open number of `FT_Size` objects.
When you are sure that all the used font sizes will not be greater than 256, you can enable `LV_FREETYPE_SBIT_CACHE`, which is much more memory efficient for small bitmaps. When you are sure that all the used font sizes will not be greater than 256, you can enable `LV_FREETYPE_SBIT_CACHE`, which is much more memory efficient for small bitmaps.
You can use `lv_ft_font_init()` to create FreeType fonts. It returns `true` to indicate success, at the same time, the `font` member of `lv_ft_info_t` will be filled with a pointer to an LVGL font, and you can use it like any LVGL font. By default, the FreeType extension doesn't use LVGL's file system.
Font style supports bold and italic, you can use the following macros to set:
1. `FT_FONT_STYLE_NORMAL`:default style.
1. `FT_FONT_STYLE_ITALIC`:Italic style
1. `FT_FONT_STYLE_BOLD`:bold style
They can be combined.eg:`FT_FONT_STYLE_BOLD | FT_FONT_STYLE_ITALIC`.
Note that, the FreeType extension doesn't use LVGL's file system.
You can simply pass the path to the font as usual on your operating system or platform. You can simply pass the path to the font as usual on your operating system or platform.
If you want FreeType to use lvgl's memory allocation and file system interface, you can enable `LV_FREETYPE_USE_LVGL_PORT` in `lv_conf.h`, convenient for unified management.
The font style supports *Italic* and **Bold** fonts processed by software, and can be set with reference to the following values:
- `LV_FREETYPE_FONT_STYLE_NORMAL` - Default style.
- `LV_FREETYPE_FONT_STYLE_ITALIC` - Italic style.
- `LV_FREETYPE_FONT_STYLE_BOLD` - Bold style.
They can be combined.eg: `LV_FREETYPE_FONT_STYLE_BOLD | LV_FREETYPE_FONT_STYLE_ITALIC`.
Use the `lv_freetype_font_create()` function to create a font. To delete a font, use `lv_freetype_font_del()`. For more detailed usage, please refer to example code.
## Example ## Example
```eval_rst ```eval_rst
.. include:: ../../examples/libs/freetype/index.rst .. include:: ../../examples/libs/freetype/index.rst

View File

@@ -2,26 +2,31 @@
#if LV_BUILD_EXAMPLES #if LV_BUILD_EXAMPLES
#if LV_USE_FREETYPE #if LV_USE_FREETYPE
#if LV_FREETYPE_USE_LVGL_PORT
#define PATH_PREFIX "A:"
#else
#define PATH_PREFIX "./"
#endif
/** /**
* Load a font with FreeType * Load a font with FreeType
*/ */
void lv_example_freetype_1(void) void lv_example_freetype_1(void)
{ {
/*Create a font*/ /*Create a font*/
static lv_ft_info_t info; lv_font_t * font = lv_freetype_font_create(PATH_PREFIX "lvgl/examples/libs/freetype/Lato-Regular.ttf",
/*FreeType uses C standard file system, so no driver letter is required.*/ 24,
info.name = "./lvgl/examples/libs/freetype/Lato-Regular.ttf"; LV_FREETYPE_FONT_STYLE_NORMAL);
info.weight = 24;
info.style = FT_FONT_STYLE_NORMAL; if(!font) {
info.mem = NULL; LV_LOG_ERROR("freetype font create failed.");
if(!lv_ft_font_init(&info)) { return;
LV_LOG_ERROR("create failed.");
} }
/*Create style with the new font*/ /*Create style with the new font*/
static lv_style_t style; static lv_style_t style;
lv_style_init(&style); lv_style_init(&style);
lv_style_set_text_font(&style, info.font); lv_style_set_text_font(&style, font);
lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER); lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);
/*Create a label with the new style*/ /*Create a label with the new style*/

View File

@@ -3,16 +3,12 @@ import lvgl as lv
import display_driver import display_driver
import fs_driver import fs_driver
info = lv.ft_info_t() font = lv.freetype_font_create("./Lato-Regular.ttf", 24, lv.FREETYPE_FONT_STYLE.NORMAL)
info.name ="./Lato-Regular.ttf"
info.weight = 24
info.style = lv.FT_FONT_STYLE.NORMAL
info.font_init()
# Create style with the new font # Create style with the new font
style = lv.style_t() style = lv.style_t()
style.init() style.init()
style.set_text_font(info.font) style.set_text_font(font)
style.set_text_align(lv.TEXT_ALIGN.CENTER) style.set_text_align(lv.TEXT_ALIGN.CENTER)
# Create a label with the new style # Create a label with the new style

View File

@@ -636,18 +636,21 @@
/*FreeType library*/ /*FreeType library*/
#define LV_USE_FREETYPE 0 #define LV_USE_FREETYPE 0
#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]*/
#define LV_FREETYPE_CACHE_SIZE (16 * 1024) #define LV_FREETYPE_CACHE_SIZE (64 * 1024)
#if LV_FREETYPE_CACHE_SIZE >= 0
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ /*Let FreeType to use LVGL memory and file porting*/
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ #define LV_FREETYPE_USE_LVGL_PORT 0
/* if font size >= 256, must be configured as image cache */
#define LV_FREETYPE_SBIT_CACHE 0 /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
/* (0:use system defaults) */ /* if font size >= 256, must be configured as image cache */
#define LV_FREETYPE_CACHE_FT_FACES 0 #define LV_FREETYPE_SBIT_CACHE 0
#define LV_FREETYPE_CACHE_FT_SIZES 0
#endif /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
/* (0:use system defaults) */
#define LV_FREETYPE_CACHE_FT_FACES 4
#define LV_FREETYPE_CACHE_FT_SIZES 4
#endif #endif
/* Built-in TTF decoder */ /* Built-in TTF decoder */

View File

@@ -0,0 +1,33 @@
/*
* This file registers the FreeType modules compiled into the library.
*
* If you use GNU make, this file IS NOT USED! Instead, it is created in
* the objects directory (normally `<topdir>/objs/`) based on information
* from `<topdir>/modules.cfg`.
*
* Please read `docs/INSTALL.ANY` and `docs/CUSTOMIZE` how to compile
* FreeType without GNU make.
*
*/
/* FT_USE_MODULE( FT_Module_Class, autofit_module_class ) */
FT_USE_MODULE(FT_Driver_ClassRec, tt_driver_class)
/* FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class ) */
/* FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class ) */
/* FT_USE_MODULE( FT_Module_Class, psaux_module_class ) */
/* FT_USE_MODULE( FT_Module_Class, psnames_module_class ) */
/* FT_USE_MODULE( FT_Module_Class, pshinter_module_class ) */
FT_USE_MODULE(FT_Module_Class, sfnt_module_class)
FT_USE_MODULE(FT_Renderer_Class, ft_smooth_renderer_class)
/* FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) */
/* FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class ) */
/* FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class ) */
/* FT_USE_MODULE( FT_Renderer_Class, ft_svg_renderer_class ) */
/* EOF */

1029
src/libs/freetype/ftoption.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -20,74 +20,66 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#ifdef FT_CONFIG_OPTION_ERROR_STRINGS
#define FT_ERROR_MSG(msg, error_code) \
LV_LOG_ERROR(msg " error(%d): %s", (int)error_code, FT_Error_String(error_code))
#else
#define FT_ERROR_MSG(msg, error_code) \
LV_LOG_ERROR(msg " error(%d)", (int)error_code)
#endif
#if LV_FREETYPE_CACHE_SIZE <= 0
#error "LV_FREETYPE_CACHE_SIZE must > 0"
#endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
typedef struct { typedef struct _lv_freetype_font_dsc_t {
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;
typedef struct {
const void * mem;
const char * name;
size_t mem_size;
#if LV_FREETYPE_CACHE_SIZE < 0
FT_Size size;
#endif
lv_font_t * font; lv_font_t * font;
uint16_t style; char * pathname;
uint16_t height; uint16_t size;
} lv_font_fmt_ft_dsc_t; uint16_t style;
} lv_freetype_font_dsc_t;
typedef struct _lv_freetype_context_t {
FT_Library library;
FTC_Manager cache_manager;
FTC_CMapCache cmap_cache;
FT_Face current_face;
#if LV_FREETYPE_SBIT_CACHE
FTC_SBitCache sbit_cache;
FTC_SBit sbit;
#else
FTC_ImageCache image_cache;
FT_Glyph image_glyph;
#endif
} lv_freetype_context_t;
/********************** /**********************
* STATIC PROTOTYPES * 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);
#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 const char * name_refer_save(const char * name); static FT_Error freetpye_face_requester(FTC_FaceID face_id,
static void name_refer_del(const char * name); FT_Library library,
static const char * name_refer_find(const char * name); FT_Pointer req_data,
FT_Face * aface);
static FT_Error freetype_get_bold_glyph(const lv_font_t * font,
FT_Face face,
FT_UInt glyph_index,
lv_font_glyph_dsc_t * dsc_out);
static bool freetype_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 * freetype_get_glyph_bitmap_cb(const lv_font_t * font,
uint32_t unicode_letter);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
static FT_Library library;
static lv_ll_t names_ll;
#if LV_FREETYPE_CACHE_SIZE >= 0 static lv_freetype_context_t ft_ctx;
static FTC_Manager cache_manager;
static FTC_CMapCache cmap_cache;
static FT_Face current_face = NULL;
#if LV_FREETYPE_SBIT_CACHE
static FTC_SBitCache sbit_cache;
static FTC_SBit sbit;
#else
static FTC_ImageCache image_cache;
static FT_Glyph image_glyph;
#endif
#else
static lv_faces_control_t face_control;
#endif
/********************** /**********************
* MACROS * MACROS
@@ -97,143 +89,205 @@ static lv_ll_t names_ll;
* GLOBAL FUNCTIONS * GLOBAL FUNCTIONS
**********************/ **********************/
bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes) lv_res_t 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;
error = FT_Init_FreeType(&ft_ctx.library);
if(error) { if(error) {
LV_LOG_ERROR("init freeType error(%d)", error); FT_ERROR_MSG("FT_Init_FreeType", error);
return false; return LV_RES_INV;
} }
_lv_ll_init(&names_ll, sizeof(name_refer_t)); error = FTC_Manager_New(ft_ctx.library,
max_faces,
#if LV_FREETYPE_CACHE_SIZE >= 0 max_sizes,
error = FTC_Manager_New(library, max_faces, max_sizes, max_bytes,
max_bytes, font_face_requester, NULL, &cache_manager); freetpye_face_requester,
NULL,
&ft_ctx.cache_manager);
if(error) { if(error) {
FT_Done_FreeType(library); FT_Done_FreeType(ft_ctx.library);
LV_LOG_ERROR("Failed to open cache manager"); FT_ERROR_MSG("FTC_Manager_New", error);
return false; return LV_RES_INV;
} }
error = FTC_CMapCache_New(cache_manager, &cmap_cache); error = FTC_CMapCache_New(ft_ctx.cache_manager, &ft_ctx.cmap_cache);
if(error) { if(error) {
LV_LOG_ERROR("Failed to open Cmap Cache"); FT_ERROR_MSG("FTC_CMapCache_New", error);
goto Fail; goto failed;
} }
#if LV_FREETYPE_SBIT_CACHE #if LV_FREETYPE_SBIT_CACHE
error = FTC_SBitCache_New(cache_manager, &sbit_cache); error = FTC_SBitCache_New(ft_ctx.cache_manager, &ft_ctx.sbit_cache);
if(error) { if(error) {
LV_LOG_ERROR("Failed to open sbit cache"); FT_ERROR_MSG("FTC_SBitCache_New", error);
goto Fail; goto failed;
} }
#else #else
error = FTC_ImageCache_New(cache_manager, &image_cache); error = FTC_ImageCache_New(ft_ctx.cache_manager, &ft_ctx.image_cache);
if(error) { if(error) {
LV_LOG_ERROR("Failed to open image cache"); FT_ERROR_MSG("FTC_ImageCache_New", error);
goto Fail; goto failed;
} }
#endif #endif
return true; return LV_RES_OK;
Fail: failed:
FTC_Manager_Done(cache_manager); FTC_Manager_Done(ft_ctx.cache_manager);
FT_Done_FreeType(library); FT_Done_FreeType(ft_ctx.library);
return false; return LV_RES_INV;
#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) void lv_freetype_uninit(void)
{ {
#if LV_FREETYPE_CACHE_SIZE >= 0 FTC_Manager_Done(ft_ctx.cache_manager);
FTC_Manager_Done(cache_manager); FT_Done_FreeType(ft_ctx.library);
#endif
FT_Done_FreeType(library);
} }
bool lv_ft_font_init(lv_ft_info_t * info) lv_font_t * lv_freetype_font_create(const char * pathname, uint16_t size, uint16_t style)
{ {
#if LV_FREETYPE_CACHE_SIZE >= 0 LV_ASSERT_NULL(pathname);
return lv_ft_font_init_cache(info); LV_ASSERT(size > 0);
#else
return lv_ft_font_init_nocache(info); size_t pathname_len = lv_strlen(pathname);
#endif if(pathname_len == 0) {
LV_LOG_ERROR("pathname is empty");
return NULL;
}
size_t need_size = sizeof(lv_freetype_font_dsc_t) + sizeof(lv_font_t);
lv_freetype_font_dsc_t * dsc = lv_malloc(need_size);
LV_ASSERT_MALLOC(dsc);
if(!dsc) {
LV_LOG_ERROR("malloc failed for lv_freetype_font_dsc");
return NULL;
}
lv_memzero(dsc, need_size);
dsc->font = (lv_font_t *)(((uint8_t *)dsc) + sizeof(lv_freetype_font_dsc_t));
dsc->pathname = lv_malloc(pathname_len + 1);
LV_ASSERT_MALLOC(dsc->pathname);
if(!dsc->pathname) {
LV_LOG_ERROR("malloc failed for dsc->pathname");
lv_free(dsc);
return NULL;
}
strcpy(dsc->pathname, pathname);
dsc->size = size;
dsc->style = style;
/* use to get font info */
FT_Size face_size;
struct FTC_ScalerRec_ scaler;
scaler.face_id = (FTC_FaceID)dsc;
scaler.width = size;
scaler.height = size;
scaler.pixel = 1;
FT_Error error = FTC_Manager_LookupSize(ft_ctx.cache_manager,
&scaler,
&face_size);
if(error) {
FT_ERROR_MSG("FTC_Manager_LookupSize", error);
lv_free(dsc->pathname);
lv_free(dsc);
return NULL;
}
lv_font_t * font = dsc->font;
font->dsc = dsc;
font->get_glyph_dsc = freetype_get_glyph_dsc_cb;
font->get_glyph_bitmap = freetype_get_glyph_bitmap_cb;
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 font;
} }
void lv_ft_font_destroy(lv_font_t * font) void lv_freetype_font_del(lv_font_t * font)
{ {
#if LV_FREETYPE_CACHE_SIZE >= 0 LV_ASSERT_NULL(font);
lv_ft_font_destroy_cache(font); lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)(font->dsc);
#else LV_ASSERT_NULL(dsc);
lv_ft_font_destroy_nocache(font); FTC_Manager_RemoveFaceID(ft_ctx.cache_manager, (FTC_FaceID)dsc);
#endif lv_free(dsc->pathname);
lv_free(dsc);
} }
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
#if LV_FREETYPE_CACHE_SIZE >= 0
static FT_Error font_face_requester(FTC_FaceID face_id, static FT_Error freetpye_face_requester(FTC_FaceID face_id,
FT_Library library_is, FT_Pointer req_data, FT_Face * aface) FT_Library library,
FT_Pointer req_data,
FT_Face * aface)
{ {
LV_UNUSED(library_is); LV_UNUSED(library);
LV_UNUSED(req_data); LV_UNUSED(req_data);
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)face_id; lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)face_id;
FT_Error error; FT_Error error;
if(dsc->mem) {
error = FT_New_Memory_Face(library, dsc->mem, dsc->mem_size, 0, aface); error = FT_New_Face(ft_ctx.library, dsc->pathname, 0, aface);
}
else {
error = FT_New_Face(library, dsc->name, 0, aface);
}
if(error) { if(error) {
LV_LOG_ERROR("FT_New_Face error:%d\n", error); FT_ERROR_MSG("FT_New_Face", error);
return error;
} }
return FT_Err_Ok; return error;
} }
static bool get_bold_glyph(const lv_font_t * font, FT_Face face, static FT_Error freetype_get_bold_glyph(const lv_font_t * font,
FT_UInt glyph_index, lv_font_glyph_dsc_t * dsc_out) FT_Face face,
FT_UInt glyph_index,
lv_font_glyph_dsc_t * dsc_out)
{ {
if(FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT)) { FT_Error error;
return false; error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if(error) {
FT_ERROR_MSG("FT_Load_Glyph", error);
return error;
} }
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)(font->dsc);
if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { if(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
if(dsc->style & FT_FONT_STYLE_BOLD) { if(dsc->style & LV_FREETYPE_FONT_STYLE_BOLD) {
int strength = 1 << 6; int strength = 1 << 6;
FT_Outline_Embolden(&face->glyph->outline, strength); error = FT_Outline_Embolden(&face->glyph->outline, strength);
if(error) {
FT_ERROR_MSG("FT_Outline_Embolden", error);
}
} }
} }
if(FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL)) { error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
return false; if(error) {
FT_ERROR_MSG("FT_Render_Glyph", error);
return error;
} }
dsc_out->adv_w = (face->glyph->metrics.horiAdvance >> 6); 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_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->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_x = face->glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = face->glyph->bitmap_top - dsc_out->ofs_y = face->glyph->bitmap_top -
face->glyph->bitmap.rows; /*Y offset of the bitmap measured from the as line*/ 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*/ dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
return true; return FT_Err_Ok;
} }
static bool get_glyph_dsc_cb_cache(const lv_font_t * font, static bool freetype_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) lv_font_glyph_dsc_t * dsc_out,
uint32_t unicode_letter,
uint32_t unicode_letter_next)
{ {
LV_UNUSED(unicode_letter_next); LV_UNUSED(unicode_letter_next);
if(unicode_letter < 0x20) { if(unicode_letter < 0x20) {
@@ -246,25 +300,28 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
return true; return true;
} }
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)(font->dsc);
FTC_FaceID face_id = (FTC_FaceID)dsc; FTC_FaceID face_id = (FTC_FaceID)dsc;
FT_Size face_size; FT_Size face_size;
FT_Error error;
struct FTC_ScalerRec_ scaler; struct FTC_ScalerRec_ scaler;
scaler.face_id = face_id; scaler.face_id = face_id;
scaler.width = dsc->height; scaler.width = dsc->size;
scaler.height = dsc->height; scaler.height = dsc->size;
scaler.pixel = 1; scaler.pixel = 1;
if(FTC_Manager_LookupSize(cache_manager, &scaler, &face_size) != 0) { error = FTC_Manager_LookupSize(ft_ctx.cache_manager, &scaler, &face_size);
if(error) {
FT_ERROR_MSG("FTC_Manager_LookupSize", error);
return false; return false;
} }
FT_Face face = face_size->face; 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, face_id, charmap_index, unicode_letter); FT_UInt glyph_index = FTC_CMapCache_Lookup(ft_ctx.cmap_cache, face_id, charmap_index, unicode_letter);
dsc_out->is_placeholder = glyph_index == 0; dsc_out->is_placeholder = glyph_index == 0;
if(dsc->style & FT_FONT_STYLE_ITALIC) { if(dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) {
FT_Matrix italic_matrix; FT_Matrix italic_matrix;
italic_matrix.xx = 1 << 16; italic_matrix.xx = 1 << 16;
italic_matrix.xy = 0x5800; italic_matrix.xy = 0x5800;
@@ -273,10 +330,11 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
FT_Set_Transform(face, &italic_matrix, NULL); FT_Set_Transform(face, &italic_matrix, NULL);
} }
if(dsc->style & FT_FONT_STYLE_BOLD) { if(dsc->style & LV_FREETYPE_FONT_STYLE_BOLD) {
current_face = face; ft_ctx.current_face = face;
if(!get_bold_glyph(font, face, glyph_index, dsc_out)) { error = freetype_get_bold_glyph(font, face, glyph_index, dsc_out);
current_face = NULL; if(error) {
ft_ctx.current_face = NULL;
return false; return false;
} }
goto end; goto end;
@@ -285,16 +343,21 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
FTC_ImageTypeRec desc_type; FTC_ImageTypeRec desc_type;
desc_type.face_id = face_id; desc_type.face_id = face_id;
desc_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL; desc_type.flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
desc_type.height = dsc->height; desc_type.height = dsc->size;
desc_type.width = dsc->height; desc_type.width = dsc->size;
#if LV_FREETYPE_SBIT_CACHE #if LV_FREETYPE_SBIT_CACHE
FT_Error error = FTC_SBitCache_Lookup(sbit_cache, &desc_type, glyph_index, &sbit, NULL); error = FTC_SBitCache_Lookup(ft_ctx.sbit_cache,
&desc_type,
glyph_index,
&ft_ctx.sbit,
NULL);
if(error) { if(error) {
LV_LOG_ERROR("SBitCache_Lookup error"); FT_ERROR_MSG("FTC_SBitCache_Lookup", error);
return false; return false;
} }
FTC_SBit sbit = ft_ctx.sbit;
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]*/
dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/ dsc_out->box_w = sbit->width; /*Width of the bitmap in [px]*/
@@ -302,17 +365,21 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
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 #else
FT_Error error = FTC_ImageCache_Lookup(image_cache, &desc_type, glyph_index, &image_glyph, NULL); error = FTC_ImageCache_Lookup(ft_ctx.image_cache,
&desc_type,
glyph_index,
&ft_ctx.image_glyph,
NULL);
if(error) { if(error) {
LV_LOG_ERROR("ImageCache_Lookup error"); FT_ERROR_MSG("ImageCache_Lookup", error);
return false; return false;
} }
if(image_glyph->format != FT_GLYPH_FORMAT_BITMAP) { if(ft_ctx.image_glyph->format != FT_GLYPH_FORMAT_BITMAP) {
LV_LOG_ERROR("Glyph_To_Bitmap error"); LV_LOG_ERROR("image_glyph->format != FT_GLYPH_FORMAT_BITMAP");
return false; return false;
} }
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph; FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)ft_ctx.image_glyph;
dsc_out->adv_w = (glyph_bitmap->root.advance.x >> 16); 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_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->box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/
@@ -323,365 +390,31 @@ static bool get_glyph_dsc_cb_cache(const lv_font_t * font,
#endif #endif
end: end:
if((dsc->style & FT_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) { if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x; 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 * freetype_get_glyph_bitmap_cb(const lv_font_t * font, uint32_t unicode_letter)
{ {
LV_UNUSED(unicode_letter); LV_UNUSED(unicode_letter);
lv_font_fmt_ft_dsc_t * dsc = (lv_font_fmt_ft_dsc_t *)(font->dsc); lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc;
if(dsc->style & FT_FONT_STYLE_BOLD) { if(dsc->style & LV_FREETYPE_FONT_STYLE_BOLD) {
if(current_face && current_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) { if(ft_ctx.current_face && ft_ctx.current_face->glyph->format == FT_GLYPH_FORMAT_BITMAP) {
return (const uint8_t *)(current_face->glyph->bitmap.buffer); return (const uint8_t *)(ft_ctx.current_face->glyph->bitmap.buffer);
} }
return NULL; return NULL;
} }
#if LV_FREETYPE_SBIT_CACHE #if LV_FREETYPE_SBIT_CACHE
return (const uint8_t *)sbit->buffer; return (const uint8_t *)ft_ctx.sbit->buffer;
#else #else
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)image_glyph; FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)ft_ctx.image_glyph;
return (const uint8_t *)glyph_bitmap->bitmap.buffer; return (const uint8_t *)glyph_bitmap->bitmap.buffer;
#endif #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_malloc(need_size);
if(dsc == NULL) return false;
lv_memzero(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_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_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) {
FTC_Manager_RemoveFaceID(cache_manager, (FTC_FaceID)dsc);
name_refer_del(dsc->name);
lv_free(dsc);
}
}
#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_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_malloc(need_size);
if(dsc == NULL) return false;
lv_memzero(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_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_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_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_ll_remove(&names_ll, refer);
lv_free((void *)refer->name);
lv_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_malloc(len);
if(refer->name) {
lv_memcpy((void *)refer->name, name, len);
refer->cnt = 1;
return refer->name;
}
_lv_ll_remove(&names_ll, refer);
lv_free(refer);
}
LV_LOG_WARN("save_name_to_names error(not memory).");
return "";
}
#endif /*LV_USE_FREETYPE*/ #endif /*LV_USE_FREETYPE*/

View File

@@ -22,53 +22,46 @@ extern "C" {
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
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 { typedef enum {
const char * name; /* The name of the font file */ LV_FREETYPE_FONT_STYLE_NORMAL = 0,
const void * mem; /* The pointer of the font file */ LV_FREETYPE_FONT_STYLE_ITALIC = 1 << 0,
size_t mem_size; /* The size of the memory */ LV_FREETYPE_FONT_STYLE_BOLD = 1 << 1
lv_font_t * font; /* point to lvgl font */ } lv_freetype_font_style_t;
uint16_t weight; /* font size */
uint16_t style; /* font style */
} lv_ft_info_t;
/********************** /**********************
* GLOBAL PROTOTYPES * GLOBAL PROTOTYPES
**********************/ **********************/
/** /**
* init freetype library * Initialize the freetype library.
* @param max_faces Maximum number of opened FT_Face objects managed by this cache instance. Use 0 for defaults. * @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_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. * @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. * Note that this value does not account for managed FT_Face and FT_Size objects.
* @return true on success, otherwise false. * @return LV_RES_OK on success, otherwise LV_RES_INV.
*/ */
bool lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes); lv_res_t lv_freetype_init(uint16_t max_faces, uint16_t max_sizes, uint32_t max_bytes);
/** /**
* Destroy freetype library * Uninitialize the freetype library
*/ */
void lv_freetype_destroy(void); void lv_freetype_uninit(void);
/** /**
* Creates a font with info parameter specified. * Create a freetype font.
* @param info See lv_ft_info_t for details. * @param pathname font file path.
* when success, lv_ft_info_t->font point to the font you created. * @param size font size.
* @return true on success, otherwise false. * @param style font style(see lv_freetype_font_style_t for details).
* @return Created font, or NULL on failure.
*/ */
bool lv_ft_font_init(lv_ft_info_t * info); lv_font_t * lv_freetype_font_create(const char * pathname, uint16_t size, uint16_t style);
/** /**
* Destroy a font that has been created. * Delete a freetype font.
* @param font pointer to font. * @param font freetype font to be deleted.
*/ */
void lv_ft_font_destroy(lv_font_t * font); void lv_freetype_font_del(lv_font_t * font);
/********************** /**********************
* MACROS * MACROS

View File

@@ -0,0 +1,292 @@
/**
* @file lv_ftsystem.c
*
*/
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_FREETYPE && LV_FREETYPE_USE_LVGL_PORT
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/ftsystem.h>
#include <freetype/fterrors.h>
#include <freetype/fttypes.h>
/*********************
* DEFINES
*********************/
/* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT io
/* We use the macro STREAM_FILE for convenience to extract the */
/* system-specific stream handle from a given FreeType stream object */
#define STREAM_FILE( stream ) ( (lv_fs_file_t*)stream->descriptor.pointer )
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
FT_CALLBACK_DEF(unsigned long)
ft_lv_fs_stream_io(FT_Stream stream,
unsigned long offset,
unsigned char * buffer,
unsigned long count);
FT_CALLBACK_DEF(void)
ft_lv_fs_stream_close(FT_Stream stream);
FT_CALLBACK_DEF(void *)
ft_alloc(FT_Memory memory,
long size);
FT_CALLBACK_DEF(void *)
ft_realloc(FT_Memory memory,
long cur_size,
long new_size,
void * block);
FT_CALLBACK_DEF(void)
ft_free(FT_Memory memory,
void * block);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
#ifdef FT_DEBUG_MEMORY
extern FT_Int
ft_mem_debug_init(FT_Memory memory);
extern void
ft_mem_debug_done(FT_Memory memory);
#endif
/**********************
* GLOBAL FUNCTIONS
**********************/
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
/* documentation is in ftstream.h */
FT_BASE_DEF(FT_Error)
FT_Stream_Open(FT_Stream stream,
const char * filepathname)
{
lv_fs_file_t file;
if(!stream)
return FT_THROW(Invalid_Stream_Handle);
stream->descriptor.pointer = NULL;
stream->pathname.pointer = (char *)filepathname;
stream->base = NULL;
stream->pos = 0;
stream->read = NULL;
stream->close = NULL;
lv_fs_res_t res = lv_fs_open(&file, filepathname, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
FT_ERROR(("FT_Stream_Open:"
" could not open `%s'\n", filepathname));
return FT_THROW(Cannot_Open_Resource);
}
lv_fs_seek(&file, 0, LV_FS_SEEK_END);
uint32_t pos;
res = lv_fs_tell(&file, &pos);
if(res != LV_FS_RES_OK) {
FT_ERROR(("FT_Stream_Open:"));
FT_ERROR((" opened `%s' but zero-sized\n", filepathname));
lv_fs_close(&file);
return FT_THROW(Cannot_Open_Stream);
}
stream->size = pos;
lv_fs_seek(&file, 0, LV_FS_SEEK_SET);
lv_fs_file_t * file_p = lv_malloc(sizeof(lv_fs_file_t));
LV_ASSERT_MALLOC(file_p);
if(!file_p) {
FT_ERROR(("FT_Stream_Open: malloc failed for file_p"));
lv_fs_close(&file);
return FT_THROW(Cannot_Open_Stream);
}
*file_p = file;
stream->descriptor.pointer = file_p;
stream->read = ft_lv_fs_stream_io;
stream->close = ft_lv_fs_stream_close;
FT_TRACE1(("FT_Stream_Open:"));
FT_TRACE1((" opened `%s' (%ld bytes) successfully\n",
filepathname, stream->size));
return FT_Err_Ok;
}
#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
/* documentation is in ftobjs.h */
FT_BASE_DEF(FT_Memory)
FT_New_Memory(void)
{
FT_Memory memory;
memory = (FT_Memory)lv_malloc(sizeof(*memory));
if(memory) {
memory->user = NULL;
memory->alloc = ft_alloc;
memory->realloc = ft_realloc;
memory->free = ft_free;
#ifdef FT_DEBUG_MEMORY
ft_mem_debug_init(memory);
#endif
}
return memory;
}
/* documentation is in ftobjs.h */
FT_BASE_DEF(void)
FT_Done_Memory(FT_Memory memory)
{
#ifdef FT_DEBUG_MEMORY
ft_mem_debug_done(memory);
#endif
lv_free(memory);
}
/**********************
* STATIC FUNCTIONS
**********************/
/**
* The memory allocation function.
* @param memory A pointer to the memory object.
* @param size The requested size in bytes.
* @return The address of newly allocated block.
*/
FT_CALLBACK_DEF(void *)
ft_alloc(FT_Memory memory,
long size)
{
FT_UNUSED(memory);
return lv_malloc((size_t)size);
}
/**
* The memory reallocation function.
* @param memory A pointer to the memory object.
* @param cur_size The current size of the allocated memory block.
* @param new_size The newly requested size in bytes.
* @param block The current address of the block in memory.
* @return The address of the reallocated memory block.
*/
FT_CALLBACK_DEF(void *)
ft_realloc(FT_Memory memory,
long cur_size,
long new_size,
void * block)
{
FT_UNUSED(memory);
FT_UNUSED(cur_size);
return lv_realloc(block, (size_t)new_size);
}
/**
* The memory release function.
* @param memory A pointer to the memory object.
* @param block The address of block in memory to be freed.
*/
FT_CALLBACK_DEF(void)
ft_free(FT_Memory memory,
void * block)
{
FT_UNUSED(memory);
lv_free(block);
}
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
/**
* The function to close a stream.
* @param stream A pointer to the stream object.
*/
FT_CALLBACK_DEF(void)
ft_lv_fs_stream_close(FT_Stream stream)
{
lv_fs_file_t * file_p = STREAM_FILE(stream);
lv_fs_close(file_p);
lv_free(file_p);
stream->descriptor.pointer = NULL;
stream->size = 0;
stream->base = NULL;
}
/**
* The function to open a stream.
* @param stream A pointer to the stream object.
* @param offset The position in the data stream to start reading.
* @param buffer The address of buffer to store the read data.
* @param count The number of bytes to read from the stream.
* @return The number of bytes actually read. If `count' is zero (this is,
* the function is used for seeking), a non-zero return value
* indicates an error.
*/
FT_CALLBACK_DEF(unsigned long)
ft_lv_fs_stream_io(FT_Stream stream,
unsigned long offset,
unsigned char * buffer,
unsigned long count)
{
lv_fs_file_t * file_p;
if(!count && offset > stream->size)
return 1;
file_p = STREAM_FILE(stream);
if(stream->pos != offset)
lv_fs_seek(file_p, (long)offset, LV_FS_SEEK_SET);
if(count == 0)
return 0;
uint32_t br;
lv_fs_res_t res = lv_fs_read(file_p, buffer, count, &br);
return res == LV_FS_RES_OK ? br : 0;
}
#endif /* !FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
#endif/*LV_FREETYPE_USE_LV_FTSYSTEM*/

View File

@@ -2162,40 +2162,49 @@
#endif #endif
#endif #endif
#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]*/
#ifndef LV_FREETYPE_CACHE_SIZE #ifndef LV_FREETYPE_CACHE_SIZE
#ifdef CONFIG_LV_FREETYPE_CACHE_SIZE #ifdef CONFIG_LV_FREETYPE_CACHE_SIZE
#define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE #define LV_FREETYPE_CACHE_SIZE CONFIG_LV_FREETYPE_CACHE_SIZE
#else #else
#define LV_FREETYPE_CACHE_SIZE (16 * 1024) #define LV_FREETYPE_CACHE_SIZE (64 * 1024)
#endif #endif
#endif #endif
#if LV_FREETYPE_CACHE_SIZE >= 0
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */ /*Let FreeType to use LVGL memory and file porting*/
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */ #ifndef LV_FREETYPE_USE_LVGL_PORT
/* if font size >= 256, must be configured as image cache */ #ifdef CONFIG_LV_FREETYPE_USE_LVGL_PORT
#ifndef LV_FREETYPE_SBIT_CACHE #define LV_FREETYPE_USE_LVGL_PORT CONFIG_LV_FREETYPE_USE_LVGL_PORT
#ifdef CONFIG_LV_FREETYPE_SBIT_CACHE #else
#define LV_FREETYPE_SBIT_CACHE CONFIG_LV_FREETYPE_SBIT_CACHE #define LV_FREETYPE_USE_LVGL_PORT 0
#else
#define LV_FREETYPE_SBIT_CACHE 0
#endif
#endif #endif
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */ #endif
/* (0:use system defaults) */
#ifndef LV_FREETYPE_CACHE_FT_FACES /* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
#ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES /* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
#define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES /* if font size >= 256, must be configured as image cache */
#else #ifndef LV_FREETYPE_SBIT_CACHE
#define LV_FREETYPE_CACHE_FT_FACES 0 #ifdef CONFIG_LV_FREETYPE_SBIT_CACHE
#endif #define LV_FREETYPE_SBIT_CACHE CONFIG_LV_FREETYPE_SBIT_CACHE
#else
#define LV_FREETYPE_SBIT_CACHE 0
#endif #endif
#ifndef LV_FREETYPE_CACHE_FT_SIZES #endif
#ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES
#define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES /* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
#else /* (0:use system defaults) */
#define LV_FREETYPE_CACHE_FT_SIZES 0 #ifndef LV_FREETYPE_CACHE_FT_FACES
#endif #ifdef CONFIG_LV_FREETYPE_CACHE_FT_FACES
#define LV_FREETYPE_CACHE_FT_FACES CONFIG_LV_FREETYPE_CACHE_FT_FACES
#else
#define LV_FREETYPE_CACHE_FT_FACES 4
#endif
#endif
#ifndef LV_FREETYPE_CACHE_FT_SIZES
#ifdef CONFIG_LV_FREETYPE_CACHE_FT_SIZES
#define LV_FREETYPE_CACHE_FT_SIZES CONFIG_LV_FREETYPE_CACHE_FT_SIZES
#else
#define LV_FREETYPE_CACHE_FT_SIZES 4
#endif #endif
#endif #endif
#endif #endif