feat(freetype): refactoring freetype to make glyph dsc independent (#5131)

This commit is contained in:
Benign X
2024-01-02 04:45:19 +08:00
committed by GitHub
parent c750f30f8f
commit 4018ef89e1
5 changed files with 282 additions and 246 deletions
+2 -1
View File
@@ -50,7 +50,8 @@ typedef struct {
uint8_t bpp: 4; /**< Bit-per-pixel: 1, 2, 4, 8*/
uint8_t is_placeholder: 1; /** Glyph is missing. But placeholder will still be displayed */
lv_cache_entry_t * entry;
uint32_t glyph_index; /**< The index of the glyph in the font file. Used by the font cache*/
lv_cache_entry_t * entry; /**< The cache entry of the glyph draw data. Used by the font cache*/
} lv_font_glyph_dsc_t;
/** The bitmaps might be upscaled by 3 to achieve subpixel rendering.*/
+196
View File
@@ -0,0 +1,196 @@
/**
* @file lv_freetype_glyph.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_freetype_private.h"
/*********************
* DEFINES
*********************/
#if LV_USE_FREETYPE
#define LV_FREETYPE_GLYPH_DSC_CACHE_SIZE (LV_FREETYPE_CACHE_FT_OUTLINES * 2)
/**********************
* TYPEDEFS
**********************/
typedef struct _lv_freetype_glyph_cache_data_t {
uint32_t unicode;
uint32_t size;
lv_font_glyph_dsc_t glyph_dsc;
} 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);
static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_cache_data_t * lhs,
const lv_freetype_glyph_cache_data_t * rhs);
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
lv_cache_t * lv_freetype_glyph_cache_create(lv_freetype_font_dsc_t * dsc)
{
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,
.compare_cb = (lv_cache_compare_cb_t)freetype_glyph_compare_cb,
};
lv_cache_t * cache = lv_cache_create(&lv_cache_class_lru_rb_count
, sizeof(lv_freetype_glyph_cache_data_t),
LV_FREETYPE_GLYPH_DSC_CACHE_SIZE,
ops
);
if(cache == NULL) {
LV_LOG_ERROR("lv_cache_create failed");
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)
{
LV_ASSERT_NULL(font);
LV_ASSERT_NULL(g_dsc);
if(unicode_letter < 0x20) {
g_dsc->adv_w = 0;
g_dsc->box_h = 0;
g_dsc->box_w = 0;
g_dsc->ofs_x = 0;
g_dsc->ofs_y = 0;
g_dsc->bpp = 0;
return true;
}
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc;
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
lv_freetype_glyph_cache_data_t search_key = {
.unicode = unicode_letter,
.size = dsc->size,
};
lv_cache_t * glyph_cache = lv_freetype_get_glyph_cache(dsc);
lv_cache_entry_t * entry = lv_cache_acquire_or_create(glyph_cache, &search_key, dsc);
if(entry == NULL) {
LV_LOG_ERROR("glyph lookup failed for unicode = %u", unicode_letter);
return false;
}
lv_freetype_glyph_cache_data_t * data = lv_cache_entry_get_data(entry);
*g_dsc = data->glyph_dsc;
if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
g_dsc->adv_w = g_dsc->box_w + g_dsc->ofs_x;
}
g_dsc->entry = NULL;
lv_cache_release(glyph_cache, entry, NULL);
return true;
}
/**********************
* STATIC FUNCTIONS
**********************/
/*-----------------
* Cache Callbacks
*----------------*/
static bool freetype_glyph_create_cb(lv_freetype_glyph_cache_data_t * data, void * user_data)
{
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data;
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_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);
FT_Set_Pixel_Sizes(face, 0, dsc->size);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_COMPUTE_METRICS | FT_LOAD_NO_BITMAP);
if(error) {
FT_ERROR_MSG("FT_Load_Glyph", error);
return false;
}
FT_GlyphSlot glyph = ft_size->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;
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->bpp = 8; /*Bit per pixel: 1/2/4/8*/
dsc_out->is_placeholder = glyph_index == 0;
dsc_out->glyph_index = glyph_index;
return true;
}
static void freetype_glyph_free_cb(lv_freetype_glyph_cache_data_t * data, void * user_data)
{
LV_UNUSED(data);
LV_UNUSED(user_data);
}
static lv_cache_compare_res_t freetype_glyph_compare_cb(const lv_freetype_glyph_cache_data_t * lhs,
const lv_freetype_glyph_cache_data_t * rhs)
{
if(lhs->unicode != rhs->unicode) {
return lhs->unicode > rhs->unicode ? 1 : -1;
}
if(lhs->size != rhs->size) {
return lhs->size > rhs->size ? 1 : -1;
}
return 0;
}
#endif
+61 -108
View File
@@ -20,36 +20,32 @@
**********************/
struct _lv_freetype_cache_context_t {
lv_cache_t * cache;
FT_Face face;
};
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;
lv_font_glyph_dsc_t glyph_dsc;
lv_draw_buf_t * draw_buf;
};
} lv_freetype_image_cache_data_t;
/**********************
* STATIC PROTOTYPES
**********************/
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, lv_font_glyph_dsc_t * g_dsc,
uint32_t unicode_letter,
uint8_t * bitmap_out);
static bool freetype_image_create_cb(lv_freetype_cache_node_t * data, void * user_data);
static void freetype_image_free_cb(lv_freetype_cache_node_t * node, void * user_data);
static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_cache_node_t * lhs,
const lv_freetype_cache_node_t * rhs);
static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void * user_data);
static void freetype_image_free_cb(lv_freetype_image_cache_data_t * node, void * user_data);
static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_cache_data_t * lhs,
const lv_freetype_image_cache_data_t * rhs);
static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_t * g_dsc);
/**********************
@@ -72,34 +68,18 @@ lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_conte
LV_ASSERT_MALLOC(cache_ctx);
lv_memzero(cache_ctx, sizeof(lv_freetype_cache_context_t));
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_ctx->cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_cache_node_t),
LV_FREETYPE_CACHE_FT_OUTLINES, ops);
if(cache_ctx->cache == NULL) {
LV_LOG_ERROR("lv_cache_create failed");
lv_free(cache_ctx);
return NULL;
}
return cache_ctx;
}
void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_ctx)
{
LV_ASSERT_NULL(cache_ctx);
lv_cache_destroy(cache_ctx->cache, NULL);
lv_free(cache_ctx);
}
bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc)
{
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb;
dsc->font.get_glyph_bitmap = freetype_get_glyph_bitmap_cb;
dsc->font.release_glyph = freetype_image_release_cb;
@@ -113,70 +93,50 @@ bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc)
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) {
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
**********************/
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)
{
if(unicode_letter < 0x20) {
dsc_out->adv_w = 0;
dsc_out->box_h = 0;
dsc_out->box_w = 0;
dsc_out->ofs_x = 0;
dsc_out->ofs_y = 0;
dsc_out->bpp = 0;
return true;
}
lv_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_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_out->is_placeholder = glyph_index == 0;
dsc->context->cache_context->face = face;
lv_freetype_cache_node_t search_key = {
.glyph_index = glyph_index,
.size = dsc->size,
};
lv_cache_entry_t * entry = lv_cache_acquire_or_create(dsc->context->cache_context->cache, &search_key, dsc);
if(entry == NULL) {
LV_LOG_ERROR("glyph lookup failed for glyph_index = %u", glyph_index);
return false;
}
lv_freetype_cache_node_t * data = lv_cache_entry_get_data(entry);
*dsc_out = data->glyph_dsc;
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->entry = NULL;
lv_cache_release(dsc->context->cache_context->cache, entry, NULL);
return true;
}
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)
@@ -195,19 +155,19 @@ static const uint8_t * freetype_get_glyph_bitmap_cb(const lv_font_t * font, lv_f
FT_Face face = ft_size->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->context->cache_context->face = face;
dsc->cache_node->face = face;
lv_cache_t * cache = dsc->context->cache_context->cache;
lv_cache_t * cache = dsc->cache_node->image_cache;
lv_freetype_cache_node_t search_key = {
lv_freetype_image_cache_data_t search_key = {
.glyph_index = glyph_index,
.size = dsc->size
.size = dsc->size,
};
lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache, &search_key, dsc);
g_dsc->entry = entry;
lv_freetype_cache_node_t * cache_node = lv_cache_entry_get_data(entry);
lv_freetype_image_cache_data_t * cache_node = lv_cache_entry_get_data(entry);
return cache_node->draw_buf->data;
}
@@ -216,7 +176,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->context->cache_context->cache, g_dsc->entry, NULL);
lv_cache_release(dsc->cache_node->image_cache, g_dsc->entry, NULL);
g_dsc->entry = NULL;
}
@@ -224,13 +184,13 @@ static void freetype_image_release_cb(const lv_font_t * font, lv_font_glyph_dsc_
* Cache Callbacks
*----------------*/
static bool freetype_image_create_cb(lv_freetype_cache_node_t * data, void * user_data)
static bool freetype_image_create_cb(lv_freetype_image_cache_data_t * data, void * user_data)
{
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)user_data;
FT_Error error;
FT_Face face = dsc->context->cache_context->face;
FT_Face face = dsc->cache_node->face;
FT_Set_Pixel_Sizes(face, 0, dsc->size);
error = FT_Load_Glyph(face, data->glyph_index, FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL);
if(error) {
@@ -252,33 +212,26 @@ static bool freetype_image_create_cb(lv_freetype_cache_node_t * data, void * use
FT_BitmapGlyph glyph_bitmap = (FT_BitmapGlyph)glyph;
lv_font_glyph_dsc_t * dsc_out = &data->glyph_dsc;
uint16_t box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/
uint16_t box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/
dsc_out->adv_w = FT_F16DOT16_TO_INT(glyph_bitmap->root.advance.x);
dsc_out->box_h = glyph_bitmap->bitmap.rows; /*Height of the bitmap in [px]*/
dsc_out->box_w = glyph_bitmap->bitmap.width; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = glyph_bitmap->left; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = glyph_bitmap->top -
glyph_bitmap->bitmap.rows; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 8; /*Bit per pixel: 1/2/4/8*/
uint32_t stride = lv_draw_buf_width_to_stride(box_w, LV_COLOR_FORMAT_A8);
data->draw_buf = lv_draw_buf_create(box_w, box_h, LV_COLOR_FORMAT_A8, stride);
uint32_t stride = lv_draw_buf_width_to_stride(dsc_out->box_w, LV_COLOR_FORMAT_A8);
data->draw_buf = lv_draw_buf_create(dsc_out->box_w, dsc_out->box_h, LV_COLOR_FORMAT_A8, stride);
for(int y = 0; y < dsc_out->box_h; ++y) {
lv_memcpy((uint8_t *)(data->draw_buf->data) + y * stride, glyph_bitmap->bitmap.buffer + y * dsc_out->box_w,
dsc_out->box_w);
for(int y = 0; y < box_h; ++y) {
lv_memcpy((uint8_t *)(data->draw_buf->data) + y * stride, glyph_bitmap->bitmap.buffer + y * box_w,
box_w);
}
return true;
}
static void freetype_image_free_cb(lv_freetype_cache_node_t * data, void * user_data)
static void freetype_image_free_cb(lv_freetype_image_cache_data_t * data, void * user_data)
{
LV_UNUSED(user_data);
lv_draw_buf_destroy(data->draw_buf);
}
static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_cache_node_t * lhs,
const lv_freetype_cache_node_t * rhs)
static lv_cache_compare_res_t freetype_image_compare_cb(const lv_freetype_image_cache_data_t * lhs,
const lv_freetype_image_cache_data_t * rhs)
{
if(lhs->glyph_index != rhs->glyph_index) {
return lhs->glyph_index > rhs->glyph_index ? 1 : -1;
+17 -137
View File
@@ -17,8 +17,6 @@
#define LV_FREETYPE_OUTLINE_REF_SIZE_DEF 128
#define LV_FREETYPE_GLYPH_DSC_CACHE_SIZE (LV_FREETYPE_CACHE_FT_OUTLINES * 2)
#if LV_FREETYPE_CACHE_FT_OUTLINES <= 0
#error "LV_FREETYPE_CACHE_FT_OUTLINES must be greater than 0"
#endif
@@ -34,12 +32,6 @@ struct _lv_freetype_cache_context_t {
void * user_data;
};
typedef struct _lv_freetype_glyph_dsc_node_t {
FT_UInt glyph_index;
uint32_t size;
lv_font_glyph_dsc_t glyph_dsc;
} lv_freetype_glyph_dsc_node_t;
struct _lv_freetype_cache_node_t {
lv_freetype_cache_context_t * cache_context;
@@ -48,13 +40,12 @@ struct _lv_freetype_cache_node_t {
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;
/*glyph size cache*/
lv_cache_t * glyph_dsc_cache;
int dsc_cnt;
};
typedef struct _lv_freetype_outline_node_t {
@@ -69,15 +60,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 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, 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_context_t * ctx, const char * pathname,
lv_freetype_font_style_t style);
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);
@@ -87,12 +75,6 @@ static void freetype_glyph_outline_free_cb(lv_freetype_outline_node_t * node, lv
static lv_cache_compare_res_t freetype_glyph_outline_cmp_cb(const lv_freetype_outline_node_t * node_a,
const lv_freetype_outline_node_t * node_b);
/*glyph dsc cache lru callbacks*/
static bool freetype_glyph_dsc_create_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc);
static void freetype_glyph_dsc_free_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc);
static lv_cache_compare_res_t freetype_glyph_dsc_cmp_cb(const lv_freetype_glyph_dsc_node_t * node_a,
const lv_freetype_glyph_dsc_node_t * node_b);
/**********************
* STATIC VARIABLES
**********************/
@@ -142,8 +124,7 @@ void lv_freetype_cache_context_delete(lv_freetype_cache_context_t * cache_contex
bool lv_freetype_on_font_create(lv_freetype_font_dsc_t * dsc)
{
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
dsc->cache_node = lv_freetype_cache_node_lookup(dsc->context, lv_freetype_get_pathname(dsc->face_id), dsc->style);
dsc->font.get_glyph_dsc = freetype_get_glyph_dsc_cb;
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;
@@ -206,6 +187,12 @@ bool lv_freetype_is_outline_font(const lv_font_t * font)
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;
}
/**********************
* STATIC FUNCTIONS
**********************/
@@ -214,12 +201,13 @@ bool lv_freetype_is_outline_font(const lv_font_t * font)
* FACE CACHE
*------------------*/
static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_context_t * ctx,
const char * pathname, lv_freetype_font_style_t style)
static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_font_dsc_t * dsc, const char * pathname)
{
LV_ASSERT_NULL(ctx);
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;
@@ -269,20 +257,13 @@ static lv_freetype_cache_node_t * lv_freetype_cache_node_lookup(lv_freetype_cont
cache->ref_cnt = 1;
cache->cache_context = cache_context;
lv_cache_ops_t glyph_dsc_cache_ops = {
.create_cb = (lv_cache_create_cb_t)freetype_glyph_dsc_create_cb,
.free_cb = (lv_cache_free_cb_t)freetype_glyph_dsc_free_cb,
.compare_cb = (lv_cache_compare_cb_t)freetype_glyph_dsc_cmp_cb,
};
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_dsc_cache = lv_cache_create(&lv_cache_class_lru_rb_count, sizeof(lv_freetype_glyph_dsc_node_t),
LV_FREETYPE_GLYPH_DSC_CACHE_SIZE,
glyph_dsc_cache_ops);
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);
@@ -315,112 +296,11 @@ static void lv_freetype_cache_node_drop(lv_freetype_font_dsc_t * dsc)
lv_ll_t * cache_ll = &cache_node->cache_context->cache_ll;
_lv_ll_remove(cache_ll, cache_node);
lv_cache_destroy(cache_node->glyph_dsc_cache, dsc);
lv_cache_destroy(cache_node->glyph_outline_cache, dsc);
lv_freetype_glyph_cache_delete(cache_node->glyph_cache);
lv_free(cache_node);
}
/*-------------------
* GLYPH DSC CACHE
*------------------*/
static bool freetype_glyph_dsc_create_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc)
{
lv_font_glyph_dsc_t * dsc_out = &glyph_dsc_node->glyph_dsc;
FT_UInt glyph_index = glyph_dsc_node->glyph_index;
/* cache miss, load dsc */
FT_Size ft_size = lv_freetype_lookup_size(dsc);
if(!ft_size) {
return false;
}
FT_Error error = FT_Load_Glyph(ft_size->face, glyph_index, FT_LOAD_COMPUTE_METRICS | FT_LOAD_NO_BITMAP);
if(error) {
FT_ERROR_MSG("FT_Load_Glyph", error);
return false;
}
LV_LOG_INFO("glyph_index = %u, cnt = %d", glyph_index, ++dsc->cache_node->dsc_cnt);
FT_GlyphSlot glyph = ft_size->face->glyph;
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 = 8; /*Bit per pixel: 1/2/4/8*/
dsc_out->is_placeholder = glyph_index == 0;
return true;
}
static void freetype_glyph_dsc_free_cb(lv_freetype_glyph_dsc_node_t * glyph_dsc_node, lv_freetype_font_dsc_t * dsc)
{
LV_UNUSED(glyph_dsc_node);
LV_UNUSED(dsc);
LV_LOG_INFO("cnt = %d", --dsc->cache_node->dsc_cnt);
}
static lv_cache_compare_res_t freetype_glyph_dsc_cmp_cb(const lv_freetype_glyph_dsc_node_t * node_a,
const lv_freetype_glyph_dsc_node_t * node_b)
{
if(node_a->glyph_index != node_b->glyph_index)
return (node_a->glyph_index > node_b->glyph_index) ? 1 : -1;
if(node_a->size != node_b->size)
return (node_a->size > node_b->size) ? 1 : -1;
return 0;
}
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_ASSERT_NULL(font);
LV_ASSERT_NULL(dsc_out);
if(unicode_letter < 0x20) {
dsc_out->adv_w = 0;
dsc_out->box_h = 0;
dsc_out->box_w = 0;
dsc_out->ofs_x = 0;
dsc_out->ofs_y = 0;
dsc_out->bpp = 0;
return true;
}
lv_freetype_font_dsc_t * dsc = (lv_freetype_font_dsc_t *)font->dsc;
LV_ASSERT_FREETYPE_FONT_DSC(dsc);
lv_freetype_cache_node_t * cache_node = dsc->cache_node;
FT_UInt charmap_index = FT_Get_Charmap_Index(cache_node->face->charmap);
FT_UInt glyph_index = FTC_CMapCache_Lookup(dsc->context->cmap_cache, dsc->face_id, charmap_index, unicode_letter);
lv_freetype_glyph_dsc_node_t tmp_node;
tmp_node.glyph_index = glyph_index;
tmp_node.size = dsc->size;
lv_cache_entry_t * entry = lv_cache_acquire_or_create(cache_node->glyph_dsc_cache, &tmp_node, dsc);
if(entry == NULL) {
return false;
}
lv_freetype_glyph_dsc_node_t * new_node = lv_cache_entry_get_data(entry);
*dsc_out = new_node->glyph_dsc;
if((dsc->style & LV_FREETYPE_FONT_STYLE_ITALIC) && (unicode_letter_next == '\0')) {
dsc_out->adv_w = dsc_out->box_w + dsc_out->ofs_x;
}
lv_cache_release(cache_node->glyph_dsc_cache, entry, NULL);
return true;
}
/*-------------------
* OUTLINE CACHE
*------------------*/
+6
View File
@@ -105,6 +105,10 @@ lv_freetype_cache_context_t * lv_freetype_cache_context_create(lv_freetype_conte
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_on_font_create(lv_freetype_font_dsc_t * dsc);
void lv_freetype_on_font_delete(lv_freetype_font_dsc_t * dsc);
@@ -113,6 +117,8 @@ 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);
/**********************
* MACROS
**********************/