[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>
This commit is contained in:
		| @@ -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) { | ||||
|     UNUSED(context); | ||||
|     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) { | ||||
| @@ -230,7 +230,7 @@ Desktop* desktop_alloc() { | ||||
|  | ||||
|     // Lock icon | ||||
|     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( | ||||
|         desktop->lock_icon_viewport, desktop_lock_icon_draw_callback, desktop); | ||||
|     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 { | ||||
|                 switch(model->pin.data[i]) { | ||||
|                 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; | ||||
|                 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; | ||||
|                 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; | ||||
|                 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; | ||||
|                 default: | ||||
|                     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); | ||||
|  | ||||
|     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)) { | ||||
|   | ||||
| @@ -221,7 +221,7 @@ void canvas_draw_bitmap( | ||||
|     y += canvas->offset_y; | ||||
|     uint8_t* bitmap_data = NULL; | ||||
|     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( | ||||
| @@ -237,13 +237,138 @@ void canvas_draw_icon_animation( | ||||
|     uint8_t* icon_data = NULL; | ||||
|     compress_icon_decode( | ||||
|         canvas->compress_icon, icon_animation_get_data(icon_animation), &icon_data); | ||||
|     u8g2_DrawXBM( | ||||
|     canvas_draw_u8g2_bitmap( | ||||
|         &canvas->fb, | ||||
|         x, | ||||
|         y, | ||||
|         icon_animation_get_width(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) { | ||||
| @@ -254,7 +379,8 @@ void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, const Icon* icon) { | ||||
|     y += canvas->offset_y; | ||||
|     uint8_t* icon_data = NULL; | ||||
|     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) { | ||||
| @@ -364,7 +490,7 @@ void canvas_draw_xbm( | ||||
|     furi_assert(canvas); | ||||
|     x += canvas->offset_x; | ||||
|     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) { | ||||
|   | ||||
| @@ -64,6 +64,22 @@ typedef struct { | ||||
|     uint8_t descender; | ||||
| } CanvasFontParameters; | ||||
|  | ||||
| /** Icon flip */ | ||||
| typedef enum { | ||||
|     IconFlipNone, | ||||
|     IconFlipHorizontal, | ||||
|     IconFlipVertical, | ||||
|     IconFlipBoth, | ||||
| } IconFlip; | ||||
|  | ||||
| /** Icon rotation */ | ||||
| typedef enum { | ||||
|     IconRotation0, | ||||
|     IconRotation90, | ||||
|     IconRotation180, | ||||
|     IconRotation270, | ||||
| } IconRotation; | ||||
|  | ||||
| /** Canvas anonymous structure */ | ||||
| typedef struct Canvas Canvas; | ||||
|  | ||||
| @@ -217,6 +233,22 @@ void canvas_draw_bitmap( | ||||
|     uint8_t height, | ||||
|     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. | ||||
|  * | ||||
|  * @param      canvas          Canvas instance | ||||
|   | ||||
| @@ -78,3 +78,22 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation); | ||||
|  * @return     CanvasOrientation | ||||
|  */ | ||||
| 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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user