16#ifdef BUILD_SCREENSHOTS
26#ifdef SCREEN_SIZE_WALLET
27#define MAX_FONT_HEIGHT 54
28#define AVERAGE_CHAR_WIDTH 40
30#define MAX_FONT_HEIGHT 24
31#define AVERAGE_CHAR_WIDTH 24
35#define COMBINED_HEIGHT 9
38#define MAX_RLE_COPY_PIXELS 6
94static uint16_t get_bitmap_byte_cnt(
const nbgl_font_t *font, uint8_t charId)
96 if ((charId < font->first_char) || (charId > font->
last_char)) {
101 if (charId < font->last_char) {
115#ifdef SCREEN_SIZE_WALLET
133static void nbgl_draw1BPPImageRle(
nbgl_area_t *area,
134 const uint8_t *buffer,
138 uint8_t nb_skipped_bytes)
142 size_t nb_zeros = (size_t) nb_skipped_bytes * 8;
145 size_t remaining_height = area->width;
146 size_t remaining_width = area->height;
147 size_t dst_index = 0;
151#ifdef BUILD_SCREENSHOTS
152 assert((buf_area->width & 7) == 0);
153 assert((buf_area->height & 7) == 0);
156 dst += buf_area->y0 * buf_area->width / 8;
157 dst += buf_area->x0 / 8;
158 white_pixel = 0x80 >> (buf_area->x0 & 7);
161 while (remaining_height && (index < buffer_len || nb_zeros || nb_ones)) {
163 while (!nb_zeros && !nb_ones && index < buffer_len) {
164 uint8_t
byte = buffer[index++];
165 nb_ones =
byte & 0x0F;
166 nb_zeros =
byte >> 4;
176 pixels |= white_pixel;
181 dst[dst_index++] |= pixels;
187 if (!remaining_width) {
189 remaining_width = area->height;
192 dst[dst_index] |= pixels;
195 dst += buf_area->width / 8;
198 white_pixel = 0x80 >> (buf_area->x0 & 7);
205 dst[dst_index] |= pixels;
210static inline void get_next_pixels(
rle_context_t *context,
size_t remaining_width)
215 context->
nb_pix = remaining_width;
216 context->
color = 0xF;
226 context->
nb_pix = (
byte & 0x3F) + 1;
227 context->
color = 0x0F;
238 context->
nb_pix = ((
byte & 0x30) >> 4);
240 context->
pixels[0] =
byte & 0x0F;
242 context->
pixels[1] =
byte >> 4;
243 context->
pixels[2] =
byte & 0x0F;
244 if (context->
nb_pix >= 4) {
246 context->
pixels[3] =
byte >> 4;
247 context->
pixels[4] =
byte & 0x0F;
248 if (context->
nb_pix >= 6) {
250 context->
pixels[5] =
byte >> 4;
253 context->
color = 0x10;
258 context->
nb_pix = (
byte & 0x70) >> 4;
260 context->
color =
byte & 0x0F;
296static void nbgl_draw4BPPImageRle(
nbgl_area_t *area,
297 const uint8_t *buffer,
301 uint8_t nb_skipped_bytes)
304 size_t remaining_height = area->width;
305 size_t remaining_width = area->height;
306 size_t dst_index = 0;
307 uint8_t dst_shift = 4;
315#ifdef BUILD_SCREENSHOTS
316 assert((buf_area->width & 7) == 0);
317 assert((buf_area->height & 7) == 0);
324 if (nb_skipped_bytes) {
325 context.
nb_pix = nb_skipped_bytes * 2;
329 dst += buf_area->y0 * buf_area->width / 2;
330 dst += buf_area->x0 / 2;
333 if (buf_area->x0 & 1) {
337 while (remaining_height) {
341 if (context.
nb_pix == 0) {
342 get_next_pixels(&context, remaining_width);
346 if (nb_pix > remaining_width) {
347 nb_pix = remaining_width;
351 if (context.
color <= 0x0F) {
353 if (context.
color == 0x0F) {
354 dst[dst_index] = dst_pixel;
355 dst_index += nb_pix / 2;
362 dst_pixel = dst[dst_index];
366 for (uint8_t i = 0; i < nb_pix; i++) {
367 dst_pixel &= ~(0x0F << dst_shift);
368 dst_pixel |= context.
color << dst_shift;
372 dst[dst_index] = dst_pixel;
374 dst_pixel = dst[dst_index];
380 uint8_t *pixels = context.
pixels;
382 pixels += context.
color & 0x0F;
386 for (uint8_t i = 0; i < nb_pix; i++) {
387 uint8_t color = pixels[i];
390 dst_pixel &= ~(0x0F << dst_shift);
391 dst_pixel |= color << dst_shift;
396 dst[dst_index] = dst_pixel;
398 dst_pixel = dst[dst_index];
402 context.
color += nb_pix;
407 remaining_width -= nb_pix;
410 if (remaining_width == 0) {
412 remaining_width = area->height;
415 dst[dst_index] = dst_pixel;
418 dst += buf_area->width / 2;
419 dst_pixel = dst[dst_index];
420 if (buf_area->x0 & 1) {
442static void nbgl_drawImageRle(
nbgl_area_t *text_area,
443 const uint8_t *buffer,
447 uint8_t nb_skipped_bytes)
450 nbgl_draw4BPPImageRle(text_area, buffer, buffer_len, buf_area, dst, nb_skipped_bytes);
453 nbgl_draw1BPPImageRle(text_area, buffer, buffer_len, buf_area, dst, nb_skipped_bytes);
467 const uint8_t *buffer,
471 uint32_t buffer_len = ((area->width * area->height) + 1) / 2;
474 size_t remaining_height = area->width;
475 size_t remaining_width = area->height;
476 size_t dst_index = 0;
477 uint8_t dst_shift = 4;
479 uint8_t src_nb_pix, src_pixels[2];
485#ifdef BUILD_SCREENSHOTS
486 assert((buf_area->width & 7) == 0);
487 assert((buf_area->height & 7) == 0);
490 dst += buf_area->y0 * buf_area->width / 2;
491 dst += buf_area->x0 / 2;
494 if (buf_area->x0 & 1) {
497 src_pixels[0] = buffer[index++];
498 src_pixels[1] = src_pixels[0] >> 4;
499 src_pixels[0] &= 0x0F;
502 while (remaining_height) {
506 if (src_nb_pix == 0) {
507 if (index < buffer_len) {
508 src_pixels[0] = buffer[index++];
509 src_pixels[1] = src_pixels[0] >> 4;
510 src_pixels[0] &= 0x0F;
516 src_pixels[0] = 0x0F;
517 src_pixels[1] = 0x0F;
518 src_nb_pix = remaining_width;
523 if (nb_pix > remaining_width) {
524 nb_pix = remaining_width;
527 for (uint8_t i = 0; i < nb_pix; i++) {
528 uint8_t color = src_pixels[i];
531 dst_pixel &= ~(0x0F << dst_shift);
532 dst_pixel |= color << dst_shift;
537 dst[dst_index] = dst_pixel;
539 dst_pixel = dst[dst_index];
544 src_nb_pix -= nb_pix;
545 remaining_width -= nb_pix;
548 if (remaining_width == 0) {
550 remaining_width = area->height;
553 dst[dst_index] = dst_pixel;
556 dst += buf_area->width / 2;
557 dst_pixel = dst[dst_index];
558 if (buf_area->x0 & 1) {
579 const uint8_t *buffer,
584 uint32_t buffer_len = ((area->width * area->height) + 7) / 8;
586 size_t remaining_height = area->width;
587 size_t remaining_width = area->height;
588 size_t dst_index = 0;
591 uint8_t src_byte, src_msk;
593#ifdef BUILD_SCREENSHOTS
594 assert((buf_area->width & 7) == 0);
595 assert((buf_area->height & 7) == 0);
598 dst += buf_area->y0 * buf_area->width / 8;
599 dst += buf_area->x0 / 8;
600 white_pixel = 0x80 >> (buf_area->x0 & 7);
603 src_byte = buffer[index++];
606 while (remaining_height && (index < buffer_len || src_msk)) {
608 if (!src_msk && index < buffer_len) {
609 src_byte = buffer[index++];
613 if (src_byte & src_msk) {
614 pixels |= white_pixel;
624 dst[dst_index++] |= pixels;
630 if (!remaining_width) {
632 remaining_width = area->height;
635 dst[dst_index] |= pixels;
638 dst += buf_area->width / 8;
641 white_pixel = 0x80 >> (buf_area->x0 & 7);
648 dst[dst_index] |= pixels;
661 const uint8_t *buffer,
666 nbgl_draw4BPPImage(text_area, buffer, buf_area, dst);
669 nbgl_draw1BPPImage(text_area, buffer, buf_area, dst);
681static void pack_ram_buffer(
nbgl_area_t *area, uint16_t width, uint16_t height)
687 uint16_t bytes_per_line;
690 src += area->y0 * area->width / 2;
692 bytes_per_line = (width + 1) / 2;
693 skip = (area->width + 1) / 2;
698 skip -= bytes_per_line;
699 for (uint16_t h = 0; h < height; h++) {
700 for (uint16_t w = 0; w < bytes_per_line; w++) {
701 uint8_t
byte = *src++ & 0x0F;
710 for (uint16_t y = 0; y < height; y++) {
711 memmove(dst, src, bytes_per_line);
712 dst += bytes_per_line;
721 uint8_t dst_pixel = 0;
722 uint8_t dst_shift = 7;
724 src += area->y0 * area->width / 8;
726 for (uint16_t y = 0; y < height; y++) {
727 src_shift = (7 - (area->x0 & 7));
730 for (uint16_t x = 0; x < width; x++) {
731 dst_pixel |= ((src_pixel >> src_shift) & 1) << dst_shift;
732 if (dst_shift == 0) {
739 if (src_shift == 0) {
742 src_pixel = src[src_index];
746 src += area->width / 8;
749 if (dst_shift != 7) {
763static void display_ram_buffer(int16_t x_min,
773 buf_area->x0 = x_min;
774 buf_area->y0 = y_min;
775 char_area->height = ((x_max - x_min) + 3) & 0xFFFC;
776 char_area->width = y_max - y_min;
778 pack_ram_buffer(buf_area, char_area->height, char_area->width);
787 const uint8_t **text,
801#ifdef HAVE_UNICODE_SUPPORT
803 = nbgl_getUnicodeFontCharacter(char_info->
unicode);
805 if (unicodeCharacter == NULL) {
806#ifdef BUILD_SCREENSHOTS
808 "Inside update_char_info, unicode (%c)[0x%X] is not supported!\n",
812 update_char_info(char_info, text, textLen, unicode_ctx, font);
816#if defined(HAVE_LANGUAGE_PACK)
822#ifdef SCREEN_SIZE_WALLET
832 char_info->
x_min = 0;
833 char_info->
y_min = 0;
843 char_info->
x_min = -(int16_t) unicodeCharacter->
width;
849 char_info->
x_min = (uint16_t) unicodeCharacter->x_min_offset;
850 char_info->
x_max -= (uint16_t) unicodeCharacter->x_max_offset;
853 char_info->byte_cnt = nbgl_getUnicodeFontCharacterByteCount();
854 char_info->encoding = unicodeCharacter->encoding;
855 char_info->height = char_info->y_max - char_info->y_min;
863 if (char_info->unicode ==
'\f' || char_info->unicode ==
'\b') {
868#ifdef BUILD_SCREENSHOTS
870 "Inside update_char_info, unicode (%c)[0x%X] is not supported!\n",
874 update_char_info(char_info, text, textLen, unicode_ctx, font);
882 char_info->encoding = character->
encoding;
883 char_info->over_previous = 0;
885 char_info->x_max = char_info->width;
886 char_info->y_max = font->
height;
890 char_info->nb_skipped_bytes = (character->
x_min_offset & 7) << 3;
891 char_info->nb_skipped_bytes |= character->
y_min_offset & 7;
892 char_info->x_min = 0;
893 char_info->y_min = 0;
896 char_info->nb_skipped_bytes = 0;
898 char_info->y_min = font->
y_min;
904 char_info->byte_cnt = get_bitmap_byte_cnt(font, char_info->unicode);
905 char_info->height = char_info->y_max - char_info->y_min;
926 int16_t x = area->x0;
930#ifdef HAVE_UNICODE_SUPPORT
935#ifdef SCREEN_SIZE_WALLET
945 uint8_t redraw_buf_area = 0;
957#ifdef HAVE_UNICODE_SUPPORT
964 buf_area.backgroundColor = 0xF;
967 buf_area.backgroundColor = 0;
969#ifdef BUILD_SCREENSHOTS
981 "nbgl_drawText: x0 = %d, y0 = %d, w = %d, h = %d, fontColor = %d, "
982 "backgroundColor=%d, text = %s\n",
988 area->backgroundColor,
991 current_area.backgroundColor = area->backgroundColor;
994#ifndef SCREEN_SIZE_WALLET
995 while (textLen > 0) {
997 update_char_info(¤t_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1002 if (current_char.
unicode ==
'\f') {
1006 if (current_char.
unicode ==
'\b') {
1009#ifdef HAVE_UNICODE_SUPPORT
1010 unicode_ctx = nbgl_getUnicodeFont(fontId);
1016#ifdef HAVE_UNICODE_SUPPORT
1017 unicode_ctx = nbgl_getUnicodeFont(fontId);
1025 current_area.x0 = x + current_char.
x_min;
1026 current_area.y0 = area->y0 + current_char.
y_min;
1027 current_area.height = (current_char.
y_max - current_char.
y_min);
1028 current_area.width = (current_char.
x_max - current_char.
x_min);
1050 update_char_info(&next_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1052 while (textLen > 0 || next_char.
unicode) {
1054 current_char = next_char;
1056 update_char_info(&next_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1064 current_area.x0 = x + current_char.
x_min;
1066 current_area.y0 = area->y0 + current_char.
y_min;
1067 current_area.height = (current_char.
y_max - current_char.
y_min);
1068 current_area.width = (current_char.
x_max - current_char.
x_min);
1074 if (redraw_buf_area) {
1075 display_ram_buffer(buf_x_min,
1084 redraw_buf_area = 0;
1093 memset(
ramBuffer, 0xFF, (buf_area.height * buf_area.width / 2));
1096 memset(
ramBuffer, 0x0, (buf_area.height * buf_area.width / 8));
1103 buf_x_min = buf_area.x0;
1104 buf_x_max = buf_x_min + current_area.height;
1105 buf_y_min = buf_area.y0;
1106 buf_y_max = buf_y_min + current_area.width;
1114 if (previous_char.
unicode == 0) {
1115#ifdef BUILD_SCREENSHOTS
1117 "WARNING: First character '%c'(0x%X) is a composed one! (text=>%s<=)\n",
1126 if (current_char.
unicode != 0x00E31
1127 && (x + current_char.
x_min + current_char.
width) > next_x) {
1128 next_x = x + current_char.
x_min + current_char.
width;
1131 if (current_char.
unicode == 0x00E33) {
1148 if (current_char.
unicode >= 0x0E48 && current_char.
unicode <= 0x0E4C) {
1149 if (next_char.
unicode == 0x00E33) {
1153 -= (current_char.
y_max - current_char.
y_min) - 2;
1156 else if (previous_char.
unicode >= 0x0E31 && previous_char.
unicode <= 0x0E37) {
1158 buf_area.x0 = buf_x_min - (current_char.
y_max - current_char.
y_min) - 1;
1160 else if (current_char.
unicode == 0x0E4B && previous_char.
unicode == 0x0E1B) {
1162 buf_area.y0 -= current_char.
x_min / 2;
1166 if (buf_area.x0 < buf_x_min) {
1167 buf_x_min = buf_area.x0;
1169 if ((buf_area.x0 + current_area.height) > buf_x_max) {
1170 buf_x_max = buf_area.x0 + current_area.height;
1172 if (buf_area.y0 < buf_y_min) {
1173 buf_y_min = buf_area.y0;
1175 if ((buf_area.y0 + current_area.width) > buf_y_max) {
1176 buf_y_max = buf_area.y0 + current_area.width;
1183 nbgl_drawImageRle(¤t_area,
1191 nbgl_drawImage(¤t_area, current_char.
buffer, &buf_area,
ramBuffer);
1196 redraw_buf_area = 1;
1197 previous_area = current_area;
1200 previous_char = current_char;
1203 if (redraw_buf_area) {
1206 buf_x_min, buf_y_min, buf_x_max, buf_y_max, area, &buf_area, &previous_area, fontColor);
#define LOG_DEBUG(__logger,...)
CCASSERT(qr_code_buffer, sizeof(QrCodeBuffer_t)<=GZLIB_UNCOMPRESSED_CHUNK)
Middle Level API of the new BOLOS Graphical Library.
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.
#define AVERAGE_CHAR_WIDTH
#define MAX_RLE_COPY_PIXELS
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,...
@ BAGL_FONT_OPEN_SANS_REGULAR_11px_1bpp
@ BAGL_FONT_OPEN_SANS_EXTRABOLD_11px_1bpp
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_frontDrawImageRle(const nbgl_area_t *area, const uint8_t *buffer, uint32_t buffer_len, color_t fore_color, uint8_t nb_skipped_bytes)
Side screen low-Level driver API, to draw elementary forms.
#define GZLIB_UNCOMPRESSED_CHUNK
size of gzlib uncompression buffer in bytes
#define NO_TRANSFORMATION
nbgl_bpp_t
Enum to represent the number of bits per pixel (BPP)
@ NBGL_BPP_1
1 bit per pixel
@ NBGL_BPP_4
4 bits per pixel
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)
uint32_t width
width of character in pixels
uint32_t encoding
method used to encode bitmap data
uint32_t x_min_offset
x_min = x_min_offset
uint32_t bitmap_offset
offset of this character in chars buffer
uint32_t y_min_offset
y_min = (y_min + y_min_offset)
uint32_t x_max_offset
x_max = width - x_max_offset
uint32_t y_max_offset
y_max = (height - y_max_offset)
structure defining an ASCII font
uint8_t char_kerning
kerning for the font
uint8_t crop
If false, x_min_offset+y_min_offset=bytes to skip.
uint8_t first_char
ASCII code of the first character in bitmap and in characters fields.
uint32_t bitmap_len
Size in bytes of the associated bitmap.
uint8_t const * bitmap
array containing bitmaps of all characters
const nbgl_font_character_t *const characters
array containing definitions of all characters
uint8_t height
height of all characters in pixels
uint8_t last_char
ASCII code of the last character in bitmap and in characters fields.
uint8_t y_min
Most top Y coordinate of any char in the font.
uint8_t bpp
number of bits per pixels
structure defining a unicode character (except the bitmap)
uint32_t width
width of character in pixels
uint32_t x_min_offset
x_min = x_min_offset
uint32_t y_min_offset
y_min = (y_min + y_min_offset)
uint32_t y_max_offset
y_max = (height - y_max_offset)
uint32_t over_previous
flag set to 1 when displayed over previous char
uint32_t x_max_offset
x_max = width - x_max_offset
uint32_t bitmap_offset
offset of this character in chars buffer
uint8_t crop
If false, x_min_offset+y_min_offset=bytes to skip.
uint8_t y_min
Most top Y coordinate of any char in the font.
uint8_t height
height of all characters in pixels
uint8_t line_height
height of a line for all characters in pixels
const nbgl_font_unicode_t * font
uint8_t pixels[MAX_RLE_COPY_PIXELS]