In some cases it is useful to obtain more than just two bounding boxes from a menu, e.g. to line up all descriptions vertically.
Use an array to obtain bounding-box information and calculate it separately for each item. Signed-off-by: Simon Glass <s...@chromium.org> --- boot/scene.c | 61 +++++++++++++++++++++++++++---------------- boot/scene_internal.h | 46 ++++++++++++++++++++++++++------ boot/scene_menu.c | 58 ++++++++++++++++++++++++++-------------- 3 files changed, 115 insertions(+), 50 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index ff6712a0db6..6142d2b736d 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -326,9 +326,9 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) */ static void scene_render_background(struct scene_obj *obj, bool box_only) { + struct vidconsole_bbox bbox[SCENEBB_count], *sel; struct expo *exp = obj->scene->expo; const struct expo_theme *theme = &exp->theme; - struct vidconsole_bbox bbox, label_bbox; struct udevice *dev = exp->display; struct video_priv *vid_priv; struct udevice *cons = exp->cons; @@ -347,17 +347,20 @@ static void scene_render_background(struct scene_obj *obj, bool box_only) } /* see if this object wants to render a background */ - if (scene_obj_calc_bbox(obj, &bbox, &label_bbox)) + if (scene_obj_calc_bbox(obj, bbox)) + return; + + sel = &bbox[SCENEBB_label]; + if (!sel->valid) return; vidconsole_push_colour(cons, fore, back, &old); - video_fill_part(dev, label_bbox.x0 - inset, label_bbox.y0 - inset, - label_bbox.x1 + inset, label_bbox.y1 + inset, + video_fill_part(dev, sel->x0 - inset, sel->y0 - inset, + sel->x1 + inset, sel->y1 + inset, vid_priv->colour_fg); vidconsole_pop_colour(cons, &old); if (box_only) { - video_fill_part(dev, label_bbox.x0, label_bbox.y0, - label_bbox.x1, label_bbox.y1, + video_fill_part(dev, sel->x0, sel->y0, sel->x1, sel->y1, vid_priv->colour_bg); } } @@ -730,8 +733,7 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event) return 0; } -int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox, - struct vidconsole_bbox *label_bbox) +int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox bbox[]) { switch (obj->type) { case SCENEOBJT_NONE: @@ -741,14 +743,15 @@ int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox, case SCENEOBJT_MENU: { struct scene_obj_menu *menu = (struct scene_obj_menu *)obj; - scene_menu_calc_bbox(menu, bbox, label_bbox); + scene_menu_calc_bbox(menu, bbox); break; } case SCENEOBJT_TEXTLINE: { struct scene_obj_textline *tline; tline = (struct scene_obj_textline *)obj; - scene_textline_calc_bbox(tline, bbox, label_bbox); + scene_textline_calc_bbox(tline, &bbox[SCENEBB_all], + &bbox[SCENEBB_label]); break; } } @@ -916,28 +919,42 @@ int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter, return 0; } +int scene_bbox_join(const struct vidconsole_bbox *src, int inset, + struct vidconsole_bbox *dst) +{ + if (dst->valid) { + dst->x0 = min(dst->x0, src->x0 - inset); + dst->y0 = min(dst->y0, src->y0); + dst->x1 = max(dst->x1, src->x1 + inset); + dst->y1 = max(dst->y1, src->y1); + } else { + dst->x0 = src->x0 - inset; + dst->y0 = src->y0; + dst->x1 = src->x1 + inset; + dst->y1 = src->y1; + dst->valid = true; + } + + return 0; +} + int scene_bbox_union(struct scene *scn, uint id, int inset, struct vidconsole_bbox *bbox) { struct scene_obj *obj; + struct vidconsole_bbox local; if (!id) return 0; obj = scene_obj_find(scn, id, SCENEOBJT_NONE); if (!obj) return log_msg_ret("obj", -ENOENT); - 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.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.x1 + inset; - bbox->y1 = obj->bbox.y1; - bbox->valid = true; - } + local.x0 = obj->bbox.x0; + local.y0 = obj->bbox.y0; + local.x1 = obj->bbox.x1; + local.y1 = obj->bbox.y1; + local.valid = true; + scene_bbox_join(&local, inset, bbox); return 0; } diff --git a/boot/scene_internal.h b/boot/scene_internal.h index ec9008ea593..ac2a36d6e4d 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -13,6 +13,27 @@ struct vidconsole_bbox; typedef int (*expo_scene_obj_iterator)(struct scene_obj *obj, void *priv); +/** + * enum scene_bbox_t - Parts of an object which can have a bounding box + * + * Objects can provide any or all of these bounding boxes + * + * @SCENEBB_label: Menu-item label + * @SCENEBB_key: Menu-item key label + * @SCENEBB_desc: Menu-item Description + * @SCENEBB_curitem: Current item (pointed to) + * @SCENEBB_all: All the above objects combined + */ +enum scene_bbox_t { + SCENEBB_label, + SCENEBB_key, + SCENEBB_desc, + SCENEBB_curitem, + SCENEBB_all, + + SCENEBB_count, +}; + /** * expo_lookup_scene_id() - Look up a scene ID * @@ -291,6 +312,19 @@ struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu, struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu, int val); +/** + * scene_bbox_join() - update bouding box with a given src box + * + * Updates @dst so that it encompasses the bounding box @src + * + * @src: Input bounding box + * @inset: Amount of inset to use for width + * @dst: Bounding box to update + * Return: 0 if OK, -ve on error + */ +int scene_bbox_join(const struct vidconsole_bbox *src, int inset, + struct vidconsole_bbox *dst); + /** * scene_bbox_union() - update bouding box with the demensions of an object * @@ -319,13 +353,11 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline); * scene_menu_calc_bbox() - Calculate bounding boxes for the menu * * @menu: Menu to process - * @bbox: Returns bounding box of menu including prompts - * @label_bbox: Returns bounding box of labels + * @bbox: List of bounding box to fill in * Return: 0 if OK, -ve on error */ void scene_menu_calc_bbox(struct scene_obj_menu *menu, - struct vidconsole_bbox *bbox, - struct vidconsole_bbox *label_bbox); + struct vidconsole_bbox *bbox); /** * scene_textline_calc_bbox() - Calculate bounding box for the textline @@ -343,12 +375,10 @@ void scene_textline_calc_bbox(struct scene_obj_textline *menu, * scene_obj_calc_bbox() - Calculate bounding boxes for an object * * @obj: Object to process - * @bbox: Returns bounding box of object including prompts - * @label_bbox: Returns bounding box of labels (active area) + * @bbox: Returns bounding boxes for object * Return: 0 if OK, -ve on error */ -int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox, - struct vidconsole_bbox *label_bbox); +int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox); /** * scene_textline_open() - Open a textline object diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 490fb42995c..6d945cfa62d 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -132,55 +132,73 @@ static int menu_point_to_item(struct scene_obj_menu *menu, uint item_id) } void scene_menu_calc_bbox(struct scene_obj_menu *menu, - struct vidconsole_bbox *bbox, - struct vidconsole_bbox *label_bbox) + struct vidconsole_bbox *bbox) { const struct expo_theme *theme = &menu->obj.scene->expo->theme; const struct scene_menitem *item; + int i; - bbox->valid = false; - scene_bbox_union(menu->obj.scene, menu->title_id, 0, bbox); + for (i = 0; i < SCENEBB_count; i++) + bbox[i].valid = false; - label_bbox->valid = false; + scene_bbox_union(menu->obj.scene, menu->title_id, 0, + &bbox[SCENEBB_all]); list_for_each_entry(item, &menu->item_head, sibling) { + struct vidconsole_bbox local; + + local.valid = false; scene_bbox_union(menu->obj.scene, item->label_id, - theme->menu_inset, bbox); - scene_bbox_union(menu->obj.scene, item->key_id, 0, bbox); - scene_bbox_union(menu->obj.scene, item->desc_id, 0, bbox); - scene_bbox_union(menu->obj.scene, item->preview_id, 0, bbox); + theme->menu_inset, &local); + scene_bbox_union(menu->obj.scene, item->key_id, 0, &local); + scene_bbox_union(menu->obj.scene, item->desc_id, 0, &local); + scene_bbox_union(menu->obj.scene, item->preview_id, 0, &local); + + scene_bbox_join(&local, 0, &bbox[SCENEBB_all]); - /* Get the bounding box of all labels */ + /* Get the bounding box of all individual fields */ scene_bbox_union(menu->obj.scene, item->label_id, - theme->menu_inset, label_bbox); + theme->menu_inset, &bbox[SCENEBB_label]); + scene_bbox_union(menu->obj.scene, item->key_id, + theme->menu_inset, &bbox[SCENEBB_key]); + scene_bbox_union(menu->obj.scene, item->desc_id, + theme->menu_inset, &bbox[SCENEBB_desc]); + + if (menu->cur_item_id == item->id) + scene_bbox_join(&local, 0, &bbox[SCENEBB_curitem]); } /* * subtract the final menuitem's gap to keep the insert the same top * and bottom */ - label_bbox->y1 -= theme->menuitem_gap_y; + bbox[SCENEBB_label].y1 -= theme->menuitem_gap_y; } int scene_menu_calc_dims(struct scene_obj_menu *menu) { - struct vidconsole_bbox bbox, label_bbox; + struct vidconsole_bbox bbox[SCENEBB_count], *cur; const struct scene_menitem *item; - scene_menu_calc_bbox(menu, &bbox, &label_bbox); + scene_menu_calc_bbox(menu, bbox); /* Make all labels the same size */ - if (label_bbox.valid) { + cur = &bbox[SCENEBB_label]; + if (cur->valid) { list_for_each_entry(item, &menu->item_head, sibling) { scene_obj_set_size(menu->obj.scene, item->label_id, - label_bbox.x1 - label_bbox.x0, - label_bbox.y1 - label_bbox.y0); + cur->x1 - cur->x0, + cur->y1 - cur->y0); } } - if (bbox.valid) { - menu->obj.dims.x = bbox.x1 - bbox.x0; - menu->obj.dims.y = bbox.y1 - bbox.y0; + cur = &bbox[SCENEBB_all]; + if (cur->valid) { + menu->obj.dims.x = cur->x1 - cur->x0; + menu->obj.dims.y = cur->y1 - cur->y0; + + menu->obj.bbox.x1 = cur->x1; + menu->obj.bbox.y1 = cur->y1; } return 0; -- 2.43.0