"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

expo: Support object alignment

Add support for left, right and centred alignment for text, in the
horizontal dimension.

Also support top, bottom and centred in the vertical dimension, for the
text object as a whole.

Alignment is not yet implemented for images. It has no meaning for
menus. A textline object uses a text object internally, so alignment
is supported there.

Provide some documentation to explain how objects are positioned.

Signed-off-by: Simon Glass <sjg@chromium.org>

Simon Glass 09f6f915 0635004e

+216 -8
+102 -5
boot/scene.c
··· 306 306 return 0; 307 307 } 308 308 309 + int scene_obj_set_halign(struct scene *scn, uint id, enum scene_obj_align aln) 310 + { 311 + struct scene_obj *obj; 312 + 313 + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); 314 + if (!obj) 315 + return log_msg_ret("osh", -ENOENT); 316 + obj->horiz = aln; 317 + 318 + return 0; 319 + } 320 + 321 + int scene_obj_set_valign(struct scene *scn, uint id, enum scene_obj_align aln) 322 + { 323 + struct scene_obj *obj; 324 + 325 + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); 326 + if (!obj) 327 + return log_msg_ret("osv", -ENOENT); 328 + obj->vert = aln; 329 + 330 + return 0; 331 + } 332 + 309 333 int scene_obj_set_hide(struct scene *scn, uint id, bool hide) 310 334 { 311 335 int ret; ··· 331 355 return 0; 332 356 } 333 357 358 + static void handle_alignment(enum scene_obj_align horiz, 359 + enum scene_obj_align vert, 360 + struct scene_obj_bbox *bbox, 361 + struct scene_obj_dims *dims, 362 + int xsize, int ysize, 363 + struct scene_obj_offset *offset) 364 + { 365 + int width, height; 366 + 367 + width = bbox->x1 - bbox->x0; 368 + height = bbox->y1 - bbox->y0; 369 + 370 + switch (horiz) { 371 + case SCENEOA_CENTRE: 372 + offset->xofs = (width - dims->x) / 2; 373 + break; 374 + case SCENEOA_RIGHT: 375 + offset->xofs = width - dims->x; 376 + break; 377 + case SCENEOA_LEFT: 378 + offset->xofs = 0; 379 + break; 380 + } 381 + 382 + switch (vert) { 383 + case SCENEOA_CENTRE: 384 + offset->yofs = (height - dims->y) / 2; 385 + break; 386 + case SCENEOA_BOTTOM: 387 + offset->yofs = height - dims->y; 388 + break; 389 + case SCENEOA_TOP: 390 + default: 391 + offset->yofs = 0; 392 + break; 393 + } 394 + } 395 + 334 396 int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) 335 397 { 336 398 struct scene_obj *obj; ··· 445 507 struct scene_txt_generic *gen, int x, int y, 446 508 int menu_inset) 447 509 { 448 - const struct vidconsole_mline *mline; 510 + const struct vidconsole_mline *mline, *last; 449 511 struct video_priv *vid_priv; 450 512 struct vidconsole_colour old; 451 513 enum colour_idx fore, back; 514 + struct scene_obj_dims dims; 515 + struct scene_obj_bbox bbox; 452 516 const char *str; 453 517 int ret; 454 518 ··· 482 546 obj->bbox.y1, vid_priv->colour_bg); 483 547 } 484 548 485 - if (!gen->lines.count) { 549 + mline = alist_get(&gen->lines, 0, typeof(*mline)); 550 + last = alist_get(&gen->lines, gen->lines.count - 1, typeof(*mline)); 551 + if (mline) 552 + dims.y = last->bbox.y1 - mline->bbox.y0; 553 + bbox.y0 = obj->bbox.y0; 554 + bbox.y1 = obj->bbox.y1; 555 + 556 + if (!mline) { 486 557 vidconsole_set_cursor_pos(cons, x, y); 487 558 vidconsole_put_string(cons, str); 488 559 } 560 + 489 561 alist_for_each(mline, &gen->lines) { 490 - vidconsole_set_cursor_pos(cons, x + mline->bbox.x0, 491 - y + mline->bbox.y0); 562 + struct scene_obj_offset offset; 563 + 564 + bbox.x0 = obj->bbox.x0; 565 + bbox.x1 = obj->bbox.x1; 566 + dims.x = mline->bbox.x1 - mline->bbox.x0; 567 + handle_alignment(obj->horiz, obj->vert, &bbox, &dims, 568 + obj->bbox.x1 - obj->bbox.x0, 569 + obj->bbox.y1 - obj->bbox.y0, &offset); 570 + 571 + x = obj->bbox.x0 + offset.xofs; 572 + y = obj->bbox.y0 + offset.yofs + mline->bbox.y0; 573 + if (y > bbox.y1) 574 + break; /* clip this line and any following */ 575 + vidconsole_set_cursor_pos(cons, x, y); 492 576 vidconsole_put_stringn(cons, str + mline->start, mline->len); 493 577 } 494 578 if (obj->flags & SCENEOF_POINT) ··· 515 599 int x, y, ret; 516 600 517 601 y = obj->bbox.y0; 518 - x = obj->bbox.x0; 602 + x = obj->bbox.x0 + obj->ofs.xofs; 519 603 vid_priv = dev_get_uclass_priv(dev); 520 604 521 605 switch (obj->type) { ··· 626 710 int scene_arrange(struct scene *scn) 627 711 { 628 712 struct expo_arrange_info arr; 713 + int xsize = 0, ysize = 0; 629 714 struct scene_obj *obj; 715 + struct udevice *dev; 630 716 int ret; 631 717 718 + dev = scn->expo->display; 719 + if (dev) { 720 + struct video_priv *priv = dev_get_uclass_priv(dev); 721 + 722 + xsize = priv->xsize; 723 + ysize = priv->ysize; 724 + } 725 + 632 726 ret = scene_calc_arrange(scn, &arr); 633 727 if (ret < 0) 634 728 return log_msg_ret("arr", ret); 635 729 636 730 list_for_each_entry(obj, &scn->obj_head, sibling) { 731 + handle_alignment(obj->horiz, obj->vert, &obj->bbox, &obj->dims, 732 + xsize, ysize, &obj->ofs); 733 + 637 734 switch (obj->type) { 638 735 case SCENEOBJT_NONE: 639 736 case SCENEOBJT_IMAGE:
+31
doc/develop/expo.rst
··· 107 107 of IDs of text and image objects. When adding a menu item you must create these 108 108 objects first, then create the menu item, passing in the relevant IDs. 109 109 110 + Position and alignment 111 + ~~~~~~~~~~~~~~~~~~~~~~ 112 + 113 + Objects are typically positioned automatically, when scene_arrange() is called. 114 + However it is possible to position objects manually. The scene_obj_set_pos() 115 + sets the coordinates of the top left of the object. 116 + 117 + All objects have a bounding box. Typically this is calculated by looking at the 118 + object contents, in `scene_calc_arrange()`. The calculated dimensions of each 119 + object are stored in the object's `dims` field. 120 + 121 + It is possible to adjust the size of an object with `scene_obj_set_size()` or 122 + even set the bounding box, with `scene_obj_set_bbox()`. The `SCENEOF_SIZE_VALID` 123 + flag tracks whether the width/height should be maintained when the position 124 + changes. 125 + 126 + If the bounding box is larger than the object needs, the object can be aligned 127 + to different edges within the box. Objects can be left- or right-aligned, 128 + or centred. For text objects this applies to each line of text. Normally objects 129 + are drawn starting at the top of their bounding box, but they can be aligned 130 + vertically to the bottom, or centred vertically within the box. 131 + 132 + Where the width of a text object's bounding box is smaller than the space needed 133 + to show the next, the text is word-wrapped onto multiple lines, assuming there 134 + is enough vertical space. Newline characters in the next cause a new line to be 135 + started. The measurement information is created by the Truetype console driver 136 + and stored in an alist in `struct scene_txt_generic`. 137 + 138 + When the object is drawn the `ofs` field indicates the x and y offset to use, 139 + from the top left of the bounding box. These values are affected by alignment. 140 + 110 141 Creating an expo 111 142 ---------------- 112 143
+63
include/expo.h
··· 211 211 }; 212 212 213 213 /** 214 + * struct scene_obj_offset - Offsets for drawing the object 215 + * 216 + * Stores the offset from x0, x1 at which objects are drawn 217 + * 218 + * @xofs: x offset 219 + * @yofs: y offset 220 + */ 221 + struct scene_obj_offset { 222 + int xofs; 223 + int yofs; 224 + }; 225 + 226 + /** 214 227 * struct scene_obj_dims - Dimensions of the object being drawn 215 228 * 216 229 * Image and text objects have a dimension which can change depending on what ··· 226 239 }; 227 240 228 241 /** 242 + * enum scene_obj_halign - Horizontal alignment of objects 243 + * 244 + * Objects are normally drawn on the left size of their bounding box. This 245 + * properly allows aligning on the right or having the object centred. 246 + * 247 + * @SCENEOA_LEFT: Left of object is aligned with its x coordinate 248 + * @SCENEOA_RIGHT: Right of object is aligned with x + w 249 + * @SCENEOA_CENTRE: Centre of object is aligned with centre of bounding box 250 + * @SCENEOA_TOP: Left of object is aligned with its x coordinate 251 + * @SCENEOA_BOTTOM: Right of object is aligned with x + w 252 + * 253 + * Note: It would be nice to make this a char type but Sphinx riddles: 254 + * ./include/expo.h:258: error: Cannot parse enum! 255 + * enum scene_obj_align : char { 256 + */ 257 + enum scene_obj_align { 258 + SCENEOA_LEFT, 259 + SCENEOA_RIGHT, 260 + SCENEOA_CENTRE, 261 + SCENEOA_TOP = SCENEOA_LEFT, 262 + SCENEOA_BOTTOM = SCENEOA_RIGHT, 263 + }; 264 + 265 + /** 229 266 * enum scene_obj_flags_t - flags for objects 230 267 * 231 268 * @SCENEOF_HIDE: object should be hidden ··· 255 292 * @id: ID number of the object 256 293 * @type: Type of this object 257 294 * @bbox: Bounding box for this object 295 + * @ofs: Offset from x0, y0 where the object is drawn 258 296 * @dims: Dimensions of the text/image (may be smaller than bbox) 297 + * @horiz: Horizonal alignment 298 + * @vert: Vertical alignment 259 299 * @flags: Flags for this object 260 300 * @bit_length: Number of bits used for this object in CMOS RAM 261 301 * @start_bit: Start bit to use for this object in CMOS RAM ··· 267 307 uint id; 268 308 enum scene_obj_t type; 269 309 struct scene_obj_bbox bbox; 310 + struct scene_obj_offset ofs; 270 311 struct scene_obj_dims dims; 312 + enum scene_obj_align horiz; 313 + enum scene_obj_align vert; 271 314 u8 flags; 272 315 u8 bit_length; 273 316 u16 start_bit; ··· 754 797 */ 755 798 int scene_obj_set_bbox(struct scene *scn, uint id, int x0, int y0, int x1, 756 799 int y1); 800 + 801 + /** 802 + * scene_obj_set_halign() - Set the horizontal alignment of an object 803 + * 804 + * @scn: Scene to update 805 + * @id: ID of object to update 806 + * @aln: Horizontal alignment to use 807 + * Returns: 0 if OK, -ENOENT if @id is invalid 808 + */ 809 + int scene_obj_set_halign(struct scene *scn, uint id, enum scene_obj_align aln); 810 + 811 + /** 812 + * scene_obj_set_valign() - Set the vertical alignment of an object 813 + * 814 + * @scn: Scene to update 815 + * @id: ID of object to update 816 + * @aln: Vertical alignment to use 817 + * Returns: 0 if OK, -ENOENT if @id is invalid 818 + */ 819 + int scene_obj_set_valign(struct scene *scn, uint id, enum scene_obj_align aln); 757 820 758 821 /** 759 822 * scene_obj_set_hide() - Set whether an object is hidden
+20 -3
test/boot/expo.c
··· 492 492 60)); 493 493 ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT2, 200, 600)); 494 494 495 + /* this string is clipped as it extends beyond its bottom bound */ 495 496 id = scene_txt_str(scn, "text", OBJ_TEXT3, STR_TEXT3, 496 - "this is yet\nanother string, with word-wrap", 497 + "this is yet\nanother string, with word-wrap and it goes on for quite a while", 497 498 NULL); 498 499 ut_assert(id > 0); 499 500 ut_assertok(scene_txt_set_font(scn, OBJ_TEXT3, "nimbus_sans_l_regular", 500 501 60)); 501 - ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXT3, 500, 200, 1000, 700)); 502 + ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXT3, 500, 200, 1000, 350)); 502 503 503 504 id = scene_menu(scn, "main", OBJ_MENU, &menu); 504 505 ut_assert(id > 0); ··· 665 666 ut_asserteq(ITEM2, scene_menu_get_cur_item(scn, OBJ_MENU)); 666 667 ut_assertok(scene_arrange(scn)); 667 668 ut_assertok(expo_render(exp)); 668 - ut_asserteq(14883, video_compress_fb(uts, dev, false)); 669 + ut_asserteq(16304, video_compress_fb(uts, dev, false)); 669 670 ut_assertok(video_check_copy_fb(uts, dev)); 671 + 672 + /* do some alignment checks */ 673 + ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_CENTRE)); 674 + ut_assertok(expo_render(exp)); 675 + ut_asserteq(16368, video_compress_fb(uts, dev, false)); 676 + ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_RIGHT)); 677 + ut_assertok(expo_render(exp)); 678 + ut_asserteq(16321, video_compress_fb(uts, dev, false)); 679 + 680 + ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_LEFT)); 681 + ut_assertok(scene_obj_set_valign(scn, OBJ_TEXT3, SCENEOA_CENTRE)); 682 + ut_assertok(expo_render(exp)); 683 + ut_asserteq(18763, video_compress_fb(uts, dev, false)); 684 + ut_assertok(scene_obj_set_valign(scn, OBJ_TEXT3, SCENEOA_BOTTOM)); 685 + ut_assertok(expo_render(exp)); 686 + ut_asserteq(18714, video_compress_fb(uts, dev, false)); 670 687 671 688 /* make sure only the preview for the second item is shown */ 672 689 obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE);