[FL-2524] Graphics cleanup and icon rotation (#2561)
* Canvas with rotation * Full icon rotation, cleanup of unused resources * F18 API update * Bitmap draw cleanup * More cleaning up * Migrate recovery and DFU to canvas * Make the internal draw function static * Remove all calls to u8g2_DrawXBM Co-authored-by: あく <alleteam@gmail.com>
| @ -51,10 +51,10 @@ static void dap_main_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
|     canvas_set_color(canvas, ColorBlack); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     if(model->dap_active) { |     if(model->dap_active) { | ||||||
|         canvas_draw_icon(canvas, 14, 16, &I_ArrowUpFilled_12x18); |         canvas_draw_icon(canvas, 14, 16, &I_ArrowUpFilled_12x18); | ||||||
|         canvas_draw_icon(canvas, 28, 16, &I_ArrowDownFilled_12x18); |         canvas_draw_icon_ex(canvas, 28, 16, &I_ArrowUpFilled_12x18, IconRotation180); | ||||||
|     } else { |     } else { | ||||||
|         canvas_draw_icon(canvas, 14, 16, &I_ArrowUpEmpty_12x18); |         canvas_draw_icon(canvas, 14, 16, &I_ArrowUpEmpty_12x18); | ||||||
|         canvas_draw_icon(canvas, 28, 16, &I_ArrowDownEmpty_12x18); |         canvas_draw_icon_ex(canvas, 28, 16, &I_ArrowUpEmpty_12x18, IconRotation180); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     switch(model->mode) { |     switch(model->mode) { | ||||||
| @ -76,9 +76,9 @@ static void dap_main_view_draw_callback(Canvas* canvas, void* _model) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(model->rx_active) { |     if(model->rx_active) { | ||||||
|         canvas_draw_icon(canvas, 101, 16, &I_ArrowDownFilled_12x18); |         canvas_draw_icon_ex(canvas, 101, 16, &I_ArrowUpFilled_12x18, IconRotation180); | ||||||
|     } else { |     } else { | ||||||
|         canvas_draw_icon(canvas, 101, 16, &I_ArrowDownEmpty_12x18); |         canvas_draw_icon_ex(canvas, 101, 16, &I_ArrowUpEmpty_12x18, IconRotation180); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     canvas_draw_str_aligned(canvas, 100, 38, AlignCenter, AlignTop, "UART"); |     canvas_draw_str_aligned(canvas, 100, 38, AlignCenter, AlignTop, "UART"); | ||||||
|  | |||||||
| Before Width: | Height: | Size: 160 B | 
| Before Width: | Height: | Size: 168 B | 
| @ -80,9 +80,9 @@ static void gpio_usb_uart_draw_callback(Canvas* canvas, void* _model) { | |||||||
|         canvas_draw_icon(canvas, 48, 14, &I_ArrowUpEmpty_14x15); |         canvas_draw_icon(canvas, 48, 14, &I_ArrowUpEmpty_14x15); | ||||||
| 
 | 
 | ||||||
|     if(model->rx_active) |     if(model->rx_active) | ||||||
|         canvas_draw_icon(canvas, 48, 34, &I_ArrowDownFilled_14x15); |         canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpFilled_14x15, IconRotation180); | ||||||
|     else |     else | ||||||
|         canvas_draw_icon(canvas, 48, 34, &I_ArrowDownEmpty_14x15); |         canvas_draw_icon_ex(canvas, 48, 34, &I_ArrowUpEmpty_14x15, IconRotation180); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool gpio_usb_uart_input_callback(InputEvent* event, void* context) { | static bool gpio_usb_uart_input_callback(InputEvent* event, void* context) { | ||||||
|  | |||||||
| @ -37,7 +37,7 @@ static void desktop_loader_callback(const void* message, void* context) { | |||||||
| static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { | static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { | ||||||
|     UNUSED(context); |     UNUSED(context); | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); |     canvas_draw_icon(canvas, 0, 0, &I_Lock_7x8); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) { | static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) { | ||||||
| @ -230,7 +230,7 @@ Desktop* desktop_alloc() { | |||||||
| 
 | 
 | ||||||
|     // Lock icon
 |     // Lock icon
 | ||||||
|     desktop->lock_icon_viewport = view_port_alloc(); |     desktop->lock_icon_viewport = view_port_alloc(); | ||||||
|     view_port_set_width(desktop->lock_icon_viewport, icon_get_width(&I_Lock_8x8)); |     view_port_set_width(desktop->lock_icon_viewport, icon_get_width(&I_Lock_7x8)); | ||||||
|     view_port_draw_callback_set( |     view_port_draw_callback_set( | ||||||
|         desktop->lock_icon_viewport, desktop_lock_icon_draw_callback, desktop); |         desktop->lock_icon_viewport, desktop_lock_icon_draw_callback, desktop); | ||||||
|     view_port_enabled_set(desktop->lock_icon_viewport, false); |     view_port_enabled_set(desktop->lock_icon_viewport, false); | ||||||
|  | |||||||
| @ -115,16 +115,18 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu | |||||||
|             } else { |             } else { | ||||||
|                 switch(model->pin.data[i]) { |                 switch(model->pin.data[i]) { | ||||||
|                 case InputKeyDown: |                 case InputKeyDown: | ||||||
|                     canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9); |                     canvas_draw_icon_ex( | ||||||
|  |                         canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9, IconRotation180); | ||||||
|                     break; |                     break; | ||||||
|                 case InputKeyUp: |                 case InputKeyUp: | ||||||
|                     canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9); |                     canvas_draw_icon_ex(canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9, IconRotation0); | ||||||
|                     break; |                     break; | ||||||
|                 case InputKeyLeft: |                 case InputKeyLeft: | ||||||
|                     canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7); |                     canvas_draw_icon_ex( | ||||||
|  |                         canvas, x + 2, y + 3, &I_Pin_arrow_up_7x9, IconRotation270); | ||||||
|                     break; |                     break; | ||||||
|                 case InputKeyRight: |                 case InputKeyRight: | ||||||
|                     canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_right_9x7); |                     canvas_draw_icon_ex(canvas, x + 2, y + 3, &I_Pin_arrow_up_7x9, IconRotation90); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     furi_assert(0); |                     furi_assert(0); | ||||||
| @ -147,7 +149,8 @@ static void desktop_view_pin_input_draw(Canvas* canvas, void* context) { | |||||||
|     desktop_view_pin_input_draw_cells(canvas, model); |     desktop_view_pin_input_draw_cells(canvas, model); | ||||||
| 
 | 
 | ||||||
|     if((model->pin.length > 0) && !model->locked_input) { |     if((model->pin.length > 0) && !model->locked_input) { | ||||||
|         canvas_draw_icon(canvas, 4, 53, &I_Pin_back_full_40x8); |         canvas_draw_icon(canvas, 4, 53, &I_Pin_back_arrow_10x8); | ||||||
|  |         canvas_draw_str(canvas, 16, 60, "= clear"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(model->button_label && ((model->pin.length >= MIN_PIN_SIZE) || model->locked_input)) { |     if(model->button_label && ((model->pin.length >= MIN_PIN_SIZE) || model->locked_input)) { | ||||||
|  | |||||||
| @ -221,7 +221,7 @@ void canvas_draw_bitmap( | |||||||
|     y += canvas->offset_y; |     y += canvas->offset_y; | ||||||
|     uint8_t* bitmap_data = NULL; |     uint8_t* bitmap_data = NULL; | ||||||
|     compress_icon_decode(canvas->compress_icon, compressed_bitmap_data, &bitmap_data); |     compress_icon_decode(canvas->compress_icon, compressed_bitmap_data, &bitmap_data); | ||||||
|     u8g2_DrawXBM(&canvas->fb, x, y, width, height, bitmap_data); |     canvas_draw_u8g2_bitmap(&canvas->fb, x, y, width, height, bitmap_data, IconRotation0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void canvas_draw_icon_animation( | void canvas_draw_icon_animation( | ||||||
| @ -237,13 +237,138 @@ void canvas_draw_icon_animation( | |||||||
|     uint8_t* icon_data = NULL; |     uint8_t* icon_data = NULL; | ||||||
|     compress_icon_decode( |     compress_icon_decode( | ||||||
|         canvas->compress_icon, icon_animation_get_data(icon_animation), &icon_data); |         canvas->compress_icon, icon_animation_get_data(icon_animation), &icon_data); | ||||||
|     u8g2_DrawXBM( |     canvas_draw_u8g2_bitmap( | ||||||
|         &canvas->fb, |         &canvas->fb, | ||||||
|         x, |         x, | ||||||
|         y, |         y, | ||||||
|         icon_animation_get_width(icon_animation), |         icon_animation_get_width(icon_animation), | ||||||
|         icon_animation_get_height(icon_animation), |         icon_animation_get_height(icon_animation), | ||||||
|         icon_data); |         icon_data, | ||||||
|  |         IconRotation0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void canvas_draw_u8g2_bitmap_int( | ||||||
|  |     u8g2_t* u8g2, | ||||||
|  |     u8g2_uint_t x, | ||||||
|  |     u8g2_uint_t y, | ||||||
|  |     u8g2_uint_t w, | ||||||
|  |     u8g2_uint_t h, | ||||||
|  |     bool mirror, | ||||||
|  |     bool rotation, | ||||||
|  |     const uint8_t* bitmap) { | ||||||
|  |     u8g2_uint_t blen; | ||||||
|  |     blen = w; | ||||||
|  |     blen += 7; | ||||||
|  |     blen >>= 3; | ||||||
|  | 
 | ||||||
|  |     if(rotation && !mirror) { | ||||||
|  |         x += w + 1; | ||||||
|  |     } else if(mirror && !rotation) { | ||||||
|  |         y += h - 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     while(h > 0) { | ||||||
|  |         const uint8_t* b = bitmap; | ||||||
|  |         uint16_t len = w; | ||||||
|  |         uint16_t x0 = x; | ||||||
|  |         uint16_t y0 = y; | ||||||
|  |         uint8_t mask; | ||||||
|  |         uint8_t color = u8g2->draw_color; | ||||||
|  |         uint8_t ncolor = (color == 0 ? 1 : 0); | ||||||
|  |         mask = 1; | ||||||
|  | 
 | ||||||
|  |         while(len > 0) { | ||||||
|  |             if(u8x8_pgm_read(b) & mask) { | ||||||
|  |                 u8g2->draw_color = color; | ||||||
|  |                 u8g2_DrawHVLine(u8g2, x0, y0, 1, 0); | ||||||
|  |             } else if(u8g2->bitmap_transparency == 0) { | ||||||
|  |                 u8g2->draw_color = ncolor; | ||||||
|  |                 u8g2_DrawHVLine(u8g2, x0, y0, 1, 0); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if(rotation) { | ||||||
|  |                 y0++; | ||||||
|  |             } else { | ||||||
|  |                 x0++; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             mask <<= 1; | ||||||
|  |             if(mask == 0) { | ||||||
|  |                 mask = 1; | ||||||
|  |                 b++; | ||||||
|  |             } | ||||||
|  |             len--; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         u8g2->draw_color = color; | ||||||
|  |         bitmap += blen; | ||||||
|  | 
 | ||||||
|  |         if(mirror) { | ||||||
|  |             if(rotation) { | ||||||
|  |                 x++; | ||||||
|  |             } else { | ||||||
|  |                 y--; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if(rotation) { | ||||||
|  |                 x--; | ||||||
|  |             } else { | ||||||
|  |                 y++; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         h--; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void canvas_draw_u8g2_bitmap( | ||||||
|  |     u8g2_t* u8g2, | ||||||
|  |     u8g2_uint_t x, | ||||||
|  |     u8g2_uint_t y, | ||||||
|  |     u8g2_uint_t w, | ||||||
|  |     u8g2_uint_t h, | ||||||
|  |     const uint8_t* bitmap, | ||||||
|  |     IconRotation rotation) { | ||||||
|  |     u8g2_uint_t blen; | ||||||
|  |     blen = w; | ||||||
|  |     blen += 7; | ||||||
|  |     blen >>= 3; | ||||||
|  | #ifdef U8G2_WITH_INTERSECTION | ||||||
|  |     if(u8g2_IsIntersection(u8g2, x, y, x + w, y + h) == 0) return; | ||||||
|  | #endif /* U8G2_WITH_INTERSECTION */ | ||||||
|  | 
 | ||||||
|  |     switch(rotation) { | ||||||
|  |     case IconRotation0: | ||||||
|  |         canvas_draw_u8g2_bitmap_int(u8g2, x, y, w, h, 0, 0, bitmap); | ||||||
|  |         break; | ||||||
|  |     case IconRotation90: | ||||||
|  |         canvas_draw_u8g2_bitmap_int(u8g2, x, y, w, h, 0, 1, bitmap); | ||||||
|  |         break; | ||||||
|  |     case IconRotation180: | ||||||
|  |         canvas_draw_u8g2_bitmap_int(u8g2, x, y, w, h, 1, 0, bitmap); | ||||||
|  |         break; | ||||||
|  |     case IconRotation270: | ||||||
|  |         canvas_draw_u8g2_bitmap_int(u8g2, x, y, w, h, 1, 1, bitmap); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void canvas_draw_icon_ex( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     const Icon* icon, | ||||||
|  |     IconRotation rotation) { | ||||||
|  |     furi_assert(canvas); | ||||||
|  |     furi_assert(icon); | ||||||
|  | 
 | ||||||
|  |     x += canvas->offset_x; | ||||||
|  |     y += canvas->offset_y; | ||||||
|  |     uint8_t* icon_data = NULL; | ||||||
|  |     compress_icon_decode(canvas->compress_icon, icon_get_data(icon), &icon_data); | ||||||
|  |     canvas_draw_u8g2_bitmap( | ||||||
|  |         &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_data, rotation); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, const Icon* icon) { | void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, const Icon* icon) { | ||||||
| @ -254,7 +379,8 @@ void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, const Icon* icon) { | |||||||
|     y += canvas->offset_y; |     y += canvas->offset_y; | ||||||
|     uint8_t* icon_data = NULL; |     uint8_t* icon_data = NULL; | ||||||
|     compress_icon_decode(canvas->compress_icon, icon_get_data(icon), &icon_data); |     compress_icon_decode(canvas->compress_icon, icon_get_data(icon), &icon_data); | ||||||
|     u8g2_DrawXBM(&canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_data); |     canvas_draw_u8g2_bitmap( | ||||||
|  |         &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_data, IconRotation0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void canvas_draw_dot(Canvas* canvas, uint8_t x, uint8_t y) { | void canvas_draw_dot(Canvas* canvas, uint8_t x, uint8_t y) { | ||||||
| @ -364,7 +490,7 @@ void canvas_draw_xbm( | |||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     x += canvas->offset_x; |     x += canvas->offset_x; | ||||||
|     y += canvas->offset_y; |     y += canvas->offset_y; | ||||||
|     u8g2_DrawXBM(&canvas->fb, x, y, w, h, bitmap); |     canvas_draw_u8g2_bitmap(&canvas->fb, x, y, w, h, bitmap, IconRotation0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch) { | void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch) { | ||||||
|  | |||||||
| @ -64,6 +64,22 @@ typedef struct { | |||||||
|     uint8_t descender; |     uint8_t descender; | ||||||
| } CanvasFontParameters; | } CanvasFontParameters; | ||||||
| 
 | 
 | ||||||
|  | /** Icon flip */ | ||||||
|  | typedef enum { | ||||||
|  |     IconFlipNone, | ||||||
|  |     IconFlipHorizontal, | ||||||
|  |     IconFlipVertical, | ||||||
|  |     IconFlipBoth, | ||||||
|  | } IconFlip; | ||||||
|  | 
 | ||||||
|  | /** Icon rotation */ | ||||||
|  | typedef enum { | ||||||
|  |     IconRotation0, | ||||||
|  |     IconRotation90, | ||||||
|  |     IconRotation180, | ||||||
|  |     IconRotation270, | ||||||
|  | } IconRotation; | ||||||
|  | 
 | ||||||
| /** Canvas anonymous structure */ | /** Canvas anonymous structure */ | ||||||
| typedef struct Canvas Canvas; | typedef struct Canvas Canvas; | ||||||
| 
 | 
 | ||||||
| @ -217,6 +233,22 @@ void canvas_draw_bitmap( | |||||||
|     uint8_t height, |     uint8_t height, | ||||||
|     const uint8_t* compressed_bitmap_data); |     const uint8_t* compressed_bitmap_data); | ||||||
| 
 | 
 | ||||||
|  | /** Draw icon at position defined by x,y with rotation and flip.
 | ||||||
|  |  * | ||||||
|  |  * @param      canvas   Canvas instance | ||||||
|  |  * @param      x        x coordinate | ||||||
|  |  * @param      y        y coordinate | ||||||
|  |  * @param      icon     Icon instance | ||||||
|  |  * @param      flip     IconFlip | ||||||
|  |  * @param      rotation IconRotation | ||||||
|  |  */ | ||||||
|  | void canvas_draw_icon_ex( | ||||||
|  |     Canvas* canvas, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     const Icon* icon, | ||||||
|  |     IconRotation rotation); | ||||||
|  | 
 | ||||||
| /** Draw animation at position defined by x,y.
 | /** Draw animation at position defined by x,y.
 | ||||||
|  * |  * | ||||||
|  * @param      canvas          Canvas instance |  * @param      canvas          Canvas instance | ||||||
|  | |||||||
| @ -78,3 +78,22 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation); | |||||||
|  * @return     CanvasOrientation |  * @return     CanvasOrientation | ||||||
|  */ |  */ | ||||||
| CanvasOrientation canvas_get_orientation(const Canvas* canvas); | CanvasOrientation canvas_get_orientation(const Canvas* canvas); | ||||||
|  | 
 | ||||||
|  | /** Draw a u8g2 bitmap
 | ||||||
|  |  * | ||||||
|  |  * @param      canvas   Canvas instance | ||||||
|  |  * @param      x        x coordinate | ||||||
|  |  * @param      y        y coordinate | ||||||
|  |  * @param      width    width | ||||||
|  |  * @param      height   height | ||||||
|  |  * @param      bitmap   bitmap | ||||||
|  |  * @param      rotation rotation | ||||||
|  |  */ | ||||||
|  | void canvas_draw_u8g2_bitmap( | ||||||
|  |     u8g2_t* u8g2, | ||||||
|  |     uint8_t x, | ||||||
|  |     uint8_t y, | ||||||
|  |     uint8_t width, | ||||||
|  |     uint8_t height, | ||||||
|  |     const uint8_t* bitmap, | ||||||
|  |     uint8_t rotation); | ||||||
|  | |||||||
| Before Width: | Height: | Size: 654 B | 
| Before Width: | Height: | Size: 669 B | 
| Before Width: | Height: | Size: 3.5 KiB | 
| Before Width: | Height: | Size: 3.5 KiB | 
| Before Width: | Height: | Size: 3.5 KiB | 
| Before Width: | Height: | Size: 3.6 KiB | 
| Before Width: | Height: | Size: 303 B | 
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,20.0,, | Version,+,20.1,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -539,6 +539,7 @@ Function,+,canvas_draw_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" | |||||||
| Function,+,canvas_draw_glyph,void,"Canvas*, uint8_t, uint8_t, uint16_t" | Function,+,canvas_draw_glyph,void,"Canvas*, uint8_t, uint8_t, uint16_t" | ||||||
| Function,+,canvas_draw_icon,void,"Canvas*, uint8_t, uint8_t, const Icon*" | Function,+,canvas_draw_icon,void,"Canvas*, uint8_t, uint8_t, const Icon*" | ||||||
| Function,+,canvas_draw_icon_animation,void,"Canvas*, uint8_t, uint8_t, IconAnimation*" | Function,+,canvas_draw_icon_animation,void,"Canvas*, uint8_t, uint8_t, IconAnimation*" | ||||||
|  | Function,+,canvas_draw_icon_ex,void,"Canvas*, uint8_t, uint8_t, const Icon*, IconRotation" | ||||||
| Function,+,canvas_draw_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" | Function,+,canvas_draw_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" | ||||||
| Function,+,canvas_draw_rbox,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | Function,+,canvas_draw_rbox,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | ||||||
| Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | ||||||
| @ -875,12 +876,6 @@ Function,-,furi_hal_clock_resume_tick,void, | |||||||
| Function,-,furi_hal_clock_suspend_tick,void, | Function,-,furi_hal_clock_suspend_tick,void, | ||||||
| Function,-,furi_hal_clock_switch_to_hsi,void, | Function,-,furi_hal_clock_switch_to_hsi,void, | ||||||
| Function,-,furi_hal_clock_switch_to_pll,void, | Function,-,furi_hal_clock_switch_to_pll,void, | ||||||
| Function,-,compress_alloc,Compress*,uint16_t |  | ||||||
| Function,-,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" |  | ||||||
| Function,-,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*" |  | ||||||
| Function,-,compress_free,void,Compress* |  | ||||||
| Function,-,compress_icon_decode,void,"const uint8_t*, uint8_t**" |  | ||||||
| Function,-,compress_icon_init,void, |  | ||||||
| Function,+,furi_hal_console_disable,void, | Function,+,furi_hal_console_disable,void, | ||||||
| Function,+,furi_hal_console_enable,void, | Function,+,furi_hal_console_enable,void, | ||||||
| Function,+,furi_hal_console_init,void, | Function,+,furi_hal_console_init,void, | ||||||
|  | |||||||
| 
 | 
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,20.0,, | Version,+,20.1,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -621,6 +621,7 @@ Function,+,canvas_draw_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" | |||||||
| Function,+,canvas_draw_glyph,void,"Canvas*, uint8_t, uint8_t, uint16_t" | Function,+,canvas_draw_glyph,void,"Canvas*, uint8_t, uint8_t, uint16_t" | ||||||
| Function,+,canvas_draw_icon,void,"Canvas*, uint8_t, uint8_t, const Icon*" | Function,+,canvas_draw_icon,void,"Canvas*, uint8_t, uint8_t, const Icon*" | ||||||
| Function,+,canvas_draw_icon_animation,void,"Canvas*, uint8_t, uint8_t, IconAnimation*" | Function,+,canvas_draw_icon_animation,void,"Canvas*, uint8_t, uint8_t, IconAnimation*" | ||||||
|  | Function,+,canvas_draw_icon_ex,void,"Canvas*, uint8_t, uint8_t, const Icon*, IconRotation" | ||||||
| Function,+,canvas_draw_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" | Function,+,canvas_draw_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" | ||||||
| Function,+,canvas_draw_rbox,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | Function,+,canvas_draw_rbox,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | ||||||
| Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" | ||||||
|  | |||||||
| 
 | 
| @ -2,29 +2,24 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include <flipper.h> | #include <flipper.h> | ||||||
| #include <alt_boot.h> | #include <alt_boot.h> | ||||||
| #include <u8g2_glue.h> |  | ||||||
| #include <assets_icons.h> | #include <assets_icons.h> | ||||||
| #include <toolbox/compress.h> | #include <toolbox/compress.h> | ||||||
|  | #include <gui/canvas.h> | ||||||
|  | #include <gui/canvas_i.h> | ||||||
| 
 | 
 | ||||||
| void flipper_boot_dfu_show_splash() { | void flipper_boot_dfu_show_splash() { | ||||||
|     // Initialize
 |     // Initialize
 | ||||||
|     CompressIcon* compress_icon = compress_icon_alloc(); |     Canvas* canvas = canvas_init(); | ||||||
| 
 | 
 | ||||||
|     u8g2_t* fb = malloc(sizeof(u8g2_t)); |     canvas_set_color(canvas, ColorBlack); | ||||||
|     memset(fb, 0, sizeof(u8g2_t)); |     canvas_set_font(canvas, FontPrimary); | ||||||
|     u8g2_Setup_st756x_flipper(fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); |  | ||||||
|     u8g2_InitDisplay(fb); |  | ||||||
|     u8g2_SetDrawColor(fb, 0x01); |  | ||||||
|     uint8_t* splash_data = NULL; |  | ||||||
|     compress_icon_decode(compress_icon, icon_get_data(&I_DFU_128x50), &splash_data); |  | ||||||
|     u8g2_DrawXBM(fb, 0, 64 - 50, 128, 50, splash_data); |  | ||||||
|     u8g2_SetFont(fb, u8g2_font_helvB08_tr); |  | ||||||
|     u8g2_DrawStr(fb, 2, 8, "Update & Recovery Mode"); |  | ||||||
|     u8g2_DrawStr(fb, 2, 21, "DFU Started"); |  | ||||||
|     u8g2_SetPowerSave(fb, 0); |  | ||||||
|     u8g2_SendBuffer(fb); |  | ||||||
| 
 | 
 | ||||||
|     compress_icon_free(compress_icon); |     canvas_draw_icon(canvas, 0, 64 - 50, &I_DFU_128x50); | ||||||
|  |     canvas_draw_str(canvas, 2, 8, "Update & Recovery Mode"); | ||||||
|  |     canvas_draw_str(canvas, 2, 21, "DFU Started"); | ||||||
|  |     canvas_commit(canvas); | ||||||
|  | 
 | ||||||
|  |     canvas_free(canvas); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void flipper_boot_dfu_exec() { | void flipper_boot_dfu_exec() { | ||||||
|  | |||||||
| @ -2,44 +2,43 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include <flipper.h> | #include <flipper.h> | ||||||
| #include <alt_boot.h> | #include <alt_boot.h> | ||||||
| #include <u8g2_glue.h> |  | ||||||
| #include <assets_icons.h> | #include <assets_icons.h> | ||||||
| #include <toolbox/compress.h> | #include <toolbox/compress.h> | ||||||
|  | #include <gui/canvas.h> | ||||||
|  | #include <gui/canvas_i.h> | ||||||
| 
 | 
 | ||||||
| #define COUNTER_VALUE (136U) | #define COUNTER_VALUE (136U) | ||||||
| 
 | 
 | ||||||
| static void flipper_boot_recovery_draw_splash(u8g2_t* fb, size_t progress) { | static void flipper_boot_recovery_draw_progress(Canvas* canvas, size_t progress) { | ||||||
|     if(progress < COUNTER_VALUE) { |     if(progress < COUNTER_VALUE) { | ||||||
|         // Fill the progress bar while the progress is going down
 |         // Fill the progress bar while the progress is going down
 | ||||||
|         u8g2_SetDrawColor(fb, 0x01); |         canvas_draw_rframe(canvas, 59, 41, 69, 8, 2); | ||||||
|         u8g2_DrawRFrame(fb, 59, 41, 69, 8, 2); |  | ||||||
|         size_t width = (COUNTER_VALUE - progress) * 68 / COUNTER_VALUE; |         size_t width = (COUNTER_VALUE - progress) * 68 / COUNTER_VALUE; | ||||||
|         u8g2_DrawBox(fb, 60, 42, width, 6); |         canvas_draw_box(canvas, 60, 42, width, 6); | ||||||
|     } else { |     } else { | ||||||
|         u8g2_SetDrawColor(fb, 0x00); |         canvas_draw_rframe(canvas, 59, 41, 69, 8, 2); | ||||||
|         u8g2_DrawRBox(fb, 59, 41, 69, 8, 2); |         canvas_set_color(canvas, ColorWhite); | ||||||
|  |         canvas_draw_box(canvas, 60, 42, 67, 6); | ||||||
|  |         canvas_set_color(canvas, ColorBlack); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     u8g2_SendBuffer(fb); |     canvas_commit(canvas); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void flipper_boot_recovery_draw_splash(Canvas* canvas) { | ||||||
|  |     canvas_set_color(canvas, ColorBlack); | ||||||
|  |     canvas_set_font(canvas, FontPrimary); | ||||||
|  | 
 | ||||||
|  |     canvas_draw_icon(canvas, 0, 0, &I_Erase_pin_128x64); | ||||||
|  | 
 | ||||||
|  |     canvas_commit(canvas); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void flipper_boot_recovery_exec() { | void flipper_boot_recovery_exec() { | ||||||
|     u8g2_t* fb = malloc(sizeof(u8g2_t)); |     Canvas* canvas = canvas_init(); | ||||||
|     u8g2_Setup_st756x_flipper(fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); |  | ||||||
|     u8g2_InitDisplay(fb); |  | ||||||
| 
 | 
 | ||||||
|     CompressIcon* compress_icon = compress_icon_alloc(); |     // Show recovery splashscreen
 | ||||||
|     uint8_t* splash_data = NULL; |     flipper_boot_recovery_draw_splash(canvas); | ||||||
|     compress_icon_decode(compress_icon, icon_get_data(&I_Erase_pin_128x64), &splash_data); |  | ||||||
| 
 |  | ||||||
|     u8g2_ClearBuffer(fb); |  | ||||||
|     u8g2_SetDrawColor(fb, 0x01); |  | ||||||
| 
 |  | ||||||
|     // Draw the recovery picture
 |  | ||||||
|     u8g2_DrawXBM(fb, 0, 0, 128, 64, splash_data); |  | ||||||
|     u8g2_SendBuffer(fb); |  | ||||||
|     u8g2_SetPowerSave(fb, 0); |  | ||||||
|     compress_icon_free(compress_icon); |  | ||||||
| 
 | 
 | ||||||
|     size_t counter = COUNTER_VALUE; |     size_t counter = COUNTER_VALUE; | ||||||
|     while(counter) { |     while(counter) { | ||||||
| @ -53,7 +52,7 @@ void flipper_boot_recovery_exec() { | |||||||
|             counter = COUNTER_VALUE; |             counter = COUNTER_VALUE; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         flipper_boot_recovery_draw_splash(fb, counter); |         flipper_boot_recovery_draw_progress(canvas, counter); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(!counter) { |     if(!counter) { | ||||||
|  | |||||||
 Astra
						Astra