mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-25 09:15:43 +08:00
feat(freetype): merge freetype outline and image into one context (#5154)
This commit is contained in:
@@ -1150,15 +1150,6 @@ menu "LVGL configuration"
|
||||
config LV_FREETYPE_USE_LVGL_PORT
|
||||
bool "Let FreeType to use LVGL memory and file porting"
|
||||
default n
|
||||
choice
|
||||
prompt "Freetype cache type"
|
||||
default LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
|
||||
config LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
bool "IMAGE"
|
||||
config LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||
bool "OUTLINE"
|
||||
endchoice
|
||||
config LV_FREETYPE_CACHE_FT_FACES
|
||||
int "The maximum number of FT_Face"
|
||||
default 8
|
||||
|
||||
@@ -658,11 +658,6 @@
|
||||
/*Let FreeType to use LVGL memory and file porting*/
|
||||
#define LV_FREETYPE_USE_LVGL_PORT 0
|
||||
|
||||
/*FreeType cache type:
|
||||
* LV_FREETYPE_CACHE_TYPE_IMAGE - Image cache
|
||||
* LV_FREETYPE_CACHE_TYPE_OUTLINE - Outline cache*/
|
||||
#define LV_FREETYPE_CACHE_TYPE LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#define LV_FREETYPE_CACHE_FT_FACES 8
|
||||
|
||||
@@ -417,6 +417,7 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc,
|
||||
}
|
||||
dsc->letter_coords = &letter_coords;
|
||||
if(g.bpp == LV_IMGFONT_BPP) dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE;
|
||||
else if(g.bpp == LV_VECFONT_BPP) dsc->format = LV_DRAW_LETTER_VECTOR_FORMAT;
|
||||
else dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_A8;
|
||||
|
||||
dsc->g = &g;
|
||||
|
||||
@@ -75,6 +75,7 @@ typedef struct {
|
||||
typedef enum {
|
||||
LV_DRAW_LETTER_BITMAP_FORMAT_A8,
|
||||
LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE,
|
||||
LV_DRAW_LETTER_VECTOR_FORMAT,
|
||||
} lv_draw_glyph_bitmap_format_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#define PATH_QUALITY VG_LITE_MEDIUM
|
||||
#define PATH_DATA_COORD_FORMAT VG_LITE_S16
|
||||
#define PATH_REF_SIZE 128
|
||||
#define FT_F26DOT6_SHIFT 6
|
||||
|
||||
/** After converting the font reference size, it is also necessary to scale the 26dot6 data
|
||||
@@ -31,8 +30,6 @@
|
||||
*/
|
||||
#define FT_F26DOT6_TO_PATH_SCALE(x) (LV_FREETYPE_F26DOT6_TO_FLOAT(x) / (1 << FT_F26DOT6_SHIFT))
|
||||
|
||||
#define SUPPORT_OUTLINE_FONT (LV_USE_FREETYPE && LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -46,10 +43,8 @@ static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * gly
|
||||
|
||||
static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc);
|
||||
|
||||
#if SUPPORT_OUTLINE_FONT
|
||||
static void freetype_outline_event_cb(lv_event_t * e);
|
||||
static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc);
|
||||
#endif
|
||||
static void freetype_outline_event_cb(lv_event_t * e);
|
||||
static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@@ -68,14 +63,11 @@ void lv_draw_vg_lite_label(lv_draw_unit_t * draw_unit, const lv_draw_label_dsc_t
|
||||
{
|
||||
if(dsc->opa <= LV_OPA_MIN) return;
|
||||
|
||||
#if SUPPORT_OUTLINE_FONT
|
||||
static bool is_init = false;
|
||||
if(!is_init) {
|
||||
lv_freetype_outline_set_ref_size(PATH_REF_SIZE);
|
||||
lv_freetype_outline_add_event(freetype_outline_event_cb, LV_EVENT_ALL, draw_unit);
|
||||
is_init = true;
|
||||
}
|
||||
#endif /*SUPPORT_OUTLINE_FONT*/
|
||||
|
||||
lv_draw_label_iterate_characters(draw_unit, dsc, coords, draw_letter_cb);
|
||||
}
|
||||
@@ -101,14 +93,12 @@ static void draw_letter_cb(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * gly
|
||||
#endif
|
||||
}
|
||||
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8
|
||||
|| glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
|
||||
#if SUPPORT_OUTLINE_FONT
|
||||
|| glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE
|
||||
|| glyph_draw_dsc->format == LV_DRAW_LETTER_VECTOR_FORMAT) {
|
||||
if(lv_freetype_is_outline_font(glyph_draw_dsc->g->resolved_font)) {
|
||||
draw_letter_outline(u, glyph_draw_dsc);
|
||||
}
|
||||
else
|
||||
#endif /*SUPPORT_OUTLINE_FONT*/
|
||||
{
|
||||
else {
|
||||
draw_letter_bitmap(u, glyph_draw_dsc);
|
||||
}
|
||||
}
|
||||
@@ -206,8 +196,6 @@ static void draw_letter_bitmap(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_d
|
||||
LV_VG_LITE_CHECK_ERROR(vg_lite_finish());
|
||||
}
|
||||
|
||||
#if SUPPORT_OUTLINE_FONT
|
||||
|
||||
static void draw_letter_outline(lv_draw_vg_lite_unit_t * u, const lv_draw_glyph_dsc_t * dsc)
|
||||
{
|
||||
/* get clip area */
|
||||
@@ -315,6 +303,4 @@ static void freetype_outline_event_cb(lv_event_t * e)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*SUPPORT_OUTLINE_FONT*/
|
||||
|
||||
#endif /*LV_USE_DRAW_VG_LITE*/
|
||||
|
||||
@@ -29,6 +29,7 @@ extern "C" {
|
||||
|
||||
/* imgfont identifier */
|
||||
#define LV_IMGFONT_BPP 9
|
||||
#define LV_VECFONT_BPP 0
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
|
||||
+117
-15
@@ -18,6 +18,7 @@
|
||||
*********************/
|
||||
|
||||
#define ft_ctx LV_GLOBAL_DEFAULT()->ft_context
|
||||
#define LV_FREETYPE_OUTLINE_REF_SIZE_DEF 128
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
@@ -41,6 +42,10 @@ static void lv_freetype_cleanup(lv_freetype_context_t * ctx);
|
||||
static FTC_FaceID lv_freetype_req_face_id(lv_freetype_context_t * ctx, const char * pathname);
|
||||
static void lv_freetype_drop_face_id(lv_freetype_context_t * ctx, FTC_FaceID face_id);
|
||||
|
||||
static bool cache_node_cache_create_cb(lv_freetype_cache_node_t * node, void * user_data);
|
||||
static void cache_node_cache_free_cb(lv_freetype_cache_node_t * node, void * user_data);
|
||||
static lv_cache_compare_res_t cache_node_cache_compare_cb(const lv_freetype_cache_node_t * lhs,
|
||||
const lv_freetype_cache_node_t * rhs);
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
@@ -60,7 +65,7 @@ lv_result_t lv_freetype_init(uint32_t max_faces, uint32_t max_sizes, uint32_t ma
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
ft_ctx = lv_malloc(sizeof(lv_freetype_context_t));
|
||||
ft_ctx = lv_malloc_zeroed(sizeof(lv_freetype_context_t));
|
||||
LV_ASSERT_MALLOC(ft_ctx);
|
||||
if(!ft_ctx) {
|
||||
LV_LOG_ERROR("malloc failed for lv_freetype_context_t");
|
||||
@@ -96,16 +101,15 @@ lv_result_t lv_freetype_init(uint32_t max_faces, uint32_t max_sizes, uint32_t ma
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
ctx->cache_context = lv_freetype_cache_context_create(ctx);
|
||||
|
||||
if(!ctx->cache_context) {
|
||||
LV_LOG_ERROR("cache context create failed");
|
||||
lv_freetype_cleanup(ctx);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
_lv_ll_init(&ctx->face_id_ll, sizeof(face_id_node_t));
|
||||
|
||||
lv_cache_ops_t ops = {
|
||||
.compare_cb = (lv_cache_compare_cb_t)cache_node_cache_compare_cb,
|
||||
.create_cb = (lv_cache_create_cb_t)cache_node_cache_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)cache_node_cache_free_cb,
|
||||
};
|
||||
ctx->cache_node_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_cache_node_t), INT32_MAX, ops);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -118,13 +122,26 @@ void lv_freetype_uninit(void)
|
||||
ft_ctx = NULL;
|
||||
}
|
||||
|
||||
lv_font_t * lv_freetype_font_create(const char * pathname, uint32_t size, lv_freetype_font_style_t style)
|
||||
lv_font_t * lv_freetype_font_create(const char * pathname, lv_freetype_font_render_mode_t render_mode, uint32_t size,
|
||||
lv_freetype_font_style_t style)
|
||||
{
|
||||
LV_ASSERT_NULL(pathname);
|
||||
LV_ASSERT(size > 0);
|
||||
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
|
||||
lv_freetype_cache_node_t search_key = {
|
||||
.pathname = pathname,
|
||||
.style = style,
|
||||
.render_mode = render_mode,
|
||||
};
|
||||
|
||||
lv_cache_entry_t * cache_node_entry = lv_cache_acquire_or_create(ctx->cache_node_cache, &search_key, NULL);
|
||||
if(!cache_node_entry) {
|
||||
LV_LOG_ERROR("lv_cache_acquire_or_create failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t pathname_len = lv_strlen(pathname);
|
||||
LV_ASSERT(pathname_len > 0);
|
||||
|
||||
@@ -132,10 +149,13 @@ lv_font_t * lv_freetype_font_create(const char * pathname, uint32_t size, lv_fre
|
||||
LV_ASSERT_MALLOC(dsc);
|
||||
|
||||
dsc->face_id = lv_freetype_req_face_id(ctx, pathname);
|
||||
dsc->render_mode = render_mode;
|
||||
dsc->context = ctx;
|
||||
dsc->size = size;
|
||||
dsc->style = style;
|
||||
dsc->magic_num = LV_FREETYPE_FONT_DSC_MAGIC_NUM;
|
||||
dsc->cache_node = lv_cache_entry_get_data(cache_node_entry);
|
||||
dsc->cache_node_entry = cache_node_entry;
|
||||
|
||||
/* get font info */
|
||||
FT_Size ft_size = lv_freetype_lookup_size(dsc);
|
||||
@@ -156,6 +176,7 @@ lv_font_t * lv_freetype_font_create(const char * pathname, uint32_t size, lv_fre
|
||||
int8_t thickness = FT_F26DOT6_TO_INT(FT_MulFix(scale, ft_size->face->underline_thickness));
|
||||
font->underline_position = FT_F26DOT6_TO_INT(FT_MulFix(scale, ft_size->face->underline_position));
|
||||
font->underline_thickness = thickness < 1 ? 1 : thickness;
|
||||
font->get_glyph_dsc = lv_freetype_get_glyph_dsc_cb;
|
||||
|
||||
return font;
|
||||
}
|
||||
@@ -163,11 +184,16 @@ lv_font_t * lv_freetype_font_create(const char * pathname, uint32_t size, lv_fre
|
||||
void lv_freetype_font_delete(lv_font_t * font)
|
||||
{
|
||||
LV_ASSERT_NULL(font);
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)(font->dsc);
|
||||
LV_ASSERT_NULL(dsc);
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
|
||||
lv_freetype_on_font_delete(dsc);
|
||||
lv_cache_release(ctx->cache_node_cache, dsc->cache_node_entry, NULL);
|
||||
if(lv_cache_entry_get_ref(dsc->cache_node_entry) == 0) {
|
||||
lv_cache_drop(ctx->cache_node_cache, dsc->cache_node, NULL);
|
||||
}
|
||||
|
||||
lv_freetype_drop_face_id(dsc->context, dsc->face_id);
|
||||
|
||||
/* invalidate magic number */
|
||||
@@ -218,6 +244,20 @@ const char * lv_freetype_get_pathname(FTC_FaceID face_id)
|
||||
return (const char *)face_id;
|
||||
}
|
||||
|
||||
bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_BITMAP) {
|
||||
return lv_freetype_image_font_create(dsc);
|
||||
}
|
||||
else if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE) {
|
||||
return lv_freetype_outline_font_create(dsc);
|
||||
}
|
||||
else {
|
||||
LV_LOG_ERROR("unknown render mode");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -243,10 +283,9 @@ static FT_Error lv_freetype_face_requester(FTC_FaceID face_id,
|
||||
static void lv_freetype_cleanup(lv_freetype_context_t * ctx)
|
||||
{
|
||||
LV_ASSERT_NULL(ctx);
|
||||
|
||||
if(ctx->cache_context) {
|
||||
lv_freetype_cache_context_delete(ctx->cache_context);
|
||||
ctx->cache_context = NULL;
|
||||
if(ctx->cache_node_cache) {
|
||||
lv_cache_destroy(ctx->cache_node_cache, NULL);
|
||||
ctx->cache_node_cache = NULL;
|
||||
}
|
||||
|
||||
if(ctx->cache_manager) {
|
||||
@@ -313,4 +352,67 @@ static void lv_freetype_drop_face_id(lv_freetype_context_t * ctx, FTC_FaceID fac
|
||||
LV_ASSERT_MSG(false, "face_id not found");
|
||||
}
|
||||
|
||||
/*-----------------
|
||||
* Cache Node Cache Callbacks
|
||||
*----------------*/
|
||||
|
||||
static bool cache_node_cache_create_cb(lv_freetype_cache_node_t * node, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
|
||||
/* Cache miss, load face */
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Face(ctx->library, node->pathname, 0, &face);
|
||||
if(error) {
|
||||
FT_ERROR_MSG("FT_New_Face", error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->ref_size = LV_FREETYPE_OUTLINE_REF_SIZE_DEF;
|
||||
|
||||
FT_F26Dot6 pixel_size = FT_INT_TO_F26DOT6(node->ref_size);
|
||||
error = FT_Set_Char_Size(face, 0, pixel_size, 0, 0);
|
||||
if(error) {
|
||||
FT_Done_Face(face);
|
||||
FT_ERROR_MSG("FT_Set_Char_Size", error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(node->style & LV_FREETYPE_FONT_STYLE_ITALIC) {
|
||||
lv_freetype_italic_transform(face);
|
||||
}
|
||||
|
||||
node->face = face;
|
||||
node->glyph_cache = lv_freetype_glyph_cache_create();
|
||||
|
||||
return true;
|
||||
}
|
||||
static void cache_node_cache_free_cb(lv_freetype_cache_node_t * node, void * user_data)
|
||||
{
|
||||
lv_cache_destroy(node->glyph_cache, user_data);
|
||||
lv_cache_destroy(node->draw_data_cache, user_data);
|
||||
}
|
||||
static lv_cache_compare_res_t cache_node_cache_compare_cb(const lv_freetype_cache_node_t * lhs,
|
||||
const lv_freetype_cache_node_t * rhs)
|
||||
{
|
||||
if(lhs->render_mode != rhs->render_mode) {
|
||||
return lhs->render_mode > rhs->render_mode ? 1 : -1;
|
||||
}
|
||||
if(lhs->style != rhs->style) {
|
||||
return lhs->style > rhs->style ? 1 : -1;
|
||||
}
|
||||
|
||||
if(lhs->pathname == rhs->pathname) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t cmp_res = lv_strcmp(lhs->pathname, rhs->pathname);
|
||||
if(cmp_res != 0) {
|
||||
return cmp_res > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*LV_USE_FREETYPE*/
|
||||
|
||||
@@ -20,9 +20,6 @@ extern "C" {
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_FREETYPE_CACHE_TYPE_IMAGE 0
|
||||
#define LV_FREETYPE_CACHE_TYPE_OUTLINE 1
|
||||
|
||||
#define LV_FREETYPE_F26DOT6_TO_INT(x) ((x) >> 6)
|
||||
#define LV_FREETYPE_F26DOT6_TO_FLOAT(x) ((float)(x) / 64)
|
||||
|
||||
@@ -43,7 +40,12 @@ enum {
|
||||
typedef uint16_t lv_freetype_font_style_t;
|
||||
typedef lv_freetype_font_style_t LV_FT_FONT_STYLE;
|
||||
|
||||
#if LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||
enum {
|
||||
LV_FREETYPE_FONT_RENDER_MODE_BITMAP = 0,
|
||||
LV_FREETYPE_FONT_RENDER_MODE_OUTLINE = 1,
|
||||
};
|
||||
|
||||
typedef uint16_t lv_freetype_font_render_mode_t;
|
||||
|
||||
typedef void * lv_freetype_outline_t;
|
||||
|
||||
@@ -68,8 +70,6 @@ typedef struct {
|
||||
lv_freetype_outline_vector_t control2;
|
||||
} lv_freetype_outline_event_param_t;
|
||||
|
||||
#endif /*LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE*/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
@@ -92,11 +92,13 @@ void lv_freetype_uninit(void);
|
||||
/**
|
||||
* Create a freetype font.
|
||||
* @param pathname font file path.
|
||||
* @param render_mode font render mode(see @lv_freetype_font_render_mode_t for details).
|
||||
* @param size font size.
|
||||
* @param style font style(see lv_freetype_font_style_t for details).
|
||||
* @return Created font, or NULL on failure.
|
||||
*/
|
||||
lv_font_t * lv_freetype_font_create(const char * pathname, uint32_t size, lv_freetype_font_style_t style);
|
||||
lv_font_t * lv_freetype_font_create(const char * pathname, lv_freetype_font_render_mode_t render_mode, uint32_t size,
|
||||
lv_freetype_font_style_t style);
|
||||
|
||||
/**
|
||||
* Delete a freetype font.
|
||||
@@ -104,8 +106,6 @@ lv_font_t * lv_freetype_font_create(const char * pathname, uint32_t size, lv_fre
|
||||
*/
|
||||
void lv_freetype_font_delete(lv_font_t * font);
|
||||
|
||||
#if LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||
|
||||
/**
|
||||
* Register a callback function to generate outlines for FreeType fonts.
|
||||
*
|
||||
@@ -115,10 +115,6 @@ void lv_freetype_font_delete(lv_font_t * font);
|
||||
*/
|
||||
void lv_freetype_outline_add_event(lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data);
|
||||
|
||||
void lv_freetype_outline_set_ref_size(uint32_t size);
|
||||
|
||||
uint32_t lv_freetype_outline_get_ref_size(void);
|
||||
|
||||
/**
|
||||
* Get the scale of a FreeType font.
|
||||
*
|
||||
@@ -135,8 +131,6 @@ uint32_t lv_freetype_outline_get_scale(const lv_font_t * font);
|
||||
*/
|
||||
bool lv_freetype_is_outline_font(const lv_font_t * font);
|
||||
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
|
||||
#include "lv_freetype_private.h"
|
||||
|
||||
#if LV_USE_FREETYPE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#if LV_USE_FREETYPE
|
||||
|
||||
#define LV_FREETYPE_GLYPH_DSC_CACHE_SIZE (LV_FREETYPE_CACHE_FT_OUTLINES * 2)
|
||||
/**********************
|
||||
@@ -28,8 +29,6 @@ typedef struct _lv_freetype_glyph_cache_data_t {
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter,
|
||||
uint32_t unicode_letter_next);
|
||||
|
||||
static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data);
|
||||
static void freetype_glyph_free_cb(lv_freetype_glyph_cache_data_t * data, void * user_data);
|
||||
@@ -46,10 +45,8 @@ static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
lv_cache_t * lv_freetype_glyph_cache_create(lv_freetype_font_dsc_t * dsc)
|
||||
lv_cache_t * lv_freetype_glyph_cache_create(void)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
|
||||
lv_cache_ops_t ops = {
|
||||
.create_cb = (lv_cache_create_cb_t)freetype_glyph_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)freetype_glyph_free_cb,
|
||||
@@ -66,17 +63,11 @@ lv_cache_t * lv_freetype_glyph_cache_create(lv_freetype_font_dsc_t * dsc)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb;
|
||||
return cache;
|
||||
}
|
||||
|
||||
void lv_freetype_glyph_cache_delete(lv_cache_t * cache)
|
||||
{
|
||||
lv_cache_destroy(cache, NULL);
|
||||
}
|
||||
|
||||
static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter,
|
||||
uint32_t unicode_letter_next)
|
||||
bool lv_freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter,
|
||||
uint32_t unicode_letter_next)
|
||||
{
|
||||
LV_ASSERT_NULL(font);
|
||||
LV_ASSERT_NULL(g_dsc);
|
||||
@@ -99,7 +90,7 @@ static bool freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_
|
||||
.size = dsc->size,
|
||||
};
|
||||
|
||||
lv_cache_t * glyph_cache = lv_freetype_get_glyph_cache(dsc);
|
||||
lv_cache_t * glyph_cache = dsc->cache_node->glyph_cache;
|
||||
|
||||
lv_cache_entry_t * entry = lv_cache_acquire_or_create(glyph_cache, &search_key, dsc);
|
||||
if(entry == NULL) {
|
||||
@@ -133,14 +124,9 @@ static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void
|
||||
|
||||
FT_Error error;
|
||||
|
||||
FT_Size ft_size = lv_freetype_lookup_size(dsc);
|
||||
if(!ft_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
lv_font_glyph_dsc_t * dsc_out = &data->glyph_dsc;
|
||||
|
||||
FT_Face face = ft_size->face;
|
||||
FT_Face face = dsc->cache_node->face;
|
||||
FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||
FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, data->unicode);
|
||||
|
||||
@@ -151,27 +137,29 @@ static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_GlyphSlot glyph = ft_size->face->glyph;
|
||||
FT_GlyphSlot glyph = face->glyph;
|
||||
|
||||
#if LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||
dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->metrics.horiAdvance);
|
||||
dsc_out->box_h = FT_F26DOT6_TO_INT(glyph->metrics.height); /*Height of the bitmap in [px]*/
|
||||
dsc_out->box_w = FT_F26DOT6_TO_INT(glyph->metrics.width); /*Width of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingX); /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingY -
|
||||
glyph->metrics.height); /*Y offset of the bitmap measured from the as line*/
|
||||
#elif LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_BITMAP
|
||||
FT_Bitmap * glyph_bitmap = &ft_size->face->glyph->bitmap;
|
||||
if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE) {
|
||||
dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->metrics.horiAdvance);
|
||||
dsc_out->box_h = FT_F26DOT6_TO_INT(glyph->metrics.height); /*Height of the bitmap in [px]*/
|
||||
dsc_out->box_w = FT_F26DOT6_TO_INT(glyph->metrics.width); /*Width of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingX); /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = FT_F26DOT6_TO_INT(glyph->metrics.horiBearingY -
|
||||
glyph->metrics.height); /*Y offset of the bitmap measured from the as line*/
|
||||
dsc_out->bpp = LV_VECFONT_BPP; /*Bit per pixel: 1/2/4/8*/
|
||||
}
|
||||
else if(dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_BITMAP) {
|
||||
FT_Bitmap * glyph_bitmap = &face->glyph->bitmap;
|
||||
|
||||
dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->advance.x); /*Width of the glyph in [pf]*/
|
||||
dsc_out->box_h = glyph_bitmap->rows; /*Height of the bitmap in [px]*/
|
||||
dsc_out->box_w = glyph_bitmap->width; /*Width of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = glyph->bitmap_top -
|
||||
dsc_out->box_h; /*Y offset of the bitmap measured from the as line*/
|
||||
#endif
|
||||
dsc_out->adv_w = FT_F26DOT6_TO_INT(glyph->advance.x); /*Width of the glyph in [pf]*/
|
||||
dsc_out->box_h = glyph_bitmap->rows; /*Height of the bitmap in [px]*/
|
||||
dsc_out->box_w = glyph_bitmap->width; /*Width of the bitmap in [px]*/
|
||||
dsc_out->ofs_x = glyph->bitmap_left; /*X offset of the bitmap in [pf]*/
|
||||
dsc_out->ofs_y = glyph->bitmap_top -
|
||||
dsc_out->box_h; /*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*/
|
||||
dsc_out->is_placeholder = glyph_index == 0;
|
||||
dsc_out->glyph_index = glyph_index;
|
||||
|
||||
@@ -193,4 +181,5 @@ static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_FREETYPE*/
|
||||
|
||||
@@ -9,25 +9,16 @@
|
||||
|
||||
#include "lv_freetype_private.h"
|
||||
|
||||
#if LV_USE_FREETYPE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#if LV_USE_FREETYPE && LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_freetype_cache_context_t {
|
||||
};
|
||||
|
||||
struct _lv_freetype_cache_node_t {
|
||||
FT_Face face;
|
||||
lv_cache_t * image_cache;
|
||||
lv_cache_t * glyph_cache;
|
||||
};
|
||||
|
||||
typedef struct _lv_freetype_image_cache_data_t {
|
||||
FT_UInt glyph_index;
|
||||
uint32_t size;
|
||||
@@ -60,79 +51,38 @@ static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_context_t * ctx)
|
||||
{
|
||||
LV_UNUSED(ctx);
|
||||
|
||||
lv_freetype_cache_context_t * cache_ctx = lv_malloc(sizeof(lv_freetype_cache_context_t));
|
||||
LV_ASSERT_MALLOC(cache_ctx);
|
||||
lv_memzero(cache_ctx, sizeof(lv_freetype_cache_context_t));
|
||||
|
||||
return cache_ctx;
|
||||
}
|
||||
|
||||
void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_ctx)
|
||||
{
|
||||
LV_ASSERT_NULL(cache_ctx);
|
||||
lv_free(cache_ctx);
|
||||
}
|
||||
|
||||
bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc)
|
||||
bool lv_freetype_image_font_create(lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb;
|
||||
dsc->font.release_glyph = freetype_image_release_cb;
|
||||
|
||||
FT_Size ft_size = lv_freetype_lookup_size(dsc);
|
||||
if(!ft_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_Face face = ft_size->face;
|
||||
FT_Face face = dsc->cache_node->face;
|
||||
|
||||
if(dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) {
|
||||
lv_freetype_italic_transform(face);
|
||||
}
|
||||
|
||||
lv_freetype_cache_node_t * cache_node = lv_malloc_zeroed(sizeof(lv_freetype_cache_node_t));
|
||||
if(cache_node == NULL) {
|
||||
LV_LOG_ERROR("cache_node alloc failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
lv_cache_ops_t ops = {
|
||||
.compare_cb = (lv_cache_compare_cb_t)freetype_image_compare_cb,
|
||||
.create_cb = (lv_cache_create_cb_t)freetype_image_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)freetype_image_free_cb,
|
||||
};
|
||||
|
||||
cache_node->image_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_image_cache_data_t),
|
||||
LV_FREETYPE_CACHE_FT_OUTLINES, ops);
|
||||
cache_node->glyph_cache = lv_freetype_glyph_cache_create(dsc);
|
||||
if(cache_node->image_cache == NULL || cache_node->glyph_cache == NULL) {
|
||||
if(dsc->cache_node->draw_data_cache) {
|
||||
return true;
|
||||
}
|
||||
|
||||
dsc->cache_node->draw_data_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_image_cache_data_t),
|
||||
LV_FREETYPE_CACHE_FT_OUTLINES, ops);
|
||||
if(dsc->cache_node->draw_data_cache == NULL || dsc->cache_node->glyph_cache == NULL) {
|
||||
LV_LOG_ERROR("lv_cache_create failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc->cache_node = cache_node;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_freetype_on_font_delete(lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
lv_cache_destroy(dsc->cache_node->image_cache, NULL);
|
||||
lv_freetype_glyph_cache_delete(dsc->cache_node->glyph_cache);
|
||||
lv_free(dsc->cache_node);
|
||||
}
|
||||
|
||||
lv_cache_t * lv_freetype_get_glyph_cache(const lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
return dsc->cache_node->glyph_cache;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -147,17 +97,11 @@ static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_f
|
||||
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc;
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
|
||||
FT_Size ft_size = lv_freetype_lookup_size(dsc);
|
||||
if(!ft_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_Face face = ft_size->face;
|
||||
FT_Face face = dsc->cache_node->face;
|
||||
FT_UInt charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||
FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter);
|
||||
dsc->cache_node->face = face;
|
||||
|
||||
lv_cache_t * cache = dsc->cache_node->image_cache;
|
||||
lv_cache_t * cache = dsc->cache_node->draw_data_cache;
|
||||
|
||||
lv_freetype_image_cache_data_t search_key = {
|
||||
.glyph_index = glyph_index,
|
||||
@@ -176,7 +120,7 @@ static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_
|
||||
{
|
||||
LV_ASSERT_NULL(font);
|
||||
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc;
|
||||
lv_cache_release(dsc->cache_node->image_cache, g_dsc->entry, NULL);
|
||||
lv_cache_release(dsc->cache_node->draw_data_cache, g_dsc->entry, NULL);
|
||||
g_dsc->entry = NULL;
|
||||
}
|
||||
|
||||
@@ -223,6 +167,8 @@ static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void
|
||||
box_w);
|
||||
}
|
||||
|
||||
FT_Done_Glyph(glyph);
|
||||
|
||||
return true;
|
||||
}
|
||||
static void freetype_image_free_cb(lv_freetype_image_cache_data_t * data, void * user_data)
|
||||
@@ -241,4 +187,5 @@ static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_FREETYPE*/
|
||||
|
||||
@@ -9,14 +9,12 @@
|
||||
|
||||
#include "lv_freetype_private.h"
|
||||
|
||||
#if LV_USE_FREETYPE && LV_FREETYPE_CACHE_TYPE == LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||
#if LV_USE_FREETYPE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define LV_FREETYPE_OUTLINE_REF_SIZE_DEF 128
|
||||
|
||||
#if LV_FREETYPE_CACHE_FT_OUTLINES <= 0
|
||||
#error "LV_FREETYPE_CACHE_FT_OUTLINES must be greater than 0"
|
||||
#endif
|
||||
@@ -25,29 +23,6 @@
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_freetype_cache_context_t {
|
||||
uint32_t ref_size;
|
||||
lv_ll_t cache_ll;
|
||||
lv_event_cb_t event_cb;
|
||||
void * user_data;
|
||||
};
|
||||
|
||||
struct _lv_freetype_cache_node_t {
|
||||
lv_freetype_cache_context_t * cache_context;
|
||||
|
||||
int ref_cnt;
|
||||
const char * pathname;
|
||||
lv_freetype_font_style_t style;
|
||||
FT_Face face;
|
||||
|
||||
/*glyph cache*/
|
||||
lv_cache_t * glyph_cache;
|
||||
|
||||
/*glyph outline cache*/
|
||||
lv_cache_t * glyph_outline_cache;
|
||||
int outline_cnt;
|
||||
};
|
||||
|
||||
typedef struct _lv_freetype_outline_node_t {
|
||||
FT_UInt glyph_index;
|
||||
lv_freetype_outline_t outline;
|
||||
@@ -59,14 +34,12 @@ typedef struct _lv_freetype_outline_node_t {
|
||||
|
||||
static lv_freetype_outline_t outline_create(lv_freetype_context_t * ctx, FT_Face face, FT_UInt glyph_index,
|
||||
uint32_t size, uint32_t strength);
|
||||
static lv_result_t outline_delete(lv_freetype_cache_context_t * cache_context, lv_freetype_outline_t outline);
|
||||
static lv_result_t outline_delete(lv_freetype_context_t * ctx, lv_freetype_outline_t outline);
|
||||
static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc,
|
||||
uint32_t unicode_letter,
|
||||
uint8_t * bitmap_out);
|
||||
static void freetype_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc);
|
||||
|
||||
static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_font_dsc_t * dsc, const char * pathname);
|
||||
static void lv_freetype_cache_node_drop(lv_freetype_font_dsc_t * dsc);
|
||||
static lv_cache_entry_t * lv_freetype_outline_lookup(lv_freetype_font_dsc_t * dsc, uint32_t unicode_letter);
|
||||
|
||||
/*glyph dsc cache lru callbacks*/
|
||||
@@ -87,84 +60,42 @@ static lv_cache_compare_res_t freetype_glyph_outline_cmp_cb(const lv_freetype_ou
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_context_t * ctx)
|
||||
{
|
||||
LV_UNUSED(ctx);
|
||||
lv_freetype_cache_context_t * cache_ctx;
|
||||
cache_ctx = lv_malloc(sizeof(lv_freetype_cache_context_t));
|
||||
LV_ASSERT_MALLOC(cache_ctx);
|
||||
lv_memzero(cache_ctx, sizeof(lv_freetype_cache_context_t));
|
||||
|
||||
_lv_ll_init(&cache_ctx->cache_ll, sizeof(lv_freetype_cache_node_t));
|
||||
cache_ctx->ref_size = LV_FREETYPE_OUTLINE_REF_SIZE_DEF;
|
||||
|
||||
LV_LOG_INFO("cache_context = %p", cache_ctx);
|
||||
return cache_ctx;
|
||||
}
|
||||
|
||||
void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_context)
|
||||
{
|
||||
LV_ASSERT_NULL(cache_context);
|
||||
|
||||
lv_freetype_cache_node_t * cache;
|
||||
lv_ll_t * cache_ll = &cache_context->cache_ll;
|
||||
|
||||
_LV_LL_READ(cache_ll, cache) {
|
||||
LV_LOG_ERROR("cache_node: ptr = %p, ref_cnt = %d",
|
||||
cache, cache->ref_cnt);
|
||||
}
|
||||
|
||||
/* Must ensure that cache_node is not used */
|
||||
LV_ASSERT(_lv_ll_get_len(cache_ll) == 0);
|
||||
|
||||
LV_LOG_INFO("cache_context = %p", cache_context);
|
||||
lv_free(cache_context);
|
||||
}
|
||||
|
||||
bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc)
|
||||
bool lv_freetype_outline_font_create(lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
dsc->cache_node = lv_freetype_cache_node_lookup(dsc, lv_freetype_get_pathname(dsc->face_id));
|
||||
dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb;
|
||||
dsc->font.release_glyph = freetype_release_glyph_cb;
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_freetype_on_font_delete(lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
LV_ASSERT_NULL(dsc->cache_node);
|
||||
lv_freetype_cache_node_drop(dsc);
|
||||
lv_cache_ops_t glyph_outline_cache_ops = {
|
||||
.create_cb = (lv_cache_create_cb_t)freetype_glyph_outline_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)freetype_glyph_outline_free_cb,
|
||||
.compare_cb = (lv_cache_compare_cb_t)freetype_glyph_outline_cmp_cb,
|
||||
};
|
||||
|
||||
if(dsc->cache_node->draw_data_cache) {
|
||||
return true;
|
||||
}
|
||||
|
||||
dsc->cache_node->draw_data_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_outline_node_t),
|
||||
LV_FREETYPE_CACHE_FT_OUTLINES,
|
||||
glyph_outline_cache_ops);
|
||||
|
||||
LV_LOG_INFO("outline cache(name: %s, style: 0x%x) create %p, ref_cnt = %d",
|
||||
dsc->cache_node->pathname,
|
||||
dsc->cache_node->style,
|
||||
dsc->cache_node->draw_data_cache,
|
||||
lv_cache_entry_get_ref(dsc->cache_node_entry));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_freetype_outline_add_event(lv_event_cb_t event_cb, lv_event_code_t filter, void * user_data)
|
||||
{
|
||||
LV_UNUSED(user_data);
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
lv_freetype_cache_context_t * cache_context = ctx->cache_context;
|
||||
LV_ASSERT_NULL(cache_context);
|
||||
|
||||
LV_UNUSED(filter);
|
||||
cache_context->event_cb = event_cb;
|
||||
cache_context->user_data = user_data;
|
||||
}
|
||||
|
||||
void lv_freetype_outline_set_ref_size(uint32_t size)
|
||||
{
|
||||
LV_ASSERT(size > 0);
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
lv_freetype_cache_context_t * cache_context = ctx->cache_context;
|
||||
LV_ASSERT_NULL(cache_context);
|
||||
|
||||
cache_context->ref_size = size;
|
||||
}
|
||||
|
||||
uint32_t lv_freetype_outline_get_ref_size(void)
|
||||
{
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
lv_freetype_cache_context_t * cache_context = ctx->cache_context;
|
||||
LV_ASSERT_NULL(cache_context);
|
||||
|
||||
return cache_context->ref_size;
|
||||
ctx->event_cb = event_cb;
|
||||
}
|
||||
|
||||
uint32_t lv_freetype_outline_get_scale(const lv_font_t * font)
|
||||
@@ -173,7 +104,7 @@ uint32_t lv_freetype_outline_get_scale(const lv_font_t * font)
|
||||
const lv_freetype_font_dsc_t * dsc = font->dsc;
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
|
||||
return FT_INT_TO_F26DOT6(dsc->size) / dsc->context->cache_context->ref_size;
|
||||
return FT_INT_TO_F26DOT6(dsc->size) / dsc->cache_node->ref_size;
|
||||
}
|
||||
|
||||
bool lv_freetype_is_outline_font(const lv_font_t * font)
|
||||
@@ -184,123 +115,13 @@ bool lv_freetype_is_outline_font(const lv_font_t * font)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
lv_cache_t * lv_freetype_get_glyph_cache(const lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
|
||||
return dsc->cache_node->glyph_cache;
|
||||
return dsc->render_mode == LV_FREETYPE_FONT_RENDER_MODE_OUTLINE;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
/*-------------------
|
||||
* FACE CACHE
|
||||
*------------------*/
|
||||
|
||||
static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_font_dsc_t * dsc, const char * pathname)
|
||||
{
|
||||
LV_ASSERT_NULL(pathname);
|
||||
|
||||
lv_freetype_context_t * ctx = dsc->context;
|
||||
lv_freetype_font_style_t style = dsc->style;
|
||||
|
||||
lv_freetype_cache_context_t * cache_context = ctx->cache_context;
|
||||
|
||||
lv_freetype_cache_node_t * cache;
|
||||
lv_ll_t * cache_ll = &cache_context->cache_ll;
|
||||
|
||||
/* Search cache */
|
||||
_LV_LL_READ(cache_ll, cache) {
|
||||
if(strcmp(pathname, cache->pathname) == 0 && style == cache->style) {
|
||||
lv_freetype_cache_node_t * head = _lv_ll_get_head(cache_ll);
|
||||
_lv_ll_move_before(cache_ll, cache, head);
|
||||
cache->ref_cnt++;
|
||||
LV_LOG_INFO("outline cache(name: %s, style: 0x%x) hit %p, ref_cnt = %d",
|
||||
pathname, style, cache, cache->ref_cnt);
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cache miss, load face */
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Face(ctx->library, pathname, 0, &face);
|
||||
if(error) {
|
||||
FT_ERROR_MSG("FT_New_Face", error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FT_F26Dot6 pixel_size = FT_INT_TO_F26DOT6(cache_context->ref_size);
|
||||
error = FT_Set_Char_Size(face, 0, pixel_size, 0, 0);
|
||||
if(error) {
|
||||
FT_Done_Face(face);
|
||||
FT_ERROR_MSG("FT_Set_Char_Size", error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(style & LV_FREETYPE_FONT_STYLE_ITALIC) {
|
||||
lv_freetype_italic_transform(face);
|
||||
}
|
||||
|
||||
/* Init cache node */
|
||||
cache = _lv_ll_ins_head(cache_ll);
|
||||
LV_ASSERT_MALLOC(cache);
|
||||
lv_memzero(cache, sizeof(lv_freetype_cache_node_t));
|
||||
|
||||
cache->face = face;
|
||||
cache->style = style;
|
||||
cache->pathname = pathname;
|
||||
|
||||
cache->ref_cnt = 1;
|
||||
cache->cache_context = cache_context;
|
||||
|
||||
lv_cache_ops_t glyph_outline_cache_ops = {
|
||||
.create_cb = (lv_cache_create_cb_t)freetype_glyph_outline_create_cb,
|
||||
.free_cb = (lv_cache_free_cb_t)freetype_glyph_outline_free_cb,
|
||||
.compare_cb = (lv_cache_compare_cb_t)freetype_glyph_outline_cmp_cb,
|
||||
};
|
||||
|
||||
cache->glyph_cache = lv_freetype_glyph_cache_create(dsc);
|
||||
cache->glyph_outline_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_outline_node_t),
|
||||
LV_FREETYPE_CACHE_FT_OUTLINES,
|
||||
glyph_outline_cache_ops);
|
||||
|
||||
LV_LOG_INFO("outline cache(name: %s, style: 0x%x) create %p, ref_cnt = %d",
|
||||
pathname, style, cache, cache->ref_cnt);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void lv_freetype_cache_node_drop(lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_ASSERT_NULL(dsc);
|
||||
LV_ASSERT_NULL(dsc->cache_node);
|
||||
lv_freetype_cache_node_t * cache_node = dsc->cache_node;
|
||||
|
||||
cache_node->ref_cnt--;
|
||||
|
||||
LV_LOG_INFO("outline cache(%s) drop %p, ref_cnt = %d",
|
||||
cache_node->pathname, cache_node, cache_node->ref_cnt);
|
||||
|
||||
if(cache_node->ref_cnt > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("outline cache(%s) free %p", cache_node->pathname, cache_node);
|
||||
|
||||
FT_Done_Face(cache_node->face);
|
||||
|
||||
lv_ll_t * cache_ll = &cache_node->cache_context->cache_ll;
|
||||
_lv_ll_remove(cache_ll, cache_node);
|
||||
|
||||
lv_cache_destroy(cache_node->glyph_outline_cache, dsc);
|
||||
lv_freetype_glyph_cache_delete(cache_node->glyph_cache);
|
||||
lv_free(cache_node);
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
* OUTLINE CACHE
|
||||
*------------------*/
|
||||
@@ -311,14 +132,14 @@ static bool freetype_glyph_outline_create_cb(lv_freetype_outline_node_t * node,
|
||||
outline = outline_create(dsc->context,
|
||||
dsc->cache_node->face,
|
||||
node->glyph_index,
|
||||
dsc->cache_node->cache_context->ref_size,
|
||||
dsc->cache_node->ref_size,
|
||||
dsc->style & LV_FREETYPE_FONT_STYLE_BOLD ? 1 : 0);
|
||||
|
||||
if(!outline) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LV_LOG_INFO("glyph_index = %u, cnt = %d", node->glyph_index, ++dsc->cache_node->outline_cnt);
|
||||
LV_LOG_INFO("glyph_index = %u", node->glyph_index);
|
||||
|
||||
node->outline = outline;
|
||||
return true;
|
||||
@@ -326,9 +147,11 @@ static bool freetype_glyph_outline_create_cb(lv_freetype_outline_node_t * node,
|
||||
|
||||
static void freetype_glyph_outline_free_cb(lv_freetype_outline_node_t * node, lv_freetype_font_dsc_t * dsc)
|
||||
{
|
||||
LV_UNUSED(dsc);
|
||||
|
||||
lv_freetype_outline_t outline = node->outline;
|
||||
outline_delete(dsc->context->cache_context, outline);
|
||||
LV_LOG_INFO("cnt = %d", --dsc->cache_node->outline_cnt);
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
outline_delete(ctx, outline);
|
||||
}
|
||||
|
||||
static lv_cache_compare_res_t freetype_glyph_outline_cmp_cb(const lv_freetype_outline_node_t * node_a,
|
||||
@@ -366,7 +189,7 @@ static void freetype_release_glyph_cb(const lv_font_t * font, lv_font_glyph_dsc_
|
||||
if(g_dsc->entry == NULL) {
|
||||
return;
|
||||
}
|
||||
lv_cache_release(dsc->cache_node->glyph_outline_cache, g_dsc->entry, NULL);
|
||||
lv_cache_release(dsc->cache_node->draw_data_cache, g_dsc->entry, NULL);
|
||||
g_dsc->entry = NULL;
|
||||
}
|
||||
|
||||
@@ -380,7 +203,7 @@ static lv_cache_entry_t * lv_freetype_outline_lookup(lv_freetype_font_dsc_t * ds
|
||||
lv_freetype_outline_node_t tmp_node;
|
||||
tmp_node.glyph_index = glyph_index;
|
||||
|
||||
lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache_node->glyph_outline_cache, &tmp_node, dsc);
|
||||
lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache_node->draw_data_cache, &tmp_node, dsc);
|
||||
if(!entry) {
|
||||
LV_LOG_ERROR("glyph outline lookup failed for glyph_index = %u", glyph_index);
|
||||
return NULL;
|
||||
@@ -394,10 +217,11 @@ static void ft_vector_to_lv_vector(lv_freetype_outline_vector_t * dest, const FT
|
||||
dest->y = src ? src->y : 0;
|
||||
}
|
||||
|
||||
static lv_result_t outline_send_event(lv_freetype_cache_context_t * ctx, lv_event_code_t code,
|
||||
static lv_result_t outline_send_event(lv_freetype_context_t * ctx, lv_event_code_t code,
|
||||
lv_freetype_outline_event_param_t * param)
|
||||
{
|
||||
if(!ctx->event_cb) {
|
||||
LV_LOG_ERROR("event_cb is not set");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
@@ -405,7 +229,7 @@ static lv_result_t outline_send_event(lv_freetype_cache_context_t * ctx, lv_even
|
||||
lv_memzero(&e, sizeof(e));
|
||||
e.code = code;
|
||||
e.param = param;
|
||||
e.user_data = ctx->user_data;
|
||||
e.user_data = NULL;
|
||||
|
||||
ctx->event_cb(&e);
|
||||
|
||||
@@ -420,7 +244,6 @@ static lv_result_t outline_push_point(
|
||||
const FT_Vector * to)
|
||||
{
|
||||
lv_freetype_context_t * ctx = lv_freetype_get_context();
|
||||
lv_freetype_cache_context_t * cache_context = ctx->cache_context;
|
||||
|
||||
lv_freetype_outline_event_param_t param;
|
||||
lv_memzero(¶m, sizeof(param));
|
||||
@@ -430,7 +253,7 @@ static lv_result_t outline_push_point(
|
||||
ft_vector_to_lv_vector(¶m.control2, control2);
|
||||
ft_vector_to_lv_vector(¶m.to, to);
|
||||
|
||||
return outline_send_event(cache_context, LV_EVENT_INSERT, ¶m);
|
||||
return outline_send_event(ctx, LV_EVENT_INSERT, ¶m);
|
||||
}
|
||||
|
||||
static int outline_move_to_cb(
|
||||
@@ -499,11 +322,10 @@ static lv_freetype_outline_t outline_create(
|
||||
}
|
||||
|
||||
lv_result_t res;
|
||||
lv_freetype_cache_context_t * cache_context = ctx->cache_context;
|
||||
lv_freetype_outline_event_param_t param;
|
||||
|
||||
lv_memzero(¶m, sizeof(param));
|
||||
res = outline_send_event(cache_context, LV_EVENT_CREATE, ¶m);
|
||||
res = outline_send_event(ctx, LV_EVENT_CREATE, ¶m);
|
||||
|
||||
lv_freetype_outline_t outline = param.outline;
|
||||
|
||||
@@ -525,7 +347,7 @@ static lv_freetype_outline_t outline_create(
|
||||
error = FT_Outline_Decompose(&face->glyph->outline, &outline_funcs, outline);
|
||||
if(error) {
|
||||
FT_ERROR_MSG("FT_Outline_Decompose", error);
|
||||
outline_delete(ctx->cache_context, outline);
|
||||
outline_delete(ctx, outline);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -533,20 +355,20 @@ static lv_freetype_outline_t outline_create(
|
||||
res = outline_push_point(outline, LV_FREETYPE_OUTLINE_END, NULL, NULL, NULL);
|
||||
if(res != LV_RESULT_OK) {
|
||||
LV_LOG_ERROR("Outline object close failed");
|
||||
outline_delete(ctx->cache_context, outline);
|
||||
outline_delete(ctx, outline);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
static lv_result_t outline_delete(lv_freetype_cache_context_t * cache_context, lv_freetype_outline_t outline)
|
||||
static lv_result_t outline_delete(lv_freetype_context_t * ctx, lv_freetype_outline_t outline)
|
||||
{
|
||||
lv_freetype_outline_event_param_t param;
|
||||
lv_memzero(¶m, sizeof(param));
|
||||
param.outline = outline;
|
||||
|
||||
return outline_send_event(cache_context, LV_EVENT_DELETE, ¶m);
|
||||
return outline_send_event(ctx, LV_EVENT_DELETE, ¶m);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /*LV_USE_FREETYPE*/
|
||||
|
||||
@@ -60,15 +60,32 @@ extern "C" {
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_freetype_cache_context_t lv_freetype_cache_context_t;
|
||||
typedef struct _lv_freetype_cache_node_t lv_freetype_cache_node_t;
|
||||
|
||||
struct _lv_freetype_cache_node_t {
|
||||
const char * pathname;
|
||||
lv_freetype_font_style_t style;
|
||||
lv_freetype_font_render_mode_t render_mode;
|
||||
|
||||
uint32_t ref_size; /**< Reference size for calculating outline glyph's real size.*/
|
||||
|
||||
FT_Face face;
|
||||
|
||||
/*glyph cache*/
|
||||
lv_cache_t * glyph_cache;
|
||||
|
||||
/*draw data cache*/
|
||||
lv_cache_t * draw_data_cache;
|
||||
};
|
||||
|
||||
typedef struct _lv_freetype_context_t {
|
||||
FT_Library library;
|
||||
FTC_Manager cache_manager;
|
||||
FTC_CMapCache cmap_cache;
|
||||
lv_freetype_cache_context_t * cache_context;
|
||||
lv_ll_t face_id_ll;
|
||||
lv_event_cb_t event_cb;
|
||||
|
||||
lv_cache_t * cache_node_cache;
|
||||
} lv_freetype_context_t;
|
||||
|
||||
typedef struct _lv_freetype_font_dsc_t {
|
||||
@@ -76,8 +93,10 @@ typedef struct _lv_freetype_font_dsc_t {
|
||||
lv_font_t font;
|
||||
uint32_t size;
|
||||
lv_freetype_font_style_t style;
|
||||
lv_freetype_font_render_mode_t render_mode;
|
||||
lv_freetype_context_t * context;
|
||||
lv_freetype_cache_node_t * cache_node;
|
||||
lv_cache_entry_t * cache_node_entry;
|
||||
FTC_FaceID face_id;
|
||||
} lv_freetype_font_dsc_t;
|
||||
|
||||
@@ -101,23 +120,20 @@ lv_freetype_context_t * lv_freetype_get_context(void);
|
||||
*/
|
||||
FT_Size lv_freetype_lookup_size(const lv_freetype_font_dsc_t * dsc);
|
||||
|
||||
lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_context_t * ctx);
|
||||
lv_cache_t * lv_freetype_glyph_cache_create(void);
|
||||
|
||||
void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_ctx);
|
||||
|
||||
lv_cache_t * lv_freetype_glyph_cache_create(lv_freetype_font_dsc_t * dsc);
|
||||
|
||||
void lv_freetype_glyph_cache_delete(lv_cache_t * cache);
|
||||
bool lv_freetype_get_glyph_dsc_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc, uint32_t unicode_letter,
|
||||
uint32_t unicode_letter_next);
|
||||
|
||||
bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc);
|
||||
|
||||
void lv_freetype_on_font_delete(lv_freetype_font_dsc_t * dsc);
|
||||
|
||||
void lv_freetype_italic_transform(FT_Face face);
|
||||
|
||||
const char * lv_freetype_get_pathname(FTC_FaceID face_id);
|
||||
|
||||
lv_cache_t * lv_freetype_get_glyph_cache(const lv_freetype_font_dsc_t * dsc);
|
||||
bool lv_freetype_image_font_create(lv_freetype_font_dsc_t * dsc);
|
||||
|
||||
bool lv_freetype_outline_font_create(lv_freetype_font_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -2190,17 +2190,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*FreeType cache type:
|
||||
* LV_FREETYPE_CACHE_TYPE_IMAGE - Image cache
|
||||
* LV_FREETYPE_CACHE_TYPE_OUTLINE - Outline cache*/
|
||||
#ifndef LV_FREETYPE_CACHE_TYPE
|
||||
#ifdef CONFIG_LV_FREETYPE_CACHE_TYPE
|
||||
#define LV_FREETYPE_CACHE_TYPE CONFIG_LV_FREETYPE_CACHE_TYPE
|
||||
#else
|
||||
#define LV_FREETYPE_CACHE_TYPE LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
|
||||
/* (0:use system defaults) */
|
||||
#ifndef LV_FREETYPE_CACHE_FT_FACES
|
||||
|
||||
@@ -235,18 +235,6 @@ extern "C" {
|
||||
# define CONFIG_LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_FULL
|
||||
#endif
|
||||
|
||||
/*------------------
|
||||
* FREETYPE
|
||||
*-----------------*/
|
||||
|
||||
#ifdef CONFIG_LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
# define CONFIG_LV_FREETYPE_CACHE_TYPE LV_FREETYPE_CACHE_TYPE_IMAGE
|
||||
#elif defined(CONFIG_LV_FREETYPE_CACHE_TYPE_SBIT)
|
||||
# define CONFIG_LV_FREETYPE_CACHE_TYPE LV_FREETYPE_CACHE_TYPE_SBIT
|
||||
#elif defined(CONFIG_LV_FREETYPE_CACHE_TYPE_OUTLINE)
|
||||
# define CONFIG_LV_FREETYPE_CACHE_TYPE LV_FREETYPE_CACHE_TYPE_OUTLINE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user