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 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
преди 18 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 various canvas handling functions such as character
  15. * and string drawing.
  16. */
  17. #include "config.h"
  18. #include "common.h"
  19. #if !defined(__KERNEL__)
  20. # include <stdio.h> /* BUFSIZ */
  21. # include <string.h>
  22. # include <stdlib.h>
  23. # include <stdarg.h>
  24. # if defined(HAVE_ERRNO_H)
  25. # include <errno.h>
  26. # endif
  27. # if defined(HAVE_UNISTD_H)
  28. # include <unistd.h>
  29. # endif
  30. # if defined(HAVE_SIGNAL_H)
  31. # include <signal.h>
  32. # endif
  33. # if defined(HAVE_SYS_IOCTL_H)
  34. # include <sys/ioctl.h>
  35. # endif
  36. #endif
  37. #include "cucul.h"
  38. #include "cucul_internals.h"
  39. /** \brief Print an ASCII character.
  40. *
  41. * This function prints an ASCII character at the given coordinates, using
  42. * the default foreground and background values. If the coordinates are
  43. * outside the canvas boundaries, nothing is printed. If the character
  44. * value is a non-printable character or is outside the ASCII range, it is
  45. * replaced with a space. To print a sequence of bytes forming an UTF-8
  46. * character, use cucul_putstr() instead.
  47. *
  48. * This function never fails.
  49. *
  50. * \param cv A handle to the libcucul canvas.
  51. * \param x X coordinate.
  52. * \param y Y coordinate.
  53. * \param ch The character to print.
  54. * \return This function always returns 0.
  55. */
  56. int cucul_putchar(cucul_canvas_t *cv, int x, int y, char ch)
  57. {
  58. if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height)
  59. return 0;
  60. if((unsigned char)ch < 0x20 || (unsigned char)ch > 0x7f)
  61. ch = 0x20;
  62. cv->chars[x + y * cv->width] = ch;
  63. cv->attr[x + y * cv->width] = (cv->bgcolor << 16) | cv->fgcolor;
  64. return 0;
  65. }
  66. /** \brief Print a string.
  67. *
  68. * This function prints an UTF-8 string at the given coordinates, using the
  69. * default foreground and background values. The coordinates may be outside
  70. * the canvas boundaries (eg. a negative Y coordinate) and the string will
  71. * be cropped accordingly if it is too long.
  72. *
  73. * This function never fails.
  74. *
  75. * \param cv A handle to the libcucul canvas.
  76. * \param x X coordinate.
  77. * \param y Y coordinate.
  78. * \param s The string to print.
  79. * \return This function always returns 0.
  80. */
  81. int cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s)
  82. {
  83. uint32_t *chars, *attr;
  84. unsigned int len;
  85. if(y < 0 || y >= (int)cv->height || x >= (int)cv->width)
  86. return 0;
  87. len = _cucul_strlen_utf8(s);
  88. if(x < 0)
  89. {
  90. if(len < (unsigned int)-x)
  91. return 0;
  92. len -= -x;
  93. s = _cucul_skip_utf8(s, -x);
  94. x = 0;
  95. }
  96. chars = cv->chars + x + y * cv->width;
  97. attr = cv->attr + x + y * cv->width;
  98. if(x + len >= cv->width)
  99. len = cv->width - x;
  100. while(len)
  101. {
  102. *chars++ = _cucul_utf8_to_utf32(s);
  103. *attr++ = (cv->bgcolor << 16) | cv->fgcolor;
  104. s = _cucul_skip_utf8(s, 1);
  105. len--;
  106. }
  107. return 0;
  108. }
  109. /** \brief Print a formated string.
  110. *
  111. * This function formats a string at the given coordinates, using the
  112. * default foreground and background values. The coordinates may be outside
  113. * the canvas boundaries (eg. a negative Y coordinate) and the string will
  114. * be cropped accordingly if it is too long. The syntax of the format
  115. * string is the same as for the C printf() function.
  116. *
  117. * This function never fails.
  118. *
  119. * \param cv A handle to the libcucul canvas.
  120. * \param x X coordinate.
  121. * \param y Y coordinate.
  122. * \param format The format string to print.
  123. * \param ... Arguments to the format string.
  124. * \return This function always returns 0.
  125. */
  126. int cucul_printf(cucul_canvas_t *cv, int x, int y, char const *format, ...)
  127. {
  128. char tmp[BUFSIZ];
  129. char *buf = tmp;
  130. va_list args;
  131. if(y < 0 || y >= (int)cv->height || x >= (int)cv->width)
  132. return 0;
  133. if(cv->width - x + 1 > BUFSIZ)
  134. buf = malloc(cv->width - x + 1);
  135. va_start(args, format);
  136. #if defined(HAVE_VSNPRINTF)
  137. vsnprintf(buf, cv->width - x + 1, format, args);
  138. #else
  139. vsprintf(buf, format, args);
  140. #endif
  141. buf[cv->width - x] = '\0';
  142. va_end(args);
  143. cucul_putstr(cv, x, y, buf);
  144. if(buf != tmp)
  145. free(buf);
  146. return 0;
  147. }
  148. /** \brief Clear the canvas.
  149. *
  150. * This function clears the canvas using the current background colour.
  151. *
  152. * This function never fails.
  153. *
  154. * \param cv The canvas to clear.
  155. * \return This function always returns 0.
  156. */
  157. int cucul_clear_canvas(cucul_canvas_t *cv)
  158. {
  159. uint32_t color = (cv->bgcolor << 16) | cv->fgcolor;
  160. unsigned int n;
  161. /* We could use SLsmg_cls() etc., but drawing empty lines is much faster */
  162. for(n = cv->width * cv->height; n--; )
  163. {
  164. cv->chars[n] = (uint32_t)' ';
  165. cv->attr[n] = color;
  166. }
  167. return 0;
  168. }
  169. /** \brief Blit a canvas onto another one.
  170. *
  171. * This function blits a canvas onto another one at the given coordinates.
  172. * An optional mask canvas can be used.
  173. *
  174. * If an error occurs, -1 is returned and \b errno is set accordingly:
  175. * - \c EINVAL A mask was specified but the mask size and source canvas
  176. * size do not match.
  177. *
  178. * \param dst The destination canvas.
  179. * \param x X coordinate.
  180. * \param y Y coordinate.
  181. * \param src The source canvas.
  182. * \param mask The mask canvas.
  183. * \return 0 in case of success, -1 if an error occurred.
  184. */
  185. int cucul_blit(cucul_canvas_t *dst, int x, int y,
  186. cucul_canvas_t const *src, cucul_canvas_t const *mask)
  187. {
  188. int i, j, starti, startj, endi, endj;
  189. if(mask && (src->width != mask->width || src->height != mask->height))
  190. {
  191. #if defined(HAVE_ERRNO_H)
  192. errno = EINVAL;
  193. #endif
  194. return -1;
  195. }
  196. starti = x < 0 ? -x : 0;
  197. startj = y < 0 ? -y : 0;
  198. endi = (x + src->width >= dst->width) ? dst->width - x : src->width;
  199. endj = (y + src->height >= dst->height) ? dst->height - y : src->height;
  200. if(starti >= endi || startj >= endj)
  201. return 0;
  202. for(j = startj; j < endj; j++)
  203. {
  204. if(mask)
  205. {
  206. for(i = starti; i < endi; i++)
  207. {
  208. if(mask->chars[j * src->width + i] == (uint32_t)' ')
  209. continue;
  210. dst->chars[(j + y) * dst->width + (i + x)]
  211. = src->chars[j * src->width + i];
  212. dst->attr[(j + y) * dst->width + (i + x)]
  213. = src->attr[j * src->width + i];
  214. }
  215. }
  216. else
  217. {
  218. memcpy(dst->chars + (j + y) * dst->width + starti + x,
  219. src->chars + j * src->width + starti,
  220. (endi - starti) * 4);
  221. memcpy(dst->attr + (j + y) * dst->width + starti + x,
  222. src->attr + j * src->width + starti,
  223. (endi - starti) * 4);
  224. }
  225. }
  226. return 0;
  227. }
  228. /*
  229. * XXX: The following functions are not exported
  230. */
  231. void _cucul_putchar32(cucul_canvas_t *cv, int x, int y, uint32_t ch)
  232. {
  233. if(x < 0 || x >= (int)cv->width ||
  234. y < 0 || y >= (int)cv->height)
  235. return;
  236. cv->chars[x + y * cv->width] = ch;
  237. cv->attr[x + y * cv->width] = (cv->bgcolor << 16) | cv->fgcolor;
  238. }