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

Reply via email to