]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
expo: Separate dimensions from the bounding box
authorSimon Glass <sjg@chromium.org>
Fri, 2 May 2025 14:46:33 +0000 (08:46 -0600)
committerSimon Glass <sjg@chromium.org>
Fri, 30 May 2025 08:49:32 +0000 (09:49 +0100)
At present each object has a width and height and the bounding box is
implicit in that.

This is not flexible enough to handle objects which are larger than
their contents might need. For example, when centring a text object we
might want to have it stretch across the whole width of the display even
if the text itself does not need that much space.

Create a new 'dimensions' field and convert the existing width/height
into x1/y1 coordinates.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/scene.c
boot/scene_menu.c
boot/scene_textline.c
include/expo.h
test/boot/expo.c

index 49dac90ceed3213785c7843f6c29c2e011be46f7..325dd23641f4ef75a2b17e84c08ef77f10a67fc7 100644 (file)
@@ -206,12 +206,17 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
 int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
 {
        struct scene_obj *obj;
+       int w, h;
 
        obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
        if (!obj)
                return log_msg_ret("find", -ENOENT);
+       w = obj->bbox.x1 - obj->bbox.x0;
+       h = obj->bbox.y1 - obj->bbox.y0;
        obj->bbox.x0 = x;
        obj->bbox.y0 = y;
+       obj->bbox.x1 = obj->bbox.x0 + w;
+       obj->bbox.y1 = obj->bbox.y0 + h;
 
        return 0;
 }
@@ -223,8 +228,9 @@ int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
        obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
        if (!obj)
                return log_msg_ret("find", -ENOENT);
-       obj->bbox.w = w;
-       obj->bbox.h = h;
+       obj->bbox.x1 = obj->bbox.x0 + w;
+       obj->bbox.y1 = obj->bbox.y0 + h;
+       obj->flags |= SCENEOF_SIZE_VALID;
 
        return 0;
 }
@@ -419,8 +425,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
                        if (obj->flags & SCENEOF_POINT) {
                                vidconsole_push_colour(cons, fore, back, &old);
                                video_fill_part(dev, x - theme->menu_inset, y,
-                                               x + obj->bbox.w,
-                                               y + obj->bbox.h,
+                                               obj->bbox.x1,
+                                               obj->bbox.y1,
                                                vid_priv->colour_bg);
                        }
                        vidconsole_set_cursor_pos(cons, x, y);
@@ -765,8 +771,13 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
                                ret = scene_obj_get_hw(scn, obj->id, &width);
                                if (ret < 0)
                                        return log_msg_ret("get", ret);
-                               obj->bbox.w = width;
-                               obj->bbox.h = ret;
+                               obj->dims.x = width;
+                               obj->dims.y = ret;
+                               if (!(obj->flags & SCENEOF_SIZE_VALID)) {
+                                       obj->bbox.x1 = obj->bbox.x0 + width;
+                                       obj->bbox.y1 = obj->bbox.y0 + ret;
+                                       obj->flags |= SCENEOF_SIZE_VALID;
+                               }
                        }
                        break;
                }
@@ -917,13 +928,13 @@ int scene_bbox_union(struct scene *scn, uint id, int inset,
        if (bbox->valid) {
                bbox->x0 = min(bbox->x0, obj->bbox.x0 - inset);
                bbox->y0 = min(bbox->y0, obj->bbox.y0);
-               bbox->x1 = max(bbox->x1, obj->bbox.x0 + obj->bbox.w + inset);
-               bbox->y1 = max(bbox->y1, obj->bbox.y0 + obj->bbox.h);
+               bbox->x1 = max(bbox->x1, obj->bbox.x1 + inset);
+               bbox->y1 = max(bbox->y1, obj->bbox.y1);
        } else {
                bbox->x0 = obj->bbox.x0 - inset;
                bbox->y0 = obj->bbox.y0;
-               bbox->x1 = obj->bbox.x0 + obj->bbox.w + inset;
-               bbox->y1 = obj->bbox.y0 + obj->bbox.h;
+               bbox->x1 = obj->bbox.x1 + inset;
+               bbox->y1 = obj->bbox.y1;
                bbox->valid = true;
        }
 
index c47c20305275eff4ba54cd1edc3f1f9775d8790e..dbc6793e30251313c88264f126d5c38539e88a6a 100644 (file)
@@ -186,8 +186,8 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu)
        }
 
        if (bbox.valid) {
-               menu->obj.bbox.w = bbox.x1 - bbox.x0;
-               menu->obj.bbox.h = bbox.y1 - bbox.y0;
+               menu->obj.dims.x = bbox.x1 - bbox.x0;
+               menu->obj.dims.y = bbox.y1 - bbox.y0;
        }
 
        return 0;
