expo: Separate dimensions from the bounding box
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>
diff --git a/boot/scene.c b/boot/scene.c
index 49dac90..325dd23 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -206,12 +206,17 @@
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 @@
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 @@
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 @@
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 @@
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;
}
diff --git a/boot/scene_menu.c b/boot/scene_menu.c
index c47c203..dbc6793 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -186,8 +186,8 @@
}
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 @@
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;
}
diff --git a/boot/scene_textline.c b/boot/scene_textline.c
index a513d55..f1d6ff7 100644
--- a/boot/scene_textline.c
+++ b/boot/scene_textline.c
@@ -61,7 +61,8 @@
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 @@
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;
diff --git a/include/expo.h b/include/expo.h
index b6de031..6f0547a 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -9,6 +9,7 @@
#include <abuf.h>
#include <dm/ofnode_decl.h>
+#include <linux/bitops.h>
#include <linux/list.h>
struct udevice;
@@ -196,28 +197,46 @@
*
* @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;
+};
+
+/**
* enum scene_obj_flags_t - flags for objects
*
* @SCENEOF_HIDE: object should be hidden
* @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 @@
* @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 @@
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;
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 9c94082..94c13e9 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -550,39 +550,39 @@
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);