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,
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);
821#ifdef SCREEN_SIZE_WALLET
831 char_info->
x_min = 0;
832 char_info->
y_min = 0;
842 char_info->
x_min = -(int16_t) unicodeCharacter->
width;
848 char_info->
x_min = (uint16_t) unicodeCharacter->x_min_offset;
849 char_info->
x_max -= (uint16_t) unicodeCharacter->x_max_offset;
853 char_info->encoding = unicodeCharacter->encoding;
854 char_info->height = char_info->y_max - char_info->y_min;
858 if (char_info->unicode ==
'\f' || char_info->unicode ==
'\b') {
863#ifdef BUILD_SCREENSHOTS
865 "Inside update_char_info, unicode (%c)[0x%X] is not supported!\n",
869 update_char_info(char_info, text, textLen, unicode_ctx, font);
877 char_info->encoding = character->
encoding;
878 char_info->over_previous = 0;
880 char_info->x_max = char_info->width;
881 char_info->y_max = font->
height;
885 char_info->nb_skipped_bytes = (character->
x_min_offset & 7) << 3;
886 char_info->nb_skipped_bytes |= character->
y_min_offset & 7;
887 char_info->x_min = 0;
888 char_info->y_min = 0;
891 char_info->nb_skipped_bytes = 0;
893 char_info->y_min = font->
y_min;
899 char_info->byte_cnt = get_bitmap_byte_cnt(font, char_info->unicode);
900 char_info->height = char_info->y_max - char_info->y_min;
921 int16_t x = area->x0;
926#ifdef SCREEN_SIZE_WALLET
936 uint8_t redraw_buf_area = 0;
957 buf_area.backgroundColor = 0xF;
960 buf_area.backgroundColor = 0;
962#ifdef BUILD_SCREENSHOTS
974 "nbgl_drawText: x0 = %d, y0 = %d, w = %d, h = %d, fontColor = %d, "
975 "backgroundColor=%d, text = %s\n",
981 area->backgroundColor,
984 current_area.backgroundColor = area->backgroundColor;
987#ifndef SCREEN_SIZE_WALLET
988 while (textLen > 0) {
990 update_char_info(¤t_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
995 if (current_char.
unicode ==
'\f') {
999 if (current_char.
unicode ==
'\b') {
1014 current_area.x0 = x + current_char.
x_min;
1015 current_area.y0 = area->y0 + current_char.
y_min;
1016 current_area.height = (current_char.
y_max - current_char.
y_min);
1017 current_area.width = (current_char.
x_max - current_char.
x_min);
1039 update_char_info(&next_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1041 while (textLen > 0 || next_char.
unicode) {
1043 current_char = next_char;
1045 update_char_info(&next_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1053 current_area.x0 = x + current_char.
x_min;
1055 current_area.y0 = area->y0 + current_char.
y_min;
1056 current_area.height = (current_char.
y_max - current_char.
y_min);
1057 current_area.width = (current_char.
x_max - current_char.
x_min);
1063 if (redraw_buf_area) {
1064 display_ram_buffer(buf_x_min,
1073 redraw_buf_area = 0;
1082 memset(
ramBuffer, 0xFF, (buf_area.height * buf_area.width / 2));
1085 memset(
ramBuffer, 0x0, (buf_area.height * buf_area.width / 8));
1092 buf_x_min = buf_area.x0;
1093 buf_x_max = buf_x_min + current_area.height;
1094 buf_y_min = buf_area.y0;
1095 buf_y_max = buf_y_min + current_area.width;
1103 if (previous_char.
unicode == 0) {
1104#ifdef BUILD_SCREENSHOTS
1106 "WARNING: First character '%c'(0x%X) is a composed one! (text=>%s<=)\n",
1115 if (current_char.
unicode != 0x00E31
1116 && (x + current_char.
x_min + current_char.
width) > next_x) {
1117 next_x = x + current_char.
x_min + current_char.
width;
1120 if (current_char.
unicode == 0x00E33) {
1137 if (current_char.
unicode >= 0x0E48 && current_char.
unicode <= 0x0E4C) {
1138 if (next_char.
unicode == 0x00E33) {
1142 -= (current_char.
y_max - current_char.
y_min) - 2;
1145 else if (previous_char.
unicode >= 0x0E31 && previous_char.
unicode <= 0x0E37) {
1147 buf_area.x0 = buf_x_min - (current_char.
y_max - current_char.
y_min) - 1;
1149 else if (current_char.
unicode == 0x0E4B && previous_char.
unicode == 0x0E1B) {
1151 buf_area.y0 -= current_char.
x_min / 2;
1155 if (buf_area.x0 < buf_x_min) {
1156 buf_x_min = buf_area.x0;
1158 if ((buf_area.x0 + current_area.height) > buf_x_max) {
1159 buf_x_max = buf_area.x0 + current_area.height;
1161 if (buf_area.y0 < buf_y_min) {
1162 buf_y_min = buf_area.y0;
1164 if ((buf_area.y0 + current_area.width) > buf_y_max) {
1165 buf_y_max = buf_area.y0 + current_area.width;
1172 nbgl_drawImageRle(¤t_area,
1180 nbgl_drawImage(¤t_area, current_char.
buffer, &buf_area,
ramBuffer);
1185 redraw_buf_area = 1;
1186 previous_area = current_area;
1189 previous_char = current_char;
1192 if (redraw_buf_area) {
1195 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
nbgl_unicode_ctx_t * nbgl_getUnicodeFont(nbgl_font_id_e font_id)
Get the font entry for the given font id (sparse font array support)
const nbgl_font_unicode_character_t * nbgl_getUnicodeFontCharacter(uint32_t unicode)
Get the unicode character object matching the given unicode (a unicode character is encoded on max of...
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)
uint32_t nbgl_getUnicodeFontCharacterByteCount(void)
Get the bitmap byte count of the latest used unicode character. (the one returned by nbgl_getUnicodeF...
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]