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.

canvas.c 6.6 KiB

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