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#ifdef HAVE_SERIALIZED_NBGL
23#include "nbgl_serialize.h"
24#include "os_io_seproxyhal.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 **********************/
142extern const char *get_ux_loc_string(uint32_t index);
143
144/**********************
145 * GLOBAL FUNCTIONS
146 **********************/
147
148static void compute_relativePosition(nbgl_obj_t *obj, nbgl_obj_t *prevObj)
149{
150 nbgl_container_t *parent = (nbgl_container_t *) (obj->parent);
151 // LOG_DEBUG(OBJ_LOGGER,"compute_relativePosition()\n");
152 // compute object absolute position thanks to layout/alignment
153 if (obj->alignment == NO_ALIGNMENT) {
154 LOG_DEBUG(
156 "compute_relativePosition() without align to, parent->layout = %d, prevObj = %p\n",
157 parent->layout,
158 prevObj);
159 // align to parent, depending of layout
160 if (parent->layout == VERTICAL) {
161 obj->rel_x0 = obj->alignmentMarginX;
162 if (prevObj != NULL) {
163 obj->rel_y0 = prevObj->rel_y0 + prevObj->area.height + obj->alignmentMarginY;
164 }
165 else {
166 obj->rel_y0 = obj->alignmentMarginY;
167 }
168 }
169 else { // HORIZONTAL
170 if (prevObj != NULL) {
171 obj->rel_x0 = prevObj->rel_x0 + prevObj->area.width + obj->alignmentMarginX;
172 }
173 else {
174 obj->rel_x0 = obj->alignmentMarginX;
175 }
176 obj->rel_y0 = obj->alignmentMarginY;
177 }
178 }
179 else {
180 nbgl_obj_t *alignToObj = obj->alignTo;
181 if (alignToObj == NULL) {
182 alignToObj = obj->parent;
183 LOG_DEBUG(OBJ_LOGGER, "compute_relativePosition() with align to parent\n");
184 }
185 else {
186 LOG_DEBUG(OBJ_LOGGER, "compute_relativePosition() with align to = %p\n", alignToObj);
187 }
188 // align to the given object, with the given constraints
189 if (alignToObj == obj->parent) {
190 // align inside if the reference is the parent
191 switch (obj->alignment) {
192 case TOP_LEFT:
193 obj->rel_x0 = obj->alignmentMarginX;
194 obj->rel_y0 = obj->alignmentMarginY;
195 break;
196 case TOP_MIDDLE:
197 obj->rel_x0
198 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
199 obj->rel_y0 = obj->alignmentMarginY;
200 break;
201 case TOP_RIGHT:
202 obj->rel_x0
203 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
204 obj->rel_y0 = obj->alignmentMarginY;
205 break;
206 case MID_LEFT:
207 obj->rel_x0 = obj->alignmentMarginX;
208 obj->rel_y0
209 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
210 break;
211 case CENTER:
212 obj->rel_x0
213 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
214 obj->rel_y0
215 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
216 break;
217 case MID_RIGHT:
218 obj->rel_x0
219 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
220 obj->rel_y0
221 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
222 break;
223 case BOTTOM_LEFT:
224 obj->rel_x0 = obj->alignmentMarginX;
225 obj->rel_y0
226 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
227 break;
228 case BOTTOM_MIDDLE:
229 obj->rel_x0
230 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
231 obj->rel_y0
232 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
233 break;
234 case BOTTOM_RIGHT:
235 obj->rel_x0
236 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
237 obj->rel_y0
238 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
239 break;
240 default:
241 // not supported
242 break;
243 }
244 }
245 else {
246 // align outside if the reference is a "brother"
247 switch (obj->alignment) {
248 case TOP_LEFT:
249 obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX;
250 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
251 break;
252 case TOP_MIDDLE:
253 obj->rel_x0 = alignToObj->rel_x0
254 + (alignToObj->area.width - obj->area.width) / 2
255 + obj->alignmentMarginX;
256 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
257 break;
258 case TOP_RIGHT:
259 obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)
260 - obj->alignmentMarginX;
261 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
262 break;
263
264 case LEFT_TOP:
265 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
266 obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY;
267 break;
268 case MID_LEFT:
269 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
270 obj->rel_y0 = alignToObj->rel_y0
271 + (alignToObj->area.height - obj->area.height) / 2
272 + obj->alignmentMarginY;
273 break;
274 case LEFT_BOTTOM:
275 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
276 obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height)
277 + obj->alignmentMarginY;
278 break;
279
280 case RIGHT_TOP:
281 obj->rel_x0
282 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
283 obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY;
284 break;
285 case MID_RIGHT:
286 obj->rel_x0
287 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
288 obj->rel_y0 = alignToObj->rel_y0
289 + (alignToObj->area.height - obj->area.height) / 2
290 + obj->alignmentMarginY;
291 break;
292 case RIGHT_BOTTOM:
293 obj->rel_x0
294 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
295 obj->rel_y0 = alignToObj->rel_y0 + (alignToObj->area.height - obj->area.height)
296 + obj->alignmentMarginY;
297 break;
298
299 case BOTTOM_LEFT:
300 obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX;
301 obj->rel_y0
302 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
303 break;
304 case BOTTOM_MIDDLE:
305 obj->rel_x0 = alignToObj->rel_x0
306 + (alignToObj->area.width - obj->area.width) / 2
307 + obj->alignmentMarginX;
308 obj->rel_y0
309 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
310 break;
311 case BOTTOM_RIGHT:
312 obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)
313 - obj->alignmentMarginX;
314 obj->rel_y0
315 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
316 break;
317 default:
318 // not supported
319 break;
320 }
321 }
322 }
323}
324
325static void compute_position(nbgl_obj_t *obj, nbgl_obj_t *prevObj)
326{
327 nbgl_container_t *parent = (nbgl_container_t *) (obj->parent);
328
329 compute_relativePosition(obj, prevObj);
330
331 if (parent == NULL) {
332 // HUGE issue
333 return;
334 }
335 // LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent.type = %d, parent->obj.area.x0 = %d,
336 // obj->rel_x0=%d\n",parent->type,parent->obj.area.x0,obj->rel_x0);
337 // LOG_DEBUG(OBJ_LOGGER,"compute_position(), parent->obj.area.y0 = %d,
338 // obj->rel_y0=%d\n",parent->obj.area.y0,obj->rel_y0);
339
340 obj->area.x0 = parent->obj.area.x0 + obj->rel_x0;
341 obj->area.y0 = parent->obj.area.y0 + obj->rel_y0;
342
343 if ((obj->area.x0 + obj->area.width) > SCREEN_WIDTH) {
345 "compute_position(), forbidden width, obj->type = %d, x0=%d, width=%d\n",
346 obj->type,
347 obj->area.x0,
348 obj->area.width);
349 }
350#ifdef HAVE_SE_TOUCH
351 if ((obj->area.y0 + obj->area.height) > SCREEN_HEIGHT) {
353 "compute_position(), forbidden height, obj->type = %d, y0=%d, height=%d\n",
354 obj->type,
355 obj->area.y0,
356 obj->area.height);
357 }
358#endif // HAVE_SE_TOUCH
359}
360
361static void draw_screen(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition)
362{
363 nbgl_area_t rectArea;
364
365 UNUSED(prevObj);
366 UNUSED(computePosition);
367
368 rectArea.backgroundColor = obj->obj.area.backgroundColor;
369 rectArea.x0 = obj->obj.area.x0;
370 rectArea.y0 = obj->obj.area.y0;
371 rectArea.width = obj->obj.area.width;
372 rectArea.height = obj->obj.area.height;
373 nbgl_frontDrawRect(&rectArea);
374}
375
376static void draw_container(nbgl_container_t *obj, nbgl_obj_t *prevObj, bool computePosition)
377{
378 if (computePosition) {
379 compute_position((nbgl_obj_t *) obj, prevObj);
380 }
382 "draw_container(), x0 = %d, y0 = %d, width = %d, height = %d\n",
383 obj->obj.area.x0,
384 obj->obj.area.y0,
385 obj->obj.area.width,
386 obj->obj.area.height);
387 // inherit background from parent
388 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
389 if (obj->forceClean) {
391 }
392}
393
394#ifdef HAVE_SE_TOUCH
403static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePosition)
404{
405 uint16_t textWidth = 0;
406 const char *text = NULL;
407#define ICON_TEXT_SPACE 12
408
409 if (computePosition) {
410 compute_position((nbgl_obj_t *) obj, prevObj);
411 }
413 "draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n",
414 obj->obj.area.x0,
415 obj->obj.area.y0,
416 obj->obj.area.width,
417 obj->obj.area.height);
418
419 // inherit background from parent
420 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
421 // draw the rounded corner rectangle if necessary
422 if ((obj->innerColor == obj->borderColor)
423 && (obj->innerColor != obj->obj.area.backgroundColor)) {
424 nbgl_drawRoundedRect((nbgl_area_t *) obj, obj->radius, obj->innerColor);
425 }
426 else {
428 (nbgl_area_t *) obj, obj->radius, 2, obj->innerColor, obj->borderColor);
429 }
430 // get the text of the button from the callback if not NULL
431 if (obj->onDrawCallback != NULL) {
432 obj->text = obj->onDrawCallback(obj->token);
433 }
434 text = obj->text;
435 // draw the text (right of the icon, with 8 pixels between them)
436 if (text != NULL) {
437 nbgl_area_t rectArea;
438 // Compute available with & height to display the text
439 rectArea.x0 = obj->obj.area.x0;
440 rectArea.y0 = obj->obj.area.y0;
441 // Only one line of text
442 rectArea.height = nbgl_getFontHeight(obj->fontId);
443 rectArea.y0 += (obj->obj.area.height - rectArea.height) / 2;
444 rectArea.width = obj->obj.area.width;
445 if (obj->icon != NULL) {
446 rectArea.x0 += obj->icon->width + ICON_TEXT_SPACE;
447 rectArea.width -= obj->icon->width + ICON_TEXT_SPACE;
448 }
449 // Compute the width & number of characters displayed on first line
450 uint16_t textLen;
451 nbgl_getTextMaxLenAndWidth(obj->fontId, text, rectArea.width, &textLen, &textWidth, true);
452
453#ifdef BUILD_SCREENSHOTS
454 store_string_infos(text, obj->fontId, &rectArea, true, 1, 1, false);
455#endif // BUILD_SCREENSHOTS
456
457 // Center the text, horizontally
458 if (textWidth < rectArea.width) {
459 rectArea.x0 += (rectArea.width - textWidth) / 2;
460 }
461 LOG_DEBUG(OBJ_LOGGER, "draw_button(), text = %s\n", text);
462 rectArea.backgroundColor = obj->innerColor;
463 nbgl_drawText(&rectArea, text, textLen, obj->fontId, obj->foregroundColor);
464 }
465 // draw the icon, if any
466 if (obj->icon != NULL) {
467 uint16_t iconX0, iconY0;
468 nbgl_area_t rectArea;
469
470 if (text != NULL) {
471 iconX0 = obj->obj.area.x0
472 + (obj->obj.area.width - (textWidth + obj->icon->width + ICON_TEXT_SPACE)) / 2;
473 }
474 else {
475 iconX0 = obj->obj.area.x0 + (obj->obj.area.width - obj->icon->width) / 2;
476 }
478 "draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n",
479 obj->obj.area.height,
480 obj->icon->height);
481 iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height) / 2;
482
483 rectArea.backgroundColor = obj->innerColor;
484 rectArea.x0 = iconX0;
485 rectArea.y0 = iconY0;
486 rectArea.width = obj->icon->width;
487 rectArea.height = obj->icon->height;
488 rectArea.bpp = obj->icon->bpp;
489
490 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->foregroundColor, obj->icon);
491 }
492}
493
502static void draw_line(nbgl_line_t *obj, nbgl_obj_t *prevObj, bool computePosition)
503{
504 nbgl_area_t rectArea;
505 if (computePosition) {
506 compute_position((nbgl_obj_t *) obj, prevObj);
507 }
508 LOG_DEBUG(OBJ_LOGGER, "draw_line(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
509 // inherit background from parent
510 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
512 "draw_line(), backgroundColor = %d, lineColor = %d\n",
513 obj->obj.area.backgroundColor,
514 obj->lineColor);
515 rectArea.x0 = obj->obj.area.x0;
516 rectArea.y0 = obj->obj.area.y0;
517 if (obj->direction == VERTICAL) {
518 rectArea.width = obj->obj.area.width = obj->thickness;
519 rectArea.backgroundColor = obj->lineColor;
520 rectArea.height = obj->obj.area.height;
521 nbgl_frontDrawRect(&rectArea);
522 }
523 else {
524 uint8_t mask;
525 if (obj->thickness == 1) {
526 mask = 0x1 << (obj->offset & 0x3);
527 }
528 else if (obj->thickness == 2) {
529 mask = 0x3 << ((obj->offset < 3) ? obj->offset : 2);
530 }
531 else if (obj->thickness == 3) {
532 mask = 0x7 << (obj->offset & 0x1);
533 }
534 else if (obj->thickness == 4) {
535 mask = 0xF;
536 }
537 else {
538 LOG_WARN(OBJ_LOGGER, "draw_line(), forbidden thickness = %d\n", obj->thickness);
539 return;
540 }
541 rectArea.width = obj->obj.area.width;
542 rectArea.height = obj->obj.area.height = VERTICAL_ALIGNMENT;
543 rectArea.backgroundColor = obj->obj.area.backgroundColor;
544 nbgl_frontDrawHorizontalLine(&rectArea, mask, obj->lineColor);
545 }
546}
547#else // HAVE_SE_TOUCH
556static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePosition)
557{
558 uint16_t textWidth = 0;
559 const char *text = NULL;
560#define ICON_TEXT_SPACE 2
561
562 if (computePosition) {
563 compute_position((nbgl_obj_t *) obj, prevObj);
564 }
566 "draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n",
567 obj->obj.area.x0,
568 obj->obj.area.y0,
569 obj->obj.area.width,
570 obj->obj.area.height);
571
572 // inherit background from parent
573 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
574 // draw the rounded corner rectangle if necessary
575 nbgl_drawRoundedRect((nbgl_area_t *) obj, obj->radius, obj->innerColor);
576
577 // get the text of the button from the callback if not NULL
578 if (obj->onDrawCallback != NULL) {
579 obj->text = obj->onDrawCallback(obj->token);
580 }
581 text = obj->text;
582 // draw the text (right of the icon, with ICON_TEXT_SPACE pixels between them)
583 if (text != NULL) {
584 nbgl_area_t rectArea;
585 // Compute available with & height to display the text
586 rectArea.x0 = obj->obj.area.x0;
587 rectArea.y0 = obj->obj.area.y0;
588 // Only one line of text is allowed
589 rectArea.height = nbgl_getFontHeight(obj->fontId);
590 rectArea.y0 += (obj->obj.area.height - rectArea.height) / 2;
591 rectArea.width = obj->obj.area.width;
592 if (obj->icon != NULL) {
593 rectArea.x0 += obj->icon->width + ICON_TEXT_SPACE;
594 rectArea.width -= obj->icon->width + ICON_TEXT_SPACE;
595 }
596 // Compute the width & number of characters displayed on first line
597 uint16_t textLen;
598 nbgl_getTextMaxLenAndWidth(obj->fontId, text, rectArea.width, &textLen, &textWidth, true);
599
600 // Center the text, horizontally
601 if (textWidth < rectArea.width) {
602 rectArea.x0 += (rectArea.width - textWidth) / 2;
603 }
604 LOG_DEBUG(OBJ_LOGGER, "draw_button(), text = %s\n", text);
605 rectArea.backgroundColor = obj->innerColor;
606 nbgl_drawText(&rectArea, text, textLen, obj->fontId, obj->foregroundColor);
607 }
608 // draw the icon, if any
609 if (obj->icon != NULL) {
610 uint16_t iconX0, iconY0;
611 nbgl_area_t rectArea;
612
613 if (text != NULL) {
614 iconX0 = obj->obj.area.x0
615 + (obj->obj.area.width - (textWidth + obj->icon->width + ICON_TEXT_SPACE)) / 2;
616 }
617 else {
618 iconX0 = obj->obj.area.x0 + (obj->obj.area.width - obj->icon->width) / 2;
619 }
621 "draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n",
622 obj->obj.area.height,
623 obj->icon->height);
624 iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height) / 2;
625
626 rectArea.backgroundColor = obj->innerColor;
627 rectArea.x0 = iconX0;
628 rectArea.y0 = iconY0;
629 rectArea.width = obj->icon->width;
630 rectArea.height = obj->icon->height;
631 rectArea.bpp = obj->icon->bpp;
632
633 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->foregroundColor, obj->icon);
634 }
635}
636#endif // HAVE_SE_TOUCH
637
638static void draw_image(nbgl_image_t *obj, nbgl_obj_t *prevObj, bool computePosition)
639{
640 const nbgl_icon_details_t *iconDetails;
641 nbgl_color_map_t colorMap;
642
643 // if buffer is NULL, let's try to call onDrawCallback, if not NULL, to get it
644 if (obj->buffer == NULL) {
645 if (obj->onDrawCallback != NULL) {
646 iconDetails = obj->onDrawCallback(obj->token);
647 }
648 else {
649 return;
650 }
651 }
652 else {
653 iconDetails = obj->buffer;
654 }
655 if (iconDetails == NULL) {
656 return;
657 }
658
659 // use dimension and bpp from the icon details
660 obj->obj.area.width = iconDetails->width;
661 obj->obj.area.height = iconDetails->height;
662 obj->obj.area.bpp = iconDetails->bpp;
663 if (computePosition) {
664 compute_position((nbgl_obj_t *) obj, prevObj);
665 }
666 LOG_DEBUG(OBJ_LOGGER, "draw_image(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
667 // inherit background from parent
668 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
669 if (obj->obj.area.bpp == NBGL_BPP_1) {
670 colorMap = obj->foregroundColor;
671 }
672 else if (obj->obj.area.bpp == NBGL_BPP_2) {
673 colorMap = ((WHITE << 6) | (LIGHT_GRAY << 4) | (DARK_GRAY << 2) | BLACK);
674 }
675 else {
676 colorMap = obj->foregroundColor;
677 }
678
679 nbgl_drawIcon((nbgl_area_t *) obj, obj->transformation, colorMap, iconDetails);
680}
681
682#ifdef HAVE_SE_TOUCH
683static void draw_switch(nbgl_switch_t *obj, nbgl_obj_t *prevObj, bool computePosition)
684{
685 nbgl_area_t rectArea;
686
687 // force dimensions
688 obj->obj.area.width = C_switch_60_40.width;
689 obj->obj.area.height = C_switch_60_40.height;
690 if (computePosition) {
691 compute_position((nbgl_obj_t *) obj, prevObj);
692 }
693 LOG_DEBUG(OBJ_LOGGER, "draw_switch(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
694
695 // inherit background from parent
696 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
697
698 rectArea.x0 = obj->obj.area.x0;
699 rectArea.y0 = obj->obj.area.y0;
700 rectArea.width = obj->obj.area.width;
701 rectArea.height = obj->obj.area.height;
702 rectArea.backgroundColor = obj->obj.area.backgroundColor;
703 rectArea.bpp = NBGL_BPP_1;
704 if (obj->state == OFF_STATE) {
705 nbgl_frontDrawImage(&rectArea, C_switch_60_40.bitmap, NO_TRANSFORMATION, obj->offColor);
706 }
707 else {
708 nbgl_frontDrawImage(&rectArea, C_switch_60_40.bitmap, VERTICAL_MIRROR, obj->onColor);
709 }
710}
711
712static void draw_radioButton(nbgl_radio_t *obj, nbgl_obj_t *prevObj, bool computePosition)
713{
714 nbgl_area_t rectArea;
715 const nbgl_icon_details_t *icon;
716 nbgl_color_map_t color_map;
717
718 // force dimensions
719 obj->obj.area.width = RADIO_WIDTH;
720 obj->obj.area.height = RADIO_HEIGHT;
721 if (computePosition) {
722 compute_position((nbgl_obj_t *) obj, prevObj);
723 }
725 "draw_radioButton(), x0 = %d, y0 = %d, state = %d\n",
726 obj->obj.area.x0,
727 obj->obj.area.y0,
728 obj->state);
729
730 // inherit background from parent
731 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
732
733 if (obj->state == OFF_STATE) {
734 icon = &RADIO_OFF_ICON;
735 color_map = obj->borderColor;
736 }
737 else {
738 icon = &RADIO_ON_ICON;
739 color_map = obj->activeColor;
740 }
741 rectArea.x0 = obj->obj.area.x0;
742 rectArea.y0 = obj->obj.area.y0;
743 rectArea.width = obj->obj.area.width;
744 rectArea.height = obj->obj.area.height;
745 rectArea.backgroundColor = obj->obj.area.backgroundColor;
746 rectArea.bpp = icon->bpp;
747 nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, color_map, icon);
748}
749#endif // HAVE_SE_TOUCH
750
758static void draw_progressBar(nbgl_progress_bar_t *obj, nbgl_obj_t *prevObj, bool computePosition)
759{
760#ifdef HAVE_SE_TOUCH
761
762 uint8_t stroke = 3; // 3 pixels for border
763
764 if (computePosition) {
765 compute_position((nbgl_obj_t *) obj, prevObj);
766 }
767 // force vertical position to be aligned until using nbgl_drawLine()
768 obj->obj.area.y0 &= ~(VERTICAL_ALIGNMENT - 1);
770 "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n",
771 obj->obj.area.x0,
772 obj->obj.area.y0,
773 obj->state);
774
775 // inherit background from parent
776 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
777
778 if (obj->partialRedraw == false) {
779 // Case of progress bar full draw
780 if (obj->withBorder) {
783 stroke,
784 obj->obj.area.backgroundColor,
785 obj->foregroundColor);
786 }
787 else {
789 (nbgl_area_t *) obj, RADIUS_0_PIXELS, obj->obj.area.backgroundColor);
790 }
791 // also reset previous width to be sure to clean up everything
792 obj->previousWidth = 0;
793 }
794 // Setup bar draw
795 nbgl_area_t barArea;
796 uint16_t barWidth = ((obj->state * obj->obj.area.width)) / 100;
797 int barDiffWith = barWidth - obj->previousWidth;
798 color_t barColor;
799 memcpy(&barArea, &obj->obj.area, sizeof(nbgl_area_t));
800
801 if (barDiffWith > 0) {
802 // Drawing "forward"
803 barArea.x0 = obj->obj.area.x0 + obj->previousWidth;
804 barArea.width = barDiffWith;
805 barColor = obj->foregroundColor;
806 }
807 else if (barDiffWith < 0) {
808 // Drawing "backward"
809 barArea.x0 = obj->obj.area.x0 + obj->previousWidth + barDiffWith;
810 barArea.width = -barDiffWith;
811 barColor = obj->obj.area.backgroundColor;
812 }
813
814 if (barDiffWith != 0) {
815 nbgl_drawRoundedRect((nbgl_area_t *) &barArea, RADIUS_0_PIXELS, barColor);
816 }
817
818 // reset partialRedraw to be sure that in case of full redraw of the screen we redraw the
819 // full bar
820 if (obj->partialRedraw == true) {
821 obj->partialRedraw = false;
822 }
823 obj->previousWidth = barWidth;
824
825 extendRefreshArea(&barArea);
826 objRefreshAreaDone = true;
827#else // HAVE_SE_TOUCH
828 uint8_t stroke = 1; // 1 pixels for border
829 uint16_t levelWidth;
830
831 if (computePosition) {
832 compute_position((nbgl_obj_t *) obj, prevObj);
833 }
835 "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n",
836 obj->obj.area.x0,
837 obj->obj.area.y0,
838 obj->state);
839
840 // inherit background from parent
841 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
842
843 // draw external part if necessary
844 if (obj->withBorder) {
846 RADIUS_3_PIXELS,
847 stroke,
848 obj->obj.area.backgroundColor,
849 obj->foregroundColor);
850 }
851 else {
852 nbgl_drawRoundedRect((nbgl_area_t *) obj, RADIUS_3_PIXELS, obj->obj.area.backgroundColor);
853 }
854 // draw level
855 levelWidth = MIN((obj->obj.area.width - 2) * obj->state / 100, (obj->obj.area.width - 2));
856 if (levelWidth > 0) {
857 nbgl_area_t rectArea;
858 rectArea.width = levelWidth;
859 rectArea.height = obj->obj.area.height - 2;
860 rectArea.backgroundColor = obj->foregroundColor;
861 rectArea.bpp = NBGL_BPP_1;
862 rectArea.x0 = obj->obj.area.x0 + 1;
863 rectArea.y0 = obj->obj.area.y0 + 1;
864
865 nbgl_frontDrawRect(&rectArea);
866 }
867#endif // HAVE_SE_TOUCH
868}
869
870#ifdef HAVE_SE_TOUCH
879static void draw_pageIndicator(nbgl_page_indicator_t *obj,
880 nbgl_obj_t *prevObj,
881 bool computePosition)
882{
883 nbgl_area_t rectArea;
884 uint16_t dashWidth;
885
886 // display nothing if less than two pages
887 if (obj->nbPages < 2) {
888 return;
889 }
890
891 if (obj->nbPages <= NB_MAX_PAGES_WITH_DASHES) {
892 int i;
893 // force height
894 obj->obj.area.height = 4;
895
896 if (computePosition) {
897 compute_position((nbgl_obj_t *) obj, prevObj);
898 }
900 "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n",
901 obj->obj.area.x0,
902 obj->obj.area.y0,
903 obj->activePage,
904 obj->nbPages);
905
906 // inherit background from parent
907 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
908
909 dashWidth = (obj->obj.area.width - ((obj->nbPages - 1) * INTER_DASHES)) / obj->nbPages;
910 rectArea.x0 = obj->obj.area.x0;
911 rectArea.y0 = obj->obj.area.y0;
912 rectArea.width = dashWidth;
913 rectArea.height = obj->obj.area.height;
914 rectArea.backgroundColor = obj->obj.area.backgroundColor;
915 rectArea.bpp = NBGL_BPP_1;
916 // draw dashes
917 for (i = 0; i < obj->activePage; i++) {
919 &rectArea, 0xF, (obj->style == PROGRESSIVE_INDICATOR) ? BLACK : LIGHT_GRAY);
920 rectArea.x0 += dashWidth + INTER_DASHES;
921 }
922 nbgl_frontDrawHorizontalLine(&rectArea, 0xF, BLACK);
923 rectArea.x0 += dashWidth + INTER_DASHES;
924 i++;
925
926 for (; i < obj->nbPages; i++) {
928 rectArea.x0 += dashWidth + INTER_DASHES;
929 }
930 }
931 else {
932 char navText[11]; // worst case is "ccc of nnn"
933
934 SPRINTF(navText, "%d of %d", obj->activePage + 1, obj->nbPages);
935 // force height
936 obj->obj.area.height = nbgl_getFontHeight(SMALL_REGULAR_FONT);
937 // the width must be at least 80
938 obj->obj.area.width = nbgl_getTextWidth(SMALL_REGULAR_FONT, navText);
939
940 if (computePosition) {
941 compute_position((nbgl_obj_t *) obj, prevObj);
942 }
944 "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n",
945 obj->obj.area.x0,
946 obj->obj.area.y0,
947 obj->activePage,
948 obj->nbPages);
949
950 // inherit background from parent
951 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
952
953 // draw active page
954 rectArea.x0 = obj->obj.area.x0;
955 rectArea.y0 = obj->obj.area.y0;
956 rectArea.width = obj->obj.area.width;
957 rectArea.height = obj->obj.area.height;
958 rectArea.backgroundColor = obj->obj.area.backgroundColor;
959 rectArea.bpp = NBGL_BPP_1;
960 nbgl_drawText(&rectArea, navText, strlen(navText), SMALL_REGULAR_FONT, DARK_GRAY);
961 }
962}
963#endif // HAVE_SE_TOUCH
964
973static void draw_textArea(nbgl_text_area_t *obj, nbgl_obj_t *prevObj, bool computePosition)
974{
975 nbgl_area_t rectArea;
976 uint16_t textWidth, fontHeight, lineHeight, textHeight, midHeight;
977 uint8_t line, nbLines;
978 const char *text;
979 nbgl_font_id_e fontId = obj->fontId;
980
981 if (computePosition) {
982 compute_position((nbgl_obj_t *) obj, prevObj);
983 }
984 // get the text of the button from the callback if not NULL
985 if (obj->onDrawCallback != NULL) {
986 obj->text = obj->onDrawCallback(obj->token);
987 }
988 text = obj->text;
989 if (text == NULL) {
990 return;
991 }
992
993 LOG_DEBUG(
995 "draw_textArea(), wrapping = %d, x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n",
996 obj->wrapping,
997 obj->obj.area.x0,
998 obj->obj.area.y0,
999 obj->obj.area.width,
1000 obj->obj.area.height,
1001 text);
1002
1003 // inherit background from parent
1004 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1005
1006 // draw background to make sure it's clean
1007#ifdef SCREEN_SIZE_NANO
1008 if (obj->style == INVERTED_COLORS) {
1009 obj->obj.area.backgroundColor = WHITE;
1010 rectArea.backgroundColor = BLACK;
1011 }
1012 else
1013#endif // SCREEN_SIZE_NANO
1014 {
1015 // inherit background from parent
1016 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1017 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1018 }
1019 rectArea.x0 = obj->obj.area.x0;
1020 rectArea.y0 = obj->obj.area.y0;
1021 rectArea.width = obj->obj.area.width;
1022 rectArea.height = obj->obj.area.height;
1023#ifdef SCREEN_SIZE_NANO
1024 if (obj->style == INVERTED_COLORS) {
1025 nbgl_drawRoundedRect(&rectArea, RADIUS_1_PIXEL, WHITE);
1026 }
1027 else
1028#endif // SCREEN_SIZE_NANO
1029 {
1030 nbgl_frontDrawRect(&rectArea);
1031 }
1032
1033 fontHeight = nbgl_getFontHeight(fontId);
1034 lineHeight = nbgl_getFontLineHeight(fontId);
1035 // special case of autoHideLongLine, when the text is too long for a line, draw '...' at the
1036 // beginning
1037 if (obj->autoHideLongLine == true) {
1038#ifdef BUILD_SCREENSHOTS
1039 nbgl_getTextNbLinesInWidth(fontId, text, obj->obj.area.width, obj->wrapping);
1040 store_string_infos(text,
1041 fontId,
1042 &obj->obj.area,
1043 obj->wrapping,
1044 last_nb_lines,
1045 last_nb_pages,
1046 last_bold_state);
1047#endif // BUILD_SCREENSHOTS
1048 textWidth = nbgl_getSingleLineTextWidth(fontId, text);
1049 if (textWidth > obj->obj.area.width) {
1050 uint16_t lineWidth, lineLen;
1051 uint16_t dotsWidth;
1052
1053 dotsWidth = nbgl_getTextWidth(fontId, "...");
1054 rectArea.x0 = obj->obj.area.x0;
1055 rectArea.y0 = obj->obj.area.y0 + (obj->obj.area.height - fontHeight) / 2;
1056 rectArea.width = dotsWidth;
1057 nbgl_drawText(&rectArea, "...", 3, fontId, obj->textColor);
1058 // then draw the end of text
1060 fontId, text, obj->obj.area.width - dotsWidth, &lineLen, &lineWidth);
1061 rectArea.x0 += dotsWidth;
1062 rectArea.width = lineWidth;
1063 nbgl_drawText(&rectArea,
1064 &text[nbgl_getTextLength(text) - lineLen],
1065 lineLen,
1066 obj->fontId,
1067 obj->textColor);
1068 return;
1069 }
1070 }
1071
1072 // get nb lines in the given width (depending of wrapping)
1073 nbLines = nbgl_getTextNbLinesInWidth(fontId, text, obj->obj.area.width, obj->wrapping);
1074#ifdef BUILD_SCREENSHOTS
1075 store_string_infos(
1076 text, fontId, &obj->obj.area, obj->wrapping, last_nb_lines, last_nb_pages, last_bold_state);
1077#endif // BUILD_SCREENSHOTS
1078 // saturate nb lines if nbMaxLines is greater than 0
1079 if ((obj->nbMaxLines > 0) && (obj->nbMaxLines < nbLines)) {
1080 nbLines = obj->nbMaxLines;
1081 }
1082
1083 textHeight = (nbLines - 1) * lineHeight + fontHeight;
1084
1085 midHeight = (obj->obj.area.height - textHeight) / 2;
1086#ifdef SCREEN_SIZE_NANO
1087 if (obj->style == INVERTED_COLORS) {
1088 midHeight--;
1089 }
1090#endif // SCREEN_SIZE_NANO
1091
1092 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1093 rectArea.height = fontHeight;
1094 // draw each line
1095 for (line = 0; line < nbLines; line++) {
1096 uint16_t lineWidth, lineLen;
1097
1099 fontId, text, obj->obj.area.width, &lineLen, &lineWidth, obj->wrapping);
1100 if (obj->textAlignment == MID_LEFT) {
1101 rectArea.x0 = obj->obj.area.x0;
1102 }
1103 else if (obj->textAlignment == CENTER) {
1104 rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - lineWidth) / 2;
1105 }
1106 else if (obj->textAlignment == MID_RIGHT) {
1107 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - lineWidth;
1108 }
1109 else {
1110 LOG_FATAL(OBJ_LOGGER, "Forbidden obj->textAlignment = %d\n", obj->textAlignment);
1111 }
1112 rectArea.y0 = obj->obj.area.y0 + midHeight + line * lineHeight;
1113 rectArea.width = lineWidth;
1114
1116 "draw_textArea(), [%s] line %d, lineLen %d lineWidth = %d, obj.area.height = %d, "
1117 "textHeight = %d, nbMaxLines = %d, wrapping = %d\n",
1118 text,
1119 line,
1120 lineLen,
1121 lineWidth,
1122 obj->obj.area.height,
1123 textHeight,
1124 obj->nbMaxLines,
1125 obj->wrapping);
1126 if ((obj->nbMaxLines == 0) || (line < (obj->nbMaxLines - 1))) {
1127 fontId = nbgl_drawText(&rectArea, text, lineLen, fontId, obj->textColor);
1128 }
1129 else {
1130#ifdef HAVE_SE_TOUCH
1131 uint16_t dotsWidth = nbgl_getSingleLineTextWidth(obj->fontId, "...");
1132 // for last chunk, if nbMaxLines is used, replace the 3 last chars by "..."
1133 // draw line except 3 last chars
1134 if ((lineWidth + dotsWidth) >= obj->obj.area.width) {
1135 lineLen -= 3;
1136 }
1137 nbgl_drawText(&rectArea, text, lineLen, obj->fontId, obj->textColor);
1138 rectArea.x0 += nbgl_getSingleLineTextWidthInLen(obj->fontId, text, lineLen);
1139
1140 // draw "..." after the other chars
1141 rectArea.width = dotsWidth;
1142 nbgl_drawText(&rectArea, "...", 3, obj->fontId, obj->textColor);
1143#else // HAVE_SE_TOUCH
1144 nbgl_drawText(&rectArea, text, lineLen, fontId, obj->textColor);
1145#endif // HAVE_SE_TOUCH
1146 return;
1147 }
1148 text += lineLen;
1149 /* skip trailing \n */
1150 if (*text == '\n') {
1151 text++;
1152 }
1153 }
1154}
1155
1156#ifdef NBGL_QRCODE
1165static void draw_qrCode(nbgl_qrcode_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1166{
1167 nbgl_area_t rectArea;
1168
1169 if (computePosition) {
1170 compute_position((nbgl_obj_t *) obj, prevObj);
1171 }
1172 // be sure to align vertical position on multiple of 4
1173 obj->obj.area.y0 &= ~0x3;
1175 "draw_qrCode(), x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n",
1176 obj->obj.area.x0,
1177 obj->obj.area.y0,
1178 obj->obj.area.width,
1179 obj->obj.area.height,
1180 obj->text);
1181
1182 // inherit background from parent
1183 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1184
1185 rectArea.x0 = obj->obj.area.x0;
1186 rectArea.y0 = obj->obj.area.y0;
1187 rectArea.width = obj->obj.area.width;
1188 rectArea.height = obj->obj.area.height;
1189 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1190 nbgl_drawQrCode(&rectArea, obj->version, obj->text, obj->foregroundColor);
1191}
1192#endif // NBGL_QRCODE
1193
1194#ifdef NBGL_KEYBOARD
1202static void draw_keyboard(nbgl_keyboard_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1203{
1204#ifndef HAVE_SE_TOUCH
1205 obj->obj.area.width = KEYBOARD_WIDTH;
1206 obj->obj.area.height = KEYBOARD_KEY_HEIGHT;
1207#endif // HAVE_SE_TOUCH
1208
1209 if (computePosition) {
1210 compute_position((nbgl_obj_t *) obj, prevObj);
1211 }
1212 LOG_DEBUG(
1213 OBJ_LOGGER, "draw_keyboard(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1214
1215 // inherit background from parent
1216 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1217
1219}
1220#endif // NBGL_KEYBOARD
1221
1222#ifdef NBGL_KEYPAD
1230static void draw_keypad(nbgl_keypad_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1231{
1232#ifndef HAVE_SE_TOUCH
1233 obj->obj.area.height = KEYPAD_HEIGHT;
1234 obj->obj.area.width = KEYPAD_WIDTH;
1235#endif // HAVE_SE_TOUCH
1236
1237 if (computePosition) {
1238 compute_position((nbgl_obj_t *) obj, prevObj);
1239 }
1240 obj->obj.area.y0 &= ~0x3;
1241 LOG_DEBUG(OBJ_LOGGER, "draw_keypad(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1242
1243 // inherit background from parent
1244 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1245
1246 nbgl_objDrawKeypad(obj);
1247}
1248#endif // NBGL_KEYPAD
1249
1250#ifdef HAVE_SE_TOUCH
1258static void draw_spinner(nbgl_spinner_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1259{
1260 nbgl_area_t rectArea;
1261 color_t foreColor;
1262
1263 obj->obj.area.width = SPINNER_WIDTH;
1264 obj->obj.area.height = SPINNER_HEIGHT;
1265
1266 if (computePosition) {
1267 compute_position((nbgl_obj_t *) obj, prevObj);
1268 }
1269 obj->obj.area.y0 &= ~0x3;
1270 LOG_DEBUG(OBJ_LOGGER, "draw_spinner(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1271
1272 // inherit background from parent
1273 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1274 // foreground color is the opposite of background one
1275 foreColor = (obj->obj.area.backgroundColor == WHITE) ? BLACK : WHITE;
1276
1277 rectArea.bpp = NBGL_BPP_1;
1278 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1279 // if position is OxFF, it means "fixed" so draw 4 corners
1280 if (obj->position == 0xFF) {
1281 // draw horizontal segments
1282 rectArea.x0 = obj->obj.area.x0;
1283 rectArea.y0 = obj->obj.area.y0;
1284 rectArea.width = 20;
1285 rectArea.height = 4;
1286 nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top left
1287 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1288 nbgl_frontDrawHorizontalLine(&rectArea, 0x7, foreColor); // top right
1289 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1290 nbgl_frontDrawHorizontalLine(&rectArea, 0xE, foreColor); // bottom right
1291 rectArea.x0 = obj->obj.area.x0;
1292 nbgl_frontDrawHorizontalLine(&rectArea, 0xE, foreColor); // bottom left
1293 // draw vertical segments
1294 rectArea.x0 = obj->obj.area.x0;
1295 rectArea.y0 = obj->obj.area.y0;
1296 rectArea.width = 3;
1297 rectArea.height = 12;
1298 rectArea.backgroundColor = foreColor;
1299 nbgl_frontDrawRect(&rectArea); // top left
1300 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1301 nbgl_frontDrawRect(&rectArea); // top right
1302 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1303 nbgl_frontDrawRect(&rectArea); // bottom right
1304 rectArea.x0 = obj->obj.area.x0;
1305 nbgl_frontDrawRect(&rectArea); // bottom left
1306 }
1307 else {
1308 uint8_t mask;
1309 // clean up full rectangle
1310 rectArea.x0 = obj->obj.area.x0;
1311 rectArea.y0 = obj->obj.area.y0;
1312 rectArea.width = obj->obj.area.width;
1313 rectArea.height = obj->obj.area.height;
1314 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1315 nbgl_frontDrawRect(&rectArea); // top left
1316
1317 // draw horizontal segment in foreColor
1318 rectArea.width = 20;
1319 rectArea.height = 4;
1320 switch (obj->position) {
1321 case 0: // top left corner
1322 rectArea.x0 = obj->obj.area.x0;
1323 rectArea.y0 = obj->obj.area.y0;
1324 mask = 0x7;
1325 break;
1326 case 1: // top right
1327 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1328 rectArea.y0 = obj->obj.area.y0;
1329 mask = 0x7;
1330 break;
1331 case 2: // bottom right
1332 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1333 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1334 mask = 0xE;
1335 break;
1336 case 3: // bottom left
1337 rectArea.x0 = obj->obj.area.x0;
1338 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1339 mask = 0xE;
1340 break;
1341 default:
1342 return;
1343 }
1344 nbgl_frontDrawHorizontalLine(&rectArea, mask, foreColor);
1345
1346 // draw vertical segment in foreColor
1347 rectArea.width = 3;
1348 rectArea.height = 12;
1349 rectArea.backgroundColor = foreColor;
1350 switch (obj->position) {
1351 case 0: // top left corner
1352 rectArea.x0 = obj->obj.area.x0;
1353 rectArea.y0 = obj->obj.area.y0;
1354 break;
1355 case 1: // top right corner
1356 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1357 rectArea.y0 = obj->obj.area.y0;
1358 break;
1359 case 2: // bottom right corner
1360 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1361 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1362 break;
1363 case 3: // bottom left corner
1364 rectArea.x0 = obj->obj.area.x0;
1365 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1366 break;
1367 default:
1368 return;
1369 }
1370 nbgl_frontDrawRect(&rectArea);
1371 }
1372}
1373
1374#else // HAVE_SE_TOUCH
1375
1383static void draw_textEntry(nbgl_text_entry_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1384{
1385 nbgl_area_t rectArea;
1386 int textLen = strlen(obj->text);
1387 uint32_t offsetX;
1388
1389 if (computePosition) {
1390 compute_position((nbgl_obj_t *) obj, prevObj);
1391 }
1392
1394 "draw_textEntry(), x0 = %d, y0 = %d, width = %d, height = %d\n",
1395 obj->obj.area.x0,
1396 obj->obj.area.y0,
1397 obj->obj.area.width,
1398 obj->obj.area.height);
1399
1400 // draw background to make sure it's clean
1401 obj->obj.area.backgroundColor = WHITE;
1402 rectArea.backgroundColor = BLACK;
1403 rectArea.x0 = obj->obj.area.x0;
1404 rectArea.y0 = obj->obj.area.y0;
1405 rectArea.width = obj->obj.area.width;
1406 rectArea.height = obj->obj.area.height;
1407 rectArea.bpp = NBGL_BPP_1;
1408 nbgl_drawRoundedRect(&rectArea, RADIUS_3_PIXELS, WHITE);
1409
1410 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1411 rectArea.height = nbgl_getFontHeight(obj->fontId);
1412 if (obj->nbChars > NB_MAX_LETTERS) {
1413 return;
1414 }
1415 offsetX = (obj->obj.area.width - (obj->nbChars * 10)) / 2;
1416 // draw each of the nb chars
1417 for (int i = 0; i < obj->nbChars; i++) {
1418 char digit;
1419 rectArea.x0 = obj->obj.area.x0 + offsetX + (i * 10);
1420 rectArea.y0 = obj->obj.area.y0 - 2;
1421 rectArea.width = 8;
1422 if (textLen < obj->nbChars) {
1423 if (i < textLen) {
1424 digit = obj->text[i];
1425 }
1426 else {
1427 digit = '_';
1428 }
1429 }
1430 else {
1431 // first char is '..' to notify continuing
1432 if (i == 0) {
1434 continue;
1435 }
1436 else if (i < (obj->nbChars - 1)) {
1437 digit = obj->text[textLen - obj->nbChars + 1 + i];
1438 }
1439 else {
1440 digit = '_';
1441 }
1442 }
1444 }
1445}
1446#endif // HAVE_SE_TOUCH
1447
1455static void draw_image_file(nbgl_image_file_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1456{
1457 if (obj->buffer == NULL) {
1458 return;
1459 }
1460 if (computePosition) {
1461 compute_position((nbgl_obj_t *) obj, prevObj);
1462 }
1463
1464 LOG_DEBUG(
1465 OBJ_LOGGER, "draw_image_file(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1466 obj->obj.area.backgroundColor = WHITE;
1467 nbgl_frontDrawImageFile((nbgl_area_t *) obj, obj->buffer, BLACK, ramBuffer);
1468}
1469
1470#ifdef NBGL_MASKING
1471static void draw_mask_control(nbgl_mask_control_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1472{
1473 if (computePosition) {
1474 compute_position((nbgl_obj_t *) obj, prevObj);
1475 }
1476
1477 if (obj->enableMasking) {
1478 nbgl_frontControlAreaMasking(obj->maskIndex, &obj->obj.area);
1479 }
1480 else {
1481 nbgl_frontControlAreaMasking(obj->maskIndex, NULL);
1482 }
1483}
1484#endif // NBGL_MASKING
1485
1493static void draw_object(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1494{
1495 LOG_DEBUG(OBJ_LOGGER, "draw_object() obj->type = %d, prevObj = %p\n", obj->type, prevObj);
1496 objRefreshAreaDone = false;
1497 if ((obj->type < NB_OBJ_TYPES) && (draw_functions[obj->type] != NULL)) {
1498 if ((obj->type != SCREEN) && (obj->parent == NULL)) {
1499 LOG_WARN(OBJ_LOGGER, "object with type [%d] has not parent\n", obj->type);
1500 return;
1501 }
1502 draw_function_t func = (draw_function_t) PIC(draw_functions[obj->type]);
1503 func(obj, prevObj, computePosition);
1504 }
1505 else {
1506 LOG_WARN(OBJ_LOGGER, "Not existing object type [%d]\n", obj->type);
1507 return;
1508 }
1509
1510#ifdef HAVE_SERIALIZED_NBGL
1511 io_seproxyhal_send_nbgl_serialized(NBGL_DRAW_OBJ, obj);
1512#endif
1513 if (!objRefreshAreaDone) {
1514 extendRefreshArea(&obj->area);
1515 }
1516}
1517
1527static void draw_obj_and_chidren(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition)
1528{
1529 uint8_t i = 0;
1530 LOG_DEBUG(OBJ_LOGGER, "draw_obj_and_chidren(): obj = %p\n", obj);
1531 // draw the object itself
1532 draw_object(obj, prevObj, computePosition);
1533
1534 if ((obj->type == SCREEN) || (obj->type == CONTAINER)) {
1535 nbgl_container_t *container = (nbgl_container_t *) obj;
1536 nbgl_obj_t *prev = NULL;
1537 LOG_DEBUG(
1538 OBJ_LOGGER, "draw_obj_and_chidren(): container->children = %p\n", container->children);
1539 // draw the children, if any
1540 if (container->children != NULL) {
1541 for (i = 0; i < container->nbChildren; i++) {
1542 nbgl_obj_t *current = container->children[i];
1543 if (current != NULL) {
1544 current->parent = (nbgl_obj_t *) container;
1545 draw_obj_and_chidren(current, prev, true);
1546 if (current->alignTo == NULL) {
1547 prev = current;
1548 }
1549 }
1550 }
1551 }
1552 }
1553}
1554
1561static void extendRefreshArea(nbgl_area_t *area)
1562{
1563 int16_t x1, y1; // bottom right corner
1564 x1 = refreshArea.x0 + refreshArea.width;
1565 y1 = refreshArea.y0 + refreshArea.height;
1566
1567 // if obj top-left is on left of current top-left corner, move top-left corner
1568 if (area->x0 < refreshArea.x0) {
1569 // No negative coordinates
1570 refreshArea.x0 = MAX(0, area->x0);
1571 }
1572 // if obj bottom-right is on right of current bottom-right corner, move bottom-right corner
1573 if (((area->x0 + area->width) > x1) || (refreshArea.width == 0)) {
1574 // Not beyond width
1575 x1 = MIN(SCREEN_WIDTH, area->x0 + area->width);
1576 }
1577 // if obj top-left is on top of current top-left corner, move top-left corner
1578 if (area->y0 < refreshArea.y0) {
1579 // No negative coordinates and align on lower multiple of alignment
1580 refreshArea.y0 = MAX(0, area->y0) & ~(VERTICAL_ALIGNMENT - 1);
1581 }
1582 // if obj bottom-right is on bottom of current bottom-right corner, move bottom-right corner
1583 if (((area->y0 + area->height) > y1) || (refreshArea.height == 0)) {
1584 // Not beyond height
1585 y1 = MIN(SCREEN_HEIGHT, area->y0 + area->height);
1586 // align on upper multiple of alignment
1587 y1 = (y1 + (VERTICAL_ALIGNMENT - 1)) & ~(VERTICAL_ALIGNMENT - 1);
1588 }
1589
1590 // sanity check
1591 if (x1 > SCREEN_WIDTH) {
1593 "extendRefreshArea: Impossible area x0 = %d width %d\n",
1594 refreshArea.x0,
1595 refreshArea.width);
1596 }
1597 if (y1 > SCREEN_HEIGHT) {
1598#ifdef HAVE_SE_TOUCH
1600 "extendRefreshArea: Impossible area y0 = %d height %d\n",
1601 refreshArea.y0,
1602 refreshArea.height);
1603#else // HAVE_SE_TOUCH
1604 y1 = SCREEN_HEIGHT;
1605#endif // HAVE_SE_TOUCH
1606 }
1607 // recompute width and height
1608 refreshArea.width = x1 - refreshArea.x0;
1609 refreshArea.height = y1 - refreshArea.y0;
1610
1611 // revaluate area bpp
1612 if (area->bpp > refreshArea.bpp) {
1613 refreshArea.bpp = area->bpp;
1614 }
1615}
1616
1623{
1624 bool computePosition = false;
1625 bool fromApp;
1626
1627 LOG_DEBUG(OBJ_LOGGER, "nbgl_objDraw(): obj = %p\n", obj);
1628 // check whether it's necessary to compute position, and if this object belongs to
1629 // an Application screen
1630 if (obj->type == SCREEN) {
1631 // always compute position for screen and all sub-objects
1632 computePosition = true;
1633 fromApp = !(((nbgl_screen_t *) obj)->isUxScreen);
1634 }
1635 else {
1636 nbgl_obj_t *parent = obj;
1637 // search screen in parenthood
1638 while (parent->parent != NULL) {
1639 parent = parent->parent;
1640 }
1641 if (parent->type == SCREEN) {
1642 fromApp = !(((nbgl_screen_t *) parent)->isUxScreen);
1643 }
1644 else {
1645 // should never happen
1646 fromApp = false;
1647 }
1648 }
1649 // actually draw the object and its children, if it is allowed
1650 if (objDrawingDisabled && fromApp) {
1651 return;
1652 }
1653 draw_obj_and_chidren(obj, NULL, computePosition);
1654}
1655
1665
1672{
1673 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1674 return;
1675 }
1676
1679 "nbgl_refreshSpecial(), x0,y0 = [%d, %d], w,h = [%d, %d]\n",
1680 refreshArea.x0,
1681 refreshArea.y0,
1682 refreshArea.width,
1683 refreshArea.height);
1685}
1686
1688{
1689 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1690 return;
1691 }
1692
1693 nbgl_frontRefreshArea(&refreshArea, mode, post_refresh);
1695 "nbgl_refreshSpecialNoPoff(), x0,y0 = [%d, %d], w,h = [%d, %d]\n",
1696 refreshArea.x0,
1697 refreshArea.y0,
1698 refreshArea.width,
1699 refreshArea.height);
1701}
1702
1708{
1709 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1710 return false;
1711 }
1712 return true;
1713}
1714
1720{
1721#ifdef HAVE_SERIALIZED_NBGL
1722 io_seproxyhal_send_nbgl_serialized(NBGL_REFRESH_AREA, (nbgl_obj_t *) &refreshArea);
1723#endif
1724 refreshArea.x0 = SCREEN_WIDTH - 1;
1725 refreshArea.width = 0;
1726 refreshArea.y0 = SCREEN_HEIGHT - 1;
1727 refreshArea.height = 0;
1728 refreshArea.bpp = NBGL_BPP_2;
1729}
1730
1737{
1738 // init area to the smallest size
1740 objDrawingDisabled = false;
1741#ifdef HAVE_SE_TOUCH
1742 nbgl_touchInit(false);
1743#endif
1744}
1745
1751void nbgl_objAllowDrawing(bool enable)
1752{
1753 objDrawingDisabled = !enable;
1754}
1755
1762{
1763 return ramBuffer;
1764}
1765
1772{
1773 nbgl_obj_t *parent = obj;
1774 // search screen in parenthood
1775 while (parent->parent != NULL) {
1776 parent = parent->parent;
1777 }
1778 if (parent->type == SCREEN) {
1779 return (((nbgl_screen_t *) parent)->isUxScreen);
1780 }
1781 else {
1782 // should never happen
1783 return true;
1784 }
1785}
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:1622
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
Definition nbgl_obj.c:1661
void nbgl_refreshReset(void)
This functions resets all changes since the last refresh.
Definition nbgl_obj.c:1719
void nbgl_objAllowDrawing(bool enable)
This functions enables or disables drawing/refresh for all further calls.
Definition nbgl_obj.c:1751
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:1671
bool nbgl_objIsUx(nbgl_obj_t *obj)
This function returns true if the object belongs to a UxScreen.
Definition nbgl_obj.c:1771
const char * get_ux_loc_string(uint32_t index)
void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh)
Definition nbgl_obj.c:1687
uint8_t * nbgl_objGetRAMBuffer(void)
This function is used to get the all purpose RAM buffer.
Definition nbgl_obj.c:1761
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:1707
void nbgl_objInit(void)
This functions inits all internal of nbgl objects layer.
Definition nbgl_obj.c:1736
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:274
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
signed short int16_t
Definition usbd_conf.h:50
unsigned short uint16_t
Definition usbd_conf.h:54
unsigned char uint8_t
Definition usbd_conf.h:53