Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(font_glyph_format): refactor draw and font format into lv_font_glyph_format_t #5540

Merged
merged 2 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ menu "LVGL configuration"
config LV_FONT_FMT_TXT_LARGE
bool "Enable it if you have fonts with a lot of characters."
help
The limit depends on the font size, font face and bpp
The limit depends on the font size, font face and format
but with > 10,000 characters if you see issues probably you
need to enable it.

Expand Down
21 changes: 12 additions & 9 deletions docs/overview/font.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ For example:

lv_style_set_text_font(&my_style, &lv_font_montserrat_28); /*Set a larger font*/

Fonts have a **bpp (bits per pixel)** property. It shows how many bits
are used to describe a pixel in a font. The value stored for a pixel
determines the pixel's opacity. This way, with higher *bpp*, the edges
of the letter can be smoother. The possible *bpp* values are 1, 2, 4 and
8 (higher values mean better quality).
Fonts have a **format** property. It describes how the glyph draw data is stored.
It has *2* categories: `Legacy simple format` and `Advanced format`.
In the legacy simple format, the font is stored in a simple array of bitmaps.
In the advanced format, the font is stored in a different way like `Vector`, `SVG`, etc.

The *bpp* property also affects the amount of memory needed to store a
font. For example, *bpp = 4* makes a font nearly four times larger
compared to *bpp = 1*.
In the legacy simple format, the value stored for a pixel determines the pixel's opacity.
This way, with higher *bpp (bit per pixel)*, the edges of the letter can be smoother.
The possible *bpp* values are 1, 2, 4 and 8 (higher values mean better quality).

The *format* property also affects the amount of memory needed to store a
font. For example, *format = LV_FONT_GLYPH_FORMAT_A4* makes a font nearly four times larger
compared to *format = LV_FONT_GLYPH_FORMAT_A1*.

Unicode support
***************
Expand Down Expand Up @@ -382,7 +385,7 @@ To do this, a custom :cpp:type:`lv_font_t` variable needs to be created:
dsc_out->box_w = 6; /*Width of the bitmap in [px]*/
dsc_out->ofs_x = 0; /*X offset of the bitmap in [pf]*/
dsc_out->ofs_y = 3; /*Y offset of the bitmap measured from the as line*/
dsc_out->bpp = 2; /*Bits per pixel: 1/2/4/8*/
dsc_out->format= LV_FONT_GLYPH_FORMAT_A2;

return true; /*true: glyph found; false: glyph was not found*/
}
Expand Down
17 changes: 3 additions & 14 deletions src/draw/lv_draw_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc,

