LineDrawer.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. FinalSun/FinalAlert 2 Mission Editor
  3. Copyright (C) 1999-2024 Electronic Arts, Inc.
  4. Authored by Matthias Wagner
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. */
  16. #include "StdAfx.h"
  17. #include "LineDrawer.h"
  18. #include <cassert>
  19. #include <memory>
  20. static int ModLookup[] = {
  21. 1,
  22. 2,
  23. 3,
  24. 4
  25. };
  26. LineDrawer::LineDrawer(void* dest, int bytes_per_pixel, int width, int height, int pitch):
  27. m_dest(dest),
  28. m_bytes_per_pixel(bytes_per_pixel),
  29. m_width(width),
  30. m_height(height),
  31. m_pitch(pitch),
  32. m_last_x(0),
  33. m_last_y(0)
  34. {
  35. }
  36. void LineDrawer::MoveTo(int to_x, int to_y)
  37. {
  38. m_last_x = to_x;
  39. m_last_y = to_y;
  40. }
  41. void LineDrawer::LineTo(int to_x, int to_y, int color, LineStyle style)
  42. {
  43. DrawLine(m_last_x, m_last_y, to_x, to_y, color, style);
  44. }
  45. void LineDrawer::DrawLine(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style)
  46. {
  47. const int w = to_x - from_x;
  48. const int h = to_y - from_y;
  49. m_last_x = to_x;
  50. m_last_y = to_y;
  51. if (abs(w) >= abs(h)) {
  52. return w >= 0 ? DrawLineImplX(from_x, from_y, to_x, to_y, color, style) : DrawLineImplX(to_x, to_y, from_x, from_y, color, style);
  53. }
  54. else {
  55. return h >= 0 ? DrawLineImplY(from_x, from_y, to_x, to_y, color, style) : DrawLineImplY(to_x, to_y, from_x, from_y, color, style);
  56. }
  57. }
  58. void LineDrawer::Rectangle(int from_x, int from_y, int to_x, int to_y, int color, LineStyle style)
  59. {
  60. MoveTo(from_x, from_y);
  61. LineTo(to_x, from_y, color, style);
  62. LineTo(to_x, to_y, color, style);
  63. LineTo(from_x, to_y, color, style);
  64. LineTo(from_x, from_y, color, style);
  65. }
  66. void LineDrawer::SetPixel(char* const dest, const int cur_x, const int cur_y, const int color)
  67. {
  68. if (cur_x >= 0 && cur_y >= 0 && cur_x < m_width && cur_y < m_height)
  69. memcpy(&dest[cur_x * m_bytes_per_pixel + cur_y * m_pitch], &color, m_bytes_per_pixel);
  70. }
  71. void LineDrawer::DrawLineImplX(const int from_x, const int from_y, const int to_x, const int to_y, const int color, const LineStyle style)
  72. {
  73. // X major line drawing
  74. assert (from_x <= to_x);
  75. const int w = to_x - from_x;
  76. const int h = abs(to_y - from_y);
  77. assert (w >= h);
  78. const int increment_e = 2 * h;
  79. const int increment_ne = 2 * (h - w);
  80. const int y_inc = (to_y - from_y) < 0 ? -1 : 1;
  81. int d = 2 * h - w;
  82. int cur_x = from_x;
  83. int cur_y = from_y;
  84. const int mod = ModLookup[static_cast<int>(style)];
  85. char* dest = reinterpret_cast<char*>(m_dest);
  86. SetPixel(dest, cur_x, cur_y, color);
  87. for(; cur_x < to_x; ++cur_x)
  88. {
  89. if (d < 0) {
  90. d += increment_e;
  91. }
  92. else {
  93. d += increment_ne;
  94. cur_y += y_inc;
  95. }
  96. if (mod == 1 || (cur_x - from_x) % mod == 0)
  97. SetPixel(dest, cur_x, cur_y, color);
  98. }
  99. }
  100. void LineDrawer::DrawLineImplY(const int from_x, const int from_y, const int to_x, const int to_y, const int color, LineStyle style)
  101. {
  102. // Y major line drawing
  103. assert(from_y <= to_y);
  104. const int w = abs(to_x - from_x);
  105. const int h = to_y - from_y;
  106. assert(h >= w);
  107. const int increment_e = 2 * w;
  108. const int increment_ne = 2 * (w - h);
  109. const int x_inc = (to_x - from_x) < 0 ? -1 : 1;
  110. int d = 2 * w - h;
  111. int cur_x = from_x;
  112. int cur_y = from_y;
  113. const int mod = ModLookup[static_cast<int>(style)];
  114. char* dest = reinterpret_cast<char*>(m_dest);
  115. SetPixel(dest, cur_x, cur_y, color);
  116. for (; cur_y < to_y; ++cur_y)
  117. {
  118. if (d < 0) {
  119. d += increment_e;
  120. }
  121. else {
  122. d += increment_ne;
  123. cur_x += x_inc;
  124. }
  125. if (mod == 1 || (cur_y - from_y) % mod == 0)
  126. SetPixel(dest, cur_x, cur_y, color);
  127. }
  128. }