Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nbgl_obj.c
Go to the documentation of this file.
1
6/*********************
7 * INCLUDES
8 *********************/
9#include <string.h>
10
11#include "app_config.h"
12#include "nbgl_obj.h"
13#include "nbgl_draw.h"
14#include "nbgl_front.h"
15#include "nbgl_debug.h"
16#include "nbgl_screen.h"
17#include "nbgl_touch.h"
18#include "os_print.h"
19#include "os_helpers.h"
20#include "os_pic.h"
21#include "glyphs.h"
22#include "os_io_seph_ux.h"
23#ifdef HAVE_SERIALIZED_NBGL
24#include "nbgl_serialize.h"
25#endif
26#ifdef BUILD_SCREENSHOTS
27#include "json_scenario.h"
28#endif // BUILD_SCREENSHOTS
29
30/*********************
31 * DEFINES
32 *********************/
33// max number of letters in TEXT_ENTRY
34#define NB_MAX_LETTERS 9
35
36#if defined(TARGET_STAX)
37#define INTER_DASHES 10
38#elif defined(TARGET_FLEX)
39#define INTER_DASHES 8
40#endif // TARGETS
41
42/**********************
43 * TYPEDEFS
44 **********************/
45typedef void (*draw_function_t)(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition);
46
47/**********************
48 * STATIC PROTOTYPES
49 **********************/
50static void draw_screen(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition);
51static void draw_container(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition);
52static void draw_image(nbgl_image_t *obj, nbgl_obj_t *prevObj, bool computePosition);
53static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePosition);
54#ifdef HAVE_SE_TOUCH
55static void draw_line(nbgl_line_t *obj, nbgl_obj_t *prevObj, bool computePosition);
56static void draw_switch(nbgl_switch_t *obj, nbgl_obj_t *prevObj, bool computePosition);
57static void draw_radioButton(nbgl_radio_t *obj, nbgl_obj_t *prevObj, bool computePosition);
58static void draw_pageIndicator(nbgl_page_indicator_t *obj,
59 nbgl_obj_t *prevObj,
60 bool computePosition);
61static void draw_spinner(nbgl_spinner_t *obj, nbgl_obj_t *prevObj, bool computePosition);
62#else // HAVE_SE_TOUCH
63static void draw_textEntry(nbgl_text_entry_t *obj, nbgl_obj_t *prevObj, bool computePosition);
64#endif // HAVE_SE_TOUCH
65static void draw_progressBar(nbgl_progress_bar_t *obj, nbgl_obj_t *prevObj, bool computePosition);
66static void draw_textArea(nbgl_text_area_t *obj, nbgl_obj_t *prevObj, bool computePosition);
67#ifdef NBGL_QRCODE
68static void draw_qrCode(nbgl_qrcode_t *obj, nbgl_obj_t *prevObj, bool computePosition);
69#endif // NBGL_QRCODE
70#ifdef NBGL_KEYBOARD
71static void draw_keyboard(nbgl_keyboard_t *obj, nbgl_obj_t *prevObj, bool computePosition);
72#endif // NBGL_KEYBOARD
73#ifdef NBGL_KEYPAD
74static void draw_keypad(nbgl_keypad_t *obj, nbgl_obj_t *prevObj, bool computePosition);
75#endif // NBGL_KEYPAD
76static void draw_image_file(nbgl_image_file_t *obj, nbgl_obj_t *prevObj, bool computePosition);
77#ifdef NBGL_MASKING
78static void draw_mask_control(nbgl_mask_control_t *obj, nbgl_obj_t *prevObj, bool computePosition);
79#endif // NBGL_MASKING
80
81static void extendRefreshArea(nbgl_area_t *obj);
82
83/**********************
84 * STATIC VARIABLES
85 **********************/
86// area to resfresh
87static nbgl_area_t refreshArea;
88
89// boolean used to enable/forbid drawing/refresh by Application
90static bool objDrawingDisabled;
91
92// boolean used to indicate a manual refresh area extension
93static bool objRefreshAreaDone;
94
95// indexed by nbgl_obj_type_t
96static const draw_function_t draw_functions[NB_OBJ_TYPES] = {
97 [SCREEN] = (draw_function_t) draw_screen,
98 [CONTAINER] = (draw_function_t) draw_container,
99 [IMAGE] = (draw_function_t) draw_image,
100 [TEXT_AREA] = (draw_function_t) draw_textArea,
101 [BUTTON] = (draw_function_t) draw_button,
102#ifdef HAVE_SE_TOUCH
103 [LINE] = (draw_function_t) draw_line,
104 [SWITCH] = (draw_function_t) draw_switch,
105 [PAGE_INDICATOR] = (draw_function_t) draw_pageIndicator,
106 [RADIO_BUTTON] = (draw_function_t) draw_radioButton,
107#ifdef NBGL_QRCODE
108 [QR_CODE] = (draw_function_t) draw_qrCode,
109#endif // NBGL_QRCODE
110 [SPINNER] = (draw_function_t) draw_spinner,
111#endif // HAVE_SE_TOUCH
112 [PROGRESS_BAR] = (draw_function_t) draw_progressBar,
113#ifdef NBGL_KEYBOARD
114 [KEYBOARD] = (draw_function_t) draw_keyboard,
115#endif // NBGL_KEYBOARD
116#ifdef NBGL_KEYPAD
117 [KEYPAD] = (draw_function_t) draw_keypad,
118#endif // NBGL_KEYPAD
119 [IMAGE_FILE] = (draw_function_t) draw_image_file,
120#ifndef HAVE_SE_TOUCH
121 [TEXT_ENTRY] = (draw_function_t) draw_textEntry,
122#endif // HAVE_SE_TOUCH
123#ifdef NBGL_MASKING
124 [MASK_CONTROL] = (draw_function_t) draw_mask_control,
125#endif // NBGL_MASKING
126};
127/**********************
128 * VARIABLES
129 **********************/
130// buffer used either for image file uncompression and side screen string drawing
132
133#ifdef BUILD_SCREENSHOTS
134// Variables used to store important values (nb lines, bold state etc)
135extern uint16_t last_nb_lines, last_nb_pages;
136extern bool last_bold_state, verbose;
137#endif // BUILD_SCREENSHOTS
138
139/**********************
140 * STATIC PROTOTYPES
141 **********************/
142
143/**********************
144 * GLOBAL FUNCTIONS
145 **********************/
146
147static void compute_relativePosition(nbgl_obj_t *obj, nbgl_obj_t *prevObj)
148{
149 nbgl_container_t *parent = (nbgl_container_t *) (obj->parent);
150 // LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition()\n");
151 // compute object absolute position thanks to layout/alignment
152 if (obj->alignment == NO_ALIGNMENT) {
153 LOG_DEBUG(
155 "compute_relativePosition() without align to, parent->layout = %d, prevObj = %p\n",
156 parent->layout,
157 prevObj);
158 // align to parent, depending of layout
159 if (parent->layout == VERTICAL) {
160 obj->rel_x0 = obj->alignmentMarginX;
161 if (prevObj != NULL) {
162 obj->rel_y0 = prevObj->rel_y0 + prevObj->area.height + obj->alignmentMarginY;
163 }
164 else {
165 obj->rel_y0 = obj->alignmentMarginY;
166 }
167 }
168 else { // HORIZONTAL
169 if (prevObj != NULL) {
170 obj->rel_x0 = prevObj->rel_x0 + prevObj->area.width + obj->alignmentMarginX;
171 }
172 else {
173 obj->rel_x0 = obj->alignmentMarginX;
174 }
175 obj->rel_y0 = obj->alignmentMarginY;
176 }
177 }
178 else {
179 nbgl_obj_t *alignToObj = obj->alignTo;
180 if (alignToObj == NULL) {
181 alignToObj = obj->parent;
182 LOG_DEBUG(OBJ_LOGGER, "compute_relativePosition() with align to parent\n");
183 }
184 else {
185 LOG_DEBUG(OBJ_LOGGER, "compute_relativePosition() with align to = %p\n", alignToObj);
186 }
187 // align to the given object, with the given constraints
188 if (alignToObj == obj->parent) {
189 // align inside if the reference is the parent
190 switch (obj->alignment) {
191 case TOP_LEFT:
192 obj->rel_x0 = obj->alignmentMarginX;
193 obj->rel_y0 = obj->alignmentMarginY;
194 break;
195 case TOP_MIDDLE:
196 obj->rel_x0
197 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
198 obj->rel_y0 = obj->alignmentMarginY;
199 break;
200 case TOP_RIGHT:
201 obj->rel_x0
202 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
203 obj->rel_y0 = obj->alignmentMarginY;
204 break;
205 case MID_LEFT:
206 obj->rel_x0 = obj->alignmentMarginX;
207 obj->rel_y0
208 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
209 break;
210 case CENTER:
211 obj->rel_x0
212 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
213 obj->rel_y0
214 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
215 break;
216 case MID_RIGHT:
217 obj->rel_x0
218 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
219 obj->rel_y0
220 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
221 break;
222 case BOTTOM_LEFT:
223 obj->rel_x0 = obj->alignmentMarginX;
224 obj->rel_y0
225 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
226 break;
227 case BOTTOM_MIDDLE:
228 obj->rel_x0
229 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
230 obj->rel_y0
231 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
232 break;
233 case BOTTOM_RIGHT:
234 obj->rel_x0
235 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
236 obj->rel_y0
237 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
238 break;
239 default:
240 // not supported
241 break;
242 }
243 }
244 else {
245 // align outside if the reference is a "brother"
246 switch (obj->alignment) {
247 case TOP_LEFT:
248 obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX;
249 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
250 break;
251 case TOP_MIDDLE:
252 obj->rel_x0 = alignToObj->rel_x0
253 + (alignToObj->area.width - obj->area.width) / 2
254 + obj->alignmentMarginX;
255 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
256 break;
257 case TOP_RIGHT:
258 obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)
259 - obj->alignmentMarginX;
260 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
261 break;
262
263 case LEFT_TOP:
264 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
265 obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY;
266 break;
267 case MID_LEFT:
268 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
269 obj->rel_y0 = alignToObj->rel_y0
270 + (alignToObj->area.height - obj->area.height) / 2
271 + obj->alignmentMarginY;
272 break;
273 case LEFT_BOTTOM:
274 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
275 obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height)
276 + obj->alignmentMarginY;
277 break;
278
279 case RIGHT_TOP:
280 obj->rel_x0
281 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
282 obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY;
283 break;
284 case MID_RIGHT:
285 obj->rel_x0
286 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
287 obj->rel_y0 = alignToObj->rel_y0
288 + (alignToObj->area.height - obj->area.height) / 2
289 + obj->alignmentMarginY;
290 break;
291 case RIGHT_BOTTOM:
292 obj->rel_x0
293 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
294 obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height)
295 + obj->alignmentMarginY;
296 break;
297
298 case BOTTOM_LEFT:
299 obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX;
300 obj->rel_y0
301 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
302 break;
303 case BOTTOM_MIDDLE:
304 obj->rel_x0 = alignToObj->rel_x0
305 + (alignToObj->area.width - obj->area.width) / 2
306 + obj->alignmentMarginX;
307 obj->rel_y0
308 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
309 break;
310 case BOTTOM_RIGHT:
311 obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)
312 - obj->alignmentMarginX;
313 obj->rel_y0
314 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
315 break;
316 default:
317 // not supported
318 break;
319 }
320 }
321 }
322}
323
324static void compute_position(nbgl_obj_t *obj, nbgl_obj_t *prevObj)
325{
326 nbgl_container_t *parent = (nbgl_container_t *) (obj->parent);
327
328 compute_relativePosition(obj, prevObj);
329
330 if (parent == NULL) {
331 // HUGE issue
332 return;
333 }
334 // LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent.type = %d, parent->obj.area.x0 = %d,
335 // obj->rel_x0=%d\n",parent->type,parent->obj.area.x0,obj->rel_x0);
336 // LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent->obj.area.y0 = %d,
337 // obj->rel_y0=%d\n",parent->obj.area.y0,obj->rel_y0);
338
339 obj->area.x0 = parent->obj.area.x0 + obj->rel_x0;
340 obj->area.y0 = parent->obj.area.y0 + obj->rel_y0;
341
342 if ((obj->area.x0 + obj->area.width) > SCREEN_WIDTH) {
344 "compute_position(), forbidden width, obj->type = %d, x0=%d, width=%d\n",
345 obj->type,
346 obj->area.x0,
347 obj->area.width);
348 }
349#ifdef HAVE_SE_TOUCH
350 if ((obj->area.y0 + obj->area.height) > SCREEN_HEIGHT) {
352 "compute_position(), forbidden height, obj->type = %d, y0=%d, height=%d\n",
353 obj->type,
354 obj->area.y0,
355 obj->area.height);
356 }
357#endif // HAVE_SE_TOUCH
358}
359
360static void draw_screen(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition)
361{
362 nbgl_area_t rectArea;
363
364 UNUSED(prevObj);
365 UNUSED(computePosition);
366
367 rectArea.backgroundColor = obj->obj.area.backgroundColor;
368 rectArea.x0 = obj->obj.area.x0;
369 rectArea.y0 = obj->obj.area.y0;
370 rectArea.width = obj->obj.area.width;
371 rectArea.height = obj->obj.area.height;
372 nbgl_frontDrawRect(&rectArea);
373}
374
375static void draw_container(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition)
376{
377 if (computePosition) {
378 compute_position((nbgl_obj_t *) obj, prevObj);
379 }
381 "draw_container(), x0 = %d, y0 = %d, width = %d, height = %d\n",
382 obj->obj.area.x0,
383 obj->obj.area.y0,
384 obj->obj.area.width,
385 obj->obj.area.height);
386 // inherit background from parent
387 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
388 if (obj->forceClean) {
390 }
391}
392
393#ifdef HAVE_SE_TOUCH
402static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePosition)
403{
404 uint16_t textWidth = 0;
405 const char *text = NULL;
406#define ICON_TEXT_SPACE 12
407
408 if (computePosition) {
409 compute_position((nbgl_obj_t *) obj, prevObj);
410 }
412 "draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n",
413 obj->obj.area.x0,
414 obj->obj.area.y0,
415 obj->obj.area.width,
416 obj->obj.area.height);
417
418 // inherit background from parent
419 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
420 // draw the rounded corner rectangle if necessary
421 if ((obj->innerColor == obj->borderColor)
422 && (obj->innerColor != obj->obj.area.backgroundColor)) {
423 nbgl_drawRoundedRect((nbgl_area_t *) obj, obj->radius, obj->innerColor);
424 }
425 else {
427 (nbgl_area_t *) obj, obj->radius, 2, obj->innerColor, obj->borderColor);
428 }
429 // get the text of the button from the callback if not NULL
430 if (obj->onDrawCallback != NULL) {
431 obj->text = obj->onDrawCallback(obj->token);
432 }
433 text = obj->text;
434 // draw the text (right of the icon, with 8 pixels between them)
435 if (text != NULL) {
436 nbgl_area_t rectArea;
437 // Compute available with & height to display the text
438 rectArea.x0 = obj->obj.area.x0;
439 rectArea.y0 = obj->obj.area.y0;
440 // Only one line of text
441 rectArea.height = nbgl_getFontHeight(obj->fontId);
442 rectArea.y0 += (obj->obj.area.height - rectArea.height) / 2;
443 rectArea.width = obj->obj.area.width;
444 if (obj->icon != NULL) {
445 rectArea.x0 += obj->icon->width + ICON_TEXT_SPACE;
446 rectArea.width -= obj->icon->width + ICON_TEXT_SPACE;
447 }
448 // Compute the width & number of characters displayed on first line
449 uint16_t textLen;
450 nbgl_getTextMaxLenAndWidth(obj->fontId, text, rectArea.width, &textLen, &textWidth, true);
451
452#ifdef BUILD_SCREENSHOTS
453 store_string_infos(text, obj->fontId, &rectArea, true, 1, 1, false);
454#endif // BUILD_SCREENSHOTS
455
456 // Center the text, horizontally
457 if (textWidth < rectArea.width) {
458 rectArea.x0 += (rectArea.width - textWidth) / 2;
459 }
460 LOG_DEBUG(OBJ_LOGGER, "draw_button(), text = %s\n", text);
461 rectArea.backgroundColor = obj->innerColor;
462 nbgl_drawText(&rectArea, text, textLen, obj->fontId, obj->foregroundColor);
463 }
464 // draw the icon, if any
465 if (obj->icon != NULL) {
466 uint16_t iconX0, iconY0;
467 nbgl_area_t rectArea;
468
469 if (text != NULL) {
470 iconX0 = obj->obj.area.x0
471 + (obj->obj.area.width - (textWidth + obj->icon->width + ICON_TEXT_SPACE)) / 2;
472 }
473 else {
474 iconX0 = obj->obj.area.x0 + (obj->obj.area.width - obj->icon->width) / 2;
475 }
477 "draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n",
478 obj->obj.area.height,
479 obj->icon->height);
480 iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height) / 2;
481
482 rectArea.backgroundColor = obj->innerColor;
483 rectArea.x0 = iconX0;
484 rectArea.y0 = iconY0;
485 rectArea.width = obj->icon->width;
486 rectArea.height = obj->icon->height;
487 rectArea.bpp = obj->icon->bpp;
488
489 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->foregroundColor, obj->icon);
490 }
491}
492
501static void draw_line(nbgl_line_t *obj, nbgl_obj_t *prevObj, bool computePosition)
502{
503 nbgl_area_t rectArea;
504 if (computePosition) {
505 compute_position((nbgl_obj_t *) obj, prevObj);
506 }
507 LOG_DEBUG(OBJ_LOGGER, "draw_line(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
508 // inherit background from parent
509 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
511 "draw_line(), backgroundColor = %d, lineColor = %d\n",
512 obj->obj.area.backgroundColor,
513 obj->lineColor);
514 rectArea.x0 = obj->obj.area.x0;
515 rectArea.y0 = obj->obj.area.y0;
516 if (obj->direction == VERTICAL) {
517 rectArea.width = obj->obj.area.width = obj->thickness;
518 rectArea.backgroundColor = obj->lineColor;
519 rectArea.height = obj->obj.area.height;
520 nbgl_frontDrawRect(&rectArea);
521 }
522 else {
523 uint8_t mask;
524 if (obj->thickness == 1) {
525 mask = 0x1 << (obj->offset & 0x3);
526 }
527 else if (obj->thickness == 2) {
528 mask = 0x3 << ((obj->offset < 3) ? obj->offset : 2);
529 }
530 else if (obj->thickness == 3) {
531 mask = 0x7 << (obj->offset & 0x1);
532 }
533 else if (obj->thickness == 4) {
534 mask = 0xF;
535 }
536 else {
537 LOG_WARN(OBJ_LOGGER, "draw_line(), forbidden thickness = %d\n", obj->thickness);
538 return;
539 }
540 rectArea.width = obj->obj.area.width;
541 rectArea.height = obj->obj.area.height = VERTICAL_ALIGNMENT;
542 rectArea.backgroundColor = obj->obj.area.backgroundColor;
543 nbgl_frontDrawHorizontalLine(&rectArea, mask, obj->lineColor);
544 }
545}
546#else // HAVE_SE_TOUCH
555static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePosition)
556{
557 uint16_t textWidth = 0;
558 const char *text = NULL;
559#define ICON_TEXT_SPACE 2
560
561 if (computePosition) {
562 compute_position((nbgl_obj_t *) obj, prevObj);
563 }
565 "draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n",
566 obj->obj.area.x0,
567 obj->obj.area.y0,
568 obj->obj.area.width,
569 obj->obj.area.height);
570
571 // inherit background from parent
572 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
573 // draw the rounded corner rectangle if necessary
574 nbgl_drawRoundedRect((nbgl_area_t *) obj, obj->radius, obj->innerColor);
575
576 // get the text of the button from the callback if not NULL
577 if (obj->onDrawCallback != NULL) {
578 obj->text = obj->onDrawCallback(obj->token);
579 }
580 text = obj->text;
581 // draw the text (right of the icon, with ICON_TEXT_SPACE pixels between them)
582 if (text != NULL) {
583 nbgl_area_t rectArea;
584 // Compute available with & height to display the text
585 rectArea.x0 = obj->obj.area.x0;
586 rectArea.y0 = obj->obj.area.y0;
587 // Only one line of text is allowed
588 rectArea.height = nbgl_getFontHeight(obj->fontId);
589 rectArea.y0 += (obj->obj.area.height - rectArea.height) / 2;
590 rectArea.width = obj->obj.area.width;
591 if (obj->icon != NULL) {
592 rectArea.x0 += obj->icon->width + ICON_TEXT_SPACE;
593 rectArea.width -= obj->icon->width + ICON_TEXT_SPACE;
594 }
595 // Compute the width & number of characters displayed on first line
596 uint16_t textLen;
597 nbgl_getTextMaxLenAndWidth(obj->fontId, text, rectArea.width, &textLen, &textWidth, true);
598
599 // Center the text, horizontally
600 if (textWidth < rectArea.width) {
601 rectArea.x0 += (rectArea.width - textWidth) / 2;
602 }
603 LOG_DEBUG(OBJ_LOGGER, "draw_button(), text = %s\n", text);
604 rectArea.backgroundColor = obj->innerColor;
605 nbgl_drawText(&rectArea, text, textLen, obj->fontId, obj->foregroundColor);
606 }
607 // draw the icon, if any
608 if (obj->icon != NULL) {
609 uint16_t iconX0, iconY0;
610 nbgl_area_t rectArea;
611
612 if (text != NULL) {
613 iconX0 = obj->obj.area.x0
614 + (obj->obj.area.width - (textWidth + obj->icon->width + ICON_TEXT_SPACE)) / 2;
615 }
616 else {
617 iconX0 = obj->obj.area.x0 + (obj->obj.area.width - obj->icon->width) / 2;
618 }
620 "draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n",
621 obj->obj.area.height,
622 obj->icon->height);
623 iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height) / 2;
624
625 rectArea.backgroundColor = obj->innerColor;
626 rectArea.x0 = iconX0;
627 rectArea.y0 = iconY0;
628 rectArea.width = obj->icon->width;
629 rectArea.height = obj->icon->height;
630 rectArea.bpp = obj->icon->bpp;
631
632 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->foregroundColor, obj->icon);
633 }
634}
635#endif // HAVE_SE_TOUCH
636
637static void draw_image(nbgl_image_t *obj, nbgl_obj_t *prevObj, bool computePosition)
638{
639 const nbgl_icon_details_t *iconDetails;
640 nbgl_color_map_t colorMap;
641
642 // if buffer is NULL, let's try to call onDrawCallback, if not NULL, to get it
643 if (obj->buffer == NULL) {
644 if (obj->onDrawCallback != NULL) {
645 iconDetails = obj->onDrawCallback(obj->token);
646 }
647 else {
648 return;
649 }
650 }
651 else {
652 iconDetails = obj->buffer;
653 }
654 if (iconDetails == NULL) {
655 return;
656 }
657
658 // use dimension and bpp from the icon details
659 obj->obj.area.width = iconDetails->width;
660 obj->obj.area.height = iconDetails->height;
661 obj->obj.area.bpp = iconDetails->bpp;
662 if (computePosition) {
663 compute_position((nbgl_obj_t *) obj, prevObj);
664 }
665 LOG_DEBUG(OBJ_LOGGER, "draw_image(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
666 // inherit background from parent
667 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
668 if (obj->obj.area.bpp == NBGL_BPP_1) {
669 colorMap = obj->foregroundColor;
670 }
671 else if (obj->obj.area.bpp == NBGL_BPP_2) {
672 colorMap = ((WHITE << 6) | (LIGHT_GRAY << 4) | (DARK_GRAY << 2) | BLACK);
673 }
674 else {
675 colorMap = obj->foregroundColor;
676 }
677
678 nbgl_drawIcon((nbgl_area_t *) obj, obj->transformation, colorMap, iconDetails);
679}
680
681#ifdef HAVE_SE_TOUCH
682static void draw_switch(nbgl_switch_t *obj, nbgl_obj_t *prevObj, bool computePosition)
683{
684 nbgl_area_t rectArea;
685
686 // force dimensions
687 obj->obj.area.width = C_switch_60_40.width;
688 obj->obj.area.height = C_switch_60_40.height;
689 if (computePosition) {
690 compute_position((nbgl_obj_t *) obj, prevObj);
691 }
692 LOG_DEBUG(OBJ_LOGGER, "draw_switch(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
693
694 // inherit background from parent
695 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
696
697 rectArea.x0 = obj->obj.area.x0;
698 rectArea.y0 = obj->obj.area.y0;
699 rectArea.width = obj->obj.area.width;
700 rectArea.height = obj->obj.area.height;
701 rectArea.backgroundColor = obj->obj.area.backgroundColor;
702 rectArea.bpp = NBGL_BPP_1;
703 if (obj->state == OFF_STATE) {
704 nbgl_frontDrawImage(&rectArea, C_switch_60_40.bitmap, NO_TRANSFORMATION, obj->offColor);
705 }
706 else {
707 nbgl_frontDrawImage(&rectArea, C_switch_60_40.bitmap, VERTICAL_MIRROR, obj->onColor);
708 }
709}
710
711static void draw_radioButton(nbgl_radio_t *obj, nbgl_obj_t *prevObj, bool computePosition)
712{
713 nbgl_area_t rectArea;
714 const nbgl_icon_details_t *icon;
715 nbgl_color_map_t color_map;
716
717 // force dimensions
718 obj->obj.area.width = RADIO_WIDTH;
719 obj->obj.area.height = RADIO_HEIGHT;
720 if (computePosition) {
721 compute_position((nbgl_obj_t *) obj, prevObj);
722 }
724 "draw_radioButton(), x0 = %d, y0 = %d, state = %d\n",
725 obj->obj.area.x0,
726 obj->obj.area.y0,
727 obj->state);
728
729 // inherit background from parent
730 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
731
732 if (obj->state == OFF_STATE) {
733 icon = &RADIO_OFF_ICON;
734 color_map = obj->borderColor;
735 }
736 else {
737 icon = &RADIO_ON_ICON;
738 color_map = obj->activeColor;
739 }
740 rectArea.x0 = obj->obj.area.x0;
741 rectArea.y0 = obj->obj.area.y0;
742 rectArea.width = obj->obj.area.width;
743 rectArea.height = obj->obj.area.height;
744 rectArea.backgroundColor = obj->obj.area.backgroundColor;
745 rectArea.bpp = icon->bpp;
746 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, color_map, icon);
747}
748#endif // HAVE_SE_TOUCH
749
757static void draw_progressBar(nbgl_progress_bar_t *obj, nbgl_obj_t *prevObj, bool computePosition)
758{
759#ifdef HAVE_SE_TOUCH
760
761 uint8_t stroke = 3; // 3 pixels for border
762
763 if (computePosition) {
764 compute_position((nbgl_obj_t *) obj, prevObj);
765 }
766 // force vertical position to be aligned until using nbgl_drawLine()
767 obj->obj.area.y0 &= ~(VERTICAL_ALIGNMENT - 1);
769 "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n",
770 obj->obj.area.x0,
771 obj->obj.area.y0,
772 obj->state);
773
774 // inherit background from parent
775 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
776
777 if (obj->partialRedraw == false) {
778 // Case of progress bar full draw
779 if (obj->withBorder) {
782 stroke,
783 obj->obj.area.backgroundColor,
784 obj->foregroundColor);
785 }
786 else {
788 (nbgl_area_t *) obj, RADIUS_0_PIXELS, obj->obj.area.backgroundColor);
789 }
790 // also reset previous width to be sure to clean up everything
791 obj->previousWidth = 0;
792 }
793 // Setup bar draw
794 nbgl_area_t barArea;
795 uint16_t barWidth = ((obj->state * obj->obj.area.width)) / 100;
796 int barDiffWith = barWidth - obj->previousWidth;
797 color_t barColor;
798 memcpy(&barArea, &obj->obj.area, sizeof(nbgl_area_t));
799
800 if (barDiffWith > 0) {
801 // Drawing "forward"
802 barArea.x0 = obj->obj.area.x0 + obj->previousWidth;
803 barArea.width = barDiffWith;
804 barColor = obj->foregroundColor;
805 }
806 else if (barDiffWith < 0) {
807 // Drawing "backward"
808 barArea.x0 = obj->obj.area.x0 + obj->previousWidth + barDiffWith;
809 barArea.width = -barDiffWith;
810 barColor = obj->obj.area.backgroundColor;
811 }
812
813 if (barDiffWith != 0) {
814 nbgl_drawRoundedRect((nbgl_area_t *) &barArea, RADIUS_0_PIXELS, barColor);
815 }
816
817 // reset partialRedraw to be sure that in case of full redraw of the screen we redraw the
818 // full bar
819 if (obj->partialRedraw == true) {
820 obj->partialRedraw = false;
821 }
822 obj->previousWidth = barWidth;
823
824 extendRefreshArea(&barArea);
825 objRefreshAreaDone = true;
826#else // HAVE_SE_TOUCH
827 uint8_t stroke = 1; // 1 pixels for border
828 uint16_t levelWidth;
829
830 if (computePosition) {
831 compute_position((nbgl_obj_t *) obj, prevObj);
832 }
834 "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n",
835 obj->obj.area.x0,
836 obj->obj.area.y0,
837 obj->state);
838
839 // inherit background from parent
840 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
841
842 // draw external part if necessary
843 if (obj->withBorder) {
845 RADIUS_3_PIXELS,
846 stroke,
847 obj->obj.area.backgroundColor,
848 obj->foregroundColor);
849 }
850 else {
851 nbgl_drawRoundedRect((nbgl_area_t *) obj, RADIUS_3_PIXELS, obj->obj.area.backgroundColor);
852 }
853 // draw level
854 levelWidth = MIN((obj->obj.area.width - 2) * obj->state / 100, (obj->obj.area.width - 2));
855 if (levelWidth > 0) {
856 nbgl_area_t rectArea;
857 rectArea.width = levelWidth;
858 rectArea.height = obj->obj.area.height - 2;
859 rectArea.backgroundColor = obj->foregroundColor;
860 rectArea.bpp = NBGL_BPP_1;
861 rectArea.x0 = obj->obj.area.x0 + 1;
862 rectArea.y0 = obj->obj.area.y0 + 1;
863
864 nbgl_frontDrawRect(&rectArea);
865 }
866#endif // HAVE_SE_TOUCH
867}
868
869#ifdef HAVE_SE_TOUCH
878static void draw_pageIndicator(nbgl_page_indicator_t *obj,
879 nbgl_obj_t *prevObj,
880 bool computePosition)
881{
882 nbgl_area_t rectArea;
883 uint16_t dashWidth;
884
885 // display nothing if less than two pages
886 if (obj->nbPages < 2) {
887 return;
888 }
889
890 if (obj->nbPages <= NB_MAX_PAGES_WITH_DASHES) {
891 int i;
892 // force height
893 obj->obj.area.height = 4;
894
895 if (computePosition) {
896 compute_position((nbgl_obj_t *) obj, prevObj);
897 }
899 "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n",
900 obj->obj.area.x0,
901 obj->obj.area.y0,
902 obj->activePage,
903 obj->nbPages);
904
905 // inherit background from parent
906 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
907
908 dashWidth = (obj->obj.area.width - ((obj->nbPages - 1) * INTER_DASHES)) / obj->nbPages;
909 rectArea.x0 = obj->obj.area.x0;
910 rectArea.y0 = obj->obj.area.y0;
911 rectArea.width = dashWidth;
912 rectArea.height = obj->obj.area.height;
913 rectArea.backgroundColor = obj->obj.area.backgroundColor;
914 rectArea.bpp = NBGL_BPP_1;
915 // draw dashes
916 for (i = 0; i < obj->activePage; i++) {
918 &rectArea, 0xF, (obj->style == PROGRESSIVE_INDICATOR) ? BLACK : LIGHT_GRAY);
919 rectArea.x0 += dashWidth + INTER_DASHES;
920 }
921 nbgl_frontDrawHorizontalLine(&rectArea, 0xF, BLACK);
922 rectArea.x0 += dashWidth + INTER_DASHES;
923 i++;
924
925 for (; i < obj->nbPages; i++) {
927 rectArea.x0 += dashWidth + INTER_DASHES;
928 }
929 }
930 else {
931 char navText[11]; // worst case is "ccc of nnn"
932
933 SPRINTF(navText, "%d of %d", obj->activePage + 1, obj->nbPages);
934 // force height
935 obj->obj.area.height = nbgl_getFontHeight(SMALL_REGULAR_FONT);
936 // the width must be at least 80
937 obj->obj.area.width = nbgl_getTextWidth(SMALL_REGULAR_FONT, navText);
938
939 if (computePosition) {
940 compute_position((nbgl_obj_t *) obj, prevObj);
941 }
943 "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n",
944 obj->obj.area.x0,
945 obj->obj.area.y0,
946 obj->activePage,
947 obj->nbPages);
948
949 // inherit background from parent
950 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
951
952 // draw active page
953 rectArea.x0 = obj->obj.area.x0;
954 rectArea.y0 = obj->obj.area.y0;
955 rectArea.width = obj->obj.area.width;
956 rectArea.height = obj->obj.area.height;
957 rectArea.backgroundColor = obj->obj.area.backgroundColor;
958 rectArea.bpp = NBGL_BPP_1;
959 nbgl_drawText(&rectArea, navText, strlen(navText), SMALL_REGULAR_FONT, DARK_GRAY);
960 }
961}
962#endif // HAVE_SE_TOUCH
963
972static void draw_textArea(nbgl_text_area_t *obj, nbgl_obj_t *prevObj, bool computePosition)
973{
974 nbgl_area_t rectArea;
975 uint16_t textWidth, fontHeight, lineHeight, textHeight, midHeight;
976 uint8_t line, nbLines;
977 const char *text;
978 nbgl_font_id_e fontId = obj->fontId;
979
980 if (computePosition) {
981 compute_position((nbgl_obj_t *) obj, prevObj);
982 }
983 // get the text of the button from the callback if not NULL
984 if (obj->onDrawCallback != NULL) {
985 obj->text = obj->onDrawCallback(obj->token);
986 }
987 text = obj->text;
988 if (text == NULL) {
989 return;
990 }
991
992 LOG_DEBUG(
994 "draw_textArea(), wrapping = %d, x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n",
995 obj->wrapping,
996 obj->obj.area.x0,
997 obj->obj.area.y0,
998 obj->obj.area.width,
999 obj->obj.area.height,
1000 text);
1001
1002 // inherit background from parent
1003 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1004
1005 // draw background to make sure it's clean
1006#ifdef SCREEN_SIZE_NANO
1007 if (obj->style == INVERTED_COLORS) {
1008 obj->obj.area.backgroundColor = WHITE;
1009 rectArea.backgroundColor = BLACK;
1010 }
1011 else
1012#endif // SCREEN_SIZE_NANO
1013 {
1014 // inherit background from parent
1015 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1016 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1017 }
1018 rectArea.x0 = obj->obj.area.x0;
1019 rectArea.y0 = obj->obj.area.y0;
1020 rectArea.width = obj->obj.area.width;
1021 rectArea.height = obj->obj.area.height;
1022#ifdef SCREEN_SIZE_NANO
1023 if (obj->style == INVERTED_COLORS) {
1024 nbgl_drawRoundedRect(&rectArea, RADIUS_1_PIXEL, WHITE);
1025 }
1026 else
1027#endif // SCREEN_SIZE_NANO
1028 {
1029 nbgl_frontDrawRect(&rectArea);
1030 }
1031
1032 fontHeight = nbgl_getFontHeight(fontId);
1033 lineHeight = nbgl_getFontLineHeight(fontId);
1034 // special case of autoHideLongLine, when the text is too long for a line, draw '...' at the
1035 // beginning
1036 if (obj->autoHideLongLine == true) {
1037#ifdef BUILD_SCREENSHOTS
1038 nbgl_getTextNbLinesInWidth(fontId, text, obj->obj.area.width, obj->wrapping);
1039 store_string_infos(text,
1040 fontId,
1041 &obj->obj.area,
1042 obj->wrapping,
1043 last_nb_lines,
1044 last_nb_pages,
1045 last_bold_state);
1046#endif // BUILD_SCREENSHOTS
1047 textWidth = nbgl_getSingleLineTextWidth(fontId, text);
1048 if (textWidth > obj->obj.area.width) {
1049 uint16_t lineWidth, lineLen;
1050 uint16_t dotsWidth;
1051
1052 dotsWidth = nbgl_getTextWidth(fontId, "...");
1053 rectArea.x0 = obj->obj.area.x0;
1054 rectArea.y0 = obj->obj.area.y0 + (obj->obj.area.height - fontHeight) / 2;
1055 rectArea.width = dotsWidth;
1056 nbgl_drawText(&rectArea, "...", 3, fontId, obj->textColor);
1057 // then draw the end of text
1059 fontId, text, obj->obj.area.width - dotsWidth, &lineLen, &lineWidth);
1060 rectArea.x0 += dotsWidth;
1061 rectArea.width = lineWidth;
1062 nbgl_drawText(&rectArea,
1063 &text[nbgl_getTextLength(text) - lineLen],
1064 lineLen,
1065 obj->fontId,
1066 obj->textColor);
1067 return;
1068 }
1069 }
1070
1071 // get nb lines in the given width (depending of wrapping)
1072 nbLines = nbgl_getTextNbLinesInWidth(fontId, text, obj->obj.area.width, obj->wrapping);
1073#ifdef BUILD_SCREENSHOTS
1074 store_string_infos(
1075 text, fontId, &obj->obj.area, obj->wrapping, last_nb_lines, last_nb_pages, last_bold_state);
1076#endif // BUILD_SCREENSHOTS
1077 // saturate nb lines if nbMaxLines is greater than 0
1078 if ((obj->nbMaxLines > 0) && (obj->nbMaxLines < nbLines)) {
1079 nbLines = obj->nbMaxLines;
1080 }
1081
1082 textHeight = (nbLines - 1) * lineHeight + fontHeight;
1083
1084 midHeight = (obj->obj.area.height - textHeight) / 2;
1085#ifdef SCREEN_SIZE_NANO
1086 if (obj->style == INVERTED_COLORS) {
1087 midHeight--;
1088 }
1089#endif // SCREEN_SIZE_NANO
1090
1091 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1092 rectArea.height = fontHeight;
1093 // draw each line
1094 for (line = 0; line < nbLines; line++) {
1095 uint16_t lineWidth, lineLen;
1096
1098 fontId, text, obj->obj.area.width, &lineLen, &lineWidth, obj->wrapping);
1099 if (obj->textAlignment == MID_LEFT) {
1100 rectArea.x0 = obj->obj.area.x0;
1101 }
1102 else if (obj->textAlignment == CENTER) {
1103 rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - lineWidth) / 2;
1104 }
1105 else if (obj->textAlignment == MID_RIGHT) {
1106 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - lineWidth;
1107 }
1108 else {
1109 LOG_FATAL(OBJ_LOGGER, "Forbidden obj->textAlignment = %d\n", obj->textAlignment);
1110 }
1111 rectArea.y0 = obj->obj.area.y0 + midHeight + line * lineHeight;
1112 rectArea.width = lineWidth;
1113
1115 "draw_textArea(), [%s] line %d, lineLen %d lineWidth = %d, obj.area.height = %d, "
1116 "textHeight = %d, nbMaxLines = %d, wrapping = %d\n",
1117 text,
1118 line,
1119 lineLen,
1120 lineWidth,
1121 obj->obj.area.height,
1122 textHeight,
1123 obj->nbMaxLines,
1124 obj->wrapping);
1125 if ((obj->nbMaxLines == 0) || (line < (obj->nbMaxLines - 1))) {
1126 fontId = nbgl_drawText(&rectArea, text, lineLen, fontId, obj->textColor);
1127 }
1128 else {
1129#ifdef HAVE_SE_TOUCH
1130 uint16_t dotsWidth = nbgl_getSingleLineTextWidth(obj->fontId, "...");
1131 // for last chunk, if nbMaxLines is used, replace the 3 last chars by "..."
1132 // draw line except 3 last chars
1133 if ((lineWidth + dotsWidth) >= obj->obj.area.width) {
1134 lineLen -= 3;
1135 }
1136 nbgl_drawText(&rectArea, text, lineLen, obj->fontId, obj->textColor);
1137 rectArea.x0 += nbgl_getSingleLineTextWidthInLen(obj->fontId, text, lineLen);
1138
1139 // draw "..." after the other chars
1140 rectArea.width = dotsWidth;
1141 nbgl_drawText(&rectArea, "...", 3, obj->fontId, obj->textColor);
1142#else // HAVE_SE_TOUCH
1143 nbgl_drawText(&rectArea, text, lineLen, fontId, obj->textColor);
1144#endif // HAVE_SE_TOUCH
1145 return;
1146 }
1147 text += lineLen;
1148 /* skip trailing \n */
1149 if (*text == '\n') {
1150 text++;
1151 }
1152 }
1153}
1154
1155#ifdef NBGL_QRCODE
1164static void draw_qrCode(nbgl_qrcode_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1165{
1166 nbgl_area_t rectArea;
1167
1168 if (computePosition) {
1169 compute_position((nbgl_obj_t *) obj, prevObj);
1170 }
1171 // be sure to align vertical position on multiple of 4
1172 obj->obj.area.y0 &= ~0x3;
1174 "draw_qrCode(), x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n",
1175 obj->obj.area.x0,
1176 obj->obj.area.y0,
1177 obj->obj.area.width,
1178 obj->obj.area.height,
1179 obj->text);
1180
1181 // inherit background from parent
1182 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1183
1184 rectArea.x0 = obj->obj.area.x0;
1185 rectArea.y0 = obj->obj.area.y0;
1186 rectArea.width = obj->obj.area.width;
1187 rectArea.height = obj->obj.area.height;
1188 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1189 nbgl_drawQrCode(&rectArea, obj->version, obj->text, obj->foregroundColor);
1190}
1191#endif // NBGL_QRCODE
1192
1193#ifdef NBGL_KEYBOARD
1201static void draw_keyboard(nbgl_keyboard_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1202{
1203#ifndef HAVE_SE_TOUCH
1204 obj->obj.area.width = KEYBOARD_WIDTH;
1205 obj->obj.area.height = KEYBOARD_KEY_HEIGHT;
1206#endif // HAVE_SE_TOUCH
1207
1208 if (computePosition) {
1209 compute_position((nbgl_obj_t *) obj, prevObj);
1210 }
1211 LOG_DEBUG(
1212 OBJ_LOGGER, "draw_keyboard(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1213
1214 // inherit background from parent
1215 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1216
1218}
1219#endif // NBGL_KEYBOARD
1220
1221#ifdef NBGL_KEYPAD
1229static void draw_keypad(nbgl_keypad_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1230{
1231#ifndef HAVE_SE_TOUCH
1232 obj->obj.area.height = KEYPAD_HEIGHT;
1233 obj->obj.area.width = KEYPAD_WIDTH;
1234#endif // HAVE_SE_TOUCH
1235
1236 if (computePosition) {
1237 compute_position((nbgl_obj_t *) obj, prevObj);
1238 }
1239 obj->obj.area.y0 &= ~0x3;
1240 LOG_DEBUG(OBJ_LOGGER, "draw_keypad(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1241
1242 // inherit background from parent
1243 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1244
1245 nbgl_objDrawKeypad(obj);
1246}
1247#endif // NBGL_KEYPAD
1248
1249#ifdef HAVE_SE_TOUCH
1257static void draw_spinner(nbgl_spinner_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1258{
1259 nbgl_area_t rectArea;
1260 color_t foreColor;
1261
1262 obj->obj.area.width = SPINNER_WIDTH;
1263 obj->obj.area.height = SPINNER_HEIGHT;
1264
1265 if (computePosition) {
1266 compute_position((nbgl_obj_t *) obj, prevObj);
1267 }
1268 obj->obj.area.y0 &= ~0x3;
1269 LOG_DEBUG(OBJ_LOGGER, "draw_spinner(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1270
1271 // inherit background from parent
1272 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1273 // foreground color is the opposite of background one
1274 foreColor = (obj->obj.area.backgroundColor == WHITE) ? BLACK : WHITE;
1275
1276 rectArea.bpp = NBGL_BPP_1;
1277 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1278 // if position is OxFF, it means "fixed" so draw 4 corners
1279 if (obj->position == 0xFF) {
1280 // draw horizontal segments
1281 rectArea.x0 = obj->obj.area.x0;
1282 rectArea.y0 = obj->obj.area.y0;
1283 rectArea.width = 20;
1284 rectArea.height = 4;
1285 nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top left
1286 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1287 nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top right
1288 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1289 nbgl_frontDrawHorizontalLine(&rectArea, 0xE, foreColor); // bottom right
1290 rectArea.x0 = obj->obj.area.x0;
1291 nbgl_frontDrawHorizontalLine(&rectArea, 0xE, foreColor); // bottom left
1292 // draw vertical segments
1293 rectArea.x0 = obj->obj.area.x0;
1294 rectArea.y0 = obj->obj.area.y0;
1295 rectArea.width = 3;
1296 rectArea.height = 12;
1297 rectArea.backgroundColor = foreColor;
1298 nbgl_frontDrawRect(&rectArea); // top left
1299 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1300 nbgl_frontDrawRect(&rectArea); // top right
1301 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1302 nbgl_frontDrawRect(&rectArea); // bottom right
1303 rectArea.x0 = obj->obj.area.x0;
1304 nbgl_frontDrawRect(&rectArea); // bottom left
1305 }
1306 else {
1307 uint8_t mask;
1308 // clean up full rectangle
1309 rectArea.x0 = obj->obj.area.x0;
1310 rectArea.y0 = obj->obj.area.y0;
1311 rectArea.width = obj->obj.area.width;
1312 rectArea.height = obj->obj.area.height;
1313 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1314 nbgl_frontDrawRect(&rectArea); // top left
1315
1316 // draw horizontal segment in foreColor
1317 rectArea.width = 20;
1318 rectArea.height = 4;
1319 switch (obj->position) {
1320 case 0: // top left corner
1321 rectArea.x0 = obj->obj.area.x0;
1322 rectArea.y0 = obj->obj.area.y0;
1323 mask = 0x7;
1324 break;
1325 case 1: // top right
1326 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1327 rectArea.y0 = obj->obj.area.y0;
1328 mask = 0x7;
1329 break;
1330 case 2: // bottom right
1331 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1332 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1333 mask = 0xE;
1334 break;
1335 case 3: // bottom left
1336 rectArea.x0 = obj->obj.area.x0;
1337 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1338 mask = 0xE;
1339 break;
1340 default:
1341 return;
1342 }
1343 nbgl_frontDrawHorizontalLine(&rectArea, mask, foreColor);
1344
1345 // draw vertical segment in foreColor
1346 rectArea.width = 3;
1347 rectArea.height = 12;
1348 rectArea.backgroundColor = foreColor;
1349 switch (obj->position) {
1350 case 0: // top left corner
1351 rectArea.x0 = obj->obj.area.x0;
1352 rectArea.y0 = obj->obj.area.y0;
1353 break;
1354 case 1: // top right corner
1355 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1356 rectArea.y0 = obj->obj.area.y0;
1357 break;
1358 case 2: // bottom right corner
1359 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1360 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1361 break;
1362 case 3: // bottom left corner
1363 rectArea.x0 = obj->obj.area.x0;
1364 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1365 break;
1366 default:
1367 return;
1368 }
1369 nbgl_frontDrawRect(&rectArea);
1370 }
1371}
1372
1373#else // HAVE_SE_TOUCH
1374
1382static void draw_textEntry(nbgl_text_entry_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1383{
1384 nbgl_area_t rectArea;
1385 int textLen = strlen(obj->text);
1386 uint32_t offsetX;
1387
1388 if (computePosition) {
1389 compute_position((nbgl_obj_t *) obj, prevObj);
1390 }
1391
1393 "draw_textEntry(), x0 = %d, y0 = %d, width = %d, height = %d\n",
1394 obj->obj.area.x0,
1395 obj->obj.area.y0,
1396 obj->obj.area.width,
1397 obj->obj.area.height);
1398
1399 // draw background to make sure it's clean
1400 obj->obj.area.backgroundColor = WHITE;
1401 rectArea.backgroundColor = BLACK;
1402 rectArea.x0 = obj->obj.area.x0;
1403 rectArea.y0 = obj->obj.area.y0;
1404 rectArea.width = obj->obj.area.width;
1405 rectArea.height = obj->obj.area.height;
1406 rectArea.bpp = NBGL_BPP_1;
1407 nbgl_drawRoundedRect(&rectArea, RADIUS_3_PIXELS, WHITE);
1408
1409 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1410 rectArea.height = nbgl_getFontHeight(obj->fontId);
1411 if (obj->nbChars > NB_MAX_LETTERS) {
1412 return;
1413 }
1414 offsetX = (obj->obj.area.width - (obj->nbChars * 10)) / 2;
1415 // draw each of the nb chars
1416 for (int i = 0; i < obj->nbChars; i++) {
1417 char digit;
1418 rectArea.x0 = obj->obj.area.x0 + offsetX + (i * 10);
1419 rectArea.y0 = obj->obj.area.y0 - 2;
1420 rectArea.width = 8;
1421 if (textLen < obj->nbChars) {
1422 if (i < textLen) {
1423 digit = obj->text[i];
1424 }
1425 else {
1426 digit = '_';
1427 }
1428 }
1429 else {
1430 // first char is '..' to notify continuing
1431 if (i == 0) {
1433 continue;
1434 }
1435 else if (i < (obj->nbChars - 1)) {
1436 digit = obj->text[textLen - obj->nbChars + 1 + i];
1437 }
1438 else {
1439 digit = '_';
1440 }
1441 }
1443 }
1444}
1445#endif // HAVE_SE_TOUCH
1446
1454static void draw_image_file(nbgl_image_file_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1455{
1456 if (obj->buffer == NULL) {
1457 return;
1458 }
1459 if (computePosition) {
1460 compute_position((nbgl_obj_t *) obj, prevObj);
1461 }
1462
1463 LOG_DEBUG(
1464 OBJ_LOGGER, "draw_image_file(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1465 obj->obj.area.backgroundColor = WHITE;
1466 nbgl_frontDrawImageFile((nbgl_area_t *) obj, obj->buffer, BLACK, ramBuffer);
1467}
1468
1469#ifdef NBGL_MASKING
1470static void draw_mask_control(nbgl_mask_control_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1471{
1472 if (computePosition) {
1473 compute_position((nbgl_obj_t *) obj, prevObj);
1474 }
1475
1476 if (obj->enableMasking) {
1477 nbgl_frontControlAreaMasking(obj->maskIndex, &obj->obj.area);
1478 }
1479 else {
1480 nbgl_frontControlAreaMasking(obj->maskIndex, NULL);
1481 }
1482}
1483#endif // NBGL_MASKING
1484
1492static void draw_object(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1493{
1494 LOG_DEBUG(OBJ_LOGGER, "draw_object() obj->type = %d, prevObj = %p\n", obj->type, prevObj);
1495 objRefreshAreaDone = false;
1496 if ((obj->type < NB_OBJ_TYPES) && (draw_functions[obj->type] != NULL)) {
1497 if ((obj->type != SCREEN) && (obj->parent == NULL)) {
1498 LOG_WARN(OBJ_LOGGER, "object with type [%d] has not parent\n", obj->type);
1499 return;
1500 }
1501 draw_function_t func = (draw_function_t) PIC(draw_functions[obj->type]);
1502 func(obj, prevObj, computePosition);
1503 }
1504 else {
1505 LOG_WARN(OBJ_LOGGER, "Not existing object type [%d]\n", obj->type);
1506 return;
1507 }
1508
1509#ifdef HAVE_SERIALIZED_NBGL
1510 io_seph_ux_send_nbgl_serialized(NBGL_DRAW_OBJ, obj);
1511#endif
1512 if (!objRefreshAreaDone) {
1513 extendRefreshArea(&obj->area);
1514 }
1515}
1516
1526static void draw_obj_and_chidren(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1527{
1528 uint8_t i = 0;
1529 LOG_DEBUG(OBJ_LOGGER, "draw_obj_and_chidren(): obj = %p\n", obj);
1530 // draw the object itself
1531 draw_object(obj, prevObj, computePosition);
1532
1533 if ((obj->type == SCREEN) || (obj->type == CONTAINER)) {
1534 nbgl_container_t *container = (nbgl_container_t *) obj;
1535 nbgl_obj_t *prev = NULL;
1536 LOG_DEBUG(
1537 OBJ_LOGGER, "draw_obj_and_chidren(): container->children = %p\n", container->children);
1538 // draw the children, if any
1539 if (container->children != NULL) {
1540 for (i = 0; i < container->nbChildren; i++) {
1541 nbgl_obj_t *current = container->children[i];
1542 if (current != NULL) {
1543 current->parent = (nbgl_obj_t *) container;
1544 draw_obj_and_chidren(current, prev, true);
1545 if (current->alignTo == NULL) {
1546 prev = current;
1547 }
1548 }
1549 }
1550 }
1551 }
1552}
1553
1560static void extendRefreshArea(nbgl_area_t *area)
1561{
1562 int16_t x1, y1; // bottom right corner
1563 x1 = refreshArea.x0 + refreshArea.width;
1564 y1 = refreshArea.y0 + refreshArea.height;
1565
1566 // if obj top-left is on left of current top-left corner, move top-left corner
1567 if (area->x0 < refreshArea.x0) {
1568 // No negative coordinates
1569 refreshArea.x0 = MAX(0, area->x0);
1570 }
1571 // if obj bottom-right is on right of current bottom-right corner, move bottom-right corner
1572 if (((area->x0 + area->width) > x1) || (refreshArea.width == 0)) {
1573 // Not beyond width
1574 x1 = MIN(SCREEN_WIDTH, area->x0 + area->width);
1575 }
1576 // if obj top-left is on top of current top-left corner, move top-left corner
1577 if (area->y0 < refreshArea.y0) {
1578 // No negative coordinates and align on lower multiple of alignment
1579 refreshArea.y0 = MAX(0, area->y0) & ~(VERTICAL_ALIGNMENT - 1);
1580 }
1581 // if obj bottom-right is on bottom of current bottom-right corner, move bottom-right corner
1582 if (((area->y0 + area->height) > y1) || (refreshArea.height == 0)) {
1583 // Not beyond height
1584 y1 = MIN(SCREEN_HEIGHT, area->y0 + area->height);
1585 // align on upper multiple of alignment
1586 y1 = (y1 + (VERTICAL_ALIGNMENT - 1)) & ~(VERTICAL_ALIGNMENT - 1);
1587 }
1588
1589 // sanity check
1590 if (x1 > SCREEN_WIDTH) {
1592 "extendRefreshArea: Impossible area x0 = %d width %d\n",
1593 refreshArea.x0,
1594 refreshArea.width);
1595 }
1596 if (y1 > SCREEN_HEIGHT) {
1597#ifdef HAVE_SE_TOUCH
1599 "extendRefreshArea: Impossible area y0 = %d height %d\n",
1600 refreshArea.y0,
1601 refreshArea.height);
1602#else // HAVE_SE_TOUCH
1603 y1 = SCREEN_HEIGHT;
1604#endif // HAVE_SE_TOUCH
1605 }
1606 // recompute width and height
1607 refreshArea.width = x1 - refreshArea.x0;
1608 refreshArea.height = y1 - refreshArea.y0;
1609
1610 // revaluate area bpp
1611 if (area->bpp > refreshArea.bpp) {
1612 refreshArea.bpp = area->bpp;
1613 }
1614}
1615
1622{
1623 bool computePosition = false;
1624 bool fromApp;
1625
1626 LOG_DEBUG(OBJ_LOGGER, "nbgl_objDraw(): obj = %p\n", obj);
1627 // check whether it's necessary to compute position, and if this object belongs to
1628 // an Application screen
1629 if (obj->type == SCREEN) {
1630 // always compute position for screen and all sub-objects
1631 computePosition = true;
1632 fromApp = !(((nbgl_screen_t *) obj)->isUxScreen);
1633 }
1634 else {
1635 nbgl_obj_t *parent = obj;
1636 // search screen in parenthood
1637 while (parent->parent != NULL) {
1638 parent = parent->parent;
1639 }
1640 if (parent->type == SCREEN) {
1641 fromApp = !(((nbgl_screen_t *) parent)->isUxScreen);
1642 }
1643 else {
1644 // should never happen
1645 fromApp = false;
1646 }
1647 }
1648 // actually draw the object and its children, if it is allowed
1649 if (objDrawingDisabled && fromApp) {
1650 return;
1651 }
1652 draw_obj_and_chidren(obj, NULL, computePosition);
1653}
1654
1664
1671{
1672 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1673 return;
1674 }
1675
1678 "nbgl_refreshSpecial(), x0,y0 = [%d, %d], w,h = [%d, %d]\n",
1679 refreshArea.x0,
1680 refreshArea.y0,
1681 refreshArea.width,
1682 refreshArea.height);
1684}
1685
1687{
1688 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1689 return;
1690 }
1691
1692 nbgl_frontRefreshArea(&refreshArea, mode, post_refresh);
1694 "nbgl_refreshSpecialNoPoff(), x0,y0 = [%d, %d], w,h = [%d, %d]\n",
1695 refreshArea.x0,
1696 refreshArea.y0,
1697 refreshArea.width,
1698 refreshArea.height);
1700}
1701
1707{
1708 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1709 return false;
1710 }
1711 return true;
1712}
1713
1719{
1720#ifdef HAVE_SERIALIZED_NBGL
1721 io_seph_ux_send_nbgl_serialized(NBGL_REFRESH_AREA, (nbgl_obj_t *) &refreshArea);
1722#endif
1723 refreshArea.x0 = SCREEN_WIDTH - 1;
1724 refreshArea.width = 0;
1725 refreshArea.y0 = SCREEN_HEIGHT - 1;
1726 refreshArea.height = 0;
1727 refreshArea.bpp = NBGL_BPP_2;
1728}
1729
1736{
1737 // init area to the smallest size
1739 objDrawingDisabled = false;
1740#ifdef HAVE_SE_TOUCH
1741 nbgl_touchInit(false);
1742#endif
1743}
1744
1750void nbgl_objAllowDrawing(bool enable)
1751{
1752 objDrawingDisabled = !enable;
1753}
1754
1761{
1762 return ramBuffer;
1763}
1764
1771{
1772 nbgl_obj_t *parent = obj;
1773 // search screen in parenthood
1774 while (parent->parent != NULL) {
1775 parent = parent->parent;
1776 }
1777 if (parent->type == SCREEN) {
1778 return (((nbgl_screen_t *) parent)->isUxScreen);
1779 }
1780 else {
1781 // should never happen
1782 return true;
1783 }
1784}
debug traces management
#define LOG_WARN(__logger,...)
Definition nbgl_debug.h:87
#define LOG_DEBUG(__logger,...)
Definition nbgl_debug.h:86
#define LOG_FATAL(__logger,...)
Definition nbgl_debug.h:88
@ OBJ_LOGGER
Definition nbgl_debug.h:30
Middle Level API of the new BOLOS Graphical Library.
void nbgl_drawIcon(nbgl_area_t *area, nbgl_transformation_t transformation, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon)
Helper function to render an icon directly from its nbgl_icon_details_t structure.
Definition nbgl_draw.c:489
nbgl_font_id_e nbgl_drawText(const nbgl_area_t *area, const char *text, uint16_t textLen, nbgl_font_id_e fontId, color_t fontColor)
This function draws the given single-line text, with the given parameters.
Definition nbgl_draw.c:538
void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, nbgl_radius_t radius, uint8_t stroke, color_t innerColor, color_t borderColor)
This functions draws a rounded corners rectangle with a border, with the given parameters.
Definition nbgl_draw.c:331
void nbgl_drawQrCode(const nbgl_area_t *area, nbgl_qrcode_version_t version, const char *text, color_t backgroundColor)
Draws the given text into a V10 QR code (QR code version is fixed using qrcodegen_VERSION_MIN/qrcodeg...
Definition nbgl_draw.c:764
void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radius, color_t innerColor)
This functions draws a rounded corners rectangle (without border), with the given parameters.
Definition nbgl_draw.c:249
void nbgl_getTextMaxLenAndWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, uint16_t *len, uint16_t *width, bool wrapping)
compute the max width of the first line of the given text fitting in maxWidth
Definition nbgl_fonts.c:472
uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char *text)
return the max width in pixels of the given text until the first or \0 is encountered
Definition nbgl_fonts.c:324
nbgl_font_id_e
Definition nbgl_fonts.h:136
@ BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp
Definition nbgl_fonts.h:143
bool nbgl_getTextMaxLenAndWidthFromEnd(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, uint16_t *len, uint16_t *width)
compute the len and width of the given text fitting in the maxWidth, starting from end of text
Definition nbgl_fonts.c:671
uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId)
return the height in pixels of the font with the given font ID
Definition nbgl_fonts.c:388
uint16_t nbgl_getTextWidth(nbgl_font_id_e fontId, const char *text)
return the max width in pixels of the given text (can be multiline)
Definition nbgl_fonts.c:350
uint16_t nbgl_getTextLength(const char *text)
return the number of bytes of the given text, excluding final ' ' or '\0'
Definition nbgl_fonts.c:444
uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
compute the number of lines of the given text fitting in the given maxWidth
Definition nbgl_fonts.c:721
uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId)
return the height in pixels of the line of font with the given font ID
Definition nbgl_fonts.c:400
uint16_t nbgl_getSingleLineTextWidthInLen(nbgl_font_id_e fontId, const char *text, uint16_t maxLen)
return the max width in pixels of the given text until the first or \0 is encountered,...
Definition nbgl_fonts.c:338
Font screen low-Level driver API, to draw elementary forms.
void nbgl_frontControlAreaMasking(uint8_t mask_index, nbgl_area_t *masked_area_or_null)
void nbgl_frontDrawImage(const nbgl_area_t *area, const uint8_t *buffer, nbgl_transformation_t transformation, nbgl_color_map_t colorMap)
void nbgl_frontDrawImageFile(const nbgl_area_t *area, const uint8_t *buffer, nbgl_color_map_t colorMap, const uint8_t *uzlib_chunk_buffer)
void nbgl_frontRefreshArea(const nbgl_area_t *area, nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh)
void nbgl_frontDrawHorizontalLine(const nbgl_area_t *area, uint8_t mask, color_t lineColor)
void nbgl_frontDrawRect(const nbgl_area_t *area)
#define ICON_TEXT_SPACE
#define NB_MAX_LETTERS
Definition nbgl_obj.c:34
void nbgl_objDraw(nbgl_obj_t *obj)
This function draws or redraws the given object and its children (recursive version)
Definition nbgl_obj.c:1621
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
Definition nbgl_obj.c:1660
void nbgl_refreshReset(void)
This functions resets all changes since the last refresh.
Definition nbgl_obj.c:1718
void nbgl_objAllowDrawing(bool enable)
This functions enables or disables drawing/refresh for all further calls.
Definition nbgl_obj.c:1750
void(* draw_function_t)(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition)
Definition nbgl_obj.c:45
void nbgl_refreshSpecial(nbgl_refresh_mode_t mode)
This functions refreshes the actual screen on display with what has changed since the last refresh,...
Definition nbgl_obj.c:1670
bool nbgl_objIsUx(nbgl_obj_t *obj)
This function returns true if the object belongs to a UxScreen.
Definition nbgl_obj.c:1770
void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh)
Definition nbgl_obj.c:1686
uint8_t * nbgl_objGetRAMBuffer(void)
This function is used to get the all purpose RAM buffer.
Definition nbgl_obj.c:1760
uint8_t ramBuffer[GZLIB_UNCOMPRESSED_CHUNK]
Definition nbgl_obj.c:131
bool nbgl_refreshIsNeeded(void)
This functions returns true if there is something to refresh.
Definition nbgl_obj.c:1706
void nbgl_objInit(void)
This functions inits all internal of nbgl objects layer.
Definition nbgl_obj.c:1735
API to draw all basic graphic objects.
struct PACKED__ nbgl_line_s nbgl_line_t
struct to represent a vertical or horizontal line
struct PACKED__ nbgl_navigation_bar_s nbgl_page_indicator_t
struct to represent a navigation bar (PAGE_INDICATOR type) There can be up to 5 page indicators,...
struct PACKED__ nbgl_radio_s nbgl_radio_t
struct to represent a radio button (RADIO_BUTTON type)
struct PACKED__ nbgl_text_area_s nbgl_text_area_t
struct to represent a text area (TEXT_AREA type)
struct PACKED__ nbgl_progress_bar_s nbgl_progress_bar_t
struct to represent a progress bar (PROGRESS_BAR type)
struct PACKED__ nbgl_keypad_s nbgl_keypad_t
struct to represent a keypad (KEYPAD type)
struct PACKED__ nbgl_mask_control_s nbgl_mask_control_t
struct PACKED__ nbgl_text_entry_s nbgl_text_entry_t
struct to represent a text entry area (TEXT_ENTRY type)
struct PACKED__ nbgl_keyboard_s nbgl_keyboard_t
struct to represent a keyboard (KEYBOARD type)
struct PACKED__ nbgl_image_s nbgl_image_t
struct to represent an image (IMAGE type)
struct PACKED__ nbgl_button_s nbgl_button_t
struct to represent a button (BUTTON type) that can contain a text and/or an icon
void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd)
This function draws a keyboard object.
#define NB_MAX_PAGES_WITH_DASHES
Definition nbgl_obj.h:182
void nbgl_objDrawKeypad(nbgl_keypad_t *kbd)
This function draws a keypad object.
struct PACKED__ nbgl_container_s nbgl_container_t
struct to represent a container (CONTAINER type)
@ PROGRESSIVE_INDICATOR
all dashes before active page are black
Definition nbgl_obj.h:388
struct PACKED__ nbgl_switch_s nbgl_switch_t
struct to represent a switch (size is fixed) (SWITCH type)
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
struct PACKED__ nbgl_spinner_s nbgl_spinner_t
struct to represent a "spinner", represented by the Ledger corners, in gray, with one of the corners ...
struct PACKED__ nbgl_image_file_s nbgl_image_file_t
struct to represent an image file object (IMAGE_FILE type) The source of the data is an image file wi...
struct PACKED__ nbgl_qrcode_s nbgl_qrcode_t
struct to represent a QR code (QR_CODE type), whose size is fixed
API to manage screens.
struct PACKED__ nbgl_screen_s nbgl_screen_t
struct to represent a screen (SCREEN type)
@ NBGL_DRAW_OBJ
@ NBGL_REFRESH_AREA
void nbgl_touchInit(bool fromUx)
Function to initialize the touch context.
Definition nbgl_touch.c:273
color_t
Definition nbgl_types.h:122
@ WHITE
Definition nbgl_types.h:126
@ DARK_GRAY
Definition nbgl_types.h:124
@ LIGHT_GRAY
Definition nbgl_types.h:125
@ BLACK
Definition nbgl_types.h:123
@ OFF_STATE
Definition nbgl_types.h:182
nbgl_post_refresh_t
Post refresh modes.
Definition nbgl_types.h:334
@ POST_REFRESH_FORCE_POWER_OFF
Force screen power off after refresh.
Definition nbgl_types.h:335
#define VERTICAL_MIRROR
Definition nbgl_types.h:82
uint8_t nbgl_color_map_t
Represents the color_map to be used for 2BPP image, or the foreground color for 1BPP image.
Definition nbgl_types.h:371
@ RADIUS_0_PIXELS
no radius (square angle)
Definition nbgl_types.h:357
@ VERTICAL
from top to bottom
Definition nbgl_types.h:191
#define MIN(x, y)
Definition nbgl_types.h:100
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
#define GZLIB_UNCOMPRESSED_CHUNK
size of gzlib uncompression buffer in bytes
Definition nbgl_types.h:287
@ TOP_MIDDLE
Definition nbgl_types.h:164
@ CENTER
Definition nbgl_types.h:167
@ BOTTOM_RIGHT
Definition nbgl_types.h:171
@ TOP_LEFT
Definition nbgl_types.h:163
@ NO_ALIGNMENT
used when parent container layout is used
Definition nbgl_types.h:162
@ BOTTOM_LEFT
Definition nbgl_types.h:169
@ LEFT_TOP
on outside left
Definition nbgl_types.h:172
@ LEFT_BOTTOM
on outside left
Definition nbgl_types.h:173
@ MID_RIGHT
Definition nbgl_types.h:168
@ RIGHT_TOP
on outside right
Definition nbgl_types.h:174
@ TOP_RIGHT
Definition nbgl_types.h:165
@ MID_LEFT
Definition nbgl_types.h:166
@ BOTTOM_MIDDLE
Definition nbgl_types.h:170
@ RIGHT_BOTTOM
on outside right
Definition nbgl_types.h:175
@ KEYPAD
Keypad.
Definition nbgl_types.h:149
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
Definition nbgl_types.h:139
@ IMAGE_FILE
Image file (with Ledger compression)
Definition nbgl_types.h:151
@ TEXT_ENTRY
area for entered text, only for Nanos
Definition nbgl_types.h:152
@ NB_OBJ_TYPES
Definition nbgl_types.h:154
@ SWITCH
Switch to turn on/off something.
Definition nbgl_types.h:143
@ RADIO_BUTTON
Indicator to inform whether something is on or off.
Definition nbgl_types.h:146
@ SPINNER
Spinner.
Definition nbgl_types.h:150
@ BUTTON
Rounded rectangle button with icon and/or text.
Definition nbgl_types.h:142
@ PROGRESS_BAR
horizontal bar to indicate progression of something (between 0% and 100%)
Definition nbgl_types.h:145
@ QR_CODE
QR Code.
Definition nbgl_types.h:147
@ PAGE_INDICATOR
horizontal bar to indicate position within pages
Definition nbgl_types.h:144
@ LINE
Vertical or Horizontal line.
Definition nbgl_types.h:140
@ KEYBOARD
Keyboard.
Definition nbgl_types.h:148
@ MASK_CONTROL
OS-specific object to enable/disable masked area.
Definition nbgl_types.h:153
@ CONTAINER
Empty container.
Definition nbgl_types.h:138
@ TEXT_AREA
Area to contain text line(s)
Definition nbgl_types.h:141
@ SCREEN
Main screen.
Definition nbgl_types.h:137
#define MAX(x, y)
Definition nbgl_types.h:103
#define NO_TRANSFORMATION
Definition nbgl_types.h:76
@ NBGL_BPP_1
1 bit per pixel
Definition nbgl_types.h:266
@ NBGL_BPP_2
2 bits per pixel
Definition nbgl_types.h:267
struct PACKED__ nbgl_area_s nbgl_area_t
Represents a rectangle area of the screen.
nbgl_refresh_mode_t
different modes of refresh for nbgl_refreshSpecial()
Definition nbgl_types.h:308
@ FULL_COLOR_CLEAN_REFRESH
to be used for lock screen display (cleaner but longer refresh)
Definition nbgl_types.h:311