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
41#define COMBINED_HEIGHT 9
44#define MAX_RLE_COPY_PIXELS 5
47#define RLE_CMD_COPY_2 0x00
48#define RLE_CMD_COPY_3 0x01
49#define RLE_CMD_COPY_4 0x02
50#define RLE_CMD_COPY_5 0x03
51#define RLE_CMD_FILL_3 0x04
52#define RLE_CMD_FILL_2 0x05
53#define RLE_CMD_2PATTERN_INDEXED_B2W 0x06
54#define RLE_CMD_2PATTERN_INDEXED_W2B 0x07
55#define RLE_CMD_1PATTERN_B2W 0x08
56#define RLE_CMD_1PATTERN_W2B 0x09
57#define RLE_CMD_2PATTERN_B2W 0x0A
58#define RLE_CMD_2PATTERN_W2B 0x0B
59#define RLE_CMD_FILL_BLACK 0x0C
60#define RLE_CMD_FILL_1 0x0D
61#define RLE_CMD_FILL_WHITE 0x0E
62#define RLE_CMD_FILL_WHITE_16 0x0F
103static uint16_t get_bitmap_byte_cnt(
const nbgl_font_t *font, uint8_t charId)
105 if ((charId < font->first_char) || (charId > font->
last_char)) {
110 if (charId < font->last_char) {
124#ifdef SCREEN_SIZE_WALLET
142static void nbgl_draw1BPPImageRle(
nbgl_area_t *area,
143 const uint8_t *buffer,
147 uint8_t nb_skipped_bytes)
151 size_t nb_zeros = (size_t) nb_skipped_bytes * 8;
154 size_t remaining_height = area->width;
155 size_t remaining_width = area->height;
156 size_t dst_index = 0;
160#ifdef BUILD_SCREENSHOTS
161 assert((buf_area->width & 7) == 0);
162 assert((buf_area->height & 7) == 0);
165 dst += buf_area->y0 * buf_area->width / 8;
166 dst += buf_area->x0 / 8;
167 white_pixel = 0x80 >> (buf_area->x0 & 7);
170 while (remaining_height && (index < buffer_len || nb_zeros || nb_ones)) {
172 while (!nb_zeros && !nb_ones && index < buffer_len) {
173 uint8_t
byte = buffer[index++];
174 nb_ones =
byte & 0x0F;
175 nb_zeros =
byte >> 4;
185 pixels |= white_pixel;
190 dst[dst_index++] |= pixels;
196 if (!remaining_width) {
198 remaining_width = area->height;
201 dst[dst_index] |= pixels;
204 dst += buf_area->width / 8;
207 white_pixel = 0x80 >> (buf_area->x0 & 7);
214 dst[dst_index] |= pixels;
219static inline uint8_t get_next_quartet(
rle_context_t *context)
225 quartet = context->
byte >> 4;
228 else if (context->
nb_bits == 4) {
229 quartet = context->
byte & 0x0F;
245static inline void get_next_pixels(
rle_context_t *context,
size_t remaining_width)
248 uint8_t cmd = get_next_quartet(context);
253 context->
nb_pix = remaining_width;
254 context->
copy =
false;
255 context->
color = 0xF;
276 for (uint8_t i = 0; i < cmd; i++) {
277 context->
pixels[i] = get_next_quartet(context);
279 context->
copy =
true;
287 context->
copy =
false;
288 context->
color = get_next_quartet(context);
289 context->
nb_pix = get_next_quartet(context) + 3;
294 context->
copy =
false;
295 context->
color = get_next_quartet(context);
301 context->
copy =
false;
303 context->
nb_pix = get_next_quartet(context) + 1;
308 context->
copy =
false;
309 context->
color = get_next_quartet(context);
315 context->
copy =
false;
316 context->
color = 0x0F;
317 context->
nb_pix = get_next_quartet(context) + 1;
322 context->
copy =
false;
323 context->
color = 0x0F;
324 context->
nb_pix = get_next_quartet(context) + 16 + 1;
331 uint8_t index = get_next_quartet(context);
332 uint8_t pattern = context->
patterns[index];
334 context->
pixels[0] = 0x00;
335 context->
pixels[1] = pattern >> 4;
336 context->
pixels[2] = pattern & 0x0F;
337 context->
pixels[3] = 0x0F;
339 context->
copy =
true;
346 uint8_t index = get_next_quartet(context);
347 uint8_t pattern = context->
patterns[index];
349 context->
pixels[0] = 0x0F;
350 context->
pixels[1] = pattern & 0x0F;
351 context->
pixels[2] = pattern >> 4;
352 context->
pixels[3] = 0x00;
354 context->
copy =
true;
361 context->
pixels[0] = 0x00;
362 context->
pixels[1] = get_next_quartet(context);
363 context->
pixels[2] = 0x0F;
365 context->
copy =
true;
372 context->
pixels[0] = 0x0F;
373 context->
pixels[1] = get_next_quartet(context);
374 context->
pixels[2] = 0x00;
376 context->
copy =
true;
383 context->
pixels[0] = 0x00;
384 context->
pixels[1] = get_next_quartet(context);
385 context->
pixels[2] = get_next_quartet(context);
386 context->
pixels[3] = 0x0F;
388 context->
copy =
true;
395 context->
pixels[0] = 0x0F;
396 context->
pixels[2] = get_next_quartet(context);
397 context->
pixels[1] = get_next_quartet(context);
398 context->
pixels[3] = 0x00;
400 context->
copy =
true;
444 const uint8_t *buffer,
446 const uint8_t *patterns,
449 uint8_t nb_skipped_bytes)
452 size_t remaining_height = area->width;
453 size_t remaining_width = area->height;
454 size_t dst_index = 0;
455 uint8_t dst_shift = 4;
463#ifdef BUILD_SCREENSHOTS
464 assert((buf_area->width & 7) == 0);
465 assert((buf_area->height & 7) == 0);
472 context.
byte = buffer[0];
477 if (nb_skipped_bytes) {
478 context.
nb_pix = nb_skipped_bytes * 2;
480 context.
copy =
false;
483 dst += buf_area->y0 * buf_area->width / 2;
484 dst += buf_area->x0 / 2;
487 if (buf_area->x0 & 1) {
491 while (remaining_height) {
495 if (context.
nb_pix == 0) {
496 get_next_pixels(&context, remaining_width);
500 if (nb_pix > remaining_width) {
501 nb_pix = remaining_width;
505 if (context.
copy ==
false) {
507 if (context.
color == 0x0F) {
508 dst[dst_index] = dst_pixel;
509 dst_index += nb_pix / 2;
516 dst_pixel = dst[dst_index];
520 for (uint8_t i = 0; i < nb_pix; i++) {
521 dst_pixel &= ~(0x0F << dst_shift);
522 dst_pixel |= context.
color << dst_shift;
526 dst[dst_index] = dst_pixel;
528 dst_pixel = dst[dst_index];
534 uint8_t *pixels = context.
pixels;
540 for (uint8_t i = 0; i < nb_pix; i++) {
541 uint8_t color = pixels[i];
544 dst_pixel &= ~(0x0F << dst_shift);
545 dst_pixel |= color << dst_shift;
550 dst[dst_index] = dst_pixel;
552 dst_pixel = dst[dst_index];
561 remaining_width -= nb_pix;
564 if (remaining_width == 0) {
566 remaining_width = area->height;
569 dst[dst_index] = dst_pixel;
572 dst += buf_area->width / 2;
573 dst_pixel = dst[dst_index];
574 if (buf_area->x0 & 1) {
597static void nbgl_drawImageRle(
nbgl_area_t *text_area,
598 const uint8_t *buffer,
600 const uint8_t *patterns,
603 uint8_t nb_skipped_bytes)
607 text_area, buffer, buffer_len, patterns, buf_area, dst, nb_skipped_bytes);
610 nbgl_draw1BPPImageRle(text_area, buffer, buffer_len, buf_area, dst, nb_skipped_bytes);
624 const uint8_t *buffer,
628 uint32_t buffer_len = ((area->width * area->height) + 1) / 2;
631 size_t remaining_height = area->width;
632 size_t remaining_width = area->height;
633 size_t dst_index = 0;
634 uint8_t dst_shift = 4;
636 uint8_t src_nb_pix, src_pixels[2];
642#ifdef BUILD_SCREENSHOTS
643 assert((buf_area->width & 7) == 0);
644 assert((buf_area->height & 7) == 0);
647 dst += buf_area->y0 * buf_area->width / 2;
648 dst += buf_area->x0 / 2;
651 if (buf_area->x0 & 1) {
654 src_pixels[0] = buffer[index++];
655 src_pixels[1] = src_pixels[0] >> 4;
656 src_pixels[0] &= 0x0F;
659 while (remaining_height) {
663 if (src_nb_pix == 0) {
664 if (index < buffer_len) {
665 src_pixels[0] = buffer[index++];
666 src_pixels[1] = src_pixels[0] >> 4;
667 src_pixels[0] &= 0x0F;
673 src_pixels[0] = 0x0F;
674 src_pixels[1] = 0x0F;
675 src_nb_pix = remaining_width;
680 if (nb_pix > remaining_width) {
681 nb_pix = remaining_width;
684 for (uint8_t i = 0; i < nb_pix; i++) {
685 uint8_t color = src_pixels[i];
688 dst_pixel &= ~(0x0F << dst_shift);
689 dst_pixel |= color << dst_shift;
694 dst[dst_index] = dst_pixel;
696 dst_pixel = dst[dst_index];
701 src_nb_pix -= nb_pix;
702 remaining_width -= nb_pix;
705 if (remaining_width == 0) {
707 remaining_width = area->height;
710 dst[dst_index] = dst_pixel;
713 dst += buf_area->width / 2;
714 dst_pixel = dst[dst_index];
715 if (buf_area->x0 & 1) {
736 const uint8_t *buffer,
741 uint32_t buffer_len = ((area->width * area->height) + 7) / 8;
743 size_t remaining_height = area->width;
744 size_t remaining_width = area->height;
745 size_t dst_index = 0;
748 uint8_t src_byte, src_msk;
750#ifdef BUILD_SCREENSHOTS
751 assert((buf_area->width & 7) == 0);
752 assert((buf_area->height & 7) == 0);
755 dst += buf_area->y0 * buf_area->width / 8;
756 dst += buf_area->x0 / 8;
757 white_pixel = 0x80 >> (buf_area->x0 & 7);
760 src_byte = buffer[index++];
763 while (remaining_height && (index < buffer_len || src_msk)) {
765 if (!src_msk && index < buffer_len) {
766 src_byte = buffer[index++];
770 if (src_byte & src_msk) {
771 pixels |= white_pixel;
781 dst[dst_index++] |= pixels;
787 if (!remaining_width) {
789 remaining_width = area->height;
792 dst[dst_index] |= pixels;
795 dst += buf_area->width / 8;
798 white_pixel = 0x80 >> (buf_area->x0 & 7);
805 dst[dst_index] |= pixels;
818 const uint8_t *buffer,
823 nbgl_draw4BPPImage(text_area, buffer, buf_area, dst);
826 nbgl_draw1BPPImage(text_area, buffer, buf_area, dst);
838static void pack_ram_buffer(
nbgl_area_t *area, uint16_t width, uint16_t height)
844 uint16_t bytes_per_line;
847 src += area->y0 * area->width / 2;
849 bytes_per_line = (width + 1) / 2;
850 skip = (area->width + 1) / 2;
855 skip -= bytes_per_line;
856 for (uint16_t h = 0; h < height; h++) {
857 for (uint16_t w = 0; w < bytes_per_line; w++) {
858 uint8_t
byte = *src++ & 0x0F;
867 for (uint16_t y = 0; y < height; y++) {
868 memmove(dst, src, bytes_per_line);
869 dst += bytes_per_line;
878 uint8_t dst_pixel = 0;
879 uint8_t dst_shift = 7;
881 src += area->y0 * area->width / 8;
883 for (uint16_t y = 0; y < height; y++) {
884 src_shift = (7 - (area->x0 & 7));
887 for (uint16_t x = 0; x < width; x++) {
888 dst_pixel |= ((src_pixel >> src_shift) & 1) << dst_shift;
889 if (dst_shift == 0) {
896 if (src_shift == 0) {
899 src_pixel = src[src_index];
903 src += area->width / 8;
906 if (dst_shift != 7) {
920static void display_ram_buffer(int16_t x_min,
930 buf_area->x0 = x_min;
931 buf_area->y0 = y_min;
932 char_area->height = ((x_max - x_min) + 3) & 0xFFFC;
933 char_area->width = y_max - y_min;
935 pack_ram_buffer(buf_area, char_area->height, char_area->width);
944 const uint8_t **text,
962 if (unicodeCharacter == NULL) {
963#ifdef BUILD_SCREENSHOTS
965 "Inside update_char_info, unicode (%c)[0x%X] is not supported!\n",
979#ifdef SCREEN_SIZE_WALLET
989 char_info->
x_min = 0;
990 char_info->
y_min = 0;
1000 char_info->
x_min = -(int16_t) unicodeCharacter->
width;
1021#ifdef BUILD_SCREENSHOTS
1023 "Inside update_char_info, unicode (%c)[0x%X] is not supported!\n",
1046 char_info->
x_min = 0;
1047 char_info->
y_min = 0;
1080 int16_t x = area->x0;
1085#ifdef SCREEN_SIZE_WALLET
1095 uint8_t redraw_buf_area = 0;
1116 buf_area.backgroundColor = 0xF;
1119 buf_area.backgroundColor = 0;
1121#ifdef BUILD_SCREENSHOTS
1133 "nbgl_drawText: x0 = %d, y0 = %d, w = %d, h = %d, fontColor = %d, "
1134 "backgroundColor=%d, text = %s\n",
1140 area->backgroundColor,
1143 current_area.backgroundColor = area->backgroundColor;
1146#ifndef SCREEN_SIZE_WALLET
1147 while (textLen > 0) {
1149 update_char_info(¤t_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1154 if (current_char.
unicode ==
'\f') {
1158 if (current_char.
unicode ==
'\b') {
1173 current_area.x0 = x + current_char.
x_min;
1174 current_area.y0 = area->y0 + current_char.
y_min;
1175 current_area.height = (current_char.
y_max - current_char.
y_min);
1176 current_area.width = (current_char.
x_max - current_char.
x_min);
1198 update_char_info(&next_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1200 while (textLen > 0 || next_char.
unicode) {
1202 current_char = next_char;
1204 update_char_info(&next_char, (
const uint8_t **) &text, &textLen, unicode_ctx, font);
1212 current_area.x0 = x + current_char.
x_min;
1214 current_area.y0 = area->y0 + current_char.
y_min;
1215 current_area.height = (current_char.
y_max - current_char.
y_min);
1216 current_area.width = (current_char.
x_max - current_char.
x_min);
1222 if (redraw_buf_area) {
1223 display_ram_buffer(buf_x_min,
1232 redraw_buf_area = 0;
1241 memset(
ramBuffer, 0xFF, (buf_area.height * buf_area.width / 2));
1244 memset(
ramBuffer, 0x0, (buf_area.height * buf_area.width / 8));
1251 buf_x_min = buf_area.x0;
1252 buf_x_max = buf_x_min + current_area.height;
1253 buf_y_min = buf_area.y0;
1254 buf_y_max = buf_y_min + current_area.width;
1262 if (previous_char.
unicode == 0) {
1263#ifdef BUILD_SCREENSHOTS
1265 "WARNING: First character '%c'(0x%X) is a composed one! (text=>%s<=)\n",
1274 if (current_char.
unicode != 0x00E31
1275 && (x + current_char.
x_min + current_char.
width) > next_x) {
1276 next_x = x + current_char.
x_min + current_char.
width;
1279 if (current_char.
unicode == 0x00E33) {
1296 if (current_char.
unicode >= 0x0E48 && current_char.
unicode <= 0x0E4C) {
1297 if (next_char.
unicode == 0x00E33) {
1301 -= (current_char.
y_max - current_char.
y_min) - 2;
1304 else if (previous_char.
unicode >= 0x0E31 && previous_char.
unicode <= 0x0E37) {
1306 buf_area.x0 = buf_x_min - (current_char.
y_max - current_char.
y_min) - 1;
1308 else if (current_char.
unicode == 0x0E4B && previous_char.
unicode == 0x0E1B) {
1310 buf_area.y0 -= current_char.
x_min / 2;
1314 if (buf_area.x0 < buf_x_min) {
1315 buf_x_min = buf_area.x0;
1317 if ((buf_area.x0 + current_area.height) > buf_x_max) {
1318 buf_x_max = buf_area.x0 + current_area.height;
1320 if (buf_area.y0 < buf_y_min) {
1321 buf_y_min = buf_area.y0;
1323 if ((buf_area.y0 + current_area.width) > buf_y_max) {
1324 buf_y_max = buf_area.y0 + current_area.width;
1331 nbgl_drawImageRle(¤t_area,
1340 nbgl_drawImage(¤t_area, current_char.
buffer, &buf_area,
ramBuffer);
1345 redraw_buf_area = 1;
1346 previous_area = current_area;
1349 previous_char = current_char;
1352 if (redraw_buf_area) {
1355 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.
#define RLE_CMD_2PATTERN_INDEXED_B2W
#define RLE_CMD_FILL_BLACK
STATIC void nbgl_draw4BPPImageRle(nbgl_area_t *area, const uint8_t *buffer, uint32_t buffer_len, const uint8_t *patterns, nbgl_area_t *buf_area, uint8_t *dst, uint8_t nb_skipped_bytes)
Uncompress a 4BPP RLE-encoded glyph and draw it in a RAM buffer (we handle transparency,...
#define RLE_CMD_2PATTERN_W2B
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 RLE_CMD_FILL_WHITE_16
#define RLE_CMD_2PATTERN_INDEXED_W2B
#define AVERAGE_CHAR_WIDTH
#define RLE_CMD_1PATTERN_W2B
#define RLE_CMD_FILL_WHITE
STATIC void update_char_info(character_info_t *char_info, const uint8_t **text, uint16_t *textLen, nbgl_unicode_ctx_t *unicode_ctx, const nbgl_font_t *font)
#define MAX_RLE_COPY_PIXELS
#define RLE_CMD_1PATTERN_B2W
#define RLE_CMD_2PATTERN_B2W
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 encoding
method used to encode bitmap data
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]