
From: Simon Glass <sjg@chromium.org> At present boxes are not supported in the expo_build format. Also, it is now possible to draw filled boxes, a recently added feature to the video API. Expand the box feature slightly to resolve these two items. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/dts/cedit.dtsi | 13 +++++++++++++ boot/bootflow_menu.c | 2 +- boot/expo_build.c | 30 ++++++++++++++++++++++++++++++ boot/scene.c | 18 ++++++++++++++++-- doc/develop/expo.rst | 16 ++++++++++++++++ include/expo.h | 15 ++++++++++++++- include/test/cedit-test.h | 5 ++++- test/boot/expo.c | 37 +++++++++++++++++++++++++++++++++++-- 8 files changed, 129 insertions(+), 7 deletions(-) diff --git a/arch/sandbox/dts/cedit.dtsi b/arch/sandbox/dts/cedit.dtsi index facd7a49bef..b4408eeefd8 100644 --- a/arch/sandbox/dts/cedit.dtsi +++ b/arch/sandbox/dts/cedit.dtsi @@ -62,6 +62,19 @@ title = "Machine name"; edit-id = <ID_MACHINE_NAME_EDIT>; }; + + test-box { + type = "box"; + id = <ID_TEST_BOX>; + width = <5>; + }; + + test-box-filled { + type = "box"; + id = <ID_TEST_BOX_FILLED>; + width = <3>; + fill; + }; }; }; diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index 5e0e365d12b..dc075a8f4b2 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -55,7 +55,7 @@ int bootflow_menu_new(struct expo **expp) if (ret < 0) return log_msg_ret("scn", ret); - ret = scene_box(scn, "box", OBJ_BOX, 2, NULL); + ret = scene_box(scn, "box", OBJ_BOX, 2, false, NULL); if (ret < 0) return log_msg_ret("bmb", ret); ret |= scene_obj_set_bbox(scn, OBJ_BOX, 30, 90, 1366 - 30, 720); diff --git a/boot/expo_build.c b/boot/expo_build.c index 9a99a21e5e0..f8ae5bcbbf7 100644 --- a/boot/expo_build.c +++ b/boot/expo_build.c @@ -282,6 +282,34 @@ static int menu_build(struct build_info *info, ofnode node, struct scene *scn, return 0; } +static int box_build(struct build_info *info, ofnode node, + struct scene *scn, uint id, struct scene_obj **objp) +{ + struct scene_obj_box *box; + const char *name; + u32 width; + bool fill; + int ret; + + name = ofnode_get_name(node); + + info->err_prop = "width"; + ret = ofnode_read_u32(node, "width", &width); + if (ret) + return log_msg_ret("wid", -ENOENT); + + /* fill property is optional, defaults to false */ + fill = ofnode_read_bool(node, "fill"); + + ret = scene_box(scn, name, id, width, fill, &box); + if (ret < 0) + return log_msg_ret("box", ret); + + *objp = &box->obj; + + return 0; +} + static int textline_build(struct build_info *info, ofnode node, struct scene *scn, uint id, struct scene_obj **objp) { @@ -354,6 +382,8 @@ static int obj_build(struct build_info *info, ofnode node, struct scene *scn) ret = menu_build(info, node, scn, id, &obj); else if (!strcmp("textline", type)) ret = textline_build(info, node, scn, id, &obj); + else if (!strcmp("box", type)) + ret = box_build(info, node, scn, id, &obj); else ret = -EOPNOTSUPP; if (ret) diff --git a/boot/scene.c b/boot/scene.c index 493f2bbab97..0a62dc6212b 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -212,7 +212,7 @@ int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id, } int scene_box(struct scene *scn, const char *name, uint id, uint width, - struct scene_obj_box **boxp) + bool fill, struct scene_obj_box **boxp) { struct scene_obj_box *box; int ret; @@ -224,6 +224,7 @@ int scene_box(struct scene *scn, const char *name, uint id, uint width, return log_msg_ret("obj", ret); box->width = width; + box->fill = fill; if (boxp) *boxp = box; @@ -231,6 +232,19 @@ int scene_box(struct scene *scn, const char *name, uint id, uint width, return box->obj.id; } +int scene_box_set_fill(struct scene *scn, uint id, bool fill) +{ + struct scene_obj_box *box; + + box = scene_obj_find(scn, id, SCENEOBJT_BOX); + if (!box) + return log_msg_ret("find", -ENOENT); + + box->fill = fill; + + return 0; +} + int scene_txt_set_font(struct scene *scn, uint id, const char *font_name, uint font_size) { @@ -681,7 +695,7 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) struct scene_obj_box *box = (struct scene_obj_box *)obj; video_draw_box(dev, obj->bbox.x0, obj->bbox.y0, obj->bbox.x1, - obj->bbox.y1, box->width, vid_priv->colour_fg, false); + obj->bbox.y1, box->width, vid_priv->colour_fg, box->fill); break; } case SCENEOBJT_TEXTEDIT: { diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 5bdaffb14bb..5c2e3157c8f 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -366,6 +366,9 @@ type "textline" A line of text which can be edited + "box" + A rectangle with a given line width (not filled) + id type: u32, required @@ -443,6 +446,19 @@ max-chars: Specifies the maximum number of characters permitted to be in the textline. The user will be prevented from adding more. +Box nodes have the following additional properties: + +width + type: u32, required + + Specifies the line width of the box in pixels. + +fill + type: bool, optional + + Specifies whether to fill the box (true) or draw outline only (false). + Defaults to false if not specified. + Expo layout ~~~~~~~~~~~ diff --git a/include/expo.h b/include/expo.h index 522f6a93f98..c025e5494a1 100644 --- a/include/expo.h +++ b/include/expo.h @@ -495,10 +495,12 @@ struct scene_obj_textline { * * @obj: Basic object information * @width: Line-width in pixels + * @fill: true to fill the box, false to draw outline only */ struct scene_obj_box { struct scene_obj obj; uint width; + bool fill; }; /** @@ -809,11 +811,22 @@ int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars, * @name: Name to use (this is allocated by this call) * @id: ID to use for the new object (0 to allocate one) * @width: Line-width in pixels + * @fill: true to fill the box, false to draw outline only * @boxp: If non-NULL, returns the new object * Returns: ID number for the object (typically @id), or -ve on error */ int scene_box(struct scene *scn, const char *name, uint id, uint width, - struct scene_obj_box **boxp); + bool fill, struct scene_obj_box **boxp); + +/** + * scene_box_set_fill() - Set the fill property of a box object + * + * @scn: Scene containing the box + * @id: ID of the box object to update + * @fill: true to fill the box, false to draw outline only + * Returns: 0 if OK, -ENOENT if the object is not found or is not a box + */ +int scene_box_set_fill(struct scene *scn, uint id, bool fill); /** * scene_texted() - create a text editor diff --git a/include/test/cedit-test.h b/include/test/cedit-test.h index 0d38a953415..ec4f3cc0322 100644 --- a/include/test/cedit-test.h +++ b/include/test/cedit-test.h @@ -27,6 +27,9 @@ #define ID_MACHINE_NAME 17 #define ID_MACHINE_NAME_EDIT 18 -#define ID_DYNAMIC_START 19 +#define ID_TEST_BOX 19 +#define ID_TEST_BOX_FILLED 20 + +#define ID_DYNAMIC_START 21 #endif diff --git a/test/boot/expo.c b/test/boot/expo.c index 9c3eb984f97..634bab8f203 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -570,11 +570,11 @@ static int expo_render_image(struct unit_test_state *uts) ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400)); - id = scene_box(scn, "box", OBJ_BOX, 3, NULL); + id = scene_box(scn, "box", OBJ_BOX, 3, false, NULL); ut_assert(id > 0); ut_assertok(scene_obj_set_bbox(scn, OBJ_BOX, 40, 390, 1000, 510)); - id = scene_box(scn, "box2", OBJ_BOX2, 1, NULL); + id = scene_box(scn, "box2", OBJ_BOX2, 1, false, NULL); ut_assert(id > 0); ut_assertok(scene_obj_set_bbox(scn, OBJ_BOX, 500, 200, 1000, 350)); @@ -880,6 +880,39 @@ static int expo_test_build(struct unit_test_state *uts) count = list_count_nodes(&menu->item_head); ut_asserteq(3, count); + /* check the box */ + struct scene_obj_box *box = scene_obj_find(scn, ID_TEST_BOX, SCENEOBJT_NONE); + ut_assertnonnull(box); + obj = &box->obj; + ut_asserteq_ptr(scn, obj->scene); + ut_asserteq_str("test-box", obj->name); + ut_asserteq(ID_TEST_BOX, obj->id); + ut_asserteq(SCENEOBJT_BOX, obj->type); + ut_asserteq(0, obj->flags); + ut_asserteq(5, box->width); + ut_asserteq(false, box->fill); + + /* check the filled box */ + struct scene_obj_box *filled_box = scene_obj_find(scn, ID_TEST_BOX_FILLED, SCENEOBJT_NONE); + ut_assertnonnull(filled_box); + obj = &filled_box->obj; + ut_asserteq_ptr(scn, obj->scene); + ut_asserteq_str("test-box-filled", obj->name); + ut_asserteq(ID_TEST_BOX_FILLED, obj->id); + ut_asserteq(SCENEOBJT_BOX, obj->type); + ut_asserteq(0, obj->flags); + ut_asserteq(3, filled_box->width); + ut_asserteq(true, filled_box->fill); + + /* test scene_box_set_fill() function */ + ut_assertok(scene_box_set_fill(scn, ID_TEST_BOX, true)); + ut_asserteq(true, box->fill); + ut_assertok(scene_box_set_fill(scn, ID_TEST_BOX_FILLED, false)); + ut_asserteq(false, filled_box->fill); + + /* test error case */ + ut_asserteq(-ENOENT, scene_box_set_fill(scn, 9999, true)); + /* try editing some text */ ut_assertok(expo_edit_str(exp, txt->gen.str_id, &orig, ©)); ut_asserteq_str("2 GHz", orig.data); -- 2.43.0