RenderBuffer.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "RenderBuffer.h"
  2. #include "Sprite.h"
  3. #include "Helpers.h"
  4. #include "Vector.h"
  5. #include "cmath"
  6. RenderBuffer::RenderBuffer(uint8_t w, uint8_t h) : Buffer(w, h) {
  7. FURI_LOG_D("App", "New renderBuffer");
  8. }
  9. void RenderBuffer::reset() {
  10. }
  11. void RenderBuffer::render(Canvas *const canvas) {
  12. canvas_clear(canvas);
  13. for (uint8_t x = 0; x < width(); x++) {
  14. for (uint8_t y = 0; y < height(); y++) {
  15. if (test_pixel(x, y))
  16. canvas_draw_dot(canvas, x, y);
  17. }
  18. }
  19. canvas_commit(canvas);
  20. }
  21. void RenderBuffer::draw_line(int x0, int y0, int x1, int y1, PixelColor draw_mode) {
  22. int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
  23. int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
  24. int err = (dx > dy ? dx : -dy) / 2;
  25. while (true) {
  26. if (test_coordinate(x0, y0)) {
  27. set_pixel(x0, y0, draw_mode);
  28. }
  29. if (x0 == x1 && y0 == y1) break;
  30. int e2 = err;
  31. if (e2 > -dx) {
  32. err -= dy;
  33. x0 += sx;
  34. }
  35. if (e2 < dy) {
  36. err += dx;
  37. y0 += sy;
  38. }
  39. }
  40. }
  41. void RenderBuffer::draw_circle(int x, int y, int r, PixelColor color) {
  42. int16_t a = r;
  43. int16_t b = 0;
  44. int16_t decision = 1 - a;
  45. while (b <= a) {
  46. set_pixel_with_check(a + x, b + y, color);
  47. set_pixel_with_check(b + x, a + y, color);
  48. set_pixel_with_check(-a + x, b + y, color);
  49. set_pixel_with_check(-b + x, a + y, color);
  50. set_pixel_with_check(-a + x, -b + y, color);
  51. set_pixel_with_check(-b + x, -a + y, color);
  52. set_pixel_with_check(a + x, -b + y, color);
  53. set_pixel_with_check(b + x, -a + y, color);
  54. b++;
  55. if (decision <= 0) {
  56. decision += 2 * b + 1;
  57. } else {
  58. a--;
  59. decision += 2 * (b - a) + 1;
  60. }
  61. }
  62. }
  63. void RenderBuffer::draw(Sprite *const sprite, Vector position, float rotation) {
  64. switch (sprite->draw_mode) {
  65. default:
  66. case BlackOnly:
  67. draw_sprite(sprite, true, Black, position, rotation);
  68. break;
  69. case WhiteOnly:
  70. draw_sprite(sprite, false, White, position, rotation);
  71. break;
  72. case WhiteAsBlack:
  73. draw_sprite(sprite, false, Black, position, rotation);
  74. break;
  75. case BlackAsWhite:
  76. draw_sprite(sprite, true, White, position, rotation);
  77. break;
  78. case WhiteAsInverted:
  79. draw_sprite(sprite, false, Flip, position, rotation);
  80. break;
  81. case BlackAsInverted:
  82. draw_sprite(sprite, true, Flip, position, rotation);
  83. break;
  84. }
  85. }
  86. //TODO: proper scaling
  87. void
  88. RenderBuffer::draw_sprite(Sprite *const sprite, bool is_black, PixelColor draw_color, const Vector& position, float rotation) {
  89. Vector anchor = sprite->get_offset();
  90. float cosTheta = cos(rotation/* + M_PI_2*/);
  91. float sinTheta = sin(rotation/* + M_PI_2*/);
  92. float transformedX, transformedY, rotatedX, rotatedY;
  93. bool isOn;
  94. int16_t finalX, finalY;
  95. for (int y = 0; y < sprite->height(); y++) {
  96. for (int x = 0; x < sprite->width(); x++) {
  97. transformedX = (x - anchor.x);
  98. transformedY = (y - anchor.y);
  99. rotatedX = transformedX * cosTheta - transformedY * sinTheta;
  100. rotatedY = transformedX * sinTheta + transformedY * cosTheta;
  101. finalX = (int16_t) floor(rotatedX + position.x);
  102. finalY = (int16_t) floor(rotatedY + position.y);
  103. if (test_coordinate(finalX, finalY)) {
  104. isOn = sprite->test_pixel(x, y) == is_black;
  105. if (isOn)
  106. set_pixel(finalX, finalY, draw_color);
  107. }
  108. }
  109. }
  110. }
  111. RenderBuffer::~RenderBuffer() {
  112. FURI_LOG_D("App", "RenderBuffer end");
  113. }
  114. void RenderBuffer::draw_rbox(int16_t x0, int16_t y0, int16_t x1, int16_t y1, PixelColor draw_mode) {
  115. for (int16_t x = x0; x < x1; x++) {
  116. for (int16_t y = y0; y < y1; y++) {
  117. if (((x == x0 || x == x1-1) && (y == y0 || y == y1-1)) || !test_coordinate(x,y)) continue;
  118. set_pixel(x, y, draw_mode);
  119. }
  120. }
  121. }
  122. void RenderBuffer::draw_rbox_frame(int16_t x0, int16_t y0, int16_t x1, int16_t y1, PixelColor draw_mode) {
  123. draw_line(x0 + 1, y0, x1 - 1, y0, draw_mode);
  124. draw_line(x0 + 1, y1, x1 - 1, y1, draw_mode);
  125. draw_line(x0, y0 + 1, x0, y1 - 1, draw_mode);
  126. draw_line(x1, y0 + 1, x1, y1 - 1, draw_mode);
  127. }