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 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * libcucul Unicode canvas library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file conic.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Ellipse and circle drawing
  15. *
  16. * This file contains ellipse and circle drawing functions, both filled
  17. * and outline.
  18. */
  19. #include "config.h"
  20. #if !defined(__KERNEL__)
  21. # include <stdlib.h>
  22. #endif
  23. #include "cucul.h"
  24. #include "cucul_internals.h"
  25. static void ellipsepoints(cucul_t *, int, int, int, int, char);
  26. /**
  27. * \brief Draw a circle on the screen using the given character.
  28. *
  29. * \param x Center X coordinate.
  30. * \param y Center Y coordinate.
  31. * \param r Circle radius.
  32. * \param c Character to draw the circle outline with.
  33. * \return void
  34. */
  35. void cucul_draw_circle(cucul_t *qq, int x, int y, int r, char c)
  36. {
  37. int test, dx, dy;
  38. /* Optimized Bresenham. Kick ass. */
  39. for(test = 0, dx = 0, dy = r ; dx <= dy ; dx++)
  40. {
  41. ellipsepoints(qq, x, y, dx, dy, c);
  42. ellipsepoints(qq, x, y, dy, dx, c);
  43. test += test > 0 ? dx - dy-- : dx;
  44. }
  45. }
  46. /**
  47. * \brief Fill an ellipse on the screen using the given character.
  48. *
  49. * \param xo Center X coordinate.
  50. * \param yo Center Y coordinate.
  51. * \param a Ellipse X radius.
  52. * \param b Ellipse Y radius.
  53. * \param c Character to fill the ellipse with.
  54. * \return void
  55. */
  56. void cucul_fill_ellipse(cucul_t *qq, int xo, int yo, int a, int b, char c)
  57. {
  58. int d2;
  59. int x = 0;
  60. int y = b;
  61. int d1 = b*b - (a*a*b) + (a*a/4);
  62. while(a*a*y - a*a/2 > b*b*(x+1))
  63. {
  64. if(d1 < 0)
  65. {
  66. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  67. }
  68. else
  69. {
  70. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  71. cucul_draw_line(qq, xo - x, yo - y, xo + x, yo - y, c);
  72. cucul_draw_line(qq, xo - x, yo + y, xo + x, yo + y, c);
  73. y--;
  74. }
  75. x++;
  76. }
  77. cucul_draw_line(qq, xo - x, yo - y, xo + x, yo - y, c);
  78. cucul_draw_line(qq, xo - x, yo + y, xo + x, yo + y, c);
  79. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  80. while(y > 0)
  81. {
  82. if(d2 < 0)
  83. {
  84. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  85. x++;
  86. }
  87. else
  88. {
  89. d2 += a*a*(-2*y+3);
  90. }
  91. y--;
  92. cucul_draw_line(qq, xo - x, yo - y, xo + x, yo - y, c);
  93. cucul_draw_line(qq, xo - x, yo + y, xo + x, yo + y, c);
  94. }
  95. }
  96. /**
  97. * \brief Draw an ellipse on the screen using the given character.
  98. *
  99. * \param xo Center X coordinate.
  100. * \param yo Center Y coordinate.
  101. * \param a Ellipse X radius.
  102. * \param b Ellipse Y radius.
  103. * \param c Character to draw the ellipse outline with.
  104. * \return void
  105. */
  106. void cucul_draw_ellipse(cucul_t *qq, int xo, int yo, int a, int b, char c)
  107. {
  108. int d2;
  109. int x = 0;
  110. int y = b;
  111. int d1 = b*b - (a*a*b) + (a*a/4);
  112. ellipsepoints(qq, xo, yo, x, y, c);
  113. while(a*a*y - a*a/2 > b*b*(x+1))
  114. {
  115. if(d1 < 0)
  116. {
  117. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  118. }
  119. else
  120. {
  121. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  122. y--;
  123. }
  124. x++;
  125. ellipsepoints(qq, xo, yo, x, y, c);
  126. }
  127. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  128. while(y > 0)
  129. {
  130. if(d2 < 0)
  131. {
  132. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  133. x++;
  134. }
  135. else
  136. {
  137. d2 += a*a*(-2*y+3);
  138. }
  139. y--;
  140. ellipsepoints(qq, xo, yo, x, y, c);
  141. }
  142. }
  143. /**
  144. * \brief Draw a thin ellipse on the screen.
  145. *
  146. * \param xo Center X coordinate.
  147. * \param yo Center Y coordinate.
  148. * \param a Ellipse X radius.
  149. * \param b Ellipse Y radius.
  150. * \return void
  151. */
  152. void cucul_draw_thin_ellipse(cucul_t *qq, int xo, int yo, int a, int b)
  153. {
  154. /* FIXME: this is not correct */
  155. int d2;
  156. int x = 0;
  157. int y = b;
  158. int d1 = b*b - (a*a*b) + (a*a/4);
  159. ellipsepoints(qq, xo, yo, x, y, '-');
  160. while(a*a*y - a*a/2 > b*b*(x+1))
  161. {
  162. if(d1 < 0)
  163. {
  164. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  165. }
  166. else
  167. {
  168. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  169. y--;
  170. }
  171. x++;
  172. ellipsepoints(qq, xo, yo, x, y, '-');
  173. }
  174. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  175. while(y > 0)
  176. {
  177. if(d2 < 0)
  178. {
  179. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  180. x++;
  181. }
  182. else
  183. {
  184. d2 += a*a*(-2*y+3);
  185. }
  186. y--;
  187. ellipsepoints(qq, xo, yo, x, y, '|');
  188. }
  189. }
  190. static void ellipsepoints(cucul_t *qq, int xo, int yo, int x, int y, char c)
  191. {
  192. uint8_t b = 0;
  193. if(xo + x >= 0 && xo + x < (int)qq->width)
  194. b |= 0x1;
  195. if(xo - x >= 0 && xo - x < (int)qq->width)
  196. b |= 0x2;
  197. if(yo + y >= 0 && yo + y < (int)qq->height)
  198. b |= 0x4;
  199. if(yo - y >= 0 && yo - y < (int)qq->height)
  200. b |= 0x8;
  201. if((b & (0x1|0x4)) == (0x1|0x4))
  202. cucul_putchar(qq, xo + x, yo + y, c);
  203. if((b & (0x2|0x4)) == (0x2|0x4))
  204. cucul_putchar(qq, xo - x, yo + y, c);
  205. if((b & (0x1|0x8)) == (0x1|0x8))
  206. cucul_putchar(qq, xo + x, yo - y, c);
  207. if((b & (0x2|0x8)) == (0x2|0x8))
  208. cucul_putchar(qq, xo - x, yo - y, c);
  209. }