11 #include "app_config.h"
18 #include "os_helpers.h"
21 #ifdef HAVE_SERIALIZED_NBGL
23 #include "os_io_seproxyhal.h"
25 #ifdef BUILD_SCREENSHOTS
26 #include "json_scenario.h"
33 #define NB_MAX_LETTERS 9
53 bool computePosition);
83 static bool objDrawingDisabled;
86 static bool objRefreshAreaDone;
113 #ifndef HAVE_SE_TOUCH
126 #ifdef BUILD_SCREENSHOTS
131 extern uint16_t last_nb_lines, last_nb_pages;
132 extern bool last_bold_state, verbose;
152 "compute_relativePosition() without align to, parent->layout = %d, prevObj = %p\n",
157 obj->rel_x0 = obj->alignmentMarginX;
158 if (prevObj != NULL) {
159 obj->rel_y0 = prevObj->rel_y0 + prevObj->area.height + obj->alignmentMarginY;
162 obj->rel_y0 = obj->alignmentMarginY;
166 if (prevObj != NULL) {
167 obj->rel_x0 = prevObj->rel_x0 + prevObj->area.width + obj->alignmentMarginX;
170 obj->rel_x0 = obj->alignmentMarginX;
172 obj->rel_y0 = obj->alignmentMarginY;
177 if (alignToObj == NULL) {
178 alignToObj = obj->parent;
185 if (alignToObj == obj->parent) {
187 switch (obj->alignment) {
189 obj->rel_x0 = obj->alignmentMarginX;
190 obj->rel_y0 = obj->alignmentMarginY;
194 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
195 obj->rel_y0 = obj->alignmentMarginY;
199 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
200 obj->rel_y0 = obj->alignmentMarginY;
203 obj->rel_x0 = obj->alignmentMarginX;
205 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
209 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
211 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
215 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
217 = (parent->obj.area.height - obj->area.height) / 2 + obj->alignmentMarginY;
220 obj->rel_x0 = obj->alignmentMarginX;
222 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
226 = (parent->obj.area.width - obj->area.width) / 2 + obj->alignmentMarginX;
228 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
232 = (parent->obj.area.width - obj->area.width) - obj->alignmentMarginX;
234 = (parent->obj.area.height - obj->area.height) - obj->alignmentMarginY;
243 switch (obj->alignment) {
245 obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX;
246 obj->rel_y0 = alignToObj->rel_y0 - obj->area.height - obj->alignmentMarginY;
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;
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;
261 obj->rel_x0 = alignToObj->rel_x0 - obj->area.width - obj->alignmentMarginX;
262 obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY;
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;
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;
278 = alignToObj->rel_x0 + alignToObj->area.width + obj->alignmentMarginX;
279 obj->rel_y0 = alignToObj->rel_y0 + obj->alignmentMarginY;
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;
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;
296 obj->rel_x0 = alignToObj->rel_x0 + obj->alignmentMarginX;
298 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
301 obj->rel_x0 = alignToObj->rel_x0
302 + (alignToObj->area.width - obj->area.width) / 2
303 + obj->alignmentMarginX;
305 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
308 obj->rel_x0 = alignToObj->rel_x0 + (alignToObj->area.width - obj->area.width)
309 - obj->alignmentMarginX;
311 = alignToObj->rel_y0 + alignToObj->area.height + obj->alignmentMarginY;
325 compute_relativePosition(obj, prevObj);
327 if (parent == NULL) {
336 obj->area.x0 = parent->obj.area.x0 + obj->rel_x0;
337 obj->area.y0 = parent->obj.area.y0 + obj->rel_y0;
341 "compute_position(), forbidden width, obj->type = %d, x0=%d, width=%d\n",
349 "compute_position(), forbidden height, obj->type = %d, y0=%d, height=%d\n",
362 UNUSED(computePosition);
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;
374 if (computePosition) {
375 compute_position((
nbgl_obj_t *) obj, prevObj);
378 "draw_container(), x0 = %d, y0 = %d, width = %d, height = %d\n",
382 obj->obj.area.height);
384 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
385 if (obj->forceClean) {
402 const char *text = NULL;
403 #define ICON_TEXT_SPACE 12
405 if (computePosition) {
406 compute_position((
nbgl_obj_t *) obj, prevObj);
409 "draw_button(), x0 = %d, y0 = %d, width = %d, height = %d\n",
413 obj->obj.area.height);
416 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
418 if ((obj->innerColor == obj->borderColor)
419 && (obj->innerColor != obj->obj.area.backgroundColor)) {
424 (
nbgl_area_t *) obj, obj->radius, 2, obj->innerColor, obj->borderColor);
427 if (obj->onDrawCallback != NULL) {
428 obj->text = obj->onDrawCallback(obj->token);
435 rectArea.x0 = obj->obj.area.x0;
436 rectArea.y0 = obj->obj.area.y0;
439 rectArea.y0 += (obj->obj.area.height - rectArea.height) / 2;
440 rectArea.width = obj->obj.area.width;
441 if (obj->icon != NULL) {
449 #ifdef BUILD_SCREENSHOTS
450 store_string_infos(text, obj->fontId, &rectArea,
true, 1, 1,
false);
454 if (textWidth < rectArea.width) {
455 rectArea.x0 += (rectArea.width - textWidth) / 2;
458 rectArea.backgroundColor = obj->innerColor;
459 nbgl_drawText(&rectArea, text, textLen, obj->fontId, obj->foregroundColor);
462 if (obj->icon != NULL) {
467 iconX0 = obj->obj.area.x0
468 + (obj->obj.area.width - (textWidth + obj->icon->width +
ICON_TEXT_SPACE)) / 2;
471 iconX0 = obj->obj.area.x0 + (obj->obj.area.width - obj->icon->width) / 2;
474 "draw_button(), obj->obj.area.height = %d, obj->iconHeight = %d\n",
475 obj->obj.area.height,
477 iconY0 = obj->obj.area.y0 + (obj->obj.area.height - obj->icon->height) / 2;
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;
501 if (computePosition) {
502 compute_position((
nbgl_obj_t *) obj, prevObj);
504 LOG_DEBUG(
OBJ_LOGGER,
"draw_line(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
506 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
508 "draw_line(), backgroundColor = %d, lineColor = %d\n",
509 obj->obj.area.backgroundColor,
511 rectArea.x0 = obj->obj.area.x0;
512 rectArea.y0 = obj->obj.area.y0;
514 rectArea.width = obj->obj.area.width = obj->thickness;
515 rectArea.backgroundColor = obj->lineColor;
516 rectArea.height = obj->obj.area.height;
521 if (obj->thickness == 1) {
522 mask = 0x1 << (obj->offset & 0x3);
524 else if (obj->thickness == 2) {
525 mask = 0x3 << ((obj->offset < 3) ? obj->offset : 2);
527 else if (obj->thickness == 3) {
528 mask = 0x7 << (obj->offset & 0x1);
530 else if (obj->thickness == 4) {
537 rectArea.width = obj->obj.area.width;
538 rectArea.height = obj->obj.area.height = 4;
539 rectArea.backgroundColor = obj->obj.area.backgroundColor;
551 if (obj->buffer == NULL) {
552 if (obj->onDrawCallback != NULL) {
553 iconDetails = obj->onDrawCallback(obj->token);
560 iconDetails = obj->buffer;
562 if (iconDetails == NULL) {
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);
573 LOG_DEBUG(
OBJ_LOGGER,
"draw_image(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
575 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
577 colorMap = obj->foregroundColor;
583 colorMap = obj->foregroundColor;
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);
600 LOG_DEBUG(
OBJ_LOGGER,
"draw_switch(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
603 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
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;
628 if (computePosition) {
629 compute_position((
nbgl_obj_t *) obj, prevObj);
632 "draw_radioButton(), x0 = %d, y0 = %d, state = %d\n",
638 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
642 color_map = obj->borderColor;
646 color_map = obj->activeColor;
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;
671 if (computePosition) {
672 compute_position((
nbgl_obj_t *) obj, prevObj);
675 "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n",
681 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
683 if (obj->partialRedraw ==
false) {
685 if (obj->withBorder) {
689 obj->obj.area.backgroundColor,
690 obj->foregroundColor);
697 obj->previousWidth = 0;
701 uint16_t barWidth = ((obj->state * obj->obj.area.width)) / 100;
702 int barDiffWith = barWidth - obj->previousWidth;
704 memcpy(&barArea, &obj->obj.area,
sizeof(
nbgl_area_t));
706 if (barDiffWith >= 0) {
708 barArea.x0 = obj->obj.area.x0 + obj->previousWidth;
709 barArea.width = barDiffWith;
710 barColor = obj->foregroundColor;
714 barArea.x0 = obj->obj.area.x0 + obj->previousWidth + barDiffWith;
715 barArea.width = -barDiffWith;
716 barColor = obj->obj.area.backgroundColor;
719 if (barDiffWith != 0) {
725 if (obj->partialRedraw ==
true) {
726 obj->partialRedraw =
false;
728 obj->previousWidth = barWidth;
730 extendRefreshArea(&barArea);
731 objRefreshAreaDone =
true;
736 if (computePosition) {
737 compute_position((
nbgl_obj_t *) obj, prevObj);
740 "draw_progressBar(), x0 = %d, y0 = %d, level = %d %%\n",
746 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
749 if (obj->withBorder) {
753 obj->obj.area.backgroundColor,
754 obj->foregroundColor);
760 levelWidth =
MIN((obj->obj.area.width - 2) * obj->state / 100, (obj->obj.area.width - 2));
761 if (levelWidth > 0) {
763 rectArea.width = levelWidth;
764 rectArea.height = obj->obj.area.height - 2;
765 rectArea.backgroundColor = obj->foregroundColor;
767 rectArea.x0 = obj->obj.area.x0 + 1;
768 rectArea.y0 = obj->obj.area.y0 + 1;
786 bool computePosition)
792 if (obj->nbPages < 2) {
799 #define INTER_DASHES 10
801 #define INTER_DASHES 8
804 obj->obj.area.height = 4;
806 if (computePosition) {
807 compute_position((
nbgl_obj_t *) obj, prevObj);
810 "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n",
817 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
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;
827 for (i = 0; i < obj->activePage; i++) {
836 for (; i < obj->nbPages; i++) {
844 SPRINTF(navText,
"%d of %d", obj->activePage + 1, obj->nbPages);
850 if (computePosition) {
851 compute_position((
nbgl_obj_t *) obj, prevObj);
854 "draw_pageIndicator(), x0 = %d, y0 = %d, page = %d/%d\n",
861 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
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;
886 uint16_t textWidth, fontHeight, lineHeight, textHeight, midHeight;
891 if (computePosition) {
892 compute_position((
nbgl_obj_t *) obj, prevObj);
895 if (obj->onDrawCallback != NULL) {
896 obj->text = obj->onDrawCallback(obj->token);
905 "draw_textArea(), wrapping = %d, x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n",
910 obj->obj.area.height,
914 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
917 #ifdef SCREEN_SIZE_NANO
918 if (obj->style == INVERTED_COLORS) {
919 obj->obj.area.backgroundColor =
WHITE;
920 rectArea.backgroundColor =
BLACK;
926 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
927 rectArea.backgroundColor = obj->obj.area.backgroundColor;
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) {
947 if (obj->autoHideLongLine ==
true) {
948 #ifdef BUILD_SCREENSHOTS
950 store_string_infos(text,
959 if (textWidth > obj->obj.area.width) {
964 rectArea.x0 = obj->obj.area.x0;
965 rectArea.y0 = obj->obj.area.y0 + (obj->obj.area.height - fontHeight) / 2;
966 rectArea.width = dotsWidth;
970 fontId, text, obj->obj.area.width - dotsWidth, &lineLen, &lineWidth);
971 rectArea.x0 += dotsWidth;
972 rectArea.width = lineWidth;
984 #ifdef BUILD_SCREENSHOTS
986 text, fontId, &obj->obj.area, obj->wrapping, last_nb_lines, last_nb_pages, last_bold_state);
989 if ((obj->nbMaxLines > 0) && (obj->nbMaxLines < nbLines)) {
990 nbLines = obj->nbMaxLines;
993 textHeight = (nbLines - 1) * lineHeight + fontHeight;
995 midHeight = (obj->obj.area.height - textHeight) / 2;
996 #ifdef SCREEN_SIZE_NANO
997 if (obj->style == INVERTED_COLORS) {
1002 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1003 rectArea.height = fontHeight;
1005 for (line = 0; line < nbLines; line++) {
1009 fontId, text, obj->obj.area.width, &lineLen, &lineWidth, obj->wrapping);
1010 if (obj->textAlignment ==
MID_LEFT) {
1011 rectArea.x0 = obj->obj.area.x0;
1013 else if (obj->textAlignment ==
CENTER) {
1014 rectArea.x0 = obj->obj.area.x0 + (obj->obj.area.width - lineWidth) / 2;
1016 else if (obj->textAlignment ==
MID_RIGHT) {
1017 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - lineWidth;
1022 rectArea.y0 = obj->obj.area.y0 + midHeight + line * lineHeight;
1023 rectArea.width = lineWidth;
1026 "draw_textArea(), %s line %d, lineLen %d lineWidth = %d, obj.area.height = %d, "
1027 "textHeight = %d, nbMaxLines = %d, wrapping = %d\n",
1032 obj->obj.area.height,
1036 if ((obj->nbMaxLines == 0) || (line < (obj->nbMaxLines - 1))) {
1037 fontId =
nbgl_drawText(&rectArea, text, lineLen, fontId, obj->textColor);
1040 #ifdef HAVE_SE_TOUCH
1043 nbgl_drawText(&rectArea, text, lineLen - 3, obj->fontId, obj->textColor);
1047 nbgl_drawText(&rectArea,
"...", 3, obj->fontId, obj->textColor);
1049 nbgl_drawText(&rectArea, text, lineLen, fontId, obj->textColor);
1055 if (*text ==
'\n') {
1074 if (computePosition) {
1075 compute_position((
nbgl_obj_t *) obj, prevObj);
1078 obj->obj.area.y0 &= ~0x3;
1080 "draw_qrCode(), x0 = %d, y0 = %d, width = %d, height = %d, text = %s\n",
1083 obj->obj.area.width,
1084 obj->obj.area.height,
1088 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
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);
1099 #ifdef NBGL_KEYBOARD
1109 #ifndef HAVE_SE_TOUCH
1110 obj->obj.area.width = KEYBOARD_WIDTH;
1114 if (computePosition) {
1115 compute_position((
nbgl_obj_t *) obj, prevObj);
1118 OBJ_LOGGER,
"draw_keyboard(), x0 = %d, y0 = %d\n", obj->obj.area.x0, obj->obj.area.y0);
1121 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1137 #ifndef HAVE_SE_TOUCH
1138 obj->obj.area.height = KEYPAD_HEIGHT;
1139 obj->obj.area.width = KEYPAD_WIDTH;
1142 if (computePosition) {
1143 compute_position((
nbgl_obj_t *) obj, prevObj);
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);
1149 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1155 #ifdef HAVE_SE_TOUCH
1171 if (computePosition) {
1172 compute_position((
nbgl_obj_t *) obj, prevObj);
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);
1178 obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor;
1183 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1185 if (obj->position == 0xFF) {
1187 rectArea.x0 = obj->obj.area.x0;
1188 rectArea.y0 = obj->obj.area.y0;
1189 rectArea.width = 20;
1190 rectArea.height = 4;
1192 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1194 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1196 rectArea.x0 = obj->obj.area.x0;
1199 rectArea.x0 = obj->obj.area.x0;
1200 rectArea.y0 = obj->obj.area.y0;
1202 rectArea.height = 12;
1203 rectArea.backgroundColor = foreColor;
1205 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1207 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1209 rectArea.x0 = obj->obj.area.x0;
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;
1223 rectArea.width = 20;
1224 rectArea.height = 4;
1225 switch (obj->position) {
1227 rectArea.x0 = obj->obj.area.x0;
1228 rectArea.y0 = obj->obj.area.y0;
1232 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1233 rectArea.y0 = obj->obj.area.y0;
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;
1242 rectArea.x0 = obj->obj.area.x0;
1243 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - 4;
1253 rectArea.height = 12;
1254 rectArea.backgroundColor = foreColor;
1255 switch (obj->position) {
1257 rectArea.x0 = obj->obj.area.x0;
1258 rectArea.y0 = obj->obj.area.y0;
1261 rectArea.x0 = obj->obj.area.x0 + obj->obj.area.width - rectArea.width;
1262 rectArea.y0 = obj->obj.area.y0;
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;
1269 rectArea.x0 = obj->obj.area.x0;
1270 rectArea.y0 = obj->obj.area.y0 + obj->obj.area.height - rectArea.height;
1291 int textLen = strlen(obj->text);
1294 if (computePosition) {
1295 compute_position((
nbgl_obj_t *) obj, prevObj);
1299 "draw_textEntry(), x0 = %d, y0 = %d, width = %d, height = %d\n",
1302 obj->obj.area.width,
1303 obj->obj.area.height);
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;
1315 rectArea.backgroundColor = obj->obj.area.backgroundColor;
1320 offsetX = (obj->obj.area.width - (obj->nbChars * 10)) / 2;
1322 for (
int i = 0; i < obj->nbChars; i++) {
1324 rectArea.x0 = obj->obj.area.x0 + offsetX + (i * 10);
1325 rectArea.y0 = obj->obj.area.y0 - 2;
1327 if (textLen < obj->nbChars) {
1329 digit = obj->text[i];
1341 else if (i < (obj->nbChars - 1)) {
1342 digit = obj->text[textLen - obj->nbChars + 1 + i];
1362 if (obj->buffer == NULL) {
1365 if (computePosition) {
1366 compute_position((
nbgl_obj_t *) obj, prevObj);
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;
1378 if (computePosition) {
1379 compute_position((
nbgl_obj_t *) obj, prevObj);
1382 if (obj->enableMasking) {
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)) {
1404 func(obj, prevObj, computePosition);
1411 #ifdef HAVE_SERIALIZED_NBGL
1414 if (!objRefreshAreaDone) {
1415 extendRefreshArea(&obj->area);
1433 draw_object(obj, prevObj, computePosition);
1439 OBJ_LOGGER,
"draw_obj_and_chidren(): container->children = %p\n", container->children);
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) {
1446 draw_obj_and_chidren(current, prev,
true);
1447 if (current->alignTo == NULL) {
1465 x1 = refreshArea.x0 + refreshArea.width;
1466 y1 = refreshArea.y0 + refreshArea.height;
1469 if (area->x0 < refreshArea.x0) {
1471 refreshArea.x0 =
MAX(0, area->x0);
1474 if (((area->x0 + area->width) > x1) || (refreshArea.width == 0)) {
1479 if (area->y0 < refreshArea.y0) {
1481 refreshArea.y0 =
MAX(0, area->y0);
1484 if (((area->y0 + area->height) > y1) || (refreshArea.height == 0)) {
1492 "extendRefreshArea: Impossible area x0 = %d width %d\n",
1497 #ifdef HAVE_SE_TOUCH
1499 "extendRefreshArea: Impossible area y0 = %d height %d\n",
1501 refreshArea.height);
1507 refreshArea.width = x1 - refreshArea.x0;
1508 refreshArea.height = y1 - refreshArea.y0;
1511 if (area->bpp > refreshArea.bpp) {
1512 refreshArea.bpp = area->bpp;
1523 bool computePosition =
false;
1529 if (obj->type ==
SCREEN) {
1531 computePosition =
true;
1537 while (parent->parent != NULL) {
1538 parent = parent->parent;
1540 if (parent->type ==
SCREEN) {
1549 if (objDrawingDisabled && fromApp) {
1552 draw_obj_and_chidren(obj, NULL, computePosition);
1572 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1578 "nbgl_refreshSpecial(), x0,y0 = [%d, %d], w,h = [%d, %d]\n",
1582 refreshArea.height);
1588 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1594 "nbgl_refreshSpecialNoPoff(), x0,y0 = [%d, %d], w,h = [%d, %d]\n",
1598 refreshArea.height);
1608 if ((refreshArea.width == 0) || (refreshArea.height == 0)) {
1620 #ifdef HAVE_SERIALIZED_NBGL
1624 refreshArea.width = 0;
1626 refreshArea.height = 0;
1647 objDrawingDisabled = !enable;
#define LOG_WARN(__logger,...)
#define LOG_DEBUG(__logger,...)
#define LOG_FATAL(__logger,...)
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.
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.
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.
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...
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.
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
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
@ BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp
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
uint8_t nbgl_getFontHeight(nbgl_font_id_e fontId)
return the height in pixels of the font with the given font ID
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)
uint16_t nbgl_getTextLength(const char *text)
return the number of bytes of the given text, excluding final ' ' or '\0'
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
uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId)
return the height in pixels of the line of font with the given font ID
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,...
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)
void nbgl_objDraw(nbgl_obj_t *obj)
This function draws or redraws the given object and its children (recursive version)
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
void nbgl_refreshReset(void)
This functions resets all changes since the last refresh.
void nbgl_objAllowDrawing(bool enable)
This functions enables or disables drawing/refresh for all further calls.
void(* draw_function_t)(nbgl_obj_t *obj, nbgl_obj_t *prevObj, bool computePosition)
void nbgl_refreshSpecial(nbgl_refresh_mode_t mode)
This functions refreshes the actual screen on display with what has changed since the last refresh,...
const char * get_ux_loc_string(uint32_t index)
void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh)
uint8_t ramBuffer[GZLIB_UNCOMPRESSED_CHUNK]
bool nbgl_refreshIsNeeded(void)
This functions returns true if there is something to refresh.
void nbgl_objInit(void)
This functions inits all internal of nbgl objects layer.
API to draw all basic graphic objects.
struct PACKED__ nbgl_line_s nbgl_line_t
struct to represent a vertical or horizontal line
struct PACKED__ nbgl_navigation_bar_s nbgl_page_indicator_t
struct to represent a navigation bar (PAGE_INDICATOR type) There can be up to 5 page indicators,...
struct PACKED__ nbgl_radio_s nbgl_radio_t
struct to represent a radio button (RADIO_BUTTON type)
struct PACKED__ nbgl_text_area_s nbgl_text_area_t
struct to represent a text area (TEXT_AREA type)
struct PACKED__ nbgl_progress_bar_s nbgl_progress_bar_t
struct to represent a progress bar (PROGRESS_BAR type)
struct PACKED__ nbgl_keypad_s nbgl_keypad_t
struct to represent a keypad (KEYPAD type)
struct PACKED__ nbgl_mask_control_s nbgl_mask_control_t
struct PACKED__ nbgl_text_entry_s nbgl_text_entry_t
struct to represent a text entry area (TEXT_ENTRY type)
struct PACKED__ nbgl_keyboard_s nbgl_keyboard_t
struct to represent a keyboard (KEYBOARD type)
struct PACKED__ nbgl_image_s nbgl_image_t
struct to represent an image (IMAGE type)
struct PACKED__ nbgl_button_s nbgl_button_t
struct to represent a button (BUTTON type) that can contain a text and/or an icon
void nbgl_objDrawKeyboard(nbgl_keyboard_t *kbd)
This function draws a keyboard object.
#define KEYBOARD_KEY_HEIGHT
#define NB_MAX_PAGES_WITH_DASHES
void nbgl_objDrawKeypad(nbgl_keypad_t *kbd)
This function draws a keypad object.
struct PACKED__ nbgl_container_s nbgl_container_t
struct to represent a container (CONTAINER type)
@ PROGRESSIVE_INDICATOR
all dashes before active page are black
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
struct PACKED__ nbgl_screen_s nbgl_screen_t
struct to represent a screen (SCREEN type)
nbgl_post_refresh_t
Post refresh modes.
@ POST_REFRESH_FORCE_POWER_OFF
Force screen power off after refresh.
uint8_t nbgl_color_map_t
Represents the color_map to be used for 2BPP image, or the foreground color for 1BPP image.
@ RADIUS_0_PIXELS
no radius (square angle)
@ VERTICAL
from top to bottom
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
@ NO_ALIGNMENT
used when parent container layout is used
@ LEFT_TOP
on outside left
@ LEFT_BOTTOM
on outside left
@ RIGHT_TOP
on outside right
@ RIGHT_BOTTOM
on outside right
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
@ IMAGE_FILE
Image file (with Ledger compression)
@ TEXT_ENTRY
area for entered text, only for Nanos
@ SWITCH
Switch to turn on/off something.
@ RADIO_BUTTON
Indicator to inform whether something is on or off.
@ BUTTON
Rounded rectangle button with icon and/or text.
@ PROGRESS_BAR
horizontal bar to indicate progression of something (between 0% and 100%)
@ PAGE_INDICATOR
horizontal bar to indicate position within pages
@ LINE
Vertical or Horizontal line.
@ MASK_CONTROL
OS-specific object to enable/disable masked area.
@ CONTAINER
Empty container.
@ TEXT_AREA
Area to contain text line(s)
#define NO_TRANSFORMATION
@ NBGL_BPP_1
1 bit per pixel
@ NBGL_BPP_2
2 bits per pixel
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()
@ FULL_COLOR_CLEAN_REFRESH
to be used for lock screen display (cleaner but longer refresh)
BOLOS_UX_LOC_STRINGS UX_LOC_STRINGS_INDEX