ui.c 6.6 KB

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