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