]> Git Repo - J-u-boot.git/blob - boot/scene.c
Merge patch series "Endian Kconfig improvements"
[J-u-boot.git] / boot / scene.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Implementation of a scene, a collection of text/image/menu items in an expo
4  *
5  * Copyright 2022 Google LLC
6  * Written by Simon Glass <[email protected]>
7  */
8
9 #define LOG_CATEGORY    LOGC_EXPO
10
11 #include <dm.h>
12 #include <expo.h>
13 #include <malloc.h>
14 #include <mapmem.h>
15 #include <menu.h>
16 #include <video.h>
17 #include <video_console.h>
18 #include <linux/input.h>
19 #include "scene_internal.h"
20
21 int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp)
22 {
23         struct scene *scn;
24
25         scn = calloc(1, sizeof(struct scene));
26         if (!scn)
27                 return log_msg_ret("expo", -ENOMEM);
28         scn->name = strdup(name);
29         if (!scn->name) {
30                 free(scn);
31                 return log_msg_ret("name", -ENOMEM);
32         }
33
34         abuf_init(&scn->buf);
35         if (!abuf_realloc(&scn->buf, EXPO_MAX_CHARS + 1)) {
36                 free(scn->name);
37                 free(scn);
38                 return log_msg_ret("buf", -ENOMEM);
39         }
40         abuf_init(&scn->entry_save);
41
42         INIT_LIST_HEAD(&scn->obj_head);
43         scn->id = resolve_id(exp, id);
44         scn->expo = exp;
45         list_add_tail(&scn->sibling, &exp->scene_head);
46
47         *scnp = scn;
48
49         return scn->id;
50 }
51
52 void scene_obj_destroy(struct scene_obj *obj)
53 {
54         if (obj->type == SCENEOBJT_MENU)
55                 scene_menu_destroy((struct scene_obj_menu *)obj);
56         free(obj->name);
57         free(obj);
58 }
59
60 void scene_destroy(struct scene *scn)
61 {
62         struct scene_obj *obj, *next;
63
64         list_for_each_entry_safe(obj, next, &scn->obj_head, sibling)
65                 scene_obj_destroy(obj);
66
67         abuf_uninit(&scn->entry_save);
68         abuf_uninit(&scn->buf);
69         free(scn->name);
70         free(scn);
71 }
72
73 int scene_title_set(struct scene *scn, uint id)
74 {
75         scn->title_id = id;
76
77         return 0;
78 }
79
80 int scene_obj_count(struct scene *scn)
81 {
82         struct scene_obj *obj;
83         int count = 0;
84
85         list_for_each_entry(obj, &scn->obj_head, sibling)
86                 count++;
87
88         return count;
89 }
90
91 void *scene_obj_find(const struct scene *scn, uint id, enum scene_obj_t type)
92 {
93         struct scene_obj *obj;
94
95         list_for_each_entry(obj, &scn->obj_head, sibling) {
96                 if (obj->id == id &&
97                     (type == SCENEOBJT_NONE || obj->type == type))
98                         return obj;
99         }
100
101         return NULL;
102 }
103
104 void *scene_obj_find_by_name(struct scene *scn, const char *name)
105 {
106         struct scene_obj *obj;
107
108         list_for_each_entry(obj, &scn->obj_head, sibling) {
109                 if (!strcmp(name, obj->name))
110                         return obj;
111         }
112
113         return NULL;
114 }
115
116 int scene_obj_add(struct scene *scn, const char *name, uint id,
117                   enum scene_obj_t type, uint size, struct scene_obj **objp)
118 {
119         struct scene_obj *obj;
120
121         obj = calloc(1, size);
122         if (!obj)
123                 return log_msg_ret("obj", -ENOMEM);
124         obj->name = strdup(name);
125         if (!obj->name) {
126                 free(obj);
127                 return log_msg_ret("name", -ENOMEM);
128         }
129
130         obj->id = resolve_id(scn->expo, id);
131         obj->scene = scn;
132         obj->type = type;
133         list_add_tail(&obj->sibling, &scn->obj_head);
134         *objp = obj;
135
136         return obj->id;
137 }
138
139 int scene_img(struct scene *scn, const char *name, uint id, char *data,
140               struct scene_obj_img **imgp)
141 {
142         struct scene_obj_img *img;
143         int ret;
144
145         ret = scene_obj_add(scn, name, id, SCENEOBJT_IMAGE,
146                             sizeof(struct scene_obj_img),
147                             (struct scene_obj **)&img);
148         if (ret < 0)
149                 return log_msg_ret("obj", ret);
150
151         img->data = data;
152
153         if (imgp)
154                 *imgp = img;
155
156         return img->obj.id;
157 }
158
159 int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
160               struct scene_obj_txt **txtp)
161 {
162         struct scene_obj_txt *txt;
163         int ret;
164
165         ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXT,
166                             sizeof(struct scene_obj_txt),
167                             (struct scene_obj **)&txt);
168         if (ret < 0)
169                 return log_msg_ret("obj", ret);
170
171         txt->str_id = str_id;
172
173         if (txtp)
174                 *txtp = txt;
175
176         return txt->obj.id;
177 }
178
179 int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id,
180                   const char *str, struct scene_obj_txt **txtp)
181 {
182         struct scene_obj_txt *txt;
183         int ret;
184
185         ret = expo_str(scn->expo, name, str_id, str);
186         if (ret < 0)
187                 return log_msg_ret("str", ret);
188         if (str_id && ret != str_id)
189                 return log_msg_ret("id", -EEXIST);
190         str_id = ret;
191
192         ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXT,
193                             sizeof(struct scene_obj_txt),
194                             (struct scene_obj **)&txt);
195         if (ret < 0)
196                 return log_msg_ret("obj", ret);
197
198         txt->str_id = str_id;
199
200         if (txtp)
201                 *txtp = txt;
202
203         return txt->obj.id;
204 }
205
206 int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
207                        uint font_size)
208 {
209         struct scene_obj_txt *txt;
210
211         txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
212         if (!txt)
213                 return log_msg_ret("find", -ENOENT);
214         txt->font_name = font_name;
215         txt->font_size = font_size;
216
217         return 0;
218 }
219
220 int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
221 {
222         struct scene_obj *obj;
223
224         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
225         if (!obj)
226                 return log_msg_ret("find", -ENOENT);
227         obj->dim.x = x;
228         obj->dim.y = y;
229
230         return 0;
231 }
232
233 int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
234 {
235         struct scene_obj *obj;
236
237         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
238         if (!obj)
239                 return log_msg_ret("find", -ENOENT);
240         obj->dim.w = w;
241         obj->dim.h = h;
242
243         return 0;
244 }
245
246 int scene_obj_set_hide(struct scene *scn, uint id, bool hide)
247 {
248         int ret;
249
250         ret = scene_obj_flag_clrset(scn, id, SCENEOF_HIDE,
251                                     hide ? SCENEOF_HIDE : 0);
252         if (ret)
253                 return log_msg_ret("flg", ret);
254
255         return 0;
256 }
257
258 int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set)
259 {
260         struct scene_obj *obj;
261
262         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
263         if (!obj)
264                 return log_msg_ret("find", -ENOENT);
265         obj->flags &= ~clr;
266         obj->flags |= set;
267
268         return 0;
269 }
270
271 int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
272 {
273         struct scene_obj *obj;
274
275         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
276         if (!obj)
277                 return log_msg_ret("find", -ENOENT);
278
279         switch (obj->type) {
280         case SCENEOBJT_NONE:
281         case SCENEOBJT_MENU:
282         case SCENEOBJT_TEXTLINE:
283                 break;
284         case SCENEOBJT_IMAGE: {
285                 struct scene_obj_img *img = (struct scene_obj_img *)obj;
286                 ulong width, height;
287                 uint bpix;
288
289                 video_bmp_get_info(img->data, &width, &height, &bpix);
290                 if (widthp)
291                         *widthp = width;
292                 return height;
293         }
294         case SCENEOBJT_TEXT: {
295                 struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
296                 struct expo *exp = scn->expo;
297                 struct vidconsole_bbox bbox;
298                 const char *str;
299                 int len, ret;
300
301                 str = expo_get_str(exp, txt->str_id);
302                 if (!str)
303                         return log_msg_ret("str", -ENOENT);
304                 len = strlen(str);
305
306                 /* if there is no console, make it up */
307                 if (!exp->cons) {
308                         if (widthp)
309                                 *widthp = 8 * len;
310                         return 16;
311                 }
312
313                 ret = vidconsole_measure(scn->expo->cons, txt->font_name,
314                                          txt->font_size, str, &bbox);
315                 if (ret)
316                         return log_msg_ret("mea", ret);
317                 if (widthp)
318                         *widthp = bbox.x1;
319
320                 return bbox.y1;
321         }
322         }
323
324         return 0;
325 }
326
327 /**
328  * scene_render_background() - Render the background for an object
329  *
330  * @obj: Object to render
331  * @box_only: true to show a box around the object, but keep the normal
332  * background colour inside
333  */
334 static void scene_render_background(struct scene_obj *obj, bool box_only)
335 {
336         struct expo *exp = obj->scene->expo;
337         const struct expo_theme *theme = &exp->theme;
338         struct vidconsole_bbox bbox, label_bbox;
339         struct udevice *dev = exp->display;
340         struct video_priv *vid_priv;
341         struct udevice *cons = exp->cons;
342         struct vidconsole_colour old;
343         enum colour_idx fore, back;
344         uint inset = theme->menu_inset;
345
346         /* draw a background for the object */
347         if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
348                 fore = VID_BLACK;
349                 back = VID_WHITE;
350         } else {
351                 fore = VID_LIGHT_GRAY;
352                 back = VID_BLACK;
353         }
354
355         /* see if this object wants to render a background */
356         if (scene_obj_calc_bbox(obj, &bbox, &label_bbox))
357                 return;
358
359         vidconsole_push_colour(cons, fore, back, &old);
360         vid_priv = dev_get_uclass_priv(dev);
361         video_fill_part(dev, label_bbox.x0 - inset, label_bbox.y0 - inset,
362                         label_bbox.x1 + inset, label_bbox.y1 + inset,
363                         vid_priv->colour_fg);
364         vidconsole_pop_colour(cons, &old);
365         if (box_only) {
366                 video_fill_part(dev, label_bbox.x0, label_bbox.y0,
367                                 label_bbox.x1, label_bbox.y1,
368                                 vid_priv->colour_bg);
369         }
370 }
371
372 /**
373  * scene_obj_render() - Render an object
374  *
375  */
376 static int scene_obj_render(struct scene_obj *obj, bool text_mode)
377 {
378         struct scene *scn = obj->scene;
379         struct expo *exp = scn->expo;
380         const struct expo_theme *theme = &exp->theme;
381         struct udevice *dev = exp->display;
382         struct udevice *cons = text_mode ? NULL : exp->cons;
383         int x, y, ret;
384
385         x = obj->dim.x;
386         y = obj->dim.y;
387
388         switch (obj->type) {
389         case SCENEOBJT_NONE:
390                 break;
391         case SCENEOBJT_IMAGE: {
392                 struct scene_obj_img *img = (struct scene_obj_img *)obj;
393
394                 if (!cons)
395                         return -ENOTSUPP;
396                 ret = video_bmp_display(dev, map_to_sysmem(img->data), x, y,
397                                         true);
398                 if (ret < 0)
399                         return log_msg_ret("img", ret);
400                 break;
401         }
402         case SCENEOBJT_TEXT: {
403                 struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
404                 const char *str;
405
406                 if (!cons)
407                         return -ENOTSUPP;
408
409                 if (txt->font_name || txt->font_size) {
410                         ret = vidconsole_select_font(cons,
411                                                      txt->font_name,
412                                                      txt->font_size);
413                 } else {
414                         ret = vidconsole_select_font(cons, NULL, 0);
415                 }
416                 if (ret && ret != -ENOSYS)
417                         return log_msg_ret("font", ret);
418                 str = expo_get_str(exp, txt->str_id);
419                 if (str) {
420                         struct video_priv *vid_priv;
421                         struct vidconsole_colour old;
422                         enum colour_idx fore, back;
423
424                         if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
425                                 fore = VID_BLACK;
426                                 back = VID_WHITE;
427                         } else {
428                                 fore = VID_LIGHT_GRAY;
429                                 back = VID_BLACK;
430                         }
431
432                         vid_priv = dev_get_uclass_priv(dev);
433                         if (obj->flags & SCENEOF_POINT) {
434                                 vidconsole_push_colour(cons, fore, back, &old);
435                                 video_fill_part(dev, x - theme->menu_inset, y,
436                                                 x + obj->dim.w,
437                                                 y + obj->dim.h,
438                                                 vid_priv->colour_bg);
439                         }
440                         vidconsole_set_cursor_pos(cons, x, y);
441                         vidconsole_put_string(cons, str);
442                         if (obj->flags & SCENEOF_POINT)
443                                 vidconsole_pop_colour(cons, &old);
444                 }
445                 break;
446         }
447         case SCENEOBJT_MENU: {
448                 struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
449
450                 if (exp->popup && (obj->flags & SCENEOF_OPEN)) {
451                         if (!cons)
452                                 return -ENOTSUPP;
453
454                         /* draw a background behind the menu items */
455                         scene_render_background(obj, false);
456                 }
457                 /*
458                  * With a vidconsole, the text and item pointer are rendered as
459                  * normal objects so we don't need to do anything here. The menu
460                  * simply controls where they are positioned.
461                  */
462                 if (cons)
463                         return -ENOTSUPP;
464
465                 ret = scene_menu_display(menu);
466                 if (ret < 0)
467                         return log_msg_ret("img", ret);
468
469                 break;
470         }
471         case SCENEOBJT_TEXTLINE:
472                 if (obj->flags & SCENEOF_OPEN)
473                         scene_render_background(obj, true);
474                 break;
475         }
476
477         return 0;
478 }
479
480 int scene_arrange(struct scene *scn)
481 {
482         struct scene_obj *obj;
483         int ret;
484
485         list_for_each_entry(obj, &scn->obj_head, sibling) {
486                 switch (obj->type) {
487                 case SCENEOBJT_NONE:
488                 case SCENEOBJT_IMAGE:
489                 case SCENEOBJT_TEXT:
490                         break;
491                 case SCENEOBJT_MENU: {
492                         struct scene_obj_menu *menu;
493
494                         menu = (struct scene_obj_menu *)obj,
495                         ret = scene_menu_arrange(scn, menu);
496                         if (ret)
497                                 return log_msg_ret("arr", ret);
498                         break;
499                 }
500                 case SCENEOBJT_TEXTLINE: {
501                         struct scene_obj_textline *tline;
502
503                         tline = (struct scene_obj_textline *)obj,
504                         ret = scene_textline_arrange(scn, tline);
505                         if (ret)
506                                 return log_msg_ret("arr", ret);
507                         break;
508                 }
509                 }
510         }
511
512         return 0;
513 }
514
515 int scene_render_deps(struct scene *scn, uint id)
516 {
517         struct scene_obj *obj;
518         int ret;
519
520         if (!id)
521                 return 0;
522         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
523         if (!obj)
524                 return log_msg_ret("obj", -ENOENT);
525
526         if (!(obj->flags & SCENEOF_HIDE)) {
527                 ret = scene_obj_render(obj, false);
528                 if (ret && ret != -ENOTSUPP)
529                         return log_msg_ret("ren", ret);
530
531                 switch (obj->type) {
532                 case SCENEOBJT_NONE:
533                 case SCENEOBJT_IMAGE:
534                 case SCENEOBJT_TEXT:
535                         break;
536                 case SCENEOBJT_MENU:
537                         scene_menu_render_deps(scn,
538                                                (struct scene_obj_menu *)obj);
539                         break;
540                 case SCENEOBJT_TEXTLINE:
541                         scene_textline_render_deps(scn,
542                                         (struct scene_obj_textline *)obj);
543                         break;
544                 }
545         }
546
547         return 0;
548 }
549
550 int scene_render(struct scene *scn)
551 {
552         struct expo *exp = scn->expo;
553         struct scene_obj *obj;
554         int ret;
555
556         list_for_each_entry(obj, &scn->obj_head, sibling) {
557                 if (!(obj->flags & SCENEOF_HIDE)) {
558                         ret = scene_obj_render(obj, exp->text_mode);
559                         if (ret && ret != -ENOTSUPP)
560                                 return log_msg_ret("ren", ret);
561                 }
562         }
563
564         /* render any highlighted object on top of the others */
565         if (scn->highlight_id && !exp->text_mode) {
566                 ret = scene_render_deps(scn, scn->highlight_id);
567                 if (ret && ret != -ENOTSUPP)
568                         return log_msg_ret("dep", ret);
569         }
570
571         return 0;
572 }
573
574 /**
575  * send_key_obj() - Handle a keypress for moving between objects
576  *
577  * @scn: Scene to receive the key
578  * @key: Key to send (KEYCODE_UP)
579  * @event: Returns resulting event from this keypress
580  * Returns: 0 if OK, -ve on error
581  */
582 static void send_key_obj(struct scene *scn, struct scene_obj *obj, int key,
583                          struct expo_action *event)
584 {
585         switch (key) {
586         case BKEY_UP:
587                 while (obj != list_first_entry(&scn->obj_head, struct scene_obj,
588                                                sibling)) {
589                         obj = list_entry(obj->sibling.prev,
590                                          struct scene_obj, sibling);
591                         if (scene_obj_can_highlight(obj)) {
592                                 event->type = EXPOACT_POINT_OBJ;
593                                 event->select.id = obj->id;
594                                 log_debug("up to obj %d\n", event->select.id);
595                                 break;
596                         }
597                 }
598                 break;
599         case BKEY_DOWN:
600                 while (!list_is_last(&obj->sibling, &scn->obj_head)) {
601                         obj = list_entry(obj->sibling.next, struct scene_obj,
602                                          sibling);
603                         if (scene_obj_can_highlight(obj)) {
604                                 event->type = EXPOACT_POINT_OBJ;
605                                 event->select.id = obj->id;
606                                 log_debug("down to obj %d\n", event->select.id);
607                                 break;
608                         }
609                 }
610                 break;
611         case BKEY_SELECT:
612                 if (scene_obj_can_highlight(obj)) {
613                         event->type = EXPOACT_OPEN;
614                         event->select.id = obj->id;
615                         log_debug("open obj %d\n", event->select.id);
616                 }
617                 break;
618         case BKEY_QUIT:
619                 event->type = EXPOACT_QUIT;
620                 log_debug("obj quit\n");
621                 break;
622         }
623 }
624
625 int scene_send_key(struct scene *scn, int key, struct expo_action *event)
626 {
627         struct scene_obj *obj;
628         int ret;
629
630         event->type = EXPOACT_NONE;
631
632         /*
633          * In 'popup' mode, arrow keys move betwen objects, unless a menu is
634          * opened
635          */
636         if (scn->expo->popup) {
637                 obj = NULL;
638                 if (scn->highlight_id) {
639                         obj = scene_obj_find(scn, scn->highlight_id,
640                                              SCENEOBJT_NONE);
641                 }
642                 if (!obj)
643                         return 0;
644
645                 if (!(obj->flags & SCENEOF_OPEN)) {
646                         send_key_obj(scn, obj, key, event);
647                         return 0;
648                 }
649
650                 switch (obj->type) {
651                 case SCENEOBJT_NONE:
652                 case SCENEOBJT_IMAGE:
653                 case SCENEOBJT_TEXT:
654                         break;
655                 case SCENEOBJT_MENU: {
656                         struct scene_obj_menu *menu;
657
658                         menu = (struct scene_obj_menu *)obj,
659                         ret = scene_menu_send_key(scn, menu, key, event);
660                         if (ret)
661                                 return log_msg_ret("key", ret);
662                         break;
663                 }
664                 case SCENEOBJT_TEXTLINE: {
665                         struct scene_obj_textline *tline;
666
667                         tline = (struct scene_obj_textline *)obj,
668                         ret = scene_textline_send_key(scn, tline, key, event);
669                         if (ret)
670                                 return log_msg_ret("key", ret);
671                         break;
672                 }
673                 }
674                 return 0;
675         }
676
677         list_for_each_entry(obj, &scn->obj_head, sibling) {
678                 if (obj->type == SCENEOBJT_MENU) {
679                         struct scene_obj_menu *menu;
680
681                         menu = (struct scene_obj_menu *)obj,
682                         ret = scene_menu_send_key(scn, menu, key, event);
683                         if (ret)
684                                 return log_msg_ret("key", ret);
685                         break;
686                 }
687         }
688
689         return 0;
690 }
691
692 int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox,
693                         struct vidconsole_bbox *label_bbox)
694 {
695         switch (obj->type) {
696         case SCENEOBJT_NONE:
697         case SCENEOBJT_IMAGE:
698         case SCENEOBJT_TEXT:
699                 return -ENOSYS;
700         case SCENEOBJT_MENU: {
701                 struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
702
703                 scene_menu_calc_bbox(menu, bbox, label_bbox);
704                 break;
705         }
706         case SCENEOBJT_TEXTLINE: {
707                 struct scene_obj_textline *tline;
708
709                 tline = (struct scene_obj_textline *)obj;
710                 scene_textline_calc_bbox(tline, bbox, label_bbox);
711                 break;
712         }
713         }
714
715         return 0;
716 }
717
718 int scene_calc_dims(struct scene *scn, bool do_menus)
719 {
720         struct scene_obj *obj;
721         int ret;
722
723         list_for_each_entry(obj, &scn->obj_head, sibling) {
724                 switch (obj->type) {
725                 case SCENEOBJT_NONE:
726                 case SCENEOBJT_TEXT:
727                 case SCENEOBJT_IMAGE: {
728                         int width;
729
730                         if (!do_menus) {
731                                 ret = scene_obj_get_hw(scn, obj->id, &width);
732                                 if (ret < 0)
733                                         return log_msg_ret("get", ret);
734                                 obj->dim.w = width;
735                                 obj->dim.h = ret;
736                         }
737                         break;
738                 }
739                 case SCENEOBJT_MENU: {
740                         struct scene_obj_menu *menu;
741
742                         if (do_menus) {
743                                 menu = (struct scene_obj_menu *)obj;
744
745                                 ret = scene_menu_calc_dims(menu);
746                                 if (ret)
747                                         return log_msg_ret("men", ret);
748                         }
749                         break;
750                 }
751                 case SCENEOBJT_TEXTLINE: {
752                         struct scene_obj_textline *tline;
753
754                         tline = (struct scene_obj_textline *)obj;
755                         ret = scene_textline_calc_dims(tline);
756                         if (ret)
757                                 return log_msg_ret("men", ret);
758
759                         break;
760                 }
761                 }
762         }
763
764         return 0;
765 }
766
767 int scene_apply_theme(struct scene *scn, struct expo_theme *theme)
768 {
769         struct scene_obj *obj;
770         int ret;
771
772         /* Avoid error-checking optional items */
773         scene_txt_set_font(scn, scn->title_id, NULL, theme->font_size);
774
775         list_for_each_entry(obj, &scn->obj_head, sibling) {
776                 switch (obj->type) {
777                 case SCENEOBJT_NONE:
778                 case SCENEOBJT_IMAGE:
779                 case SCENEOBJT_MENU:
780                 case SCENEOBJT_TEXTLINE:
781                         break;
782                 case SCENEOBJT_TEXT:
783                         scene_txt_set_font(scn, obj->id, NULL,
784                                            theme->font_size);
785                         break;
786                 }
787         }
788
789         ret = scene_arrange(scn);
790         if (ret)
791                 return log_msg_ret("arr", ret);
792
793         return 0;
794 }
795
796 void scene_set_highlight_id(struct scene *scn, uint id)
797 {
798         scn->highlight_id = id;
799 }
800
801 void scene_highlight_first(struct scene *scn)
802 {
803         struct scene_obj *obj;
804
805         list_for_each_entry(obj, &scn->obj_head, sibling) {
806                 if (scene_obj_can_highlight(obj)) {
807                         scene_set_highlight_id(scn, obj->id);
808                         return;
809                 }
810         }
811 }
812
813 static int scene_obj_open(struct scene *scn, struct scene_obj *obj)
814 {
815         int ret;
816
817         switch (obj->type) {
818         case SCENEOBJT_NONE:
819         case SCENEOBJT_IMAGE:
820         case SCENEOBJT_MENU:
821         case SCENEOBJT_TEXT:
822                 break;
823         case SCENEOBJT_TEXTLINE:
824                 ret = scene_textline_open(scn,
825                                           (struct scene_obj_textline *)obj);
826                 if (ret)
827                         return log_msg_ret("op", ret);
828                 break;
829         }
830
831         return 0;
832 }
833
834 int scene_set_open(struct scene *scn, uint id, bool open)
835 {
836         struct scene_obj *obj;
837         int ret;
838
839         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
840         if (!obj)
841                 return log_msg_ret("find", -ENOENT);
842
843         if (open) {
844                 ret = scene_obj_open(scn, obj);
845                 if (ret)
846                         return log_msg_ret("op", ret);
847         }
848
849         ret = scene_obj_flag_clrset(scn, id, SCENEOF_OPEN,
850                                     open ? SCENEOF_OPEN : 0);
851         if (ret)
852                 return log_msg_ret("flg", ret);
853
854         return 0;
855 }
856
857 int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
858                     void *priv)
859 {
860         struct scene_obj *obj;
861
862         list_for_each_entry(obj, &scn->obj_head, sibling) {
863                 int ret;
864
865                 ret = iter(obj, priv);
866                 if (ret)
867                         return log_msg_ret("itr", ret);
868         }
869
870         return 0;
871 }
872
873 int scene_bbox_union(struct scene *scn, uint id, int inset,
874                      struct vidconsole_bbox *bbox)
875 {
876         struct scene_obj *obj;
877
878         if (!id)
879                 return 0;
880         obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
881         if (!obj)
882                 return log_msg_ret("obj", -ENOENT);
883         if (bbox->valid) {
884                 bbox->x0 = min(bbox->x0, obj->dim.x - inset);
885                 bbox->y0 = min(bbox->y0, obj->dim.y);
886                 bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w + inset);
887                 bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h);
888         } else {
889                 bbox->x0 = obj->dim.x - inset;
890                 bbox->y0 = obj->dim.y;
891                 bbox->x1 = obj->dim.x + obj->dim.w + inset;
892                 bbox->y1 = obj->dim.y + obj->dim.h;
893                 bbox->valid = true;
894         }
895
896         return 0;
897 }
This page took 0.085601 seconds and 4 git commands to generate.