@@ -295,6 +295,9 @@ int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
 
        if (sel_id)
                menu_point_to_item(menu, sel_id);
+       menu->obj.bbox.x1 = menu->obj.bbox.x0 + menu->obj.dims.x;
+       menu->obj.bbox.y1 = menu->obj.bbox.y0 + menu->obj.dims.y;
+       menu->obj.flags |= SCENEOF_SIZE_VALID;
 
        return 0;
 }
index a513d555deddcce56caf4abcb102257e32b7fe04..f1d6ff7607c565f345804f92a889e36fc7192690 100644 (file)
@@ -61,7 +61,8 @@ void scene_textline_calc_bbox(struct scene_obj_textline *tline,
 
 int scene_textline_calc_dims(struct scene_obj_textline *tline)
 {
-       struct scene *scn = tline->obj.scene;
+       struct scene_obj *obj = &tline->obj;
+       struct scene *scn = obj->scene;
        struct vidconsole_bbox bbox;
        struct scene_obj_txt *txt;
        int ret;
@@ -76,11 +77,16 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline)
                return log_msg_ret("nom", ret);
 
        if (bbox.valid) {
-               tline->obj.bbox.w = bbox.x1 - bbox.x0;
-               tline->obj.bbox.h = bbox.y1 - bbox.y0;
-
-               scene_obj_set_size(scn, tline->edit_id, tline->obj.bbox.w,
-                                  tline->obj.bbox.h);
+               obj->dims.x = bbox.x1 - bbox.x0;
+               obj->dims.y = bbox.y1 - bbox.y0;
+               if (!(obj->flags & SCENEOF_SIZE_VALID)) {
+                       obj->bbox.x1 = obj->bbox.x0 + obj->dims.x;
+                       obj->bbox.y1 = obj->bbox.y0 + obj->dims.y;
+                       obj->flags |= SCENEOF_SIZE_VALID;
+               }
+               scene_obj_set_size(scn, tline->edit_id,
+                                  obj->bbox.x1 - obj->bbox.x0,
+                                  obj->bbox.y1 - obj->bbox.y0);
        }
 
        return 0;
index b6de0310071d3e2c70c5271e7448e4bac9744b2c..6f0547a4b38beaff5cfd4ae6132d4765f710169a 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <abuf.h>
 #include <dm/ofnode_decl.h>
+#include <linux/bitops.h>
 #include <linux/list.h>
 
 struct udevice;
@@ -196,14 +197,29 @@ enum scene_obj_t {
  *
  * @x0: x position, in pixels from left side
  * @y0: y position, in pixels from top
- * @w: width, in pixels
- * @h: height, in pixels
+ * @x1: x position of right size
+ * @y1: y position of bottom
  */
 struct scene_obj_bbox {
        int x0;
        int y0;
-       int w;
-       int h;
+       int x1;
+       int y1;
+};
+
+/**
+ * struct scene_obj_dims - Dimensions of the object being drawn
+ *
+ * Image and text objects have a dimension which can change depending on what
+ * they contain. For images this stores the size. For text it stores the size as
+ * rendered on the display
+ *
+ * @x: x dimension
+ * @y: y dimension
+ */
+struct scene_obj_dims {
+       int x;
+       int y;
 };
 
 /**
@@ -213,11 +229,14 @@ struct scene_obj_bbox {
  * @SCENEOF_POINT: object should be highlighted
  * @SCENEOF_OPEN: object should be opened (e.g. menu is opened so that an option
  * can be selected)
+ * @SCENEOF_SIZE_VALID: object's size (width/height) is valid, so any adjustment
+ * to x0/y0 should maintain the width/height of the object
  */
 enum scene_obj_flags_t {
        SCENEOF_HIDE    = 1 << 0,
        SCENEOF_POINT   = 1 << 1,
        SCENEOF_OPEN    = 1 << 2,
+       SCENEOF_SIZE_VALID      = BIT(3),
 };
 
 enum {
@@ -232,7 +251,8 @@ enum {
  * @name: Name of the object (allocated)
  * @id: ID number of the object
  * @type: Type of this object
- * @bbox: Dimensions for this object
+ * @bbox: Bounding box for this object
+ * @dims: Dimensions of the text/image (may be smaller than bbox)
  * @flags: Flags for this object
  * @bit_length: Number of bits used for this object in CMOS RAM
  * @start_bit: Start bit to use for this object in CMOS RAM
@@ -244,6 +264,7 @@ struct scene_obj {
        uint id;
        enum scene_obj_t type;
        struct scene_obj_bbox bbox;
+       struct scene_obj_dims dims;
        u8 flags;
        u8 bit_length;
        u16 start_bit;
index 9c940825278f52f429b1f3a6f3ad3c287f1d5513..94c13e9b71f52e112663aa7d2b3717640e4af887 100644 (file)
@@ -550,39 +550,39 @@ static int expo_render_image(struct unit_test_state *uts)
        ut_assertnonnull(obj);
        ut_asserteq(400, obj->bbox.x0);
        ut_asserteq(100, obj->bbox.y0);
-       ut_asserteq(126, obj->bbox.w);
-       ut_asserteq(40, obj->bbox.h);
+       ut_asserteq(400 + 126, obj->bbox.x1);
+       ut_asserteq(100 + 40, obj->bbox.y1);
 
        /* check dimensions of image */
        obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE);
        ut_assertnonnull(obj);
        ut_asserteq(50, obj->bbox.x0);
        ut_asserteq(20, obj->bbox.y0);
-       ut_asserteq(160, obj->bbox.w);
-       ut_asserteq(160, obj->bbox.h);
+       ut_asserteq(50 + 160, obj->bbox.x1);
+       ut_asserteq(20 + 160, obj->bbox.y1);
 
        /* check dimensions of menu labels - both should be the same width */
        obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE);
        ut_assertnonnull(obj);
        ut_asserteq(50, obj->bbox.x0);
        ut_asserteq(436, obj->bbox.y0);
-       ut_asserteq(29, obj->bbox.w);
-       ut_asserteq(18, obj->bbox.h);
+       ut_asserteq(50 + 29, obj->bbox.x1);
+       ut_asserteq(436 + 18, obj->bbox.y1);
 
        obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE);
        ut_assertnonnull(obj);
        ut_asserteq(50, obj->bbox.x0);
        ut_asserteq(454, obj->bbox.y0);
-       ut_asserteq(29, obj->bbox.w);
-       ut_asserteq(18, obj->bbox.h);
+       ut_asserteq(50 + 29, obj->bbox.x1);
+       ut_asserteq(454 + 18, obj->bbox.y1);
 
        /* check dimensions of menu */
        obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE);
        ut_assertnonnull(obj);
        ut_asserteq(50, obj->bbox.x0);
        ut_asserteq(400, obj->bbox.y0);
-       ut_asserteq(160, obj->bbox.w);
-       ut_asserteq(160, obj->bbox.h);
+       ut_asserteq(50 + 160, obj->bbox.x1);
+       ut_asserteq(400 + 160, obj->bbox.y1);
 
        /* render it */
        expo_set_scene_id(exp, SCENE1);