Use the measurement info to write each line of text separately, thus respecting word-wrapping and newlines.
Fix up the comment for scene_obj_render() while we are here. Signed-off-by: Simon Glass <s...@chromium.org> --- boot/bootflow_menu.c | 2 ++ boot/scene.c | 22 ++++++++++++++++++---- include/expo.h | 4 ++++ test/boot/expo.c | 12 +++++++++++- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index 19cd84e6454..cadffcf259a 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -234,6 +234,8 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode, if (text_mode) expo_set_text_mode(exp, text_mode); + LOGR("bmd", expo_calc_dims(exp)); + *expp = exp; return 0; diff --git a/boot/scene.c b/boot/scene.c index 8ecfa4f33bb..96e8304d8d2 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY LOGC_EXPO +#include <alist.h> #include <dm.h> #include <expo.h> #include <malloc.h> @@ -164,6 +165,7 @@ int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen, } gen->str_id = str_id; + alist_init_struct(&gen->lines, struct vidconsole_mline); return 0; } @@ -335,8 +337,8 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) struct scene_txt_generic *gen = &((struct scene_obj_txt *)obj)->gen; struct expo *exp = scn->expo; struct vidconsole_bbox bbox; + int len, ret, limit; const char *str; - int len, ret; str = expo_get_str(exp, gen->str_id); if (!str) @@ -350,8 +352,12 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) return 16; } + limit = obj->flags & SCENEOF_SIZE_VALID ? + obj->bbox.x1 - obj->bbox.x0 : -1; + ret = vidconsole_measure(scn->expo->cons, gen->font_name, - gen->font_size, str, -1, &bbox, NULL); + gen->font_size, str, limit, &bbox, + &gen->lines); if (ret) return log_msg_ret("mea", ret); if (widthp) @@ -417,6 +423,7 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev, struct scene_txt_generic *gen, int x, int y, int menu_inset) { + const struct vidconsole_mline *mline; struct video_priv *vid_priv; struct vidconsole_colour old; enum colour_idx fore, back; @@ -452,8 +459,12 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev, video_fill_part(dev, x - menu_inset, y, obj->bbox.x1, obj->bbox.y1, vid_priv->colour_bg); } - vidconsole_set_cursor_pos(cons, x, y); - vidconsole_put_string(cons, str); + + alist_for_each(mline, &gen->lines) { + vidconsole_set_cursor_pos(cons, x + mline->bbox.x0, + y + mline->bbox.y0); + vidconsole_put_stringn(cons, str + mline->start, mline->len); + } if (obj->flags & SCENEOF_POINT) vidconsole_pop_colour(cons, &old); @@ -463,6 +474,9 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev, /** * scene_obj_render() - Render an object * + * @obj: Object to render + * @text_mode: true to use text mode + * Return: 0 if OK, -ve on error */ static int scene_obj_render(struct scene_obj *obj, bool text_mode) { diff --git a/include/expo.h b/include/expo.h index 7c6ab4bf630..a79aa1da74f 100644 --- a/include/expo.h +++ b/include/expo.h @@ -8,6 +8,7 @@ #define __EXPO_H #include <abuf.h> +#include <alist.h> #include <dm/ofnode_decl.h> #include <linux/bitops.h> #include <linux/list.h> @@ -296,11 +297,14 @@ struct scene_obj_img { * @str_id: ID of the text string to display * @font_name: Name of font (allocated by caller) * @font_size: Nominal size of font in pixels + * @lines: alist of struct vidconsole_mline with a separate record for each + * line of text */ struct scene_txt_generic { uint str_id; const char *font_name; uint font_size; + struct alist lines; }; /** diff --git a/test/boot/expo.c b/test/boot/expo.c index ba60267f00c..9e0e3f207e0 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -25,6 +25,7 @@ enum { OBJ_LOGO, OBJ_TEXT, OBJ_TEXT2, + OBJ_TEXT3, OBJ_MENU, OBJ_MENU_TITLE, @@ -33,6 +34,7 @@ enum { STR_TEXT, STR_TEXT2, + STR_TEXT3, STR_MENU_TITLE, STR_POINTER_TEXT, @@ -488,6 +490,14 @@ static int expo_render_image(struct unit_test_state *uts) 60)); ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT2, 200, 600)); + id = scene_txt_str(scn, "text", OBJ_TEXT3, STR_TEXT3, + "this is yet\nanother string, with word-wrap", + NULL); + ut_assert(id > 0); + ut_assertok(scene_txt_set_font(scn, OBJ_TEXT3, "nimbus_sans_l_regular", + 60)); + ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXT3, 500, 200, 1000, 700)); + id = scene_menu(scn, "main", OBJ_MENU, &menu); ut_assert(id > 0); @@ -646,7 +656,7 @@ static int expo_render_image(struct unit_test_state *uts) ut_assertok(scene_arrange(scn)); ut_assertok(expo_render(exp)); - ut_asserteq(10345, video_compress_fb(uts, dev, false)); + ut_asserteq(14951, video_compress_fb(uts, dev, false)); ut_assertok(video_check_copy_fb(uts, dev)); /* make sure only the preview for the second item is shown */ -- 2.43.0