if(g.resolved_font) {
lv_draw_buf_t * draw_buf = NULL;
if(g.bpp < LV_IMGFONT_BPP) {
if(LV_FONT_GLYPH_FORMAT_NONE < g.format && g.format < LV_FONT_GLYPH_FORMAT_IMAGE) {
/*Only check draw buf for bitmap glyph*/
draw_buf = lv_draw_buf_reshape(dsc->_draw_buf, 0, g.box_w, g.box_h, LV_STRIDE_AUTO);
if(draw_buf == NULL) {
Expand All @@ -422,21 +422,10 @@ static void draw_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t * dsc,
}

dsc->glyph_data = (void *)lv_font_get_glyph_bitmap(&g, letter, draw_buf);
if(dsc->glyph_data == NULL) {
dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_INVALID;
}
else 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->format = dsc->glyph_data ? g.format : LV_FONT_GLYPH_FORMAT_NONE;
}
else {
dsc->format = LV_DRAW_LETTER_BITMAP_FORMAT_INVALID;
dsc->format = LV_FONT_GLYPH_FORMAT_NONE;
}

dsc->letter_coords = &letter_coords;
Expand Down
9 changes: 1 addition & 8 deletions src/draw/lv_draw_label.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,9 @@ typedef struct {
lv_draw_label_hint_t * hint;
} lv_draw_label_dsc_t;

typedef enum {
LV_DRAW_LETTER_BITMAP_FORMAT_INVALID,
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 {
void * glyph_data; /*Depends on `format` field, it could be image source or draw buf of bitmap or vector data.*/
lv_draw_glyph_bitmap_format_t format;
lv_font_glyph_format_t format;
const lv_area_t * letter_coords;
const lv_area_t * bg_coords;
const lv_font_glyph_dsc_t * g;
Expand Down
134 changes: 71 additions & 63 deletions src/draw/nxp/vglite/lv_draw_vglite_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,73 +79,81 @@ static void _draw_vglite_letter(lv_draw_unit_t * draw_unit, lv_draw_glyph_dsc_t
lv_draw_fill_dsc_t * fill_draw_dsc, const lv_area_t * fill_area)
{
if(glyph_draw_dsc) {
if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_INVALID) {
switch(glyph_draw_dsc->format) {

case LV_FONT_GLYPH_FORMAT_NONE: {
#if LV_USE_FONT_PLACEHOLDER
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
#endif
}
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) {
/*Do not draw transparent things*/
if(glyph_draw_dsc->opa <= LV_OPA_MIN)
return;

lv_layer_t * layer = draw_unit->target_layer;

lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area))
return;
lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1);

const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
const void * mask_buf = draw_buf->data;

uint32_t mask_width = lv_area_get_width(glyph_draw_dsc->letter_coords);
uint32_t mask_height = lv_area_get_height(glyph_draw_dsc->letter_coords);
uint32_t mask_stride = draw_buf->header.stride;

lv_area_t mask_area;
mask_area.x1 = blend_area.x1 - (glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1);
mask_area.y1 = blend_area.y1 - (glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1);
mask_area.x2 = mask_width - 1;
mask_area.y2 = mask_height - 1;

if(!vglite_buf_aligned(mask_buf, mask_stride, LV_COLOR_FORMAT_A8)) {
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
}
else {
/* Set src_vgbuf structure. */
vglite_set_src_buf(mask_buf, mask_width, mask_height, mask_stride, LV_COLOR_FORMAT_A8);

/* Set vgmatrix. */
vglite_set_translation_matrix(&blend_area);

lv_draw_buf_invalidate_cache((void *)mask_buf, mask_stride, LV_COLOR_FORMAT_A8, &mask_area);

_vglite_draw_letter(&mask_area, glyph_draw_dsc->color, glyph_draw_dsc->opa);
}
}
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
}
break;
case LV_FONT_GLYPH_FORMAT_A1 ... LV_FONT_GLYPH_FORMAT_A8: {
/*Do not draw transparent things*/
if(glyph_draw_dsc->opa <= LV_OPA_MIN)
return;

lv_layer_t * layer = draw_unit->target_layer;

lv_area_t blend_area;
if(!_lv_area_intersect(&blend_area, glyph_draw_dsc->letter_coords, draw_unit->clip_area))
return;
lv_area_move(&blend_area, -layer->buf_area.x1, -layer->buf_area.y1);

const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
const void * mask_buf = draw_buf->data;

uint32_t mask_width = lv_area_get_width(glyph_draw_dsc->letter_coords);
uint32_t mask_height = lv_area_get_height(glyph_draw_dsc->letter_coords);
uint32_t mask_stride = draw_buf->header.stride;

lv_area_t mask_area;
mask_area.x1 = blend_area.x1 - (glyph_draw_dsc->letter_coords->x1 - layer->buf_area.x1);
mask_area.y1 = blend_area.y1 - (glyph_draw_dsc->letter_coords->y1 - layer->buf_area.y1);
mask_area.x2 = mask_width - 1;
mask_area.y2 = mask_height - 1;

if(!vglite_buf_aligned(mask_buf, mask_stride, LV_COLOR_FORMAT_A8)) {
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
lv_draw_vglite_border(draw_unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
}
else {
/* Set src_vgbuf structure. */
vglite_set_src_buf(mask_buf, mask_width, mask_height, mask_stride, LV_COLOR_FORMAT_A8);

/* Set vgmatrix. */
vglite_set_translation_matrix(&blend_area);

lv_draw_buf_invalidate_cache((void *)mask_buf, mask_stride, LV_COLOR_FORMAT_A8, &mask_area);

_vglite_draw_letter(&mask_area, glyph_draw_dsc->color, glyph_draw_dsc->opa);
}
}
break;
case LV_FONT_GLYPH_FORMAT_IMAGE: {
#if LV_USE_IMGFONT
lv_draw_img_dsc_t img_dsc;
lv_draw_img_dsc_init(&img_dsc);
img_dsc.angle = 0;
img_dsc.zoom = LV_ZOOM_NONE;
img_dsc.opa = glyph_draw_dsc->opa;
img_dsc.src = glyph_draw_dsc->glyph_data;
lv_draw_vglite_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
lv_draw_img_dsc_t img_dsc;
lv_draw_img_dsc_init(&img_dsc);
img_dsc.angle = 0;
img_dsc.zoom = LV_ZOOM_NONE;
img_dsc.opa = glyph_draw_dsc->opa;
img_dsc.src = glyph_draw_dsc->glyph_data;
lv_draw_vglite_img(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
#endif
}
break;
default:
break;
}
}

Expand Down
111 changes: 59 additions & 52 deletions src/draw/renesas/dave2d/lv_draw_dave2d_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,73 +63,80 @@ static void lv_draw_dave2d_draw_letter_cb(lv_draw_unit_t * u, lv_draw_glyph_dsc_
(d2_border)clip_area.y2);

if(glyph_draw_dsc) {
if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_INVALID) {
switch(glyph_draw_dsc->format) {
case LV_FONT_GLYPH_FORMAT_NONE: {
#if LV_USE_FONT_PLACEHOLDER
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
//lv_draw_sw_border(u, &border_draw_dsc, glyph_draw_dsc->bg_coords);
lv_draw_dave2d_border(unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
/* Draw a placeholder rectangle*/
lv_draw_border_dsc_t border_draw_dsc;
lv_draw_border_dsc_init(&border_draw_dsc);
border_draw_dsc.opa = glyph_draw_dsc->opa;
border_draw_dsc.color = glyph_draw_dsc->color;
border_draw_dsc.width = 1;
//lv_draw_sw_border(u, &border_draw_dsc, glyph_draw_dsc->bg_coords);
lv_draw_dave2d_border(unit, &border_draw_dsc, glyph_draw_dsc->bg_coords);
#endif
}
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_A8) {
lv_area_t mask_area = letter_coords;
mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1;
// lv_draw_sw_blend_dsc_t blend_dsc;
// lv_memzero(&blend_dsc, sizeof(blend_dsc));
// blend_dsc.color = glyph_draw_dsc->color;
// blend_dsc.opa = glyph_draw_dsc->opa;
// blend_dsc.mask_buf = glyph_draw_dsc->glyph_data;
// blend_dsc.mask_area = &mask_area;
// blend_dsc.blend_area = glyph_draw_dsc->letter_coords;
// blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED;
//lv_draw_sw_blend(u, &blend_dsc);

lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;
}
break;
case LV_FONT_GLYPH_FORMAT_A1 ... LV_FONT_GLYPH_FORMAT_A8: {
lv_area_t mask_area = letter_coords;
mask_area.x2 = mask_area.x1 + lv_draw_buf_width_to_stride(lv_area_get_width(&mask_area), LV_COLOR_FORMAT_A8) - 1;
// lv_draw_sw_blend_dsc_t blend_dsc;
// lv_memzero(&blend_dsc, sizeof(blend_dsc));
// blend_dsc.color = glyph_draw_dsc->color;
// blend_dsc.opa = glyph_draw_dsc->opa;
// blend_dsc.mask_buf = glyph_draw_dsc->glyph_data;
// blend_dsc.mask_area = &mask_area;
// blend_dsc.blend_area = glyph_draw_dsc->letter_coords;
// blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED;
//lv_draw_sw_blend(u, &blend_dsc);

lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data;

#if defined(RENESAS_CORTEX_M85)
#if (BSP_CFG_DCACHE_ENABLED)
d1_cacheblockflush(unit->d2_handle, 0, draw_buf->data, draw_buf->data_size);
d1_cacheblockflush(unit->d2_handle, 0, draw_buf->data, draw_buf->data_size);
#endif
#endif
d2_settexture(unit->d2_handle, (void *)draw_buf->data,
(d2_s32)lv_draw_buf_width_to_stride((uint32_t)lv_area_get_width(&letter_coords), LV_COLOR_FORMAT_A8),
lv_area_get_width(&letter_coords), lv_area_get_height(&letter_coords), d2_mode_alpha8);
d2_settexopparam(unit->d2_handle, d2_cc_red, glyph_draw_dsc->color.red, 0);
d2_settexopparam(unit->d2_handle, d2_cc_green, glyph_draw_dsc->color.green, 0);
d2_settexopparam(unit->d2_handle, d2_cc_blue, glyph_draw_dsc->color.blue, 0);
d2_settexopparam(unit->d2_handle, d2_cc_alpha, glyph_draw_dsc->opa, 0);
d2_settexture(unit->d2_handle, (void *)draw_buf->data,
(d2_s32)lv_draw_buf_width_to_stride((uint32_t)lv_area_get_width(&letter_coords), LV_COLOR_FORMAT_A8),
lv_area_get_width(&letter_coords), lv_area_get_height(&letter_coords), d2_mode_alpha8);
d2_settexopparam(unit->d2_handle, d2_cc_red, glyph_draw_dsc->color.red, 0);
d2_settexopparam(unit->d2_handle, d2_cc_green, glyph_draw_dsc->color.green, 0);
d2_settexopparam(unit->d2_handle, d2_cc_blue, glyph_draw_dsc->color.blue, 0);
d2_settexopparam(unit->d2_handle, d2_cc_alpha, glyph_draw_dsc->opa, 0);

d2_settextureoperation(unit->d2_handle, d2_to_multiply, d2_to_multiply, d2_to_multiply, d2_to_multiply);
d2_settextureoperation(unit->d2_handle, d2_to_multiply, d2_to_multiply, d2_to_multiply, d2_to_multiply);

d2_settexturemapping(unit->d2_handle, D2_FIX4(letter_coords.x1), D2_FIX4(letter_coords.y1), D2_FIX16(0), D2_FIX16(0),
D2_FIX16(1), D2_FIX16(0), D2_FIX16(0), D2_FIX16(1));
d2_settexturemapping(unit->d2_handle, D2_FIX4(letter_coords.x1), D2_FIX4(letter_coords.y1), D2_FIX16(0), D2_FIX16(0),
D2_FIX16(1), D2_FIX16(0), D2_FIX16(0), D2_FIX16(1));

d2_settexturemode(unit->d2_handle, d2_tm_filter);
d2_settexturemode(unit->d2_handle, d2_tm_filter);

d2_setfillmode(unit->d2_handle, d2_fm_texture);
d2_setfillmode(unit->d2_handle, d2_fm_texture);

d2_renderbox(unit->d2_handle, (d2_point)D2_FIX4(letter_coords.x1),
(d2_point)D2_FIX4(letter_coords.y1),
(d2_point)D2_FIX4(lv_area_get_width(&letter_coords)),
(d2_point)D2_FIX4(lv_area_get_height(&letter_coords)));
d2_renderbox(unit->d2_handle, (d2_point)D2_FIX4(letter_coords.x1),
(d2_point)D2_FIX4(letter_coords.y1),
(d2_point)D2_FIX4(lv_area_get_width(&letter_coords)),
(d2_point)D2_FIX4(lv_area_get_height(&letter_coords)));

d2_setfillmode(unit->d2_handle, current_fillmode);
}
else if(glyph_draw_dsc->format == LV_DRAW_LETTER_BITMAP_FORMAT_IMAGE) {
d2_setfillmode(unit->d2_handle, current_fillmode);
}
break;
case LV_FONT_GLYPH_FORMAT_IMAGE: {
#if LV_USE_IMGFONT
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.rotation = 0;
img_dsc.scale_x = LV_SCALE_NONE;
img_dsc.scale_y = LV_SCALE_NONE;
img_dsc.opa = glyph_draw_dsc->opa;
img_dsc.src = glyph_draw_dsc->glyph_data;
//lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
lv_draw_image_dsc_t img_dsc;
lv_draw_image_dsc_init(&img_dsc);
img_dsc.rotation = 0;
img_dsc.scale_x = LV_SCALE_NONE;
img_dsc.scale_y = LV_SCALE_NONE;
img_dsc.opa = glyph_draw_dsc->opa;
img_dsc.src = glyph_draw_dsc->glyph_data;
//lv_draw_sw_image(draw_unit, &img_dsc, glyph_draw_dsc->letter_coords);
#endif
}
break;
default:
break;
}
}

Expand Down
Loading
Loading