From 7d84a9ffcd628a392bc27eef8521cc55b29af297 Mon Sep 17 00:00:00 2001 From: Nicolas Roggeman Date: Tue, 30 Jan 2024 16:46:13 +0100 Subject: [PATCH 1/4] Add new sizes of buttons, icons and other objects for Europa --- lib_nbgl/glyphs/leftArrow40px.bmp | Bin 0 -> 6454 bytes lib_nbgl/glyphs/left_half_64px_nocomp.bmp | Bin 0 -> 4662 bytes ...er_circle_bottom_left_44px_1bpp_nocomp.bmp | Bin 0 -> 5862 bytes ...arter_circle_top_left_44px_1bpp_nocomp.bmp | Bin 0 -> 5862 bytes ...rter_disc_bottom_left_44px_1bpp_nocomp.bmp | Bin 0 -> 5862 bytes ...quarter_disc_top_left_44px_1bpp_nocomp.bmp | Bin 0 -> 5862 bytes lib_nbgl/glyphs/rightArrow40px.bmp | Bin 0 -> 6454 bytes lib_nbgl/include/nbgl_draw.h | 5 +- lib_nbgl/include/nbgl_obj.h | 36 ++++++++++-- lib_nbgl/include/nbgl_types.h | 7 ++- lib_nbgl/src/nbgl_draw.c | 55 ++++++++++++++---- lib_nbgl/src/nbgl_obj.c | 28 ++++++--- lib_nbgl/src/nbgl_obj_keyboard.c | 20 +++++-- lib_nbgl/src/nbgl_obj_keyboard_nanos.c | 2 +- 14 files changed, 120 insertions(+), 33 deletions(-) create mode 100755 lib_nbgl/glyphs/leftArrow40px.bmp create mode 100755 lib_nbgl/glyphs/left_half_64px_nocomp.bmp create mode 100755 lib_nbgl/glyphs/quarter_circle_bottom_left_44px_1bpp_nocomp.bmp create mode 100755 lib_nbgl/glyphs/quarter_circle_top_left_44px_1bpp_nocomp.bmp create mode 100755 lib_nbgl/glyphs/quarter_disc_bottom_left_44px_1bpp_nocomp.bmp create mode 100755 lib_nbgl/glyphs/quarter_disc_top_left_44px_1bpp_nocomp.bmp create mode 100755 lib_nbgl/glyphs/rightArrow40px.bmp diff --git a/lib_nbgl/glyphs/leftArrow40px.bmp b/lib_nbgl/glyphs/leftArrow40px.bmp new file mode 100755 index 0000000000000000000000000000000000000000..85a0754374cb5ef5d6c021891be6b7b3d6b52833 GIT binary patch literal 6454 zcmeI$ElUJJ9LMo7+iW(YFW@*uymCcE1&hUU!D3JlgT?n?u~-BJu~;ky1(P=MRrvf2 zK5IF@|GOC&hCS>2lwJ7U?93hPhyU)}?oNH8+Ur_dmCybtU9PV+?)bi^yPfucbIo!q zEAU4vz%@K*QRL&Qk#nD#k`Ys#T#%-Z?GGy$ag2~l?+U&z`Wv}@7{XHyF^CWXTQiO`|KPUW#2s_qwKp|WbE|ryB~g&yJb$NYX^3Z`6gSrZQ=M>!rF`3 eEVd3KwN7Lna^@pti|SaxR|);HEi3TfD)0j?f8S^T literal 0 HcmV?d00001 diff --git a/lib_nbgl/glyphs/left_half_64px_nocomp.bmp b/lib_nbgl/glyphs/left_half_64px_nocomp.bmp new file mode 100755 index 0000000000000000000000000000000000000000..96a96dd22e57321ed1cace6d33d2de75324dfc78 GIT binary patch literal 4662 zcmeH{!41MN3`Jo94xAW)33^7{nVP}CN-C>z<8Q}Fq^e4!RF3`q`W+SCpXGi@YoX_p z_Jj6|_BBNmQ2l$$n@(x{4zt?*tRqF|+O~6Cdp+DJ0zXGIildVwy7ottvu`P8FsIm3 zOae|(uO&5(rq}XCjwS~AaUAecP!fKC5|>7B@EdWJ{a~3{JtoJrZ3^;Srpy!&$JBTP zXXSWipPG3C^9Eu!aMu5gj&pTE5u_uh9hK~Ku+*K?I2!xOLF`9CU4uB`>4cx~bVE6T v>56^=(*aJEE6nkuOimV<-=~vf8uN3ov09F1EWqKG?WJ)t9AsL!T{QjyBFYGy literal 0 HcmV?d00001 diff --git a/lib_nbgl/glyphs/quarter_circle_bottom_left_44px_1bpp_nocomp.bmp b/lib_nbgl/glyphs/quarter_circle_bottom_left_44px_1bpp_nocomp.bmp new file mode 100755 index 0000000000000000000000000000000000000000..ad16eae1b4540c29b02789c0df93ca9a2406279d GIT binary patch literal 5862 zcmeH{!3}^g2u14x9*rY-@azEI-P&1PLs67AQjdN((1c28;`{xe^Rjj6S`+O9#dt@P z`m26!Ys>KzcKCY8`3aDaVISFl8a{yOKcc)@qvZ&YyyyU8i74r19h2MA>5jGnZ0Y6o zG40kAaX=qoDozAoE?cFr1Jxr;F$6eqfMj4gt|{z*p#YNPqzl>{SS7k3V-TZg>wq)@ rHvAf7{zLF!f(H%J2p&#zAIt@Kn8wh+)9As67)b6#_z*tGS4qhMO*b74 literal 0 HcmV?d00001 diff --git a/lib_nbgl/glyphs/quarter_circle_top_left_44px_1bpp_nocomp.bmp b/lib_nbgl/glyphs/quarter_circle_top_left_44px_1bpp_nocomp.bmp new file mode 100755 index 0000000000000000000000000000000000000000..c60c0afa987bbd583f8ec4d16aca2b381ef03f34 GIT binary patch literal 5862 zcmeH`u?>JQ3+n%Sj zzTfS8y?l<6x*R1Hp@_l#%L8&K6^aDHUwFfgbc7!b8XDqsMGr@~IWq!bL{ zl#0If>IiHo7*JsaLokHVcZAJ`B_!YtzETY=j}4J{4iOIt!C>}IaO`s z(mFoZrrQtu{p-5TYuvc6{*0Zc?+OZ2Gvn9q9E^rD+tnRrdX%;*I+R+O=T#g`y6-@A z@HHt^DGmj+`gNut4p$-V!TMIdOpgy-j*C53 ze~iQI=1;%we(0bDv_Q0gF($gkwV(zltsO!K@e~%I2D=^5K{kaNp3eo;fEoTV?1kVh z@ia&=Iy8u+cy;K+z|Z)0fEmswv}Xh7j>I}}?#RD^r$*Aiz{oLBGcpaNjC=zfqsTzS zC^b+pDh%k1Is=@A^-gIqU|=xM2Pr8&0A7lEl#cb?nMt(hW6j B`CKL14HC3ZXY5-p)~=`+u{6l1vw7n={i=|056?$nyr4fSWZcE` z9vCm_j|&-h@VrHglS0Pri1CWCDIwz)p4Xs`*Yu}_jGK5~0^<$+86jgG&vRhBr9UfV zT*vbiG0q7Y*CNIyV+&a${h>q|f50{` z?pwrnkT545>SMKAap!lKc8b(E?qS6DbM5(iB*h-rDtQcizwX@>E_cql`tM8Oqh7Le z2R7Nc7n|&}3pUwjKWwtk&e&w%J+R5XyJ6cPvhTjwMu@E!_~#(0wF5UtRPfoli`3dn Wc22@(YgkfiS6N@)&MWX&1-=0CzTZy( literal 0 HcmV?d00001 diff --git a/lib_nbgl/include/nbgl_draw.h b/lib_nbgl/include/nbgl_draw.h index 2c52b0b11..de2838cc2 100644 --- a/lib_nbgl/include/nbgl_draw.h +++ b/lib_nbgl/include/nbgl_draw.h @@ -32,7 +32,10 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ -void nbgl_drawIcon(nbgl_area_t *area, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon); +void nbgl_drawIcon(nbgl_area_t *area, + nbgl_transformation_t transformation, + nbgl_color_map_t color_map, + const nbgl_icon_details_t *icon); void nbgl_drawRoundedRect(const nbgl_area_t *area, nbgl_radius_t radius, color_t innerColor); void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, nbgl_radius_t radius, diff --git a/lib_nbgl/include/nbgl_obj.h b/lib_nbgl/include/nbgl_obj.h index 74b74fb91..0b13d4386 100644 --- a/lib_nbgl/include/nbgl_obj.h +++ b/lib_nbgl/include/nbgl_obj.h @@ -28,8 +28,12 @@ extern "C" { // for Keyboard #ifdef HAVE_SE_TOUCH +#ifdef TARGET_STAX #define KEYBOARD_KEY_HEIGHT 60 -#else // HAVE_SE_TOUCH +#else // TARGET_STAX +#define KEYBOARD_KEY_HEIGHT 72 +#endif // TARGET_STAX +#else // HAVE_SE_TOUCH #define KEYBOARD_KEY_WIDTH 14 #define KEYBOARD_KEY_HEIGHT 14 #define KEYBOARD_WIDTH (5 * KEYBOARD_KEY_WIDTH) @@ -53,14 +57,27 @@ extern "C" { #define EXIT_PAGE 0xFF // external margin in pixels +#ifdef TARGET_STAX #define BORDER_MARGIN 24 +#else // TARGET_STAX +#define BORDER_MARGIN 32 +#endif // TARGET_STAX // Back button header height +#ifdef TARGET_STAX #define BACK_BUTTON_HEADER_HEIGHT 88 +#else // TARGET_STAX +#define BACK_BUTTON_HEADER_HEIGHT 96 +#endif // TARGET_STAX // common dimensions for buttons +#ifdef TARGET_STAX #define BUTTON_RADIUS RADIUS_40_PIXELS #define BUTTON_DIAMETER 80 +#else // TARGET_STAX +#define BUTTON_RADIUS RADIUS_44_PIXELS +#define BUTTON_DIAMETER 88 +#endif // TARGET_STAX #endif // HAVE_SE_TOUCH /********************** @@ -302,6 +319,7 @@ typedef struct PACKED__ nbgl_image_s { nbgl_obj_t obj; // common part color_t foregroundColor; ///< color set to '1' bits, for 1PBB images. '0' are set to background ///< color. + nbgl_transformation_t transformation; ///< usually NO_TRANSFORMATION const nbgl_icon_details_t *buffer; ///< buffer containing bitmap, with exact same size as ///< object (width*height*bpp/8 bytes) onImageDrawCallback_t onDrawCallback; ///< function called if buffer is NULL, with above token @@ -367,6 +385,15 @@ typedef struct PACKED__ nbgl_progress_bar_s { color_t foregroundColor; ///< color of the inner progress bar and border (if applicable) } nbgl_progress_bar_t; +/** + * @brief Style to apply to @ref nbgl_page_indicator_t + * + */ +typedef enum { + PROGRESSIVE_INDICATOR = 0, ///< all dashes before active page are black + CURRENT_INDICATOR ///< only current page dash is black +} nbgl_page_indicator_style_t; + /** * @brief struct to represent a navigation bar (@ref PAGE_INDICATOR type) * There can be up to 5 page indicators, whose shape is fixed. @@ -375,9 +402,10 @@ typedef struct PACKED__ nbgl_progress_bar_s { * @note height is fixed */ typedef struct PACKED__ nbgl_navigation_bar_s { - nbgl_obj_t obj; ///< common part - uint8_t nbPages; ///< number of pages. - uint8_t activePage; ///< index of active page (from 0 to nbPages-1). + nbgl_obj_t obj; ///< common part + uint8_t nbPages; ///< number of pages. + uint8_t activePage; ///< index of active page (from 0 to nbPages-1). + nbgl_page_indicator_style_t style; ///< Style to apply } nbgl_page_indicator_t; /** diff --git a/lib_nbgl/include/nbgl_types.h b/lib_nbgl/include/nbgl_types.h index aea8ed272..351ea687d 100644 --- a/lib_nbgl/include/nbgl_types.h +++ b/lib_nbgl/include/nbgl_types.h @@ -184,8 +184,13 @@ typedef enum nbgl_post_refresh_t { typedef enum { #ifdef SCREEN_SIZE_WALLET RADIUS_32_PIXELS = 0, ///< 32 pixels - RADIUS_40_PIXELS, ///< 48 pixels +#ifdef TARGET_STAX + RADIUS_40_PIXELS, ///< 40 pixels RADIUS_MAX = RADIUS_40_PIXELS, +#else // TARGET_STAX + RADIUS_44_PIXELS, ///< 44 pixels + RADIUS_MAX = RADIUS_44_PIXELS, +#endif // TARGET_STAX #else // SCREEN_SIZE_WALLET RADIUS_1_PIXEL = 0, ///< 1 pixel RADIUS_3_PIXELS, ///< 3 pixels diff --git a/lib_nbgl/src/nbgl_draw.c b/lib_nbgl/src/nbgl_draw.c index 8cb35e652..58be44170 100644 --- a/lib_nbgl/src/nbgl_draw.c +++ b/lib_nbgl/src/nbgl_draw.c @@ -71,7 +71,11 @@ static const uint8_t quarter_circle_3px_270_1bpp[] = {0x58, 0x00}; static const uint8_t radiusValues[] = { #ifdef SCREEN_SIZE_WALLET 32, - 40 +#ifdef TARGET_STAX + 40, +#else // TARGET_STAX + 44 +#endif // TARGET_STAX #else // SCREEN_SIZE_WALLET 1, 3 @@ -80,18 +84,42 @@ static const uint8_t radiusValues[] = { #ifdef SCREEN_SIZE_WALLET // indexed by nbgl_radius_t (except RADIUS_0_PIXELS) -static const uint8_t *topQuarterDiscs[] - = {C_quarter_disc_top_left_32px_1bpp_bitmap, C_quarter_disc_top_left_40px_1bpp_bitmap}; +static const uint8_t *topQuarterDiscs[] = { + C_quarter_disc_top_left_32px_1bpp_bitmap, +#ifdef TARGET_STAX + C_quarter_disc_top_left_40px_1bpp_bitmap, +#else // TARGET_STAX + C_quarter_disc_top_left_44px_1bpp_bitmap +#endif // TARGET_STAX +}; -static const uint8_t *bottomQuarterDiscs[] - = {C_quarter_disc_bottom_left_32px_1bpp_bitmap, C_quarter_disc_bottom_left_40px_1bpp_bitmap}; +static const uint8_t *bottomQuarterDiscs[] = { + C_quarter_disc_bottom_left_32px_1bpp_bitmap, +#ifdef TARGET_STAX + C_quarter_disc_bottom_left_40px_1bpp_bitmap, +#else // TARGET_STAX + C_quarter_disc_bottom_left_44px_1bpp_bitmap +#endif // TARGET_STAX +}; // indexed by nbgl_radius_t (except RADIUS_0_PIXELS) -static const uint8_t *topQuarterCircles[] - = {C_quarter_circle_top_left_32px_1bpp_bitmap, C_quarter_circle_top_left_40px_1bpp_bitmap}; +static const uint8_t *topQuarterCircles[] = { + C_quarter_circle_top_left_32px_1bpp_bitmap, +#ifdef TARGET_STAX + C_quarter_circle_top_left_40px_1bpp_bitmap, +#else // TARGET_STAX + C_quarter_circle_top_left_44px_1bpp_bitmap +#endif // TARGET_STAX +}; -static const uint8_t *bottomQuarterCircles[] = {C_quarter_circle_bottom_left_32px_1bpp_bitmap, - C_quarter_circle_bottom_left_40px_1bpp_bitmap}; +static const uint8_t *bottomQuarterCircles[] = { + C_quarter_circle_bottom_left_32px_1bpp_bitmap, +#ifdef TARGET_STAX + C_quarter_circle_bottom_left_40px_1bpp_bitmap, +#else // TARGET_STAX + C_quarter_circle_bottom_left_44px_1bpp_bitmap +#endif // TARGET_STAX +}; #endif // SCREEN_SIZE_WALLET #ifdef NBGL_QRCODE @@ -453,16 +481,21 @@ void nbgl_drawRoundedBorderedRect(const nbgl_area_t *area, * No transformation is applied to the icon. * * @param area Area of drawing + * @param transformation Transformation to apply to this icon (only available for raw image, not + * image file) * @param color_map Color map applied to icon * @param icon Icon details structure to draw */ -void nbgl_drawIcon(nbgl_area_t *area, nbgl_color_map_t color_map, const nbgl_icon_details_t *icon) +void nbgl_drawIcon(nbgl_area_t *area, + nbgl_transformation_t transformation, + nbgl_color_map_t color_map, + const nbgl_icon_details_t *icon) { if (icon->isFile) { nbgl_frontDrawImageFile(area, icon->bitmap, color_map, ramBuffer); } else { - nbgl_frontDrawImage(area, icon->bitmap, NO_TRANSFORMATION, color_map); + nbgl_frontDrawImage(area, icon->bitmap, transformation, color_map); } } diff --git a/lib_nbgl/src/nbgl_obj.c b/lib_nbgl/src/nbgl_obj.c index 7f80983a6..b24991957 100644 --- a/lib_nbgl/src/nbgl_obj.c +++ b/lib_nbgl/src/nbgl_obj.c @@ -340,8 +340,9 @@ static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePos // inherit background from parent obj->obj.area.backgroundColor = obj->obj.parent->area.backgroundColor; - // draw the rounded corner rectangle - if (obj->innerColor == obj->borderColor) { + // draw the rounded corner rectangle if necessary + if ((obj->innerColor == obj->borderColor) + && (obj->innerColor != obj->obj.area.backgroundColor)) { nbgl_drawRoundedRect((nbgl_area_t *) obj, obj->radius, obj->innerColor); } else { @@ -404,7 +405,7 @@ static void draw_button(nbgl_button_t *obj, nbgl_obj_t *prevObj, bool computePos rectArea.height = obj->icon->height; rectArea.bpp = obj->icon->bpp; - nbgl_drawIcon(&rectArea, obj->foregroundColor, obj->icon); + nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->foregroundColor, obj->icon); } } @@ -510,7 +511,7 @@ static void draw_image(nbgl_image_t *obj, nbgl_obj_t *prevObj, bool computePosit colorMap = obj->foregroundColor; } - nbgl_drawIcon((nbgl_area_t *) obj, colorMap, iconDetails); + nbgl_drawIcon((nbgl_area_t *) obj, obj->transformation, colorMap, iconDetails); } #ifdef HAVE_SE_TOUCH @@ -575,10 +576,10 @@ static void draw_radioButton(nbgl_radio_t *obj, nbgl_obj_t *prevObj, bool comput rectArea.backgroundColor = obj->obj.area.backgroundColor; rectArea.bpp = NBGL_BPP_1; if (obj->state == OFF_STATE) { - nbgl_drawIcon(&rectArea, obj->borderColor, &C_radio_inactive_32px); + nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->borderColor, &C_radio_inactive_32px); } else { - nbgl_drawIcon(&rectArea, obj->activeColor, &C_radio_active_32px); + nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, obj->activeColor, &C_radio_active_32px); } } #endif // HAVE_SE_TOUCH @@ -689,8 +690,12 @@ static void draw_pageIndicator(nbgl_page_indicator_t *obj, nbgl_area_t rectArea; uint16_t dashWidth; + if (obj->nbPages == 0) { + return; + } + if (obj->nbPages <= NB_MAX_PAGES_WITH_DASHES) { - uint8_t i; + int i; #define INTER_DASHES 10 // pixels // force height obj->obj.area.height = 4; @@ -719,10 +724,15 @@ static void draw_pageIndicator(nbgl_page_indicator_t *obj, rectArea.backgroundColor = obj->obj.area.backgroundColor; rectArea.bpp = NBGL_BPP_1; // draw dashes - for (i = 0; i <= obj->activePage; i++) { - nbgl_frontDrawHorizontalLine(&rectArea, 0xF, BLACK); + for (i = 0; i < obj->activePage; i++) { + nbgl_frontDrawHorizontalLine( + &rectArea, 0xF, (obj->style == PROGRESSIVE_INDICATOR) ? BLACK : LIGHT_GRAY); rectArea.x0 += dashWidth + INTER_DASHES; } + nbgl_frontDrawHorizontalLine(&rectArea, 0xF, BLACK); + rectArea.x0 += dashWidth + INTER_DASHES; + i++; + for (; i < obj->nbPages; i++) { nbgl_frontDrawHorizontalLine(&rectArea, 0xF, LIGHT_GRAY); rectArea.x0 += dashWidth + INTER_DASHES; diff --git a/lib_nbgl/src/nbgl_obj_keyboard.c b/lib_nbgl/src/nbgl_obj_keyboard.c index 388c159e4..3860ce833 100644 --- a/lib_nbgl/src/nbgl_obj_keyboard.c +++ b/lib_nbgl/src/nbgl_obj_keyboard.c @@ -354,6 +354,7 @@ static void keyboardDrawLetters(nbgl_keyboard_t *keyboard) nbgl_drawIcon( &rectArea, (keyboard->casing != LOWER_CASE) ? WHITE : BLACK, + NO_TRANSFORMATION, (keyboard->casing != LOCKED_UPPER_CASE) ? (&C_shift_lock32px) : (&C_shift32px)); rectArea.backgroundColor = WHITE; offsetX = keyboard->obj.area.x0 + SHIFT_KEY_WIDTH; @@ -386,7 +387,10 @@ static void keyboardDrawLetters(nbgl_keyboard_t *keyboard) else { rectArea.x0 += (BACKSPACE_KEY_WIDTH_LETTERS_ONLY - rectArea.width) / 2; } - nbgl_drawIcon(&rectArea, (keyboard->keyMask & (1 << 26)) ? WHITE : BLACK, &C_backspace32px); + nbgl_drawIcon(&rectArea, + NO_TRANSFORMATION, + (keyboard->keyMask & (1 << 26)) ? WHITE : BLACK, + &C_backspace32px); // 4th row, only in Full mode if (!keyboard->lettersOnly) { @@ -395,8 +399,10 @@ static void keyboardDrawLetters(nbgl_keyboard_t *keyboard) nbgl_drawText(&rectArea, ".?123", 5, SMALL_REGULAR_1BPP_FONT, BLACK); rectArea.x0 = SWITCH_KEY_WIDTH + (SPACE_KEY_WIDTH - C_space32px.width) / 2; - nbgl_drawIcon( - &rectArea, (keyboard->keyMask & (1 << SPACE_KEY_INDEX)) ? WHITE : BLACK, &C_space32px); + nbgl_drawIcon(&rectArea, + NO_TRANSFORMATION, + (keyboard->keyMask & (1 << SPACE_KEY_INDEX)) ? WHITE : BLACK, + &C_space32px); } } @@ -477,7 +483,7 @@ static void keyboardDrawDigits(nbgl_keyboard_t *keyboard) rectArea.y0 = keyboard->obj.area.y0 + KEYBOARD_KEY_HEIGHT * 2 + (((KEYBOARD_KEY_HEIGHT - rectArea.height) / 2) & 0xFFC); rectArea.x0 += (BACKSPACE_KEY_WIDTH_DIGITS - rectArea.width) / 2; - nbgl_drawIcon(&rectArea, BLACK, &C_backspace32px); + nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, BLACK, &C_backspace32px); // 4th row rectArea.x0 = (SWITCH_KEY_WIDTH - nbgl_getTextWidth(SMALL_REGULAR_1BPP_FONT, "ABC")) / 2; @@ -485,8 +491,10 @@ static void keyboardDrawDigits(nbgl_keyboard_t *keyboard) nbgl_drawText(&rectArea, "ABC", 3, SMALL_REGULAR_1BPP_FONT, BLACK); rectArea.x0 = SWITCH_KEY_WIDTH + (SPACE_KEY_WIDTH - C_space32px.width) / 2; - nbgl_drawIcon( - &rectArea, (keyboard->keyMask & (1 << SPACE_KEY_INDEX)) ? WHITE : BLACK, &C_space32px); + nbgl_drawIcon(&rectArea, + NO_TRANSFORMATION, + (keyboard->keyMask & (1 << SPACE_KEY_INDEX)) ? WHITE : BLACK, + &C_space32px); } static void keyboardDraw(nbgl_keyboard_t *keyboard) diff --git a/lib_nbgl/src/nbgl_obj_keyboard_nanos.c b/lib_nbgl/src/nbgl_obj_keyboard_nanos.c index d26f70337..e5776de15 100644 --- a/lib_nbgl/src/nbgl_obj_keyboard_nanos.c +++ b/lib_nbgl/src/nbgl_obj_keyboard_nanos.c @@ -95,7 +95,7 @@ static void keyboardDrawIcon(int16_t x0, int8_t y0, bool inverted, const nbgl_ic // center rectArea.x0 = x0 + (KEYBOARD_KEY_WIDTH - icon->width) / 2; rectArea.y0 = y0 + (KEYBOARD_KEY_HEIGHT - icon->height) / 2; - nbgl_drawIcon(&rectArea, inverted ? BLACK : WHITE, icon); + nbgl_drawIcon(&rectArea, NO_TRANSFORMATION, inverted ? BLACK : WHITE, icon); } static void keyboardDrawChar(int16_t x0, int8_t y0, bool inverted, const char *charPtr) From 58ddc823ea61113f100fc177f334c9767075bc76 Mon Sep 17 00:00:00 2001 From: Nicolas Roggeman Date: Tue, 30 Jan 2024 16:50:38 +0100 Subject: [PATCH 2/4] Adapt NBGL layout for Europa onboarding --- Makefile.defines | 3 + lib_nbgl/include/nbgl_layout.h | 9 +- lib_nbgl/include/nbgl_obj.h | 6 +- lib_nbgl/src/nbgl_layout.c | 477 ++++++++++++++++++++++++------- lib_nbgl/src/nbgl_navigation.c | 12 +- lib_nbgl/src/nbgl_obj_keyboard.c | 12 +- lib_nbgl/src/nbgl_use_case.c | 11 +- 7 files changed, 410 insertions(+), 120 deletions(-) diff --git a/Makefile.defines b/Makefile.defines index ae6afc2cb..809b0034e 100644 --- a/Makefile.defines +++ b/Makefile.defines @@ -205,6 +205,9 @@ DEFINES += NBGL_USE_CASE else DEFINES += HAVE_BAGL endif +ifeq ($(TARGET_NAME),TARGET_NANOS) +DEFINES += BAGL_HEIGHT=32 +endif ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_NANOS2)) ifndef USE_NBGL DEFINES += HAVE_UX_FLOW diff --git a/lib_nbgl/include/nbgl_layout.h b/lib_nbgl/include/nbgl_layout.h index b0b7fcbea..0d1e76ecb 100644 --- a/lib_nbgl/include/nbgl_layout.h +++ b/lib_nbgl/include/nbgl_layout.h @@ -26,9 +26,14 @@ extern "C" { #define NO_MORE_OBJ_ERROR -3 #define NBGL_NO_TUNE NB_TUNES +#ifdef HAVE_SE_TOUCH #define NB_MAX_SUGGESTION_BUTTONS 4 +#ifdef TARGET_STAX +#define NB_MAX_VISIBLE_SUGGESTION_BUTTONS NB_MAX_SUGGESTION_BUTTONS +#else // TARGET_STAX +#define NB_MAX_VISIBLE_SUGGESTION_BUTTONS 2 +#endif // TARGET_STAX -#ifdef HAVE_SE_TOUCH #define AVAILABLE_WIDTH (SCREEN_WIDTH - 2 * BORDER_MARGIN) #else // HAVE_SE_TOUCH // 7 pixels on each side @@ -297,6 +302,8 @@ typedef struct { const char *url; ///< URL for QR code const char *text1; ///< first text (can be null) const char *text2; ///< second text (can be null) + int16_t offsetY; ///< vertical shift to apply to this info (if > 0, shift to bottom) + bool centered; ///< if set to true, center vertically bool largeText1; ///< if set to true, use 32px font for text1 } nbgl_layoutQRCode_t; diff --git a/lib_nbgl/include/nbgl_obj.h b/lib_nbgl/include/nbgl_obj.h index 0b13d4386..e0fe94361 100644 --- a/lib_nbgl/include/nbgl_obj.h +++ b/lib_nbgl/include/nbgl_obj.h @@ -58,9 +58,11 @@ extern "C" { // external margin in pixels #ifdef TARGET_STAX -#define BORDER_MARGIN 24 +#define BORDER_MARGIN 24 +#define BOTTOM_BORDER_MARGIN 24 #else // TARGET_STAX -#define BORDER_MARGIN 32 +#define BORDER_MARGIN 32 +#define BOTTOM_BORDER_MARGIN 24 #endif // TARGET_STAX // Back button header height diff --git a/lib_nbgl/src/nbgl_layout.c b/lib_nbgl/src/nbgl_layout.c index 2555b8f8f..fac090921 100644 --- a/lib_nbgl/src/nbgl_layout.c +++ b/lib_nbgl/src/nbgl_layout.c @@ -49,13 +49,32 @@ #define TAG_VALUE_ICON_WIDTH 32 +#ifdef TARGET_STAX #define TOUCHABLE_BAR_HEIGHT 88 #define FOOTER_HEIGHT 80 +#else // TARGET_STAX +#define TOUCHABLE_BAR_HEIGHT 100 +#define FOOTER_HEIGHT 80 +#endif // TARGET_STAX #endif // HAVE_SE_TOUCH // refresh period of the spinner, in ms #define SPINNER_REFRESH_PERIOD 400 +#ifdef HAVE_SE_TOUCH +#ifdef TARGET_STAX +#define FIRST_BUTTON_INDEX 0 +#else // TARGET_STAX +// for suggestion buttons, on Europa there are other objects than buttons +enum { + PAGE_INDICATOR_INDEX = 0, + LEFT_HALF_INDEX, // half disc displayed on the bottom left + RIGHT_HALF_INDEX, // half disc displayed on the bottom right + FIRST_BUTTON_INDEX +}; +#endif // TARGET_STAX +#endif // HAVE_SE_TOUCH + /********************** * MACROS **********************/ @@ -133,12 +152,13 @@ static nbgl_layoutInternal_t gLayout[NB_MAX_LAYOUTS] = {0}; #ifdef HAVE_SE_TOUCH #ifdef NBGL_KEYBOARD static nbgl_button_t *choiceButtons[NB_MAX_SUGGESTION_BUTTONS]; +static char numText[5]; +static uint8_t nbActiveButtons; +#ifndef TARGET_STAX +static nbgl_image_t *partialButtonImages[2]; +#endif // TARGET_STAX #endif // NBGL_KEYBOARD -#ifdef NBGL_KEYBOARD -static char numText[5]; -#endif - // numbers of touchable controls for the whole page static uint8_t nbTouchableControls = 0; #endif // HAVE_SE_TOUCH @@ -166,6 +186,74 @@ static inline uint8_t get_hold_to_approve_percent(uint32_t touch_duration) return (current_step_nb * HOLD_TO_APPROVE_STEP_PERCENT); } +#if (!defined(TARGET_STAX) && defined(NBGL_KEYBOARD)) +// function used on Europa to display (or not) beginning of next button and/or end of +// previous button, and update buttons when swipping +static bool updateSuggestionButtons(nbgl_container_t *container, + nbgl_touchType_t eventType, + uint8_t currentLeftButtonIndex) +{ + bool needRefresh = false; + uint8_t page = 0; + if ((eventType == SWIPED_LEFT) && (currentLeftButtonIndex < (uint32_t) (nbActiveButtons - 2))) { + // shift all buttons on the left if there are still at least 2 buttons to display + currentLeftButtonIndex++; + container->children[FIRST_BUTTON_INDEX] + = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex]; + container->children[FIRST_BUTTON_INDEX + 1] + = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex + 1]; + page = currentLeftButtonIndex; + needRefresh = true; + } + else if ((eventType == SWIPED_RIGHT) && (currentLeftButtonIndex > 0)) { + // shift all buttons on the left if we are not already displaying the 2 first ones + currentLeftButtonIndex--; + container->children[FIRST_BUTTON_INDEX] + = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex]; + container->children[FIRST_BUTTON_INDEX + 1] + = (nbgl_obj_t *) choiceButtons[currentLeftButtonIndex + 1]; + page = currentLeftButtonIndex; + needRefresh = true; + } + // align left button on the left + if (nbActiveButtons > 0) { + container->children[FIRST_BUTTON_INDEX]->alignmentMarginX = 32; + container->children[FIRST_BUTTON_INDEX]->alignment = TOP_LEFT; + container->children[FIRST_BUTTON_INDEX]->alignTo = (nbgl_obj_t *) container; + } + + // align right button on left one + if (nbActiveButtons > 1) { + container->children[FIRST_BUTTON_INDEX + 1]->alignmentMarginX = 8; + container->children[FIRST_BUTTON_INDEX + 1]->alignment = MID_RIGHT; + container->children[FIRST_BUTTON_INDEX + 1]->alignTo + = container->children[FIRST_BUTTON_INDEX]; + } + + // on Europa, the first child is used by the progress indicator, displayed if more that 2 + // buttons + nbgl_page_indicator_t *indicator + = (nbgl_page_indicator_t *) container->children[PAGE_INDICATOR_INDEX]; + indicator->activePage = page; + + // if not on the first button, display end of previous button + if (currentLeftButtonIndex > 0) { + container->children[LEFT_HALF_INDEX] = (nbgl_obj_t *) partialButtonImages[0]; + } + else { + container->children[LEFT_HALF_INDEX] = NULL; + } + // if not on the last button, display beginning of next button + if (currentLeftButtonIndex < (nbActiveButtons - 2)) { + container->children[RIGHT_HALF_INDEX] = (nbgl_obj_t *) partialButtonImages[1]; + } + else { + container->children[RIGHT_HALF_INDEX] = NULL; + } + return needRefresh; +} +#endif // TARGET_STAX + // function used to retrieve the concerned layout and layout obj matching the given touched obj static bool getLayoutAndLayoutObj(nbgl_obj_t *obj, nbgl_layoutInternal_t **layout, @@ -218,7 +306,7 @@ static void touchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) if (obj == NULL) { return; } - + LOG_DEBUG(LAYOUT_LOGGER, "touchCallback(): eventType = %d, obj = %p\n", eventType, obj); if (getLayoutAndLayoutObj(obj, &layout, &layoutObj) == false) { // try with parent, if existing if (getLayoutAndLayoutObj(obj->parent, &layout, &layoutObj) == false) { @@ -235,6 +323,30 @@ static void touchCallback(nbgl_obj_t *obj, nbgl_touchType_t eventType) if (((eventType == SWIPED_UP) || (eventType == SWIPED_DOWN) || (eventType == SWIPED_LEFT) || (eventType == SWIPED_RIGHT)) && (obj->type == CONTAINER)) { +#if (!defined(TARGET_STAX) && defined(NBGL_KEYBOARD)) + // try if suggestions buttons + nbgl_container_t *container = (nbgl_container_t *) obj; + if (((eventType == SWIPED_LEFT) || (eventType == SWIPED_RIGHT)) + && (container->nbChildren == (nbActiveButtons + FIRST_BUTTON_INDEX)) + && (nbActiveButtons > 2)) { + uint32_t i = 0; + while (i < (uint32_t) nbActiveButtons) { + if (container->children[FIRST_BUTTON_INDEX] == (nbgl_obj_t *) choiceButtons[i]) { + break; + } + i++; + } + + if (i < (uint32_t) nbActiveButtons) { + if (updateSuggestionButtons(container, eventType, i)) { + nbgl_redrawObject((nbgl_obj_t *) container, NULL, false); + nbgl_refresh(); + } + + return; + } + } +#endif // TARGET_STAX if (layout->swipeUsage == SWIPE_USAGE_CUSTOM) { layoutObj->index = eventType; } @@ -674,6 +786,9 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description) memset(layout, 0, sizeof(nbgl_layoutInternal_t)); nbTouchableControls = 0; +#ifdef NBGL_KEYBOARD + nbActiveButtons = 0; +#endif // NBGL_KEYBOARD layout->callback = (nbgl_layoutTouchCallback_t) PIC(description->onActionCallback); layout->modal = description->modal; @@ -712,16 +827,20 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description) layout->container->obj.touchId = WHOLE_SCREEN_ID; // create 'tap to continue' text area - layout->tapText = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, 0); - layout->tapText->localized = false; - layout->tapText->text = PIC(description->tapActionText); - layout->tapText->textColor = DARK_GRAY; - layout->tapText->fontId = SMALL_REGULAR_FONT; - layout->tapText->obj.area.width = SCREEN_WIDTH - 2 * BORDER_MARGIN; - layout->tapText->obj.area.height = nbgl_getFontLineHeight(layout->tapText->fontId); - layout->tapText->textAlignment = CENTER; + layout->tapText = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, 0); + layout->tapText->localized = false; + layout->tapText->text = PIC(description->tapActionText); + layout->tapText->textColor = DARK_GRAY; + layout->tapText->fontId = SMALL_REGULAR_FONT; + layout->tapText->obj.area.width = SCREEN_WIDTH - 2 * BORDER_MARGIN; + layout->tapText->obj.area.height = nbgl_getFontLineHeight(layout->tapText->fontId); + layout->tapText->textAlignment = CENTER; +#ifdef TARGET_STAX layout->tapText->obj.alignmentMarginY = BORDER_MARGIN; - layout->tapText->obj.alignment = BOTTOM_MIDDLE; +#else // TARGET_STAX + layout->tapText->obj.alignmentMarginY = 30; +#endif // TARGET_STAX + layout->tapText->obj.alignment = BOTTOM_MIDDLE; } return (nbgl_layout_t *) layout; @@ -841,10 +960,9 @@ int nbgl_layoutAddNavigationBar(nbgl_layout_t *layout, const nbgl_layoutNavigati nbgl_line_t *line = createHorizontalLine(layoutInt->layer); line->obj.alignTo = (nbgl_obj_t *) layoutInt->bottomContainer; line->obj.alignment = TOP_MIDDLE; + line->offset = 3; layoutInt->children[layoutInt->nbChildren] = (nbgl_obj_t *) line; layoutInt->nbChildren++; - - layoutInt->container->obj.area.height -= 4; } nbgl_layoutAddSwipeInternal(layout, @@ -1054,8 +1172,9 @@ int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *ba if (barLayout->iconRight != NULL) { textArea->obj.area.width -= ((nbgl_icon_details_t *) PIC(barLayout->iconRight))->width; } - textArea->obj.area.height = container->obj.area.height; - textArea->style = NO_STYLE; + textArea->obj.area.height = nbgl_getTextHeightInWidth( + textArea->fontId, textArea->text, textArea->obj.area.width, true); + textArea->style = NO_STYLE; if ((barLayout->iconLeft != NULL) && (barLayout->centered != true)) { textArea->obj.alignmentMarginX = 12; } @@ -1065,7 +1184,7 @@ int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *ba } else { textArea->obj.alignTo = (nbgl_obj_t *) NULL; - textArea->obj.alignment = NO_ALIGNMENT; + textArea->obj.alignment = MID_LEFT; } if (barLayout->centered != true) { textArea->textAlignment = MID_LEFT; @@ -1205,8 +1324,8 @@ int nbgl_layoutAddSwitch(nbgl_layout_t *layout, const nbgl_layoutSwitch_t *switc * @brief Creates an area with given text and sub text (in gray) * * @param layout the current layout - * @param text main text for the switch - * @param subText description under main text (NULL terminated, single line, may be null) + * @param text main text (in small bold font), optional + * @param subText description under main text (in small regular font), optional * @return >= 0 if OK */ int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subText) @@ -1237,18 +1356,22 @@ int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subT if (text != NULL) { textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); - textArea->textColor = BLACK; - textArea->text = PIC(text); - textArea->textAlignment = MID_LEFT; - textArea->fontId = SMALL_BOLD_FONT; - textArea->style = NO_STYLE; - textArea->wrapping = true; - textArea->obj.alignment = NO_ALIGNMENT; + textArea->textColor = BLACK; + textArea->text = PIC(text); + textArea->textAlignment = MID_LEFT; + textArea->fontId = SMALL_BOLD_FONT; + textArea->style = NO_STYLE; + textArea->wrapping = true; + textArea->obj.alignment = NO_ALIGNMENT; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = BORDER_MARGIN; - textArea->obj.area.width = container->obj.area.width; - textArea->obj.area.height = nbgl_getTextHeightInWidth( +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 28; +#endif // TARGET_STAX + textArea->obj.area.width = container->obj.area.width; + textArea->obj.area.height = nbgl_getTextHeightInWidth( textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); - fullHeight += textArea->obj.area.height; + fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; container->children[0] = (nbgl_obj_t *) textArea; } if (subText != NULL) { @@ -1263,18 +1386,26 @@ int nbgl_layoutAddText(nbgl_layout_t *layout, const char *text, const char *subT subTextArea->fontId, subTextArea->text, subTextArea->obj.area.width, false); subTextArea->textAlignment = MID_LEFT; subTextArea->obj.alignment = NO_ALIGNMENT; - fullHeight += subTextArea->obj.area.height; if (text != NULL) { subTextArea->obj.alignmentMarginY = INTERNAL_MARGIN; fullHeight += INTERNAL_MARGIN; container->children[1] = (nbgl_obj_t *) subTextArea; } else { +#ifdef TARGET_STAX subTextArea->obj.alignmentMarginY = BORDER_MARGIN; - container->children[0] = (nbgl_obj_t *) subTextArea; +#else // TARGET_STAX + subTextArea->obj.alignmentMarginY = 28; +#endif // TARGET_STAX + container->children[0] = (nbgl_obj_t *) subTextArea; } + fullHeight += subTextArea->obj.area.height + subTextArea->obj.alignmentMarginY; } - container->obj.area.height = fullHeight + 2 * BORDER_MARGIN; +#ifdef TARGET_STAX + container->obj.area.height = fullHeight + BORDER_MARGIN; +#else // TARGET_STAX + container->obj.area.height = fullHeight + 28; +#endif // TARGET_STAX container->layout = VERTICAL; container->obj.alignmentMarginX = BORDER_MARGIN; container->obj.alignment = NO_ALIGNMENT; @@ -1371,14 +1502,12 @@ int nbgl_layoutAddRadioChoice(nbgl_layout_t *layout, const nbgl_layoutRadioChoic else { textArea->text = PIC(choices->names[i]); } - - textArea->textAlignment = MID_LEFT; - textArea->obj.area.width = 300; - textArea->obj.area.height = 24; - textArea->style = NO_STYLE; - textArea->obj.alignment = MID_LEFT; - textArea->obj.alignTo = (nbgl_obj_t *) container; - container->children[0] = (nbgl_obj_t *) textArea; + textArea->textAlignment = MID_LEFT; + textArea->obj.area.width = 300; + textArea->style = NO_STYLE; + textArea->obj.alignment = MID_LEFT; + textArea->obj.alignTo = (nbgl_obj_t *) container; + container->children[0] = (nbgl_obj_t *) textArea; // init button for this choice button->activeColor = BLACK; @@ -1390,10 +1519,9 @@ int nbgl_layoutAddRadioChoice(nbgl_layout_t *layout, const nbgl_layoutRadioChoic container->children[1] = (nbgl_obj_t *) button; container->obj.area.width = SCREEN_WIDTH - 2 * BORDER_MARGIN; - container->obj.area.height = 32; + container->obj.area.height = TOUCHABLE_BAR_HEIGHT; container->obj.alignment = NO_ALIGNMENT; container->obj.alignmentMarginX = BORDER_MARGIN; - container->obj.alignmentMarginY = BORDER_MARGIN; container->obj.alignTo = (nbgl_obj_t *) NULL; // whole container should be touchable container->obj.touchMask = (1 << TOUCHED); @@ -1411,8 +1539,10 @@ int nbgl_layoutAddRadioChoice(nbgl_layout_t *layout, const nbgl_layoutRadioChoic textArea->textColor = DARK_GRAY; textArea->fontId = SMALL_REGULAR_FONT; } + textArea->obj.area.height = nbgl_getFontHeight(textArea->fontId); + line = createHorizontalLine(layoutInt->layer); - line->obj.alignmentMarginY = BORDER_MARGIN; + line->obj.alignmentMarginY = -4; // set these new objs as child of main container addObjectToLayout(layoutInt, (nbgl_obj_t *) container); @@ -1485,7 +1615,11 @@ int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredI if (container->nbChildren > 0) { textArea->obj.alignment = BOTTOM_MIDDLE; textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = BORDER_MARGIN + 4; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = BOTTOM_BORDER_MARGIN; +#endif // TARGET_STAX } else { textArea->obj.alignment = TOP_MIDDLE; @@ -1519,14 +1653,21 @@ int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredI if (container->nbChildren > 0) { textArea->obj.alignment = BOTTOM_MIDDLE; textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; - textArea->obj.alignmentMarginY = BORDER_MARGIN; if (info->text1 != NULL) { - // if previous element is text1, only space of 16 px - textArea->obj.alignmentMarginY -= 4; +#ifdef TARGET_STAX + // if previous element is text1, only space of 20 px + textArea->obj.alignmentMarginY = 20; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 16; +#endif // TARGET_STAX } else { - // else if icon, space of 24 px - textArea->obj.alignmentMarginY += 4; +#ifdef TARGET_STAX + // else if icon, space of 28 px + textArea->obj.alignmentMarginY = 28; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 24; +#endif // TARGET_STAX } } else { @@ -1574,7 +1715,11 @@ int nbgl_layoutAddCenteredInfo(nbgl_layout_t *layout, const nbgl_layoutCenteredI if (container->nbChildren > 0) { textArea->obj.alignment = BOTTOM_MIDDLE; textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = BORDER_MARGIN; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 28; +#endif // TARGET_STAX } else { textArea->obj.alignment = TOP_MIDDLE; @@ -1912,8 +2057,8 @@ int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); - // get container children (max 2 (QRCode + text1/text2)) - container->children = nbgl_containerPoolGet(2, layoutInt->layer); + // get container children (max 2 (QRCode + text1 + text2)) + container->children = nbgl_containerPoolGet(3, layoutInt->layer); container->nbChildren = 0; qrcode = (nbgl_qrcode_t *) nbgl_objPoolGet(QR_CODE, layoutInt->layer); @@ -1929,11 +2074,10 @@ int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) // in QR V10, we use 4*4 screen pixels for one QR pixel qrcode->obj.area.width = (qrcode->version == QRCODE_V4) ? (QR_V4_NB_PIX_SIZE * 8) : (QR_V10_NB_PIX_SIZE * 4); - qrcode->obj.area.height = qrcode->obj.area.width; - qrcode->text = PIC(info->url); - qrcode->obj.area.bpp = NBGL_BPP_1; - qrcode->obj.alignment = TOP_MIDDLE; - qrcode->obj.alignmentMarginY = 24; + qrcode->obj.area.height = qrcode->obj.area.width; + qrcode->text = PIC(info->url); + qrcode->obj.area.bpp = NBGL_BPP_1; + qrcode->obj.alignment = TOP_MIDDLE; fullHeight += qrcode->obj.area.height; container->children[container->nbChildren] = (nbgl_obj_t *) qrcode; @@ -1951,14 +2095,18 @@ int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); textArea->obj.alignment = BOTTOM_MIDDLE; textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = 40; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 24; +#endif // TARGET_STAX - fullHeight += textArea->obj.area.height; + fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; container->children[container->nbChildren] = (nbgl_obj_t *) textArea; container->nbChildren++; } - else if (info->text2 != NULL) { + if (info->text2 != NULL) { textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); textArea->textColor = DARK_GRAY; textArea->text = PIC(info->text2); @@ -1970,25 +2118,28 @@ int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info) textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping); textArea->obj.alignment = BOTTOM_MIDDLE; textArea->obj.alignTo = (nbgl_obj_t *) container->children[container->nbChildren - 1]; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = 40; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 28; +#endif // TARGET_STAX - fullHeight += textArea->obj.area.height; + fullHeight += textArea->obj.area.height + textArea->obj.alignmentMarginY; container->children[container->nbChildren] = (nbgl_obj_t *) textArea; container->nbChildren++; } container->obj.area.height = fullHeight; container->layout = VERTICAL; - // center the QRCode only if it's the first (and probably only) child - if (layoutInt->container->nbChildren == 0) { + if (info->centered) { container->obj.alignment = CENTER; } else { - container->obj.alignment = BOTTOM_MIDDLE; - container->obj.alignmentMarginY = BORDER_MARGIN; + container->obj.alignment = BOTTOM_MIDDLE; container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 1]; } + container->obj.alignmentMarginY = info->offsetY; container->obj.area.width = AVAILABLE_WIDTH; @@ -2037,7 +2188,7 @@ int nbgl_layoutAddChoiceButtons(nbgl_layout_t *layout, const nbgl_layoutChoiceBu bottomButton->borderColor = WHITE; } else if (info->style == BOTH_ROUNDED_STYLE) { - bottomButton->obj.alignmentMarginY = BORDER_MARGIN; // 24 pixels from screen bottom + bottomButton->obj.alignmentMarginY = BOTTOM_BORDER_MARGIN; // 24 pixels from screen bottom bottomButton->borderColor = LIGHT_GRAY; } bottomButton->innerColor = WHITE; @@ -2183,7 +2334,7 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL container->children[container->nbChildren] = (nbgl_obj_t *) valueTextArea; container->nbChildren++; - fullHeight += valueTextArea->obj.area.height; + fullHeight += valueTextArea->obj.area.height + valueTextArea->obj.alignmentMarginY; if (pair->valueIcon != NULL) { nbgl_image_t *image = (nbgl_image_t *) nbgl_objPoolGet(IMAGE, layoutInt->layer); layoutObj_t *obj @@ -2204,8 +2355,17 @@ int nbgl_layoutAddTagValueList(nbgl_layout_t *layout, const nbgl_layoutTagValueL container->obj.area.height = fullHeight; container->layout = VERTICAL; container->obj.alignmentMarginX = BORDER_MARGIN; +#ifdef TARGET_STAX container->obj.alignmentMarginY = 12; - container->obj.alignment = NO_ALIGNMENT; +#else // TARGET_STAX + if ((i == 0) && (layoutInt->container->nbChildren == 0)) { + container->obj.alignmentMarginY = 40; + } + else { + container->obj.alignmentMarginY = 24; + } +#endif // TARGET_STAX + container->obj.alignment = NO_ALIGNMENT; addObjectToLayout(layoutInt, (nbgl_obj_t *) container); } @@ -2379,7 +2539,11 @@ int nbgl_layoutAddButton(nbgl_layout_t *layout, const nbgl_layoutButton_t *butto return -1; } +#ifdef TARGET_STAX button->obj.alignmentMarginY = BORDER_MARGIN; +#else // TARGET_STAX + button->obj.alignmentMarginY = BOTTOM_BORDER_MARGIN; +#endif // TARGET_STAX if (buttonInfo->onBottom != true) { button->obj.alignmentMarginX = BORDER_MARGIN; button->obj.alignment = NO_ALIGNMENT; @@ -2732,10 +2896,16 @@ int nbgl_layoutAddProgressIndicator(nbgl_layout_t *layout, button->obj.area.height = BUTTON_DIAMETER; button->radius = BUTTON_RADIUS; button->text = NULL; - button->icon = PIC(&C_leftArrow32px); - button->obj.touchMask = (1 << TOUCHED); - button->obj.touchId = BACK_BUTTON_ID; - container->children[1] = (nbgl_obj_t *) button; +#ifdef TARGET_STAX + button->icon = PIC(&C_leftArrow32px); + button->obj.alignmentMarginX = 4; +#else // TARGET_STAX + button->icon = PIC(&C_leftArrow40px); + button->obj.alignmentMarginX = 8; +#endif // TARGET_STAX + button->obj.touchMask = (1 << TOUCHED); + button->obj.touchId = BACK_BUTTON_ID; + container->children[1] = (nbgl_obj_t *) button; } // set this new container as child of the main container @@ -2937,18 +3107,38 @@ int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, return -1; } - container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); - container->obj.area.width = SCREEN_WIDTH; + nbActiveButtons = nbUsedButtons; + container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); + container->layout = VERTICAL; + container->obj.area.width = SCREEN_WIDTH; +#ifdef TARGET_STAX + // 2 rows of buttons with radius=32, and a intervale of 8px container->obj.area.height = 2 * 64 + 8; - container->layout = VERTICAL; - container->nbChildren = NB_MAX_SUGGESTION_BUTTONS; - container->children - = (nbgl_obj_t **) nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + container->nbChildren = nbUsedButtons; + container->children = (nbgl_obj_t **) nbgl_containerPoolGet(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, + layoutInt->layer); +#else // TARGET_STAX + // 1 row of buttons + page indicator + container->obj.area.height = 64 + 20; + // on Europa, the first child is used by the progress indicator, if more that 2 buttons + container->nbChildren = nbUsedButtons + FIRST_BUTTON_INDEX; + container->children = (nbgl_obj_t **) nbgl_containerPoolGet( + NB_MAX_VISIBLE_SUGGESTION_BUTTONS + 1, layoutInt->layer); + + // the container is swipable on Europa + container->obj.touchMask = (1 << SWIPED_LEFT) | (1 << SWIPED_RIGHT); + container->obj.touchId = CONTROLS_ID; // TODO: change this value + obj = addCallbackObj(layoutInt, (nbgl_obj_t *) container, 0, NBGL_NO_TUNE); + if (obj == NULL) { + return -1; + } +#endif // TARGET_STAX + // align this control on top of keyboard (that must have been added just before) container->obj.alignmentMarginY = BORDER_MARGIN; container->obj.alignment = TOP_MIDDLE; container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 1]; - // create suggestion buttons, even if not displayed at first + // create all possible suggestion buttons, even if not displayed at first nbgl_objPoolGetArray(BUTTON, NB_MAX_SUGGESTION_BUTTONS, 0, (nbgl_obj_t **) &choiceButtons); for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) { obj = addCallbackObj( @@ -2960,17 +3150,29 @@ int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, choiceButtons[i]->innerColor = BLACK; choiceButtons[i]->borderColor = BLACK; choiceButtons[i]->foregroundColor = WHITE; - choiceButtons[i]->obj.area.width = (SCREEN_WIDTH - 2 * BORDER_MARGIN - 8) / 2; +#ifdef TARGET_STAX + choiceButtons[i]->obj.area.width = (SCREEN_WIDTH - 2 * BORDER_MARGIN - 8) / 2; +#else // TARGET_STAX + choiceButtons[i]->obj.area.width = (SCREEN_WIDTH - 2 * 32 - 8) / 2; +#endif // TARGET_STAX choiceButtons[i]->obj.area.height = 64; choiceButtons[i]->radius = RADIUS_32_PIXELS; choiceButtons[i]->fontId = SMALL_BOLD_1BPP_FONT; choiceButtons[i]->icon = NULL; if ((i % 2) == 0) { +#ifdef TARGET_STAX choiceButtons[i]->obj.alignmentMarginX = BORDER_MARGIN; + // second row 8px under the first one if (i != 0) { choiceButtons[i]->obj.alignmentMarginY = 8; } choiceButtons[i]->obj.alignment = NO_ALIGNMENT; +#else // TARGET_STAX + choiceButtons[i]->obj.alignmentMarginX = 32 + 8; + if (i == 0) { + choiceButtons[i]->obj.alignment = TOP_LEFT; + } +#endif // TARGET_STAX } else { choiceButtons[i]->obj.alignmentMarginX = 8; @@ -2981,13 +3183,31 @@ int nbgl_layoutAddSuggestionButtons(nbgl_layout_t *layout, choiceButtons[i]->obj.touchMask = (1 << TOUCHED); choiceButtons[i]->obj.touchId = CONTROLS_ID + i; // some buttons may not be visible - if (i < nbUsedButtons) { - container->children[i] = (nbgl_obj_t *) choiceButtons[i]; - } - else { - container->children[i] = NULL; + if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbActiveButtons)) { + container->children[i + FIRST_BUTTON_INDEX] = (nbgl_obj_t *) choiceButtons[i]; } } +#ifndef TARGET_STAX + // on Europa, the first child is used by the progress indicator, if more that 2 buttons + nbgl_page_indicator_t *indicator + = (nbgl_page_indicator_t *) nbgl_objPoolGet(PAGE_INDICATOR, layoutInt->layer); + indicator->activePage = 0; + indicator->nbPages = (nbUsedButtons > 2) ? (nbUsedButtons - 1) : 0; + indicator->obj.area.width = 184; + indicator->obj.alignment = BOTTOM_MIDDLE; + indicator->style = CURRENT_INDICATOR; + container->children[PAGE_INDICATOR_INDEX] = (nbgl_obj_t *) indicator; + nbgl_objPoolGetArray(IMAGE, 2, 0, (nbgl_obj_t **) &partialButtonImages); + partialButtonImages[0]->buffer = &C_left_half_64px; + partialButtonImages[0]->obj.alignment = TOP_LEFT; + partialButtonImages[0]->foregroundColor = BLACK; + partialButtonImages[0]->transformation = VERTICAL_MIRROR; + partialButtonImages[1]->buffer = &C_left_half_64px; + partialButtonImages[1]->obj.alignment = TOP_RIGHT; + partialButtonImages[1]->foregroundColor = BLACK; + partialButtonImages[1]->transformation = NO_TRANSFORMATION; + updateSuggestionButtons(container, 0, 0); +#endif // TARGET_STAX // set this new container as child of the main container addObjectToLayout(layoutInt, (nbgl_obj_t *) container); @@ -3022,19 +3242,48 @@ int nbgl_layoutUpdateSuggestionButtons(nbgl_layout_t *layout, if ((container == NULL) || (container->obj.type != CONTAINER)) { return -1; } + nbActiveButtons = nbUsedButtons; + container->nbChildren = nbUsedButtons + FIRST_BUTTON_INDEX; // update suggestion buttons for (int i = 0; i < NB_MAX_SUGGESTION_BUTTONS; i++) { choiceButtons[i]->text = buttonTexts[i]; // some buttons may not be visible - if (i < nbUsedButtons) { - container->children[i] = (nbgl_obj_t *) choiceButtons[i]; + if (i < MIN(NB_MAX_VISIBLE_SUGGESTION_BUTTONS, nbUsedButtons)) { + if ((i % 2) == 0) { + choiceButtons[i]->obj.alignmentMarginX = BORDER_MARGIN; +#ifdef TARGET_STAX + // second row 8px under the first one + if (i != 0) { + choiceButtons[i]->obj.alignmentMarginY = 8; + } + choiceButtons[i]->obj.alignment = NO_ALIGNMENT; +#else // TARGET_STAX + if (i == 0) { + choiceButtons[i]->obj.alignment = TOP_LEFT; + } +#endif // TARGET_STAX + } + else { + choiceButtons[i]->obj.alignmentMarginX = 8; + choiceButtons[i]->obj.alignment = MID_RIGHT; + choiceButtons[i]->obj.alignTo = (nbgl_obj_t *) choiceButtons[i - 1]; + } + container->children[i + FIRST_BUTTON_INDEX] = (nbgl_obj_t *) choiceButtons[i]; } else { - container->children[i] = NULL; + container->children[i + FIRST_BUTTON_INDEX] = NULL; } } container->forceClean = true; +#ifndef TARGET_STAX + // on Europa, the first child is used by the progress indicator, if more that 2 buttons + nbgl_page_indicator_t *indicator + = (nbgl_page_indicator_t *) container->children[PAGE_INDICATOR_INDEX]; + indicator->nbPages = (nbUsedButtons > 2) ? (nbUsedButtons - 1) : 0; + indicator->activePage = 0; + updateSuggestionButtons(container, 0, 0); +#endif // TARGET_STAX nbgl_redrawObject((nbgl_obj_t *) container, NULL, false); @@ -3094,14 +3343,22 @@ int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer); textArea->textColor = BLACK; snprintf(numText, sizeof(numText), "%d.", number); - textArea->text = numText; - textArea->textAlignment = MID_LEFT; - textArea->fontId = LARGE_MEDIUM_1BPP_FONT; + textArea->text = numText; + textArea->textAlignment = CENTER; + textArea->fontId = LARGE_MEDIUM_1BPP_FONT; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = 12; - textArea->obj.alignTo = (nbgl_obj_t *) line; - textArea->obj.alignment = TOP_LEFT; - textArea->obj.area.width = 50; - textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 9; +#endif // TARGET_STAX + textArea->obj.alignTo = (nbgl_obj_t *) line; + textArea->obj.alignment = TOP_LEFT; +#ifdef TARGET_STAX + textArea->obj.area.width = 50; +#else // TARGET_STAX + textArea->obj.area.width = 66; +#endif // TARGET_STAX + textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); // set this new text area as child of the main container addObjectToLayout(layoutInt, (nbgl_obj_t *) textArea); } @@ -3112,14 +3369,21 @@ int nbgl_layoutAddEnteredText(nbgl_layout_t *layout, textArea->text = text; textArea->textAlignment = MID_LEFT; textArea->fontId = LARGE_MEDIUM_1BPP_FONT; +#ifdef TARGET_STAX textArea->obj.alignmentMarginY = 12; - textArea->obj.alignTo = (nbgl_obj_t *) line; - textArea->obj.alignment = TOP_MIDDLE; +#else // TARGET_STAX + textArea->obj.alignmentMarginY = 9; +#endif // TARGET_STAX + textArea->obj.alignTo = (nbgl_obj_t *) line; + textArea->obj.alignment = TOP_LEFT; + textArea->obj.area.width = line->obj.area.width; if (numbered) { - textArea->obj.area.width = line->obj.area.width - 2 * 50; - } - else { - textArea->obj.area.width = line->obj.area.width; +#ifdef TARGET_STAX + textArea->obj.alignmentMarginX = 50; +#else // TARGET_STAX + textArea->obj.alignmentMarginX = 66; +#endif // TARGET_STAX + textArea->obj.area.width -= textArea->obj.alignmentMarginX; } textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId); textArea->autoHideLongLine = true; @@ -3222,7 +3486,7 @@ int nbgl_layoutAddConfirmationButton(nbgl_layout_t *layout, return -1; } - button->obj.alignmentMarginY = BORDER_MARGIN; + button->obj.alignmentMarginY = BOTTOM_BORDER_MARGIN; button->obj.alignment = TOP_MIDDLE; button->foregroundColor = WHITE; if (active) { @@ -3537,7 +3801,6 @@ int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) { nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout; nbgl_container_t *container; - nbgl_line_t *line; uint8_t space; LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddHiddenDigits():\n"); @@ -3556,8 +3819,11 @@ int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) // create a container, invisible or bordered container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer); - container->nbChildren = nbDigits + 1; // +1 for the line - container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); + container->nbChildren = nbDigits; +#ifdef TARGET_STAX + container->nbChildren++; // +1 for the line +#endif // TARGET_STAX + container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer); // pixels between each icon (knowing that the effective round are 18px large and the // icon 24px) container->obj.area.width = nbDigits * C_round_24px.width + (nbDigits + 1) * space; @@ -3595,6 +3861,8 @@ int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) image->obj.alignmentMarginY = (container->obj.area.height - C_round_24px.width) / 2; } } +#ifdef TARGET_STAX + nbgl_line_t *line; // create gray line line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer); line->lineColor = LIGHT_GRAY; @@ -3607,6 +3875,7 @@ int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits) line->thickness = 2; line->offset = 2; container->children[nbDigits] = (nbgl_obj_t *) line; +#endif // TARGET_STAX // return index of keypad to be modified later on return (layoutInt->container->nbChildren - 1); diff --git a/lib_nbgl/src/nbgl_navigation.c b/lib_nbgl/src/nbgl_navigation.c index 832d3f0fb..a773f8de9 100644 --- a/lib_nbgl/src/nbgl_navigation.c +++ b/lib_nbgl/src/nbgl_navigation.c @@ -185,10 +185,14 @@ nbgl_container_t *nbgl_navigationPopulate(uint8_t nbPages, if (!withExitKey) { button->obj.area.width += BUTTON_DIAMETER / 2; } - button->obj.area.height = BUTTON_DIAMETER; - button->radius = BUTTON_RADIUS; - button->text = NULL; - button->icon = &C_rightArrow32px; + button->obj.area.height = BUTTON_DIAMETER; + button->radius = BUTTON_RADIUS; + button->text = NULL; +#ifdef TARGET_STAX + button->icon = &C_rightArrow32px; +#else // TARGET_STAX + button->icon = &C_rightArrow40px; +#endif // TARGET_STAX button->obj.alignmentMarginX = INTERNAL_SMALL_MARGIN; button->obj.alignmentMarginY = 0; button->obj.alignment = MID_RIGHT; diff --git a/lib_nbgl/src/nbgl_obj_keyboard.c b/lib_nbgl/src/nbgl_obj_keyboard.c index 3860ce833..3bab2f9bb 100644 --- a/lib_nbgl/src/nbgl_obj_keyboard.c +++ b/lib_nbgl/src/nbgl_obj_keyboard.c @@ -161,9 +161,13 @@ static void keyboardDrawCommonLines(nbgl_keyboard_t *keyboard) nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 2nd line rectArea.y0 += KEYBOARD_KEY_HEIGHT; nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 3rd line - rectArea.y0 += KEYBOARD_KEY_HEIGHT; - nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 4th line - if (!keyboard->lettersOnly) { + // in letter only mode, only draw the last line if not at bottom of screen + if ((keyboard->obj.alignmentMarginY > 0) || (!keyboard->lettersOnly)) { + rectArea.y0 += KEYBOARD_KEY_HEIGHT; + nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 4th line + } + // in non letter only mode, only draw the last line if not at bottom of screen + if ((keyboard->obj.alignmentMarginY > 0) && (!keyboard->lettersOnly)) { rectArea.y0 += KEYBOARD_KEY_HEIGHT; nbgl_frontDrawHorizontalLine(&rectArea, 0x1, keyboard->borderColor); // 5th line } @@ -353,8 +357,8 @@ static void keyboardDrawLetters(nbgl_keyboard_t *keyboard) rectArea.backgroundColor = (keyboard->casing != LOWER_CASE) ? BLACK : WHITE; nbgl_drawIcon( &rectArea, - (keyboard->casing != LOWER_CASE) ? WHITE : BLACK, NO_TRANSFORMATION, + (keyboard->casing != LOWER_CASE) ? WHITE : BLACK, (keyboard->casing != LOCKED_UPPER_CASE) ? (&C_shift_lock32px) : (&C_shift32px)); rectArea.backgroundColor = WHITE; offsetX = keyboard->obj.area.x0 + SHIFT_KEY_WIDTH; diff --git a/lib_nbgl/src/nbgl_use_case.c b/lib_nbgl/src/nbgl_use_case.c index f9349c14c..703fce614 100644 --- a/lib_nbgl/src/nbgl_use_case.c +++ b/lib_nbgl/src/nbgl_use_case.c @@ -204,11 +204,12 @@ static void pageCallback(int token, uint8_t index) .tapActionText = NULL}; addressConfirmationContext.modalLayout = nbgl_layoutGet(&layoutDescription); - nbgl_layoutQRCode_t qrCode = { - .url = addressConfirmationContext.address, - .text1 = NULL, - .text2 = addressConfirmationContext.address // display as gray text - }; + nbgl_layoutQRCode_t qrCode + = {.url = addressConfirmationContext.address, + .text1 = NULL, + .text2 = addressConfirmationContext.address, // display as gray text + .centered = true, + .offsetY = 0}; nbgl_layoutAddQRCode(addressConfirmationContext.modalLayout, &qrCode); nbgl_layoutAddBottomButton( From 0d7af344702a13bf7784b95c8dda843cad494e01 Mon Sep 17 00:00:00 2001 From: Nicolas Roggeman Date: Fri, 2 Feb 2024 15:33:38 +0100 Subject: [PATCH 3/4] Set line height of Regular 36 font to 40 instead of 44 --- lib_nbgl/fonts/config-Inter-Medium36-1bpp.ini | 2 +- lib_nbgl/fonts/config-Inter-Medium36.ini | 2 +- lib_nbgl/include/nbgl_font_inter_medium_36.inc | 2 +- lib_nbgl/include/nbgl_font_inter_medium_36_1bpp.inc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_nbgl/fonts/config-Inter-Medium36-1bpp.ini b/lib_nbgl/fonts/config-Inter-Medium36-1bpp.ini index 9eb1e2658..92742345c 100644 --- a/lib_nbgl/fonts/config-Inter-Medium36-1bpp.ini +++ b/lib_nbgl/fonts/config-Inter-Medium36-1bpp.ini @@ -6,7 +6,7 @@ loaded_baseline=30 # This font can display characters at y=-1 => we need to compensate that baseline_offset=1 fontSize=36 -lineSize=44 +lineSize=40 firstChar=0x20 lastChar=0x7E firstLine=5 diff --git a/lib_nbgl/fonts/config-Inter-Medium36.ini b/lib_nbgl/fonts/config-Inter-Medium36.ini index 0805b7b4e..b0a3f5091 100644 --- a/lib_nbgl/fonts/config-Inter-Medium36.ini +++ b/lib_nbgl/fonts/config-Inter-Medium36.ini @@ -6,7 +6,7 @@ loaded_baseline=28 # This font can display characters at y=-1 => we need to compensate that baseline_offset=1 fontSize=36 -lineSize=44 +lineSize=40 firstChar=0x20 lastChar=0x7E firstLine=5 diff --git a/lib_nbgl/include/nbgl_font_inter_medium_36.inc b/lib_nbgl/include/nbgl_font_inter_medium_36.inc index 220056272..0ae099347 100644 --- a/lib_nbgl/include/nbgl_font_inter_medium_36.inc +++ b/lib_nbgl/include/nbgl_font_inter_medium_36.inc @@ -1716,7 +1716,7 @@ __attribute__ ((section("._nbgl_fonts_"))) const nbgl_font_t fontINTER_MEDIUM_36 BAGL_FONT_INTER_MEDIUM_36px, // font id (uint8_t) NBGL_BPP_4, // bpp 48, // height of all characters in pixels - 44, // line height in pixels + 40, // line height in pixels 0, // kerning 1, // crop enabled (1) or not (0) 0, // Most top Y coordinate of any char diff --git a/lib_nbgl/include/nbgl_font_inter_medium_36_1bpp.inc b/lib_nbgl/include/nbgl_font_inter_medium_36_1bpp.inc index d83d88dba..b89786e93 100644 --- a/lib_nbgl/include/nbgl_font_inter_medium_36_1bpp.inc +++ b/lib_nbgl/include/nbgl_font_inter_medium_36_1bpp.inc @@ -655,7 +655,7 @@ __attribute__ ((section("._nbgl_fonts_"))) const nbgl_font_t fontINTER_MEDIUM_36 BAGL_FONT_INTER_MEDIUM_36px_1bpp, // font id (uint8_t) NBGL_BPP_1, // bpp 48, // height of all characters in pixels - 44, // line height in pixels + 40, // line height in pixels 0, // kerning 1, // crop enabled (1) or not (0) 0, // Most top Y coordinate of any char From f0b271cf536810e2e727aa305b7f64a567ea8367 Mon Sep 17 00:00:00 2001 From: Nicolas Roggeman Date: Fri, 2 Feb 2024 15:34:00 +0100 Subject: [PATCH 4/4] Add new 4BPP glyphs for Europa --- lib_nbgl/glyphs/ic_denied_64.bmp | Bin 0 -> 16438 bytes lib_nbgl/glyphs/ic_success_64.bmp | Bin 0 -> 16438 bytes lib_nbgl/glyphs/ic_warning_64.bmp | Bin 0 -> 16438 bytes lib_nbgl/tools/icon2glyph.py | 4 ++-- 4 files changed, 2 insertions(+), 2 deletions(-) create mode 100755 lib_nbgl/glyphs/ic_denied_64.bmp create mode 100755 lib_nbgl/glyphs/ic_success_64.bmp create mode 100755 lib_nbgl/glyphs/ic_warning_64.bmp diff --git a/lib_nbgl/glyphs/ic_denied_64.bmp b/lib_nbgl/glyphs/ic_denied_64.bmp new file mode 100755 index 0000000000000000000000000000000000000000..d9990ecc97c87a121784fbca1f8726267898570b GIT binary patch literal 16438 zcmd^^!ExL;5Jlzl-ZlZ_xJR9QX6=2el!2Lnl)*5AQ3jk0#u-cq69Pj}2-^2$wu*w- zAV6Y9Q)N|sV*qsj{=WfoWc%O$el&M)KR@{MAJB~Wb{F`>Pjh$o_g}y9Hs_Dm3;$3e zfCtclBRGQryhhNP_7w9BS`aQQ?;`Z*ZomP|`HX!p&BdX9G#3$Di4=VSw4jD(uO~0? zca-(i zx^x~v2gK8k(B}^H;0)IAE9atj0saoey-&>t;`gBV-K`w31L8>4i1(gXA8sNM4Tl09 zJ+Z}}z4GD$;*7m|^Ml8=W}UjalU}XqdQaTNol=EPdN5dQYJ_L$-WT1aRIS>3Xx}ZI zTf0<~{M5bwvUlB*ZrexyKGB1LJ@+|auS?}xjawh_AfK-e+}{t0Pn~^J;v24e;PyI~ zOB~|LjaMA;4ef@Dnx-!vyO=LE-=cp@?t-S&-44`kLG0V+@6Sl8#&i#^0EPsoxV8U&5A=Clv$}KR zhn#86)Mt1bFvq902jKPRCB>WCgEIi>_3CO}`(Z>@Y^r8zj~bqij=iI^e@<~O?ZFv9 zj<1}U_q(!GcWxgYCotE8U#y>vNh#y@-Dq_xM!Tu*OhqnVx>P( z!+g$-RlJY>J2ZGT=GL`V?eDp81t33Ot$1Cro6p_O1g@uo+NPzo{2HVD0QoY0Z&XY* z@8kKm8Fgblf4cua<^Jow#b>X1cjbE@Ymlxg&w;#vm|t_%@V@_kZS@a#7;DVc&RLVb z%{_qQ0Osn+yZ7CA+TtJH0HlAeuB~Z5CuUO*sNtS5dmS)6AI7!*;R_(kS4r#!JulSx z;BB1icmD@xPw`D@O>zRr@^0K~ax8aggu4NA-nG_(0KEO@CI0FD$W`Rs^0(v~$J_{S z2Rwh@mBYTLdC-2&4;&%EWA#P5qt{V3ipBjm4faS&G``uoM>r*wRd+>NY7}#6%Zd{55%84~+dlwh^hZzpz{BW+s z&DFEm676vh#G9R;=s~IXknsNL-*$*?6Y;(2${FFY9<1_iHQ)(A97W!hPtFl&oI__d zY$PrK)tQUe+K2mMdEQ98dQg1sF`qcZ6|bk}#5ch6@#*Z1i=2HTZ?L#qAMr3Ge0(~4 z^FvNp$bEljTF$MF=zj*qXKy~pZ4>$8b^B)=Up1obX+ir_jy5<__eVWwb9k;9BTc|N zcdegt^$;6C>RotKJwR&jOlrtCqRlbj?6Tn)XIbKR*25G8!&N*Dvd<5!ysoq-g z^4;cWy<`j;c319$dcFr&Kl4-{uh56L^S(9TaZk|K0G*HYzHWp#dQkiw66^YkIl2RA Xf%2B;h?8`}-DlDuHrOpdjd)KA& z2nHaYeum})7{M8=;aAS4cLDwZguPEaPsHy*^}Aa+UUf+w5~FZg2#C&Di|B#%q{EtwTY*iI`^R9cl=l zRST$Q%)6~$bPwRy_quV##(k*oTF+?HyCtT})`vBE;MF_XIAY^&4R^~NG(H#TtomMn z&w;lL?^8=3mvEu;DWg?hir-7bo-%xQ<)Z;4-lI=`zCtj8%#5raK`#D*NXX{{5)bi5Q`oC z*tPRnkGxwQ&A0Bs=+(2jHg@KPnAGpw&p3;(9pw|quhq6uYn$}|?rx!`)gH|UG16h{ z{y168+7Vut;8!ix-m(Yc_dVJC!<%YH_7yj*^{u>_drI(sYEkSZwPLyOrtY?5zXzrx z9J?5AZXHesO1xW5#WwE&oE@+l;rPg2tUqr#kFk9?9gv@}UhY{rTl64Scc9)eqVpW{ zms*#8ARn=sxpn0>?E!qJh@M}ppCfx?%IDG^JPt^I%Ai97u7A_rtsOuP{fP7vBRoUV!hdWZs+B z+z9t6!~ey*@sZ9#d<@_g`M%cOdLR z()+b~fUea24>em)2GdtM20bY9ZrnkxX$VJYt^O>KGk}mw&*D2r_I{bRnh`EHbN;Bw zQ|z28O`6A`{i+@ie~9qO`!TY2s@2~j9xV9LV;dlpC%$ zu;lTT^~cDb;=9rst>dWeK&l5%B{k&%EP2;j4;+Z?zn0Y4DrVNU)Po}L(gnwm@b~8& zvs6R5llE`3hxrKnJ%4_)&w!`TNiTS^wUUwe4)|XD`RCov z#Em7j?lA^mhlKwx=SrOV>-Wc>SAE~!Loe{+5`Mn@za3)xMEw8m4&WvByGG|aglEK> z1F`Q(<$Sp>Vg5ZmODpj2uRs5G_NJYjeIjqNxO*S*FeQ9^JA3m(j?3hJzB4W7-bVE6 zH=Tdp{ycj2=7ZcmkuR=j|BT~SBid5`&Xx9;5^cmy!0%f)?@M^D8H3(Fqxn>-2ObAf z??UzCZh9asAUq@gSzcVJf5j31oZ(bV(S53^TN{gpVJn^R?h3eX_D)1w>Ro5&zpw47 zA5V?3pa&B%ou9YmT(y8|n#b5Uw$MSHb3rX>ID)FrS&cq%g9C{9_1Die+__k4j)irl zL9xy5gSfx}`2JG!G3RH^KK1t%8l-Om1E}tWa)3VH;z)T7_jYT%mFA#D-wSV*nxs)V zXE1^R=(kEgL-PR~!3l((N}k1kmG2|!IIvb{iI>`#Nt#N}uvHv2pMm;btG89WeD|&V ztmQ$&?#g{o&-dW!XP)ZO75eaT-uLD^>dpne>| S87%chYuZ!H03N~S_xoQqjCR@p literal 0 HcmV?d00001 diff --git a/lib_nbgl/glyphs/ic_warning_64.bmp b/lib_nbgl/glyphs/ic_warning_64.bmp new file mode 100755 index 0000000000000000000000000000000000000000..3413c643e9397fd210d747affdf01b2c10d23f05 GIT binary patch literal 16438 zcmeHO%W>N<6jaW+r2+An3Vi0|o*9?G5>f&?h&uo~PzfkOC9njSpzJDq8WP5zkF+$F zXVwsahqt>AAjFwCzka{8hwIM^e*Xm83EvJ4KH;Z59DaQNk82;lE<5~yrXy7$x*epc zQ%qhh+BwdJ-dU^B$-#VgTN7yOCr~H#Zvp1+3H6PuOb9Iv&;ncdjpZa~Qz=_z8Tbbv zrg4usqhh8o34B}N{SN$7gDsR_6%L+Pz)UFh&iF19HMvFCYn8dgBIs^`6OePJsbBO+ z`!_*xo5tEV&-yWwn;O+?fSfjy|H9at8Kn=O$zR~RRk9mQ11)W?o?w#93GncF&)IjL z&CR`wY;plPcLcRp>B2gCPd)FP?}0y}ZLgM`6L*fr;`;!(2Y}CV2&`>!UhVooLkpaN zkWP-9QeLbX5;>2hIk$?3&L*MNlyD;#_x3%IlePZT_fDS|Y67U+cMj;q`qsH)h%-RQ z`w4SZ_le81MIYK?cNRUF7%%1tpNhVGjEHgok5DC)Tx*wXEOjdp?r?TH}zm z+;M6I#t4u1{35=Otf4mVx?Einm*9}FRV}q9cs`tC#P^XkD&A=-!lAPNQaJFm5w3-Q z#C3oT#Y;|&HpC(08XS^Ca(Y^N?PhTy?<3-@#A&o1EtmP228ZOJb|Ca!W}Uc&j!Bb| zm`82lW0<_S{;YVyJnQ7nvu`BkQCoNz0^Y26!u*%@5APi?0$*+a&y#nbZ;tWac#|{o zs4YEAUP3-YO6cdzuSNMmjWub*oPkAv**^EV~h7PEn4L5 zJbW&{+uvmWQ#!Of&+|O}KleX%?mY9)^FM!xlsEC}Yjnqi14eZ6e?mzE9tL2?}_VhoU>oLH2^M(0tiuLMyVE`QV>KiFG69ALZXa zd2e0Mlcx>tBVrp*{5+4hZdIGK(IV*Y6CRE+YOFOtsD3BRefr=0g!DsO3sB>H&*U>b znb6w#IN~f2ssZPkdHg+mrY7JFh~IfjFSbM{;)g&k$$Koxw`DAJHVLh!lppzqL{8Q^ zc$bv&)y6{u|K^8hQuf8y*7#@MQz9?tdtmkVLaBdpPTV;ftL`l1Z-G>8S?_nomU^g- zCl@dRzP+B0S;SO%pKHtD5zftP04;5{|0D*8trS=kh6(t+j9 Optional[Tuple[Image, int]]: num_colors = len(im.getcolors()) if num_colors > 16: sys.stderr.write( - "Error: input file {} has too many colors".format(file_path) + "\n") - return None + "Warn: input file {} has too many colors".format(file_path) + "\n") + num_colors = 16 # Compute bits_per_pixel # Round number of colors to a power of 2