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

263 строки
7.2 KiB

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