Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nbgl_draw.c
Go to the documentation of this file.
1
8/*********************
9 * INCLUDES
10 *********************/
11#include <string.h>
12#include "nbgl_front.h"
13#include "nbgl_draw.h"
14#include "nbgl_fonts.h"
15#include "nbgl_debug.h"
16#include "nbgl_side.h"
17#ifdef NBGL_QRCODE
18#include "qrcodegen.h"
19#endif // NBGL_QRCODE
20#include "glyphs.h"
21#include "os_pic.h"
22#include "os_utils.h"
23
24/*********************
25 * DEFINES
26 *********************/
33
34#define QR_PIXEL_WIDTH_HEIGHT 4
35
36/**********************
37 * TYPEDEFS
38 **********************/
39#ifdef NBGL_QRCODE
40typedef struct {
41 uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX];
42 uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX];
45
46#define qrcode ((QrCodeBuffer_t *) ramBuffer)->qrcode
47#define tempBuffer ((QrCodeBuffer_t *) ramBuffer)->tempBuffer
48#define QrDrawBuffer ((QrCodeBuffer_t *) ramBuffer)->QrDrawBuffer
49#endif // NBGL_QRCODE
50
51// icons to be used to draw circles or discs for a given radius
58
59/**********************
60 * STATIC PROTOTYPES
61 **********************/
62
63/**********************
64 * STATIC VARIABLES
65 **********************/
66#ifndef SCREEN_SIZE_WALLET
67static const uint8_t quarter_disc_3px_1bpp[] = {0xEC, 0xFF};
68static const uint8_t quarter_disc_3px_90_1bpp[] = {0x2F, 0xFF};
69static const uint8_t quarter_disc_3px_180_1bpp[] = {0x9B, 0xFF};
70static const uint8_t quarter_disc_3px_270_1bpp[] = {0xFA, 0x00};
71
72static const uint8_t quarter_circle_3px_1bpp[] = {0x4C, 0x00};
73static const uint8_t quarter_circle_3px_90_1bpp[] = {0x0D, 0x00};
74static const uint8_t quarter_circle_3px_180_1bpp[] = {0x19, 0x00};
75static const uint8_t quarter_circle_3px_270_1bpp[] = {0x58, 0x00};
76#endif // SCREEN_SIZE_WALLET
77
78// indexed by nbgl_radius_t (except RADIUS_0_PIXELS)
79static const uint8_t radiusValues[RADIUS_MAX + 1] = {
80#ifdef SCREEN_SIZE_WALLET
81 8,
82 32,
83 40,
84 44
85#else // SCREEN_SIZE_WALLET
86 1,
87 3
88#endif // SCREEN_SIZE_WALLET
89};
90
91#ifdef SCREEN_SIZE_WALLET
92
93#if COMMON_RADIUS == 40
94static const radiusIcons_t radiusIcons40px = {
95 C_quarter_disc_top_left_40px_1bpp_bitmap,
96 C_quarter_disc_bottom_left_40px_1bpp_bitmap,
97 C_quarter_circle_top_left_40px_1bpp_bitmap,
98 C_quarter_circle_bottom_left_40px_1bpp_bitmap,
99};
100#elif COMMON_RADIUS == 44
101static const radiusIcons_t radiusIcons44px = {
102 C_quarter_disc_top_left_44px_1bpp_bitmap,
103 C_quarter_disc_bottom_left_44px_1bpp_bitmap,
104 C_quarter_circle_top_left_44px_1bpp_bitmap,
105 C_quarter_circle_bottom_left_44px_1bpp_bitmap,
106};
107#endif
108#if SMALL_BUTTON_RADIUS == 32
109static const radiusIcons_t radiusIcons32px = {
110 C_quarter_disc_top_left_32px_1bpp_bitmap,
111 C_quarter_disc_bottom_left_32px_1bpp_bitmap,
112 C_quarter_circle_top_left_32px_1bpp_bitmap,
113 C_quarter_circle_bottom_left_32px_1bpp_bitmap,
114};
115#endif
116
117// indexed by nbgl_radius_t (except RADIUS_0_PIXELS)
118static const radiusIcons_t *radiusIcons[RADIUS_MAX + 1] = {NULL,
119#if SMALL_BUTTON_RADIUS == 32
120 &radiusIcons32px,
121#else
122 NULL,
123#endif
124#if COMMON_RADIUS == 40
125 &radiusIcons40px,
126#else
127 NULL,
128#endif
129#if COMMON_RADIUS == 44
130 &radiusIcons44px
131#else
132 NULL
133#endif // COMMON_RADIUS
134};
135#endif // SCREEN_SIZE_WALLET
136
137#ifdef NBGL_QRCODE
138// ensure that the ramBuffer also used for image file decompression is big enough for QR code
140#endif // NBGL_QRCODE
141
142/**********************
143 * VARIABLES
144 **********************/
145
146/**********************
147 * STATIC PROTOTYPES
148 **********************/
149
150static void draw_circle_helper(int x_center,
151 int y_center,
152 nbgl_radius_t radiusIndex,
153 quarter_t quarter,
154 color_t borderColor,
155 color_t innerColor,
156 color_t backgroundColor)
157{
158 const uint8_t *quarter_buffer = NULL;
159 nbgl_area_t area = {.bpp = NBGL_BPP_1, .backgroundColor = backgroundColor};
160
161 // radius is not supported
162 if (radiusIndex > RADIUS_MAX) {
163 return;
164 }
165 area.width = area.height = radiusValues[radiusIndex];
166#ifdef SCREEN_SIZE_WALLET
167 if (borderColor == innerColor) {
168 if (quarter < BAGL_FILL_CIRCLE_PI_3PI2) {
169 quarter_buffer = (const uint8_t *) PIC(radiusIcons[radiusIndex]->topLeftDisc);
170 }
171 else {
172 quarter_buffer = (const uint8_t *) PIC(radiusIcons[radiusIndex]->bottomLeftDisc);
173 }
174 }
175 else {
176 if (quarter < BAGL_FILL_CIRCLE_PI_3PI2) {
177 quarter_buffer = (const uint8_t *) PIC(radiusIcons[radiusIndex]->topLeftCircle);
178 }
179 else {
180 quarter_buffer = (const uint8_t *) PIC(radiusIcons[radiusIndex]->bottomLeftCircle);
181 }
182 }
183 switch (quarter) {
184 case BAGL_FILL_CIRCLE_3PI2_2PI: // bottom right
185 area.x0 = x_center;
186 area.y0 = y_center;
187 nbgl_frontDrawImage(&area, quarter_buffer, VERTICAL_MIRROR, borderColor);
188 break;
189 case BAGL_FILL_CIRCLE_PI_3PI2: // bottom left
190 area.x0 = x_center - area.width;
191 area.y0 = y_center;
192 nbgl_frontDrawImage(&area, quarter_buffer, NO_TRANSFORMATION, borderColor);
193 break;
194 case BAGL_FILL_CIRCLE_0_PI2: // top right
195 area.x0 = x_center;
196 area.y0 = y_center - area.width;
197 nbgl_frontDrawImage(&area, quarter_buffer, VERTICAL_MIRROR, borderColor);
198 break;
199 case BAGL_FILL_CIRCLE_PI2_PI: // top left
200 area.x0 = x_center - area.width;
201 area.y0 = y_center - area.width;
202 nbgl_frontDrawImage(&area, quarter_buffer, NO_TRANSFORMATION, borderColor);
203 break;
204 }
205#else // SCREEN_SIZE_WALLET
206 switch (quarter) {
207 case BAGL_FILL_CIRCLE_3PI2_2PI: // bottom right
208 area.x0 = x_center;
209 area.y0 = y_center;
210 quarter_buffer = (borderColor == innerColor) ? quarter_disc_3px_180_1bpp
211 : quarter_circle_3px_180_1bpp;
212 break;
213 case BAGL_FILL_CIRCLE_PI_3PI2: // bottom left
214 area.x0 = x_center - area.width;
215 area.y0 = y_center;
216 quarter_buffer = (borderColor == innerColor) ? quarter_disc_3px_270_1bpp
217 : quarter_circle_3px_270_1bpp;
218 break;
219 case BAGL_FILL_CIRCLE_0_PI2: // top right
220 area.x0 = x_center;
221 area.y0 = y_center - area.width;
222 quarter_buffer = (borderColor == innerColor) ? quarter_disc_3px_90_1bpp
223 : quarter_circle_3px_90_1bpp;
224 break;
225 case BAGL_FILL_CIRCLE_PI2_PI: // top left
226 area.x0 = x_center - area.width;
227 area.y0 = y_center - area.width;
228 quarter_buffer
229 = (borderColor == innerColor) ? quarter_disc_3px_1bpp : quarter_circle_3px_1bpp;
230 break;
231 }
232 nbgl_frontDrawImage(&area, quarter_buffer, NO_TRANSFORMATION, borderColor);
233#endif // SCREEN_SIZE_WALLET
234}
235
236/**********************
237 * GLOBAL FUNCTIONS
238 **********************/
239
249void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radiusIndex, color_t innerColor)
250{
251 nbgl_area_t rectArea;
252 uint8_t radius;
253
255 "nbgl_drawRoundedRect x0 = %d, y0 = %d, width =%d, height =%d\n",
256 area->x0,
257 area->y0,
258 area->width,
259 area->height);
260
261 if (radiusIndex <= RADIUS_MAX) {
262 radius = radiusValues[radiusIndex];
263 }
264 else if (radiusIndex == RADIUS_0_PIXELS) {
265 radius = 0;
266 }
267 else {
268 // radius not supported
269 LOG_WARN(DRAW_LOGGER, "nbgl_drawRoundedRect forbidden radius index =%d\n", radiusIndex);
270 return;
271 }
272
273 // Draw full rectangle
274 rectArea.x0 = area->x0;
275 rectArea.y0 = area->y0;
276 rectArea.width = area->width;
277 rectArea.height = area->height;
278 rectArea.backgroundColor = innerColor;
279 nbgl_frontDrawRect(&rectArea);
280 // special case when radius is null, just draw a rectangle
281 if (radiusIndex == RADIUS_0_PIXELS) {
282 return;
283 }
284
285#ifdef SCREEN_SIZE_NANO
286 if (radiusIndex == RADIUS_1_PIXEL) {
287 return;
288 }
289#endif // SCREEN_SIZE_NANO
290 // Draw 4 quarters of disc
291 draw_circle_helper(area->x0 + radius,
292 area->y0 + radius,
293 radiusIndex,
295 innerColor, // unused
296 innerColor,
297 area->backgroundColor);
298 draw_circle_helper(area->x0 + area->width - radius,
299 area->y0 + radius,
300 radiusIndex,
302 innerColor, // unused
303 innerColor,
304 area->backgroundColor);
305 draw_circle_helper(area->x0 + radius,
306 area->y0 + area->height - radius,
307 radiusIndex,
309 innerColor, // unused
310 innerColor,
311 area->backgroundColor);
312 draw_circle_helper(area->x0 + area->width - radius,
313 area->y0 + area->height - radius,
314 radiusIndex,
316 innerColor, // unused
317 innerColor,
318 area->backgroundColor);
319}
320
332 nbgl_radius_t radiusIndex,
333 uint8_t stroke,
334 color_t innerColor,
335 color_t borderColor)
336{
337 uint8_t radius;
338 nbgl_area_t rectArea;
339
340 LOG_DEBUG(
342 "nbgl_drawRoundedBorderedRect: innerColor = %d, borderColor = %d, backgroundColor=%d\n",
343 innerColor,
344 borderColor,
345 area->backgroundColor);
346
347 if (radiusIndex <= RADIUS_MAX) {
348 radius = radiusValues[radiusIndex];
349 }
350 else if (radiusIndex == RADIUS_0_PIXELS) {
351 radius = 0;
352 }
353 else {
354 // radius not supported
355 LOG_WARN(
356 DRAW_LOGGER, "nbgl_drawRoundedBorderedRect forbidden radius index =%d\n", radiusIndex);
357 return;
358 }
359 rectArea.backgroundColor = innerColor;
360
361 // special case, when border_color == inner_color == background_color, just draw a rectangle
362 if ((innerColor == borderColor) && (borderColor == area->backgroundColor)) {
363 rectArea.x0 = area->x0;
364 rectArea.y0 = area->y0;
365 rectArea.width = area->width;
366 rectArea.height = area->height;
367 nbgl_frontDrawRect(&rectArea);
368 return;
369 }
370 // Draw 3 rectangles
371 if ((2 * radius) < area->width) {
372 rectArea.x0 = area->x0 + radius;
373 rectArea.y0 = area->y0;
374 rectArea.width = area->width - (2 * radius);
375 rectArea.height = area->height;
376 nbgl_frontDrawRect(&rectArea);
377 }
378 // special case when radius is null, left and right rectangles are not necessary
379 if (radiusIndex <= RADIUS_MAX) {
380 if ((2 * radius) < area->height) {
381 rectArea.x0 = area->x0;
382 rectArea.y0 = area->y0 + radius;
383 rectArea.width = radius;
384 rectArea.height = area->height - (2 * radius);
385 nbgl_frontDrawRect(&rectArea);
386 rectArea.x0 = area->x0 + area->width - radius;
387 rectArea.y0 = area->y0 + radius;
388 nbgl_frontDrawRect(&rectArea);
389 }
390 }
391 // border
392 // 4 rectangles (with last pixel of each corner not set)
393#ifdef SCREEN_SIZE_WALLET
394 uint8_t maskTop, maskBottom;
395 if (stroke == 1) {
396 maskTop = 0x1;
397 maskBottom = 0x8;
398 }
399 else if (stroke == 2) {
400 maskTop = 0x3;
401 maskBottom = 0xC;
402 }
403 else if (stroke == 3) {
404 maskTop = 0x7;
405 maskBottom = 0xE;
406 }
407 else if (stroke == 4) {
408 maskTop = 0xF;
409 maskBottom = 0xF;
410 }
411 else {
412 LOG_WARN(DRAW_LOGGER, "nbgl_drawRoundedBorderedRect forbidden stroke=%d\n", stroke);
413 return;
414 }
415 rectArea.x0 = area->x0 + radius;
416 rectArea.y0 = area->y0;
417 rectArea.width = area->width - 2 * radius;
418 rectArea.height = 4;
419 nbgl_frontDrawHorizontalLine(&rectArea, maskTop, borderColor); // top
420 rectArea.x0 = area->x0 + radius;
421 rectArea.y0 = area->y0 + area->height - 4;
422 nbgl_frontDrawHorizontalLine(&rectArea, maskBottom, borderColor); // bottom
423#else // SCREEN_SIZE_WALLET
424 rectArea.x0 = area->x0 + radius;
425 rectArea.y0 = area->y0;
426 rectArea.width = area->width - 2 * radius;
427 rectArea.height = stroke;
428 rectArea.backgroundColor = borderColor;
429 nbgl_frontDrawRect(&rectArea); // top
430 rectArea.y0 = area->y0 + area->height - stroke;
431 nbgl_frontDrawRect(&rectArea); // bottom
432#endif // SCREEN_SIZE_WALLET
433 if ((2 * radius) < area->height) {
434 rectArea.x0 = area->x0;
435 rectArea.y0 = area->y0 + radius;
436 rectArea.width = stroke;
437 rectArea.height = area->height - 2 * radius;
438 rectArea.backgroundColor = borderColor;
439 nbgl_frontDrawRect(&rectArea); // left
440 rectArea.x0 = area->x0 + area->width - stroke;
441 nbgl_frontDrawRect(&rectArea); // right
442 }
443
444 if (radiusIndex <= RADIUS_MAX) {
445 // Draw 4 quarters of circles
446 draw_circle_helper(area->x0 + radius,
447 area->y0 + radius,
448 radiusIndex,
450 borderColor,
451 innerColor,
452 area->backgroundColor);
453 draw_circle_helper(area->x0 + area->width - radius,
454 area->y0 + radius,
455 radiusIndex,
457 borderColor,
458 innerColor,
459 area->backgroundColor);
460 draw_circle_helper(area->x0 + radius,
461 area->y0 + area->height - radius,
462 radiusIndex,
464 borderColor,
465 innerColor,
466 area->backgroundColor);
467 draw_circle_helper(area->x0 + area->width - radius,
468 area->y0 + area->height - radius,
469 radiusIndex,
471 borderColor,
472 innerColor,
473 area->backgroundColor);
474 }
475}
476
490 nbgl_transformation_t transformation,
491 nbgl_color_map_t color_map,
492 const nbgl_icon_details_t *icon)
493{
494 if (icon->isFile) {
495 nbgl_frontDrawImageFile(area, icon->bitmap, color_map, ramBuffer);
496 }
497 else {
498 nbgl_frontDrawImage(area, icon->bitmap, transformation, color_map);
499 }
500}
501
509static uint16_t get_bitmap_byte_cnt(const nbgl_font_t *font, uint8_t charId)
510{
511 if ((charId < font->first_char) || (charId > font->last_char)) {
512 return 0;
513 }
514
515 uint16_t baseId = charId - font->first_char;
516 if (charId < font->last_char) {
517 const nbgl_font_character_t *character
518 = (const nbgl_font_character_t *) PIC(&font->characters[baseId]);
519 const nbgl_font_character_t *nextCharacter
520 = (const nbgl_font_character_t *) PIC(&font->characters[baseId + 1]);
521 return (nextCharacter->bitmap_offset - character->bitmap_offset);
522 }
523 else if (charId == font->last_char) {
524 return (font->bitmap_len - font->characters[baseId].bitmap_offset);
525 }
526 return 0;
527}
528
539 const char *text,
540 uint16_t textLen,
541 nbgl_font_id_e fontId,
542 color_t fontColor)
543{
544 // text is a series of characters, each character being a bitmap
545 // we need to align bitmaps on width multiple of 4 limitation.
546 int16_t x = area->x0;
547 nbgl_area_t rectArea;
548 const nbgl_font_t *font = nbgl_getFont(fontId);
549#ifdef HAVE_UNICODE_SUPPORT
550 nbgl_unicode_ctx_t *unicode_ctx = NULL;
551#endif // HAVE_UNICODE_SUPPORT
552
554 "nbgl_drawText: x0 = %d, y0 = %d, w = %d, h = %d, fontColor = %d, "
555 "backgroundColor=%d, text = %s\n",
556 area->x0,
557 area->y0,
558 area->width,
559 area->height,
560 fontColor,
561 area->backgroundColor,
562 text);
563
564 rectArea.backgroundColor = area->backgroundColor;
565 rectArea.bpp = (nbgl_bpp_t) font->bpp;
566
567 while (textLen > 0) {
568 const nbgl_font_character_t *character;
569 uint8_t char_width;
570 uint32_t unicode;
571 bool is_unicode;
572 const uint8_t *char_buffer;
573 int16_t char_x_min;
574 int16_t char_y_min;
575 int16_t char_x_max;
576 int16_t char_y_max;
577 uint16_t char_byte_cnt;
578 uint8_t encoding;
579 uint8_t nb_skipped_bytes;
580
581 unicode = nbgl_popUnicodeChar((const uint8_t **) &text, &textLen, &is_unicode);
582
583 if (is_unicode) {
584#ifdef HAVE_UNICODE_SUPPORT
585 if (unicode_ctx == NULL) {
586 unicode_ctx = nbgl_getUnicodeFont(fontId);
587 }
588 const nbgl_font_unicode_character_t *unicodeCharacter
589 = nbgl_getUnicodeFontCharacter(unicode);
590 // if not supported char, go to next one
591 if (unicodeCharacter == NULL) {
592 continue;
593 }
594 char_width = unicodeCharacter->width;
595#if defined(HAVE_LANGUAGE_PACK)
596 char_buffer = unicode_ctx->bitmap;
597 char_buffer += unicodeCharacter->bitmap_offset;
598
599 char_x_max = char_width;
600 char_y_max = unicode_ctx->font->height;
601
602 if (!unicode_ctx->font->crop) {
603 // Take in account the skipped bytes, if any
604 nb_skipped_bytes = (unicodeCharacter->x_min_offset & 7) << 3;
605 nb_skipped_bytes |= unicodeCharacter->y_min_offset & 7;
606 char_x_min = 0;
607 char_y_min = 0;
608 }
609 else {
610 nb_skipped_bytes = 0;
611 char_x_min = (uint16_t) unicodeCharacter->x_min_offset;
612 char_y_min = unicode_ctx->font->y_min;
613 char_y_min += (uint16_t) unicodeCharacter->y_min_offset;
614 char_x_max -= (uint16_t) unicodeCharacter->x_max_offset;
615 char_y_max -= (uint16_t) unicodeCharacter->y_max_offset;
616 }
617
618 char_byte_cnt = nbgl_getUnicodeFontCharacterByteCount();
619 encoding = unicodeCharacter->encoding;
620#endif // defined(HAVE_LANGUAGE_PACK)
621#else // HAVE_UNICODE_SUPPORT
622 continue;
623#endif // HAVE_UNICODE_SUPPORT
624 }
625 else {
626 if (unicode == '\f') {
627 break;
628 }
629 // if \b, switch fontId
630 else if (unicode == '\b') {
631 if (fontId == BAGL_FONT_OPEN_SANS_REGULAR_11px_1bpp) { // switch to bold
633#ifdef HAVE_UNICODE_SUPPORT
634 unicode_ctx = nbgl_getUnicodeFont(fontId);
635#endif // HAVE_UNICODE_SUPPORT
636 font = (const nbgl_font_t *) nbgl_getFont(fontId);
637 }
638 else if (fontId == BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp) { // switch to regular
640#ifdef HAVE_UNICODE_SUPPORT
641 unicode_ctx = nbgl_getUnicodeFont(fontId);
642#endif // HAVE_UNICODE_SUPPORT
643 font = (const nbgl_font_t *) nbgl_getFont(fontId);
644 }
645 continue;
646 }
647 // if not supported char, go to next one
648 if ((unicode < font->first_char) || (unicode > font->last_char)) {
649 continue;
650 }
651 character = (const nbgl_font_character_t *) PIC(
652 &font->characters[unicode - font->first_char]);
653 char_buffer = (const uint8_t *) PIC(&font->bitmap[character->bitmap_offset]);
654 char_width = character->width;
655 encoding = character->encoding;
656
657 char_x_max = char_width;
658 char_y_max = font->height;
659
660 if (!font->crop) {
661 // Take in account the skipped bytes, if any
662 nb_skipped_bytes = (character->x_min_offset & 7) << 3;
663 nb_skipped_bytes |= character->y_min_offset & 7;
664 char_x_min = 0;
665 char_y_min = 0;
666 }
667 else {
668 nb_skipped_bytes = 0;
669 char_x_min = (uint16_t) character->x_min_offset;
670 char_y_min = font->y_min;
671 char_y_min += (uint16_t) character->y_min_offset;
672 char_x_max -= (uint16_t) character->x_max_offset;
673 char_y_max -= (uint16_t) character->y_max_offset;
674 }
675
676 char_byte_cnt = get_bitmap_byte_cnt(font, unicode);
677 }
678
679 // Render character
680 rectArea.x0 = x + char_x_min;
681 rectArea.y0 = area->y0 + char_y_min;
682 rectArea.height = (char_y_max - char_y_min);
683 rectArea.width = (char_x_max - char_x_min);
684
685 // If char_byte_cnt = 0, call nbgl_frontDrawImageRle to let speculos notice
686 // a space character was 'displayed'
687 if (!char_byte_cnt || encoding == 1) {
689 &rectArea, char_buffer, char_byte_cnt, fontColor, nb_skipped_bytes);
690 }
691 else {
692 nbgl_frontDrawImage(&rectArea, char_buffer, NO_TRANSFORMATION, fontColor);
693 }
694 x += char_width - font->char_kerning;
695 }
696 return fontId;
697}
698
699#ifdef NBGL_QRCODE
700static void nbgl_frontDrawQrInternal(const nbgl_area_t *area,
701 color_t foregroundColor,
702 nbgl_qrcode_version_t version)
703{
704 int size = qrcodegen_getSize(qrcode);
705 uint16_t idx = 0;
706
707 nbgl_area_t qrArea = {.x0 = area->x0,
708 .y0 = area->y0,
709 .backgroundColor = area->backgroundColor,
710 // QR codes are 1 BPP only
711 .bpp = NBGL_BPP_1};
712 if (version == QRCODE_V4) {
713 // for each point of the V4 QR code, paint 64 pixels in image (8 in width, 8 in height)
714 qrArea.width = 2;
715 qrArea.height = QR_PIXEL_WIDTH_HEIGHT * 2 * size;
716 // paint a column of 2*size pixels in width by 8 pixels in height
717 for (int x = 0; x < size; x++) {
718 idx = 0;
719 for (int y = 0; y < size; y++) {
720 // draw 2 columns at once
721 QrDrawBuffer[idx] = qrcodegen_getModule(qrcode, x, y) ? 0xFF : 0x00;
723 idx += 1;
724 }
725 nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor);
726 qrArea.x0 += 2;
727 nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor);
728 qrArea.x0 += 2;
729 nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor);
730 qrArea.x0 += 2;
731 nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor);
732 qrArea.x0 += 2;
733 }
734 }
735 else { // V4 small or V10
736 // for each point of the V10 QR code, paint 16 pixels in image (4 in width, 4 in height)
737 qrArea.width = QR_PIXEL_WIDTH_HEIGHT * size;
738 qrArea.height = QR_PIXEL_WIDTH_HEIGHT;
739 // paint a line of 4*size pixels in width by 4 pixels in height
740 for (int y = 0; y < size; y++) {
741 idx = 0;
742 for (int x = 0; x < size; x++) {
743 memset(&QrDrawBuffer[idx], qrcodegen_getModule(qrcode, x, y) ? 0xFF : 0x00, 2);
744 idx += 2;
745 }
746 nbgl_frontDrawImage(&qrArea, QrDrawBuffer, NO_TRANSFORMATION, foregroundColor);
747 qrArea.y0 += QR_PIXEL_WIDTH_HEIGHT;
748 }
749 }
750}
751
765 nbgl_qrcode_version_t version,
766 const char *text,
767 color_t foregroundColor)
768{
769 uint8_t versionNum = (version == QRCODE_V10) ? 10 : 4;
770 bool ok = qrcodegen_encodeText(text,
772 qrcode,
773 qrcodegen_Ecc_LOW,
774 versionNum,
775 versionNum,
776 qrcodegen_Mask_AUTO,
777 true);
778
779 if (ok) {
780 nbgl_frontDrawQrInternal(area, foregroundColor, version);
781 }
782 else {
783 LOG_WARN(
784 DRAW_LOGGER, "Impossible to draw QRCode text %s with version %d\n", text, versionNum);
785 }
786}
787#endif // NBGL_QRCODE
debug traces management
#define LOG_WARN(__logger,...)
Definition nbgl_debug.h:87
#define LOG_DEBUG(__logger,...)
Definition nbgl_debug.h:86
@ DRAW_LOGGER
Definition nbgl_debug.h:29
#define QrDrawBuffer
Definition nbgl_draw.c:48
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
#define QR_PIXEL_WIDTH_HEIGHT
Definition nbgl_draw.c:34
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
quarter_t
Definition nbgl_draw.c:27
@ BAGL_FILL_CIRCLE_PI_3PI2
Definition nbgl_draw.c:30
@ BAGL_FILL_CIRCLE_0_PI2
Definition nbgl_draw.c:28
@ BAGL_FILL_CIRCLE_3PI2_2PI
Definition nbgl_draw.c:31
@ BAGL_FILL_CIRCLE_PI2_PI
Definition nbgl_draw.c:29
#define tempBuffer
Definition nbgl_draw.c:47
#define qrcode
Definition nbgl_draw.c:46
void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, nbgl_radius_t radiusIndex, 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
CCASSERT(qr_code_buffer, sizeof(QrCodeBuffer_t)<=GZLIB_UNCOMPRESSED_CHUNK)
void nbgl_drawQrCode(const nbgl_area_t *area, nbgl_qrcode_version_t version, const char *text, color_t foregroundColor)
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 radiusIndex, color_t innerColor)
This functions draws a rounded corners rectangle (without border), with the given parameters.
Definition nbgl_draw.c:249
Middle Level API of the new BOLOS Graphical Library.
#define QR_MAX_PIX_SIZE
Definition nbgl_draw.h:25
#define QR_V4_NB_PIX_SIZE
Definition nbgl_draw.h:23
uint32_t nbgl_popUnicodeChar(const uint8_t **text, uint16_t *text_length, bool *is_unicode)
Get the coming unicode value on the given UTF-8 string. If the value is a simple ASCII character,...
Definition nbgl_fonts.c:140
nbgl_font_id_e
Definition nbgl_fonts.h:136
@ BAGL_FONT_OPEN_SANS_REGULAR_11px_1bpp
Definition nbgl_fonts.h:145
@ BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp
Definition nbgl_fonts.h:143
const nbgl_font_t * nbgl_getFont(nbgl_font_id_e fontId)
Font screen low-Level driver API, to draw elementary forms.
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_frontDrawImageRle(const nbgl_area_t *area, const uint8_t *buffer, uint32_t buffer_len, color_t fore_color, uint8_t nb_skipped_bytes)
void nbgl_frontDrawHorizontalLine(const nbgl_area_t *area, uint8_t mask, color_t lineColor)
void nbgl_frontDrawRect(const nbgl_area_t *area)
Side screen low-Level driver API, to draw elementary forms.
uint8_t ramBuffer[]
Definition nbgl_obj.c:131
color_t
Definition nbgl_types.h:120
uint8_t nbgl_transformation_t
Represents the transformation to be applied on the bitmap before rendering This is a bitfield using m...
Definition nbgl_types.h:362
#define VERTICAL_MIRROR
Definition nbgl_types.h:80
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:369
nbgl_radius_t
possible radius indexes for objects
Definition nbgl_types.h:343
@ RADIUS_MAX
Definition nbgl_types.h:349
@ RADIUS_0_PIXELS
no radius (square angle)
Definition nbgl_types.h:355
nbgl_qrcode_version_t
possible modes for QR Code
Definition nbgl_types.h:209
@ QRCODE_V10
QRCode V10, can encode text len up to 1500 chars, display size = 228*228.
Definition nbgl_types.h:211
@ QRCODE_V4
QRCode V4, can encode text len up to 62 chars, display size = 264*264.
Definition nbgl_types.h:210
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:285
#define NO_TRANSFORMATION
Definition nbgl_types.h:74
nbgl_bpp_t
Enum to represent the number of bits per pixel (BPP)
Definition nbgl_types.h:263
@ NBGL_BPP_1
1 bit per pixel
Definition nbgl_types.h:264
struct PACKED__ nbgl_area_s nbgl_area_t
Represents a rectangle area of the screen.
fonts nicknames to be used for various wallet size targets (non-Nano)
Definition nbgl_fonts.h:62
uint32_t width
width of character in pixels
Definition nbgl_fonts.h:65
uint32_t encoding
method used to encode bitmap data
Definition nbgl_fonts.h:64
uint32_t x_min_offset
x_min = x_min_offset
Definition nbgl_fonts.h:66
uint32_t bitmap_offset
offset of this character in chars buffer
Definition nbgl_fonts.h:63
uint32_t y_min_offset
y_min = (y_min + y_min_offset)
Definition nbgl_fonts.h:67
uint32_t x_max_offset
x_max = width - x_max_offset
Definition nbgl_fonts.h:68
uint32_t y_max_offset
y_max = (height - y_max_offset)
Definition nbgl_fonts.h:69
structure defining an ASCII font
Definition nbgl_fonts.h:76
uint8_t char_kerning
kerning for the font
Definition nbgl_fonts.h:82
uint8_t crop
If false, x_min_offset+y_min_offset=bytes to skip.
Definition nbgl_fonts.h:83
uint8_t first_char
ASCII code of the first character in bitmap and in characters fields.
Definition nbgl_fonts.h:86
uint32_t bitmap_len
Size in bytes of the associated bitmap.
Definition nbgl_fonts.h:77
uint8_t const * bitmap
array containing bitmaps of all characters
Definition nbgl_fonts.h:91
const nbgl_font_character_t *const characters
array containing definitions of all characters
Definition nbgl_fonts.h:90
uint8_t height
height of all characters in pixels
Definition nbgl_fonts.h:80
uint8_t last_char
ASCII code of the last character in bitmap and in characters fields.
Definition nbgl_fonts.h:88
uint8_t y_min
Most top Y coordinate of any char in the font.
Definition nbgl_fonts.h:84
uint8_t bpp
number of bits per pixels
Definition nbgl_fonts.h:79
structure defining a unicode character (except the bitmap)
Definition nbgl_fonts.h:104
uint32_t encoding
method used to encode bitmap data
Definition nbgl_fonts.h:106
uint32_t width
width of character in pixels
Definition nbgl_fonts.h:107
uint32_t x_min_offset
x_min = x_min_offset
Definition nbgl_fonts.h:108
uint32_t y_min_offset
y_min = (y_min + y_min_offset)
Definition nbgl_fonts.h:109
uint32_t y_max_offset
y_max = (height - y_max_offset)
Definition nbgl_fonts.h:111
uint32_t x_max_offset
x_max = width - x_max_offset
Definition nbgl_fonts.h:110
uint32_t bitmap_offset
offset of this character in chars buffer
Definition nbgl_fonts.h:112
uint8_t crop
If false, x_min_offset+y_min_offset=bytes to skip.
Definition nbgl_fonts.h:125
uint8_t y_min
Most top Y coordinate of any char in the font.
Definition nbgl_fonts.h:126
uint8_t height
height of all characters in pixels
Definition nbgl_fonts.h:122
const nbgl_font_unicode_t * font
Definition nbgl_fonts.h:156
const uint8_t * bitmap
Definition nbgl_fonts.h:158
const uint8_t * topLeftCircle
Definition nbgl_draw.c:55
const uint8_t * bottomLeftCircle
Definition nbgl_draw.c:56
const uint8_t * bottomLeftDisc
Definition nbgl_draw.c:54
const uint8_t * topLeftDisc
Definition nbgl_draw.c:53
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