From 102b63357f6967bdaeb7d168ecc68050554f3db6 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 7 May 2025 11:47:10 +0200 Subject: [PATCH] feat(draw_sw): draw A8 static fonts directly in SW render --- src/draw/lv_draw_label_private.h | 4 +-- src/draw/sw/lv_draw_sw_letter.c | 44 ++++++++++++++++++++++---------- src/font/lv_font.c | 27 +++++++++++++++++++- src/font/lv_font.h | 28 +++++++++++++++++--- src/font/lv_font_fmt_txt.c | 4 ++- 5 files changed, 86 insertions(+), 21 deletions(-) diff --git a/src/draw/lv_draw_label_private.h b/src/draw/lv_draw_label_private.h index f4ee4ea03b..0ec17817a6 100644 --- a/src/draw/lv_draw_label_private.h +++ b/src/draw/lv_draw_label_private.h @@ -42,8 +42,8 @@ struct _lv_draw_label_hint_t { }; struct _lv_draw_glyph_dsc_t { - const void * - glyph_data; /**< Depends on `format` field, it could be image source or draw buf of bitmap or vector data. */ + /** Depends on `format` field, it could be image source or draw buf of bitmap or vector data. */ + const void * glyph_data; lv_font_glyph_format_t format; const lv_area_t * letter_coords; const lv_area_t * bg_coords; diff --git a/src/draw/sw/lv_draw_sw_letter.c b/src/draw/sw/lv_draw_sw_letter.c index 6c831e6c31..5bb69c98bf 100644 --- a/src/draw/sw/lv_draw_sw_letter.c +++ b/src/draw/sw/lv_draw_sw_letter.c @@ -151,20 +151,38 @@ static void LV_ATTRIBUTE_FAST_MEM draw_letter_cb(lv_draw_task_t * t, lv_draw_gly case LV_FONT_GLYPH_FORMAT_A8: case LV_FONT_GLYPH_FORMAT_IMAGE: { if(glyph_draw_dsc->rotation % 3600 == 0 && glyph_draw_dsc->format != LV_FONT_GLYPH_FORMAT_IMAGE) { - glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf); lv_area_t mask_area = *glyph_draw_dsc->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; - const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data; - blend_dsc.mask_buf = draw_buf->data; - blend_dsc.mask_area = &mask_area; - blend_dsc.mask_stride = draw_buf->header.stride; - blend_dsc.blend_area = glyph_draw_dsc->letter_coords; - blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; - lv_draw_sw_blend(t, &blend_dsc); + + if(lv_font_has_static_bitmap(glyph_draw_dsc->g->resolved_font) && + glyph_draw_dsc->g->format == LV_FONT_GLYPH_FORMAT_A8) { + glyph_draw_dsc->g->req_raw_bitmap = 1; + const void * bitmap = lv_font_get_glyph_static_bitmap(glyph_draw_dsc->g); + 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 = bitmap; + blend_dsc.mask_area = &mask_area; + blend_dsc.mask_stride = glyph_draw_dsc->g->stride; + blend_dsc.blend_area = glyph_draw_dsc->letter_coords; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + lv_draw_sw_blend(t, &blend_dsc); + } + else { + glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf); + 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; + const lv_draw_buf_t * draw_buf = glyph_draw_dsc->glyph_data; + blend_dsc.mask_buf = draw_buf->data; + blend_dsc.mask_area = &mask_area; + blend_dsc.mask_stride = draw_buf->header.stride; + blend_dsc.blend_area = glyph_draw_dsc->letter_coords; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + lv_draw_sw_blend(t, &blend_dsc); + } } else { glyph_draw_dsc->glyph_data = lv_font_get_glyph_bitmap(glyph_draw_dsc->g, glyph_draw_dsc->_draw_buf); diff --git a/src/font/lv_font.c b/src/font/lv_font.c index 1066956b2f..996ee4af54 100644 --- a/src/font/lv_font.c +++ b/src/font/lv_font.c @@ -50,7 +50,31 @@ const void * lv_font_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t { const lv_font_t * font_p = g_dsc->resolved_font; LV_ASSERT_NULL(font_p); - return font_p->get_glyph_bitmap(g_dsc, draw_buf); + + const uint8_t save_req = g_dsc->req_raw_bitmap; + g_dsc->req_raw_bitmap = 0; + const void * bitmap = font_p->get_glyph_bitmap(g_dsc, draw_buf); + g_dsc->req_raw_bitmap = save_req; + + return bitmap; +} + +const void * lv_font_get_glyph_static_bitmap(lv_font_glyph_dsc_t * g_dsc) +{ + const lv_font_t * font_p = g_dsc->resolved_font; + LV_ASSERT_NULL(font_p); + + if(font_p->static_bitmap == 0) { + LV_LOG_WARN("Requesting static bitmap of a non-static bitmap of %p font", (void *)font_p); + return NULL; + } + + const uint8_t save_req = g_dsc->req_raw_bitmap; + g_dsc->req_raw_bitmap = 1; + const void * bitmap = font_p->get_glyph_bitmap(g_dsc, NULL); + g_dsc->req_raw_bitmap = save_req; + + return bitmap; } void lv_font_glyph_release_draw_data(lv_font_glyph_dsc_t * g_dsc) @@ -122,6 +146,7 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o dsc_out->format = LV_FONT_GLYPH_FORMAT_A1; dsc_out->is_placeholder = true; + return false; } diff --git a/src/font/lv_font.h b/src/font/lv_font.h index ff11a27e5e..1808918320 100644 --- a/src/font/lv_font.h +++ b/src/font/lv_font.h @@ -63,6 +63,11 @@ typedef struct { uint16_t stride;/**< Bytes in each line. If 0 than there is no padding at the end of the line. */ lv_font_glyph_format_t format; /**< Font format of the glyph see lv_font_glyph_format_t */ uint8_t is_placeholder: 1; /**< Glyph is missing. But placeholder will still be displayed*/ + + /** 0: Get bitmap should return an A8 or ARGB8888 image. + * 1: return the bitmap as it is (Maybe A1/2/4 or any proprietary formats). */ + uint8_t req_raw_bitmap: 1; + int32_t outline_stroke_width; /**< used with freetype vector fonts - width of the letter outline */ union { @@ -134,13 +139,28 @@ struct _lv_font_info_t { /** * Return with the bitmap of a font. - * @note You must call lv_font_get_glyph_dsc() to get `g_dsc` (lv_font_glyph_dsc_t) before you can call this function. - * @param g_dsc the glyph descriptor including which font to use, which supply the glyph_index and the format. - * @param draw_buf a draw buffer that can be used to store the bitmap of the glyph, it's OK not to use it. - * @return pointer to the glyph's data. It can be a draw buffer for bitmap fonts or an image source for imgfonts. + * It always converts the normal fonts to A8 format in a draw_buf with + * LV_DRAW_BUF_ALIGN and LV_DRAW_BUF_STRIDE_ALIGN + * @note You must call lv_font_get_glyph_dsc() to get `g_dsc` (lv_font_glyph_dsc_t) + * before you can call this function. + * @param g_dsc the glyph descriptor including which font to use, which supply the glyph_index + * and the format. + * @param draw_buf a draw buffer that can be used to store the bitmap of the glyph. + * @return pointer to the glyph's data. + * It can be a draw buffer for bitmap fonts or an image source for imgfonts. */ const void * lv_font_get_glyph_bitmap(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf); + +/** + * Return the bitmap as it is. It works only if the font stores the bitmap in + * a non-volitile memory. + * @param g_dsc the glyph descriptor including which font to use, which supply the glyph_index + * and the format. + * @return the bitmap as it is + */ +const void * lv_font_get_glyph_static_bitmap(lv_font_glyph_dsc_t * g_dsc); + /** * Get the descriptor of a glyph * @param font pointer to font diff --git a/src/font/lv_font_fmt_txt.c b/src/font/lv_font_fmt_txt.c index 16e2da6e18..afed8cc27b 100644 --- a/src/font/lv_font_fmt_txt.c +++ b/src/font/lv_font_fmt_txt.c @@ -90,7 +90,6 @@ const lv_font_class_t lv_builtin_font_class = { const void * lv_font_get_bitmap_fmt_txt(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf) { const lv_font_t * font = g_dsc->resolved_font; - uint8_t * bitmap_out = draw_buf->data; lv_font_fmt_txt_dsc_t * fdsc = (lv_font_fmt_txt_dsc_t *)font->dsc; uint32_t gid = g_dsc->gid.index; @@ -98,6 +97,9 @@ const void * lv_font_get_bitmap_fmt_txt(lv_font_glyph_dsc_t * g_dsc, lv_draw_buf const lv_font_fmt_txt_glyph_dsc_t * gdsc = &fdsc->glyph_dsc[gid]; + if(g_dsc->req_raw_bitmap) return &fdsc->glyph_bitmap[gdsc->bitmap_index]; + + uint8_t * bitmap_out = draw_buf->data; int32_t gsize = (int32_t) gdsc->box_w * gdsc->box_h; if(gsize == 0) return NULL;