Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

254 строки
5.9 KiB

  1. /*
  2. * libcaca ASCII-Art library
  3. * Copyright (c) 2002, 2003 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 GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  19. * 02111-1307 USA
  20. */
  21. /** \file conic.c
  22. * \version \$Id$
  23. * \author Sam Hocevar <sam@zoy.org>
  24. * \brief Ellipse and circle drawing
  25. *
  26. * This file contains ellipse and circle drawing functions, both filled
  27. * and outline.
  28. */
  29. #include "config.h"
  30. #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
  31. # include <inttypes.h>
  32. #else
  33. typedef unsigned char uint8_t;
  34. #endif
  35. #include <stdlib.h>
  36. #include "caca.h"
  37. #include "caca_internals.h"
  38. static void ellipsepoints(int, int, int, int, char);
  39. /**
  40. * \brief Draw a circle on the screen using the given character.
  41. *
  42. * \param x Center X coordinate.
  43. * \param y Center Y coordinate.
  44. * \param r Circle radius.
  45. * \param c Character to draw the circle outline with.
  46. * \return void
  47. */
  48. void caca_draw_circle(int x, int y, int r, char c)
  49. {
  50. int test, dx, dy;
  51. /* Optimized Bresenham. Kick ass. */
  52. for(test = 0, dx = 0, dy = r ; dx <= dy ; dx++)
  53. {
  54. ellipsepoints(x, y, dx, dy, c);
  55. ellipsepoints(x, y, dy, dx, c);
  56. test += test > 0 ? dx - dy-- : dx;
  57. }
  58. }
  59. /**
  60. * \brief Fill an ellipse on the screen using the given character.
  61. *
  62. * \param xo Center X coordinate.
  63. * \param yo Center Y coordinate.
  64. * \param a Ellipse X radius.
  65. * \param b Ellipse Y radius.
  66. * \param c Character to fill the ellipse with.
  67. * \return void
  68. */
  69. void caca_fill_ellipse(int xo, int yo, int a, int b, char c)
  70. {
  71. int d2;
  72. int x = 0;
  73. int y = b;
  74. int d1 = b*b - (a*a*b) + (a*a/4);
  75. while(a*a*y - a*a/2 > b*b*(x+1))
  76. {
  77. if(d1 < 0)
  78. {
  79. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  80. }
  81. else
  82. {
  83. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  84. caca_draw_line(xo - x, yo - y, xo + x, yo - y, c);
  85. caca_draw_line(xo - x, yo + y, xo + x, yo + y, c);
  86. y--;
  87. }
  88. x++;
  89. }
  90. caca_draw_line(xo - x, yo - y, xo + x, yo - y, c);
  91. caca_draw_line(xo - x, yo + y, xo + x, yo + y, c);
  92. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  93. while(y > 0)
  94. {
  95. if(d2 < 0)
  96. {
  97. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  98. x++;
  99. }
  100. else
  101. {
  102. d2 += a*a*(-2*y+3);
  103. }
  104. y--;
  105. caca_draw_line(xo - x, yo - y, xo + x, yo - y, c);
  106. caca_draw_line(xo - x, yo + y, xo + x, yo + y, c);
  107. }
  108. }
  109. /**
  110. * \brief Draw an ellipse on the screen using the given character.
  111. *
  112. * \param xo Center X coordinate.
  113. * \param yo Center Y coordinate.
  114. * \param a Ellipse X radius.
  115. * \param b Ellipse Y radius.
  116. * \param c Character to draw the ellipse outline with.
  117. * \return void
  118. */
  119. void caca_draw_ellipse(int xo, int yo, int a, int b, char c)
  120. {
  121. int d2;
  122. int x = 0;
  123. int y = b;
  124. int d1 = b*b - (a*a*b) + (a*a/4);
  125. ellipsepoints(xo, yo, x, y, c);
  126. while(a*a*y - a*a/2 > b*b*(x+1))
  127. {
  128. if(d1 < 0)
  129. {
  130. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  131. }
  132. else
  133. {
  134. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  135. y--;
  136. }
  137. x++;
  138. ellipsepoints(xo, yo, x, y, c);
  139. }
  140. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  141. while(y > 0)
  142. {
  143. if(d2 < 0)
  144. {
  145. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  146. x++;
  147. }
  148. else
  149. {
  150. d2 += a*a*(-2*y+3);
  151. }
  152. y--;
  153. ellipsepoints(xo, yo, x, y, c);
  154. }
  155. }
  156. /**
  157. * \brief Draw a thin ellipse on the screen.
  158. *
  159. * \param xo Center X coordinate.
  160. * \param yo Center Y coordinate.
  161. * \param a Ellipse X radius.
  162. * \param b Ellipse Y radius.
  163. * \return void
  164. */
  165. void caca_draw_thin_ellipse(int xo, int yo, int a, int b)
  166. {
  167. /* FIXME: this is not correct */
  168. int d2;
  169. int x = 0;
  170. int y = b;
  171. int d1 = b*b - (a*a*b) + (a*a/4);
  172. ellipsepoints(xo, yo, x, y, '-');
  173. while(a*a*y - a*a/2 > b*b*(x+1))
  174. {
  175. if(d1 < 0)
  176. {
  177. d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
  178. }
  179. else
  180. {
  181. d1 += b*b*(2*x*1) + a*a*(-2*y+2);
  182. y--;
  183. }
  184. x++;
  185. ellipsepoints(xo, yo, x, y, '-');
  186. }
  187. d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
  188. while(y > 0)
  189. {
  190. if(d2 < 0)
  191. {
  192. d2 += b*b*(2*x+2) + a*a*(-2*y+3);
  193. x++;
  194. }
  195. else
  196. {
  197. d2 += a*a*(-2*y+3);
  198. }
  199. y--;
  200. ellipsepoints(xo, yo, x, y, '|');
  201. }
  202. }
  203. static void ellipsepoints(int xo, int yo, int x, int y, char c)
  204. {
  205. uint8_t b = 0;
  206. if(xo + x >= 0 && xo + x < (int)_caca_width)
  207. b |= 0x1;
  208. if(xo - x >= 0 && xo - x < (int)_caca_width)
  209. b |= 0x2;
  210. if(yo + y >= 0 && yo + y < (int)_caca_height)
  211. b |= 0x4;
  212. if(yo - y >= 0 && yo - y < (int)_caca_height)
  213. b |= 0x8;
  214. if((b & (0x1|0x4)) == (0x1|0x4))
  215. caca_putchar(xo + x, yo + y, c);
  216. if((b & (0x2|0x4)) == (0x2|0x4))
  217. caca_putchar(xo - x, yo + y, c);
  218. if((b & (0x1|0x8)) == (0x1|0x8))
  219. caca_putchar(xo + x, yo - y, c);
  220. if((b & (0x2|0x8)) == (0x2|0x8))
  221. caca_putchar(xo - x, yo - y, c);
  222. }