You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 21 години
преди 21 години
преди 21 години
преди 21 години
преди 21 години
преди 21 години
преди 21 години
преди 21 години
преди 21 години
преди 21 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /*
  2. * libcaca Colour ASCII-Art library
  3. * Copyright (c) 2002-2012 Sam Hocevar <sam@hocevar.net>
  4. * All Rights Reserved
  5. *
  6. * This library is free software. It comes without any warranty, to
  7. * the extent permitted by applicable law. You can redistribute it
  8. * and/or modify it under the terms of the Do What the Fuck You Want
  9. * to Public License, Version 2, as published by Sam Hocevar. See
  10. * http://www.wtfpl.net/ for more details.
  11. */
  12. /*
  13. * This file contains ellipse and circle drawing functions, both filled
  14. * and outline.
  15. */
  16. #include "config.h"
  17. #if !defined(__KERNEL__)
  18. # include <stdlib.h>
  19. #endif
  20. #include "caca.h"
  21. #include "caca_internals.h"
  22. static void ellipsepoints(caca_canvas_t *, int, int, int, int, uint32_t, int);
  23. /** \brief Draw a circle on the canvas using the given character.
  24. *
  25. * This function never fails.
  26. *
  27. * \param cv The handle to the libcaca canvas.
  28. * \param x Center X coordinate.
  29. * \param y Center Y coordinate.
  30. * \param r Circle radius.
  31. * \param ch UTF-32 character to be used to draw the circle outline.
  32. * \return This function always returns 0.
  33. */
  34. int caca_draw_circle(caca_canvas_t *cv, int x, int y, int r, uint32_t ch)
  35. {
  36. int test, dx, dy;
  37. /* Optimized Bresenham. Kick ass. */
  38. for(test = 0, dx = 0, dy = r ; dx <= dy ; dx++)
  39. {
  40. ellipsepoints(cv, x, y, dx, dy, ch, 1);
  41. ellipsepoints(cv, x, y, dy, dx, ch, 1);
  42. test += test > 0 ? dx - dy-- : dx;
  43. }
  44. return 0;
  45. }
  46. /** \brief Fill an ellipse on the canvas using the given character.
  47. *
  48. * This function never fails.
  49. *
  50. * \param cv The handle to the libcaca canvas.
  51. * \param xo Center X coordinate.
  52. * \param yo Center Y coordinate.
  53. * \param a Ellipse X radius.
  54. * \param b Ellipse Y radius.
  55. * \param ch UTF-32 character to be used to fill the ellipse.
  56. * \return This function always returns 0.
  57. */
  58. int caca_fill_ellipse(caca_canvas_t *cv, int xo, int yo, int a, int b,
  59. uint32_t ch)
  60. {
  61. int d2;
  62. int x = 0;
  63. int y = b;
  64. int d1 = b*b - (a*a*b) + (a*a/4);
  65. while(a*a*y - a*a/2 > b*b*(x+1))
  66. {
  67. if(d1 < 0)
  68. {
  69. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  70. }
  71. else
  72. {
  73. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  74. caca_draw_line(cv, xo - x, yo - y, xo + x, yo - y, ch);
  75. caca_draw_line(cv, xo - x, yo + y, xo + x, yo + y, ch);
  76. y--;
  77. }
  78. x++;
  79. }
  80. caca_draw_line(cv, xo - x, yo - y, xo + x, yo - y, ch);
  81. caca_draw_line(cv, xo - x, yo + y, xo + x, yo + y, ch);
  82. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  83. while(y > 0)
  84. {
  85. if(d2 < 0)
  86. {
  87. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  88. x++;
  89. }
  90. else
  91. {
  92. d2 += a*a*(-2*y+3);
  93. }
  94. y--;
  95. caca_draw_line(cv, xo - x, yo - y, xo + x, yo - y, ch);
  96. caca_draw_line(cv, xo - x, yo + y, xo + x, yo + y, ch);
  97. }
  98. return 0;
  99. }
  100. /** \brief Draw an ellipse on the canvas using the given character.
  101. *
  102. * This function never fails.
  103. *
  104. * \param cv The handle to the libcaca canvas.
  105. * \param xo Center X coordinate.
  106. * \param yo Center Y coordinate.
  107. * \param a Ellipse X radius.
  108. * \param b Ellipse Y radius.
  109. * \param ch UTF-32 character to be used to draw the ellipse outline.
  110. * \return This function always returns 0.
  111. */
  112. int caca_draw_ellipse(caca_canvas_t *cv, int xo, int yo, int a, int b,
  113. uint32_t ch)
  114. {
  115. int d2;
  116. int x = 0;
  117. int y = b;
  118. int d1 = b*b - (a*a*b) + (a*a/4);
  119. ellipsepoints(cv, xo, yo, x, y, ch, 0);
  120. while(a*a*y - a*a/2 > b*b*(x+1))
  121. {
  122. if(d1 < 0)
  123. {
  124. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  125. }
  126. else
  127. {
  128. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  129. y--;
  130. }
  131. x++;
  132. ellipsepoints(cv, xo, yo, x, y, ch, 0);
  133. }
  134. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  135. while(y > 0)
  136. {
  137. if(d2 < 0)
  138. {
  139. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  140. x++;
  141. }
  142. else
  143. {
  144. d2 += a*a*(-2*y+3);
  145. }
  146. y--;
  147. ellipsepoints(cv, xo, yo, x, y, ch, 0);
  148. }
  149. return 0;
  150. }
  151. /** \brief Draw a thin ellipse on the canvas.
  152. *
  153. * This function never fails.
  154. *
  155. * \param cv The handle to the libcaca canvas.
  156. * \param xo Center X coordinate.
  157. * \param yo Center Y coordinate.
  158. * \param a Ellipse X radius.
  159. * \param b Ellipse Y radius.
  160. * \return This function always returns 0.
  161. */
  162. int caca_draw_thin_ellipse(caca_canvas_t *cv, int xo, int yo, int a, int b)
  163. {
  164. /* FIXME: this is not correct */
  165. int d2;
  166. int x = 0;
  167. int y = b;
  168. int d1 = b*b - (a*a*b) + (a*a/4);
  169. ellipsepoints(cv, xo, yo, x, y, '-', 1);
  170. while(a*a*y - a*a/2 > b*b*(x+1))
  171. {
  172. if(d1 < 0)
  173. {
  174. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  175. ellipsepoints(cv, xo, yo, x + 1, y, '0', 1);
  176. }
  177. else
  178. {
  179. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  180. y--;
  181. ellipsepoints(cv, xo, yo, x + 1, y, '1', 1);
  182. }
  183. x++;
  184. }
  185. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  186. while(y > 0)
  187. {
  188. if(d2 < 0)
  189. {
  190. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  191. x++;
  192. ellipsepoints(cv, xo, yo, x , y - 1, '2', 1);
  193. }
  194. else
  195. {
  196. d2 += a*a*(-2*y+3);
  197. ellipsepoints(cv, xo, yo, x , y - 1, '3', 1);
  198. }
  199. y--;
  200. }
  201. return 0;
  202. }
  203. static void ellipsepoints(caca_canvas_t *cv, int xo, int yo, int x, int y,
  204. uint32_t ch, int thin)
  205. {
  206. uint8_t b = 0;
  207. if(xo + x >= 0 && xo + x < (int)cv->width)
  208. b |= 0x1;
  209. if(xo - x >= 0 && xo - x < (int)cv->width)
  210. b |= 0x2;
  211. if(yo + y >= 0 && yo + y < (int)cv->height)
  212. b |= 0x4;
  213. if(yo - y >= 0 && yo - y < (int)cv->height)
  214. b |= 0x8;
  215. if((b & (0x1|0x4)) == (0x1|0x4)) {
  216. uint32_t c = ch;
  217. if(thin) {
  218. switch(c) {
  219. case '0':
  220. c = '-';
  221. break;
  222. case '1':
  223. c = ',';
  224. break;
  225. case '2':
  226. c = '/';
  227. break;
  228. case '3':
  229. c = '|';
  230. break;
  231. }
  232. }
  233. caca_put_char(cv, xo + x, yo + y, c);
  234. }
  235. if((b & (0x2|0x4)) == (0x2|0x4)) {
  236. uint32_t c = ch;
  237. if(thin) {
  238. switch(c) {
  239. case '0':
  240. c = '-';
  241. break;
  242. case '1':
  243. c = '.';
  244. break;
  245. case '2':
  246. c = '\\';
  247. break;
  248. case '3':
  249. c = '|';
  250. break;
  251. }
  252. }
  253. caca_put_char(cv, xo - x, yo + y, c);
  254. }
  255. if((b & (0x1|0x8)) == (0x1|0x8)) {
  256. uint32_t c = ch;
  257. if(thin) {
  258. switch(c) {
  259. case '0':
  260. c = '-';
  261. break;
  262. case '1':
  263. c = '`';
  264. break;
  265. case '2':
  266. c = '\\';
  267. break;
  268. case '3':
  269. c = '|';
  270. break;
  271. }
  272. }
  273. caca_put_char(cv, xo + x, yo - y, c);
  274. }
  275. if((b & (0x2|0x8)) == (0x2|0x8)) {
  276. uint32_t c = ch;
  277. if(thin) {
  278. switch(c) {
  279. case '0':
  280. c = '-';
  281. break;
  282. case '1':
  283. c = '\'';
  284. break;
  285. case '2':
  286. c = '/';
  287. break;
  288. case '3':
  289. c = '|';
  290. break;
  291. }
  292. }
  293. caca_put_char(cv, xo - x, yo - y, c);
  294. }
  295. }
  296. /*
  297. * XXX: The following functions are aliases.
  298. */
  299. int cucul_draw_circle(cucul_canvas_t *, int, int, int, uint32_t)
  300. CACA_ALIAS(caca_draw_circle);
  301. int cucul_draw_ellipse(cucul_canvas_t *, int, int, int, int, uint32_t)
  302. CACA_ALIAS(caca_draw_ellipse);
  303. int cucul_draw_thin_ellipse(cucul_canvas_t *, int, int, int, int)
  304. CACA_ALIAS(caca_draw_thin_ellipse);
  305. int cucul_fill_ellipse(cucul_canvas_t *, int, int, int, int, uint32_t)
  306. CACA_ALIAS(caca_fill_ellipse);