Buffer.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include <toolbox/compress.h>
  2. #include <firmware_api_table.h>
  3. #include "Buffer.h"
  4. #include "Sprite.h"
  5. Buffer::Buffer(uint8_t w, uint8_t h) : _width(w), _height(h) {
  6. data = (uint8_t *) malloc(sizeof(uint8_t) * (int)ceil(w / 8.0) * ceil(h));
  7. }
  8. Buffer::Buffer(uint8_t *d, uint8_t w, uint8_t h) {
  9. _width = w;
  10. _height = h;//ceil(i->height / 8.0);
  11. data = d;
  12. remove_buffer = false;
  13. }
  14. Buffer::~Buffer() {
  15. FURI_LOG_I("BUFFER", "deleting buffer");
  16. if (remove_buffer) {
  17. delete data;
  18. }
  19. }
  20. bool Buffer::test_pixel(uint8_t x, uint8_t y) {
  21. return data[pixel(x,y)] & (1 << (x & 7));
  22. }
  23. /**
  24. * @brief Copies the contents of the buffer into another array.
  25. *
  26. * This function copies the data from the current buffer into the provided array. The size of the array should be equal
  27. * to the size of the buffer.
  28. *
  29. * @param other The array to copy the data into.
  30. * @return void
  31. */
  32. void Buffer::copy_into(uint8_t *other) {
  33. int size = (int) (_height * ceil(_width / 8.0));
  34. for (int i = 0; i < size; i++) {
  35. other[i] = data[i];
  36. }
  37. }
  38. /**
  39. * @brief Copies data from another buffer into this buffer.
  40. *
  41. * This function copies the data from the given buffer into this buffer.
  42. * The size of the data being copied is calculated according to the width
  43. * and height of this buffer. The data is copied byte by byte.
  44. *
  45. * @param other A pointer to the data buffer to copy from.
  46. */
  47. void Buffer::copy_from(uint8_t *other) {
  48. int size = (int) (_height * ceil(_width / 8.0));
  49. for (int i = 0; i < size; i++) {
  50. data[i] = other[i];
  51. }
  52. }
  53. /**
  54. * @brief Clears the buffer by setting all data elements to 0.
  55. *
  56. * The buffer size is calculated based on the width and height attributes.
  57. * The width and height are multiplied to get the size in bytes needed to store the buffer data.
  58. * If the height is not a multiple of 8, the size is rounded up to the next multiple of 8.
  59. * Each element in the data array is set to 0 using a for loop.
  60. */
  61. void Buffer::clear() {
  62. int size = (int) (_height * ceil(_width / 8.0));
  63. memset(data, 0, sizeof(uint8_t)*size);
  64. /* for (int i = 0; i < size; i++) {
  65. data[i] = 0;
  66. }*/
  67. }
  68. /**
  69. * @brief Checks if the given coordinates are within the bounds of the buffer.
  70. *
  71. * @param x The x-coordinate.
  72. * @param y The y-coordinate.
  73. * @return True if the coordinates are within the buffer's bounds, false otherwise.
  74. */
  75. bool Buffer::test_coordinate(int x, int y) const {
  76. return x >= 0 && y >= 0 && x < _width && y < _height;
  77. }
  78. /**
  79. * @brief Sets a pixel in the buffer with a given draw mode, after checking if the pixel is within the buffer dimensions.
  80. *
  81. * @param x The x-coordinate of the pixel.
  82. * @param y The y-coordinate of the pixel.
  83. * @param draw_mode The draw mode to use for setting the pixel.
  84. *
  85. * This function checks if the pixel at the given coordinates is within the buffer dimensions by calling the `test_pixel` function.
  86. * If the pixel is within the buffer, it calls the `set_pixel` function to set the pixel with the provided draw mode.
  87. *
  88. * @see test_pixel
  89. * @see set_pixel
  90. */
  91. void Buffer::set_pixel_with_check(int16_t x, int16_t y, PixelColor draw_mode) {
  92. if (test_pixel(x, y))
  93. set_pixel(x, y, draw_mode);
  94. }
  95. /**
  96. * Sets the pixel at the specified coordinates to the specified draw mode.
  97. *
  98. * @param x The x-coordinate of the pixel.
  99. * @param y The y-coordinate of the pixel.
  100. * @param draw_mode The draw mode to apply to the pixel.
  101. */
  102. void Buffer::set_pixel(int16_t x, int16_t y, PixelColor draw_mode) {
  103. uint8_t bit = 1 << (x & 7);
  104. uint8_t *p = &data[pixel(x,y)];
  105. switch (draw_mode) {
  106. case Black:
  107. *p |= bit;
  108. break;
  109. case White:
  110. *p &= ~bit;
  111. break;
  112. case Flip:
  113. *p ^= bit;
  114. break;
  115. }
  116. }
  117. /**
  118. * @brief Swaps the buffer with the provided buffer.
  119. *
  120. * This function swaps the internal buffer with the buffer passed as a parameter. After the swap,
  121. * the caller will have ownership of the current internal buffer.
  122. *
  123. * @param buffer A pointer to the buffer to swap with.
  124. */
  125. void Buffer::swap(uint8_t *&buffer) {
  126. uint8_t *back = data;
  127. data = buffer;
  128. buffer = back;
  129. }
  130. uint16_t Buffer::pixel(uint8_t x, uint8_t y) {
  131. return (y*width()+x) / 8;
  132. }
  133. uint8_t *Buffer::decode(const Icon *icon) {
  134. uint8_t* p_icon_data;
  135. uint8_t width = icon_get_width(icon);
  136. uint8_t height = icon_get_height(icon);
  137. uint16_t size = (width/8)*height;
  138. // Create decoder instance and grab decoded data pointer
  139. // - Ideally re-use the CompressIcon and free on app exit
  140. CompressIcon* compress_icon = compress_icon_alloc();
  141. compress_icon_decode(compress_icon, icon_get_data(icon), &p_icon_data);
  142. // Copy the data since the decoder only holds on temporarily
  143. auto* icon_data = static_cast<uint8_t *>(malloc(size));
  144. memcpy(icon_data, p_icon_data, size);
  145. // Free decoder instance as we're done here
  146. compress_icon_free(compress_icon);
  147. return icon_data;
  148. }