epdpaint.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /**
  2. * @filename : epdpaint.c
  3. * @brief : Paint tools
  4. * @author : Yehui from Waveshare
  5. *
  6. * Copyright (C) Waveshare July 28 2017
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documnetation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include "epdpaint.h"
  27. void Paint_Init(Paint* paint, unsigned char* image, int width, int height) {
  28. paint->rotate = ROTATE_0;
  29. paint->image = image;
  30. /* 1 byte = 8 pixels, so the width should be the multiple of 8 */
  31. paint->width = width % 8 ? width + 8 - (width % 8) : width;
  32. paint->height = height;
  33. }
  34. /**
  35. * @brief: clear the image
  36. */
  37. void Paint_Clear(Paint* paint, int colored) {
  38. for (int x = 0; x < paint->width; x++) {
  39. for (int y = 0; y < paint->height; y++) {
  40. Paint_DrawAbsolutePixel(paint, x, y, colored);
  41. }
  42. }
  43. }
  44. /**
  45. * @brief: this draws a pixel by absolute coordinates.
  46. * this function won't be affected by the rotate parameter.
  47. */
  48. void Paint_DrawAbsolutePixel(Paint* paint, int x, int y, int colored) {
  49. if (x < 0 || x >= paint->width || y < 0 || y >= paint->height) {
  50. return;
  51. }
  52. if (IF_INVERT_COLOR) {
  53. if (colored) {
  54. paint->image[(x + y * paint->width) / 8] |= 0x80 >> (x % 8);
  55. } else {
  56. paint->image[(x + y * paint->width) / 8] &= ~(0x80 >> (x % 8));
  57. }
  58. } else {
  59. if (colored) {
  60. paint->image[(x + y * paint->width) / 8] &= ~(0x80 >> (x % 8));
  61. } else {
  62. paint->image[(x + y * paint->width) / 8] |= 0x80 >> (x % 8);
  63. }
  64. }
  65. }
  66. /**
  67. * @brief: Getters and Setters
  68. */
  69. unsigned char* Paint_GetImage(Paint* paint) {
  70. return paint->image;
  71. }
  72. int Paint_GetWidth(Paint* paint) {
  73. return paint->width;
  74. }
  75. void Paint_SetWidth(Paint* paint, int width) {
  76. paint->width = width % 8 ? width + 8 - (width % 8) : width;
  77. }
  78. int Paint_GetHeight(Paint* paint) {
  79. return paint->height;
  80. }
  81. void Paint_SetHeight(Paint* paint, int height) {
  82. paint->height = height;
  83. }
  84. int Paint_GetRotate(Paint* paint) {
  85. return paint->rotate;
  86. }
  87. void Paint_SetRotate(Paint* paint, int rotate){
  88. paint->rotate = rotate;
  89. }
  90. /**
  91. * @brief: this draws a pixel by the coordinates
  92. */
  93. void Paint_DrawPixel(Paint* paint, int x, int y, int colored) {
  94. int point_temp;
  95. if (paint->rotate == ROTATE_0) {
  96. if(x < 0 || x >= paint->width || y < 0 || y >= paint->height) {
  97. return;
  98. }
  99. Paint_DrawAbsolutePixel(paint, x, y, colored);
  100. } else if (paint->rotate == ROTATE_90) {
  101. if(x < 0 || x >= paint->height || y < 0 || y >= paint->width) {
  102. return;
  103. }
  104. point_temp = x;
  105. x = paint->width - y;
  106. y = point_temp;
  107. Paint_DrawAbsolutePixel(paint, x, y, colored);
  108. } else if (paint->rotate == ROTATE_180) {
  109. if(x < 0 || x >= paint->width || y < 0 || y >= paint->height) {
  110. return;
  111. }
  112. x = paint->width - x;
  113. y = paint->height - y;
  114. Paint_DrawAbsolutePixel(paint, x, y, colored);
  115. } else if (paint->rotate == ROTATE_270) {
  116. if(x < 0 || x >= paint->height || y < 0 || y >= paint->width) {
  117. return;
  118. }
  119. point_temp = x;
  120. x = y;
  121. y = paint->height - point_temp;
  122. Paint_DrawAbsolutePixel(paint, x, y, colored);
  123. }
  124. }
  125. /**
  126. * @brief: this draws a line on the frame buffer
  127. */
  128. void Paint_DrawLine(Paint* paint, int x0, int y0, int x1, int y1, int colored) {
  129. /* Bresenham algorithm */
  130. int dx = x1 - x0 >= 0 ? x1 - x0 : x0 - x1;
  131. int sx = x0 < x1 ? 1 : -1;
  132. int dy = y1 - y0 <= 0 ? y1 - y0 : y0 - y1;
  133. int sy = y0 < y1 ? 1 : -1;
  134. int err = dx + dy;
  135. while((x0 != x1) || (y0 != y1)) {
  136. Paint_DrawPixel(paint, x0, y0 , colored);
  137. if (2 * err >= dy) {
  138. err += dy;
  139. x0 += sx;
  140. }
  141. if (2 * err <= dx) {
  142. err += dx;
  143. y0 += sy;
  144. }
  145. }
  146. }
  147. /**
  148. * @brief: this draws a horizontal line on the frame buffer
  149. */
  150. void Paint_DrawHorizontalLine(Paint* paint, int x, int y, int line_width, int colored) {
  151. int i;
  152. for (i = x; i < x + line_width; i++) {
  153. Paint_DrawPixel(paint, i, y, colored);
  154. }
  155. }
  156. /**
  157. * @brief: this draws a vertical line on the frame buffer
  158. */
  159. void Paint_DrawVerticalLine(Paint* paint, int x, int y, int line_height, int colored) {
  160. int i;
  161. for (i = y; i < y + line_height; i++) {
  162. Paint_DrawPixel(paint, x, i, colored);
  163. }
  164. }
  165. /**
  166. * @brief: this draws a rectangle
  167. */
  168. void Paint_DrawRectangle(Paint* paint, int x0, int y0, int x1, int y1, int colored) {
  169. int min_x, min_y, max_x, max_y;
  170. min_x = x1 > x0 ? x0 : x1;
  171. max_x = x1 > x0 ? x1 : x0;
  172. min_y = y1 > y0 ? y0 : y1;
  173. max_y = y1 > y0 ? y1 : y0;
  174. Paint_DrawHorizontalLine(paint, min_x, min_y, max_x - min_x + 1, colored);
  175. Paint_DrawHorizontalLine(paint, min_x, max_y, max_x - min_x + 1, colored);
  176. Paint_DrawVerticalLine(paint, min_x, min_y, max_y - min_y + 1, colored);
  177. Paint_DrawVerticalLine(paint, max_x, min_y, max_y - min_y + 1, colored);
  178. }
  179. /**
  180. * @brief: this draws a filled rectangle
  181. */
  182. void Paint_DrawFilledRectangle(Paint* paint, int x0, int y0, int x1, int y1, int colored) {
  183. int min_x, min_y, max_x, max_y;
  184. int i;
  185. min_x = x1 > x0 ? x0 : x1;
  186. max_x = x1 > x0 ? x1 : x0;
  187. min_y = y1 > y0 ? y0 : y1;
  188. max_y = y1 > y0 ? y1 : y0;
  189. for (i = min_x; i <= max_x; i++) {
  190. Paint_DrawVerticalLine(paint, i, min_y, max_y - min_y + 1, colored);
  191. }
  192. }
  193. /**
  194. * @brief: this draws a circle
  195. */
  196. void Paint_DrawCircle(Paint* paint, int x, int y, int radius, int colored) {
  197. /* Bresenham algorithm */
  198. int x_pos = -radius;
  199. int y_pos = 0;
  200. int err = 2 - 2 * radius;
  201. int e2;
  202. do {
  203. Paint_DrawPixel(paint, x - x_pos, y + y_pos, colored);
  204. Paint_DrawPixel(paint, x + x_pos, y + y_pos, colored);
  205. Paint_DrawPixel(paint, x + x_pos, y - y_pos, colored);
  206. Paint_DrawPixel(paint, x - x_pos, y - y_pos, colored);
  207. e2 = err;
  208. if (e2 <= y_pos) {
  209. err += ++y_pos * 2 + 1;
  210. if(-x_pos == y_pos && e2 <= x_pos) {
  211. e2 = 0;
  212. }
  213. }
  214. if (e2 > x_pos) {
  215. err += ++x_pos * 2 + 1;
  216. }
  217. } while (x_pos <= 0);
  218. }
  219. /**
  220. * @brief: this draws a filled circle
  221. */
  222. void Paint_DrawFilledCircle(Paint* paint, int x, int y, int radius, int colored) {
  223. /* Bresenham algorithm */
  224. int x_pos = -radius;
  225. int y_pos = 0;
  226. int err = 2 - 2 * radius;
  227. int e2;
  228. do {
  229. Paint_DrawPixel(paint, x - x_pos, y + y_pos, colored);
  230. Paint_DrawPixel(paint, x + x_pos, y + y_pos, colored);
  231. Paint_DrawPixel(paint, x + x_pos, y - y_pos, colored);
  232. Paint_DrawPixel(paint, x - x_pos, y - y_pos, colored);
  233. Paint_DrawHorizontalLine(paint, x + x_pos, y + y_pos, 2 * (-x_pos) + 1, colored);
  234. Paint_DrawHorizontalLine(paint, x + x_pos, y - y_pos, 2 * (-x_pos) + 1, colored);
  235. e2 = err;
  236. if (e2 <= y_pos) {
  237. err += ++y_pos * 2 + 1;
  238. if(-x_pos == y_pos && e2 <= x_pos) {
  239. e2 = 0;
  240. }
  241. }
  242. if(e2 > x_pos) {
  243. err += ++x_pos * 2 + 1;
  244. }
  245. } while(x_pos <= 0);
  246. }
  247. /* END OF FILE */