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.

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