canvas.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #include "canvas_i.h"
  2. #include "icon_i.h"
  3. #include <furi.h>
  4. #include <api-hal.h>
  5. uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr);
  6. uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr);
  7. Canvas* canvas_init() {
  8. Canvas* canvas = furi_alloc(sizeof(Canvas));
  9. api_hal_power_insomnia_enter();
  10. canvas->orientation = CanvasOrientationHorizontal;
  11. u8g2_Setup_st7565_erc12864_alt_f(
  12. &canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
  13. // send init sequence to the display, display is in sleep mode after this
  14. u8g2_InitDisplay(&canvas->fb);
  15. u8g2_SetContrast(&canvas->fb, 36);
  16. // wake up display
  17. u8g2_SetPowerSave(&canvas->fb, 0);
  18. u8g2_SendBuffer(&canvas->fb);
  19. api_hal_power_insomnia_exit();
  20. return canvas;
  21. }
  22. void canvas_free(Canvas* canvas) {
  23. furi_assert(canvas);
  24. free(canvas);
  25. }
  26. void canvas_reset(Canvas* canvas) {
  27. furi_assert(canvas);
  28. canvas_clear(canvas);
  29. canvas_set_color(canvas, ColorBlack);
  30. canvas_set_font(canvas, FontSecondary);
  31. }
  32. void canvas_commit(Canvas* canvas) {
  33. furi_assert(canvas);
  34. u8g2_SetPowerSave(&canvas->fb, 0); // wake up display
  35. u8g2_SendBuffer(&canvas->fb);
  36. }
  37. uint8_t* canvas_get_buffer(Canvas* canvas) {
  38. furi_assert(canvas);
  39. return u8g2_GetBufferPtr(&canvas->fb);
  40. }
  41. size_t canvas_get_buffer_size(Canvas* canvas) {
  42. furi_assert(canvas);
  43. return u8g2_GetBufferTileWidth(&canvas->fb) * u8g2_GetBufferTileHeight(&canvas->fb) * 8;
  44. }
  45. void canvas_frame_set(
  46. Canvas* canvas,
  47. uint8_t offset_x,
  48. uint8_t offset_y,
  49. uint8_t width,
  50. uint8_t height) {
  51. furi_assert(canvas);
  52. canvas->offset_x = offset_x;
  53. canvas->offset_y = offset_y;
  54. canvas->width = width;
  55. canvas->height = height;
  56. }
  57. uint8_t canvas_width(Canvas* canvas) {
  58. furi_assert(canvas);
  59. return canvas->width;
  60. }
  61. uint8_t canvas_height(Canvas* canvas) {
  62. furi_assert(canvas);
  63. return canvas->height;
  64. }
  65. uint8_t canvas_current_font_height(Canvas* canvas) {
  66. furi_assert(canvas);
  67. return u8g2_GetMaxCharHeight(&canvas->fb);
  68. }
  69. void canvas_clear(Canvas* canvas) {
  70. furi_assert(canvas);
  71. u8g2_ClearBuffer(&canvas->fb);
  72. }
  73. void canvas_set_color(Canvas* canvas, Color color) {
  74. furi_assert(canvas);
  75. u8g2_SetDrawColor(&canvas->fb, color);
  76. }
  77. void canvas_invert_color(Canvas* canvas) {
  78. canvas->fb.draw_color = !canvas->fb.draw_color;
  79. }
  80. void canvas_set_font(Canvas* canvas, Font font) {
  81. furi_assert(canvas);
  82. u8g2_SetFontMode(&canvas->fb, 1);
  83. if(font == FontPrimary) {
  84. u8g2_SetFont(&canvas->fb, u8g2_font_helvB08_tf);
  85. } else if(font == FontSecondary) {
  86. u8g2_SetFont(&canvas->fb, u8g2_font_haxrcorp4089_tr);
  87. } else if(font == FontGlyph) {
  88. u8g2_SetFont(&canvas->fb, u8g2_font_unifont_t_symbols);
  89. } else if(font == FontKeyboard) {
  90. u8g2_SetFont(&canvas->fb, u8g2_font_profont11_mf);
  91. } else {
  92. furi_check(0);
  93. }
  94. }
  95. void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) {
  96. furi_assert(canvas);
  97. if(!str) return;
  98. x += canvas->offset_x;
  99. y += canvas->offset_y;
  100. u8g2_DrawStr(&canvas->fb, x, y, str);
  101. }
  102. void canvas_draw_str_aligned(
  103. Canvas* canvas,
  104. uint8_t x,
  105. uint8_t y,
  106. Align horizontal,
  107. Align vertical,
  108. const char* str) {
  109. furi_assert(canvas);
  110. if(!str) return;
  111. x += canvas->offset_x;
  112. y += canvas->offset_y;
  113. switch(horizontal) {
  114. case AlignLeft:
  115. break;
  116. case AlignRight:
  117. x -= u8g2_GetStrWidth(&canvas->fb, str);
  118. break;
  119. case AlignCenter:
  120. x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2);
  121. break;
  122. default:
  123. furi_check(0);
  124. break;
  125. }
  126. switch(vertical) {
  127. case AlignTop:
  128. y += u8g2_GetAscent(&canvas->fb);
  129. break;
  130. case AlignBottom:
  131. break;
  132. case AlignCenter:
  133. y += (u8g2_GetAscent(&canvas->fb) / 2);
  134. break;
  135. default:
  136. furi_check(0);
  137. break;
  138. }
  139. u8g2_DrawStr(&canvas->fb, x, y, str);
  140. }
  141. uint16_t canvas_string_width(Canvas* canvas, const char* str) {
  142. furi_assert(canvas);
  143. if(!str) return 0;
  144. return u8g2_GetStrWidth(&canvas->fb, str);
  145. }
  146. void canvas_draw_icon(Canvas* canvas, uint8_t x, uint8_t y, Icon* icon) {
  147. furi_assert(canvas);
  148. if(!icon) return;
  149. x += canvas->offset_x;
  150. y += canvas->offset_y;
  151. u8g2_DrawXBM(
  152. &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_get_data(icon));
  153. }
  154. void canvas_draw_icon_name(Canvas* canvas, uint8_t x, uint8_t y, IconName name) {
  155. furi_assert(canvas);
  156. const IconData* data = assets_icons_get_data(name);
  157. x += canvas->offset_x;
  158. y += canvas->offset_y;
  159. u8g2_DrawXBM(&canvas->fb, x, y, data->width, data->height, data->frames[0]);
  160. }
  161. void canvas_draw_dot(Canvas* canvas, uint8_t x, uint8_t y) {
  162. furi_assert(canvas);
  163. x += canvas->offset_x;
  164. y += canvas->offset_y;
  165. u8g2_DrawPixel(&canvas->fb, x, y);
  166. }
  167. void canvas_draw_box(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
  168. furi_assert(canvas);
  169. x += canvas->offset_x;
  170. y += canvas->offset_y;
  171. u8g2_DrawBox(&canvas->fb, x, y, width, height);
  172. }
  173. void canvas_draw_rbox(
  174. Canvas* canvas,
  175. uint8_t x,
  176. uint8_t y,
  177. uint8_t width,
  178. uint8_t height,
  179. uint8_t radius) {
  180. furi_assert(canvas);
  181. x += canvas->offset_x;
  182. y += canvas->offset_y;
  183. u8g2_DrawRBox(&canvas->fb, x, y, width, height, radius);
  184. }
  185. void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) {
  186. furi_assert(canvas);
  187. x += canvas->offset_x;
  188. y += canvas->offset_y;
  189. u8g2_DrawFrame(&canvas->fb, x, y, width, height);
  190. }
  191. void canvas_draw_rframe(
  192. Canvas* canvas,
  193. uint8_t x,
  194. uint8_t y,
  195. uint8_t width,
  196. uint8_t height,
  197. uint8_t radius) {
  198. furi_assert(canvas);
  199. x += canvas->offset_x;
  200. y += canvas->offset_y;
  201. u8g2_DrawRFrame(&canvas->fb, x, y, width, height, radius);
  202. }
  203. void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
  204. furi_assert(canvas);
  205. x1 += canvas->offset_x;
  206. y1 += canvas->offset_y;
  207. x2 += canvas->offset_x;
  208. y2 += canvas->offset_y;
  209. u8g2_DrawLine(&canvas->fb, x1, y1, x2, y2);
  210. }
  211. void canvas_draw_circle(Canvas* canvas, uint8_t x, uint8_t y, uint8_t radius) {
  212. furi_assert(canvas);
  213. x += canvas->offset_x;
  214. y += canvas->offset_y;
  215. u8g2_DrawCircle(&canvas->fb, x, y, radius, U8G2_DRAW_ALL);
  216. }
  217. void canvas_draw_disc(Canvas* canvas, uint8_t x, uint8_t y, uint8_t radius) {
  218. furi_assert(canvas);
  219. x += canvas->offset_x;
  220. y += canvas->offset_y;
  221. u8g2_DrawDisc(&canvas->fb, x, y, radius, U8G2_DRAW_ALL);
  222. }
  223. void canvas_draw_xbm(
  224. Canvas* canvas,
  225. uint8_t x,
  226. uint8_t y,
  227. uint8_t w,
  228. uint8_t h,
  229. const uint8_t* bitmap) {
  230. furi_assert(canvas);
  231. x += canvas->offset_x;
  232. y += canvas->offset_y;
  233. u8g2_DrawXBM(&canvas->fb, x, y, w, h, bitmap);
  234. }
  235. void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch) {
  236. furi_assert(canvas);
  237. x += canvas->offset_x;
  238. y += canvas->offset_y;
  239. u8g2_DrawGlyph(&canvas->fb, x, y, ch);
  240. }
  241. void canvas_set_bitmap_mode(Canvas* canvas, bool alpha) {
  242. u8g2_SetBitmapMode(&canvas->fb, alpha ? 1 : 0);
  243. }
  244. void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) {
  245. furi_assert(canvas);
  246. if(canvas->orientation != orientation) {
  247. canvas->orientation = orientation;
  248. if(canvas->orientation == CanvasOrientationHorizontal)
  249. u8g2_SetDisplayRotation(&canvas->fb, U8G2_R0);
  250. else if(canvas->orientation == CanvasOrientationVertical)
  251. u8g2_SetDisplayRotation(&canvas->fb, U8G2_R3);
  252. else
  253. furi_assert(0);
  254. }
  255. }
  256. CanvasOrientation canvas_get_orientation(const Canvas* canvas) {
  257. return canvas->orientation;
  258. }