ui.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "ui.h"
  2. #include <gui/canvas_i.h>
  3. #include <u8g2_glue.h>
  4. #include <gui/icon_animation_i.h>
  5. #include <gui/icon.h>
  6. #include <gui/icon_i.h>
  7. #include <furi_hal.h>
  8. TileMap* tileMap;
  9. uint8_t tileMapCount = 0;
  10. void ui_cleanup() {
  11. if(tileMap != NULL) {
  12. for(uint8_t i = 0; i < tileMapCount; i++) {
  13. if(tileMap[i].data != NULL) free(tileMap[i].data);
  14. }
  15. free(tileMap);
  16. }
  17. }
  18. void add_new_tilemap(uint8_t* data, unsigned long iconId) {
  19. TileMap* old = tileMap;
  20. tileMapCount++;
  21. tileMap = malloc(sizeof(TileMap) * tileMapCount);
  22. if(tileMapCount > 1) {
  23. for(uint8_t i = 0; i < tileMapCount; i++)
  24. tileMap[i] = old[i];
  25. }
  26. tileMap[tileMapCount - 1] = (TileMap){data, iconId};
  27. }
  28. uint8_t* get_tilemap(unsigned long icon_id) {
  29. for(uint8_t i = 0; i < tileMapCount; i++) {
  30. if(tileMap[i].iconId == icon_id) return tileMap[i].data;
  31. }
  32. return NULL;
  33. }
  34. uint32_t pixel_index(uint8_t x, uint8_t y) {
  35. return y * SCREEN_WIDTH + x;
  36. }
  37. bool in_screen(int16_t x, int16_t y) {
  38. return x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT;
  39. }
  40. unsigned flipBit(uint8_t x, uint8_t bit) {
  41. return x ^ (1 << bit);
  42. }
  43. unsigned setBit(uint8_t x, uint8_t bit) {
  44. return x | (1 << bit);
  45. }
  46. unsigned unsetBit(uint8_t x, uint8_t bit) {
  47. return x & ~(1 << bit);
  48. }
  49. bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w) {
  50. uint8_t current_bit = (y % 8);
  51. uint8_t current_row = ((y - current_bit) / 8);
  52. uint8_t current_value = data[current_row * w + x];
  53. return current_value & (1 << current_bit);
  54. }
  55. uint8_t* get_buffer(Canvas* const canvas) {
  56. return canvas->fb.tile_buf_ptr;
  57. // return canvas_get_buffer(canvas);
  58. }
  59. uint8_t* make_buffer() {
  60. return malloc(sizeof(uint8_t) * 8 * 128);
  61. }
  62. void clone_buffer(uint8_t* canvas, uint8_t* data) {
  63. for(int i = 0; i < 1024; i++) {
  64. data[i] = canvas[i];
  65. }
  66. }
  67. bool read_pixel(Canvas* const canvas, int16_t x, int16_t y) {
  68. if(in_screen(x, y)) {
  69. return test_pixel(get_buffer(canvas), x, y, SCREEN_WIDTH);
  70. }
  71. return false;
  72. }
  73. void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode) {
  74. if(in_screen(x, y)) {
  75. uint8_t current_bit = (y % 8);
  76. uint8_t current_row = ((y - current_bit) / 8);
  77. uint32_t i = pixel_index(x, current_row);
  78. uint8_t* buffer = get_buffer(canvas);
  79. uint8_t current_value = buffer[i];
  80. if(draw_mode == Inverse) {
  81. buffer[i] = flipBit(current_value, current_bit);
  82. } else {
  83. if(draw_mode == White) {
  84. buffer[i] = unsetBit(current_value, current_bit);
  85. } else {
  86. buffer[i] = setBit(current_value, current_bit);
  87. }
  88. }
  89. }
  90. }
  91. void draw_line(
  92. Canvas* const canvas,
  93. int16_t x1,
  94. int16_t y1,
  95. int16_t x2,
  96. int16_t y2,
  97. DrawMode draw_mode) {
  98. for(int16_t x = x2; x >= x1; x--) {
  99. for(int16_t y = y2; y >= y1; y--) {
  100. set_pixel(canvas, x, y, draw_mode);
  101. }
  102. }
  103. }
  104. void draw_rounded_box_frame(
  105. Canvas* const canvas,
  106. int16_t x,
  107. int16_t y,
  108. uint8_t w,
  109. uint8_t h,
  110. DrawMode draw_mode) {
  111. int16_t xMinCorner = x + 1;
  112. int16_t xMax = x + w - 1;
  113. int16_t xMaxCorner = x + w - 2;
  114. int16_t yMinCorner = y + 1;
  115. int16_t yMax = y + h - 1;
  116. int16_t yMaxCorner = y + h - 2;
  117. draw_line(canvas, xMinCorner, y, xMaxCorner, y, draw_mode);
  118. draw_line(canvas, xMinCorner, yMax, xMaxCorner, yMax, draw_mode);
  119. draw_line(canvas, x, yMinCorner, x, yMaxCorner, draw_mode);
  120. draw_line(canvas, xMax, yMinCorner, xMax, yMaxCorner, draw_mode);
  121. }
  122. void draw_rounded_box(
  123. Canvas* const canvas,
  124. int16_t x,
  125. int16_t y,
  126. uint8_t w,
  127. uint8_t h,
  128. DrawMode draw_mode) {
  129. for(int16_t o = w - 2; o >= 1; o--) {
  130. for(int16_t p = h - 2; p >= 1; p--) {
  131. set_pixel(canvas, x + o, y + p, draw_mode);
  132. }
  133. }
  134. draw_rounded_box_frame(canvas, x, y, w, h, draw_mode);
  135. }
  136. void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h) {
  137. draw_pixels(canvas, data, x, y, w, h, Inverse);
  138. }
  139. void draw_pixels(
  140. Canvas* const canvas,
  141. uint8_t* data,
  142. int16_t x,
  143. int16_t y,
  144. uint8_t w,
  145. uint8_t h,
  146. DrawMode drawMode) {
  147. for(int8_t o = 0; o < w; o++) {
  148. for(int8_t p = 0; p < h; p++) {
  149. if(in_screen(o + x, p + y) && data[p * w + o] == 1)
  150. set_pixel(canvas, o + x, p + y, drawMode);
  151. }
  152. }
  153. }
  154. void draw_rectangle(
  155. Canvas* const canvas,
  156. int16_t x,
  157. int16_t y,
  158. uint8_t w,
  159. uint8_t h,
  160. DrawMode drawMode) {
  161. for(int8_t o = 0; o < w; o++) {
  162. for(int8_t p = 0; p < h; p++) {
  163. if(in_screen(o + x, p + y)) {
  164. set_pixel(canvas, o + x, p + y, drawMode);
  165. }
  166. }
  167. }
  168. }
  169. void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h) {
  170. draw_rectangle(canvas, x, y, w, h, Inverse);
  171. }
  172. uint8_t* image_data(Canvas* const canvas, const Icon* icon) {
  173. uint8_t* data = malloc(sizeof(uint8_t) * 8 * 128);
  174. uint8_t* screen = canvas->fb.tile_buf_ptr;
  175. canvas->fb.tile_buf_ptr = data;
  176. canvas_draw_icon(canvas, 0, 0, icon);
  177. canvas->fb.tile_buf_ptr = screen;
  178. return data;
  179. }
  180. uint8_t* getOrAddIconData(Canvas* const canvas, const Icon* icon) {
  181. uint8_t* icon_data = get_tilemap((unsigned long)icon);
  182. if(icon_data == NULL) {
  183. icon_data = image_data(canvas, icon);
  184. add_new_tilemap(icon_data, (unsigned long)icon);
  185. }
  186. return icon_data;
  187. }
  188. void draw_icon_clip(
  189. Canvas* const canvas,
  190. const Icon* icon,
  191. int16_t x,
  192. int16_t y,
  193. uint8_t left,
  194. uint8_t top,
  195. uint8_t w,
  196. uint8_t h,
  197. DrawMode drawMode) {
  198. uint8_t* icon_data = getOrAddIconData(canvas, icon);
  199. for(int i = 0; i < w; i++) {
  200. for(int j = 0; j < h; j++) {
  201. bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH);
  202. if(drawMode == Filled) {
  203. set_pixel(canvas, x + i, y + j, on ? Black : White);
  204. } else if(on)
  205. set_pixel(canvas, x + i, y + j, drawMode);
  206. }
  207. }
  208. }
  209. void draw_icon_clip_flipped(
  210. Canvas* const canvas,
  211. const Icon* icon,
  212. int16_t x,
  213. int16_t y,
  214. uint8_t left,
  215. uint8_t top,
  216. uint8_t w,
  217. uint8_t h,
  218. DrawMode drawMode) {
  219. uint8_t* icon_data = getOrAddIconData(canvas, icon);
  220. for(int i = 0; i < w; i++) {
  221. for(int j = 0; j < h; j++) {
  222. bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH);
  223. if(drawMode == Filled) {
  224. set_pixel(canvas, x + w - i - 1, y + h - j - 1, on ? Black : White);
  225. } else if(on)
  226. set_pixel(canvas, x + w - i - 1, y + h - j - 1, drawMode);
  227. }
  228. }
  229. }