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