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