您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

313 行
6.9 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 a small framework for sprite loading and blitting.
  15. */
  16. #include "config.h"
  17. #if !defined(__KERNEL__)
  18. # include <stdio.h>
  19. # include <stdlib.h>
  20. # include <string.h>
  21. #endif
  22. #include "cucul.h"
  23. #include "cucul_internals.h"
  24. #if !defined(_DOXYGEN_SKIP_ME)
  25. struct cucul_frame
  26. {
  27. int w, h;
  28. int dx, dy;
  29. char *chars;
  30. int *color;
  31. };
  32. struct cucul_sprite
  33. {
  34. int nf;
  35. struct cucul_frame *frames;
  36. };
  37. #endif
  38. /** \brief Allocate a sprite loaded from a file.
  39. *
  40. * \param file The filename.
  41. * \return The sprite, or NULL if an error occured.
  42. */
  43. cucul_sprite_t *cucul_load_sprite(char const *file)
  44. {
  45. char buf[BUFSIZ];
  46. cucul_sprite_t *sprite;
  47. FILE *fd;
  48. fd = fopen(file, "r");
  49. if(fd == NULL)
  50. return NULL;
  51. sprite = malloc(sizeof(cucul_sprite_t));
  52. if(sprite == NULL)
  53. goto sprite_alloc_failed;
  54. sprite->nf = 0;
  55. sprite->frames = NULL;
  56. while(!feof(fd))
  57. {
  58. int x, y;
  59. int w = 0, h = 0, dx = 0, dy = 0;
  60. struct cucul_frame *frame;
  61. /* Get width and height */
  62. if(!fgets(buf, BUFSIZ, fd))
  63. break;
  64. sscanf(buf, "%i %i %i %i", &w, &h, &dx, &dy);
  65. if(w <= 0 || h <= 0 || w > BUFSIZ / 2)
  66. break;
  67. if(sprite->nf)
  68. {
  69. void *tmp = realloc(sprite->frames,
  70. (sprite->nf + 1) * sizeof(struct cucul_frame));
  71. if(tmp == NULL)
  72. goto frame_failed;
  73. sprite->frames = tmp;
  74. sprite->nf++;
  75. }
  76. else
  77. {
  78. sprite->frames = malloc((sprite->nf + 1) * sizeof(struct cucul_frame));
  79. if(sprite->frames == NULL)
  80. goto sprite_failed;
  81. sprite->nf++;
  82. }
  83. frame = &sprite->frames[sprite->nf - 1];
  84. frame->w = w;
  85. frame->h = h;
  86. frame->dx = dx;
  87. frame->dy = dy;
  88. frame->chars = malloc(w * h * sizeof(char));
  89. if(frame->chars == NULL)
  90. {
  91. sprite->nf--;
  92. goto frame_failed;
  93. }
  94. frame->color = malloc(w * h * sizeof(int));
  95. if(frame->color == NULL)
  96. {
  97. free(frame->chars);
  98. sprite->nf--;
  99. goto frame_failed;
  100. }
  101. for(y = 0; y < h; y++)
  102. {
  103. if(!fgets(buf, BUFSIZ, fd))
  104. goto frame_failed;
  105. for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
  106. frame->chars[w * y + x] = buf[x];
  107. for(; x < w; x++)
  108. frame->chars[w * y + x] = ' ';
  109. }
  110. for(y = 0; y < h; y++)
  111. {
  112. if(!fgets(buf, BUFSIZ, fd))
  113. goto frame_failed;
  114. for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
  115. frame->color[w * y + x] = buf[x] - 'a';
  116. for(; x < w; x++)
  117. frame->color[w * y + x] = ' ' - 'a';
  118. }
  119. continue;
  120. }
  121. if(sprite->nf == 0)
  122. goto sprite_failed;
  123. fclose(fd);
  124. return sprite;
  125. frame_failed:
  126. while(sprite->nf)
  127. {
  128. free(sprite->frames[sprite->nf - 1].color);
  129. free(sprite->frames[sprite->nf - 1].chars);
  130. sprite->nf--;
  131. }
  132. sprite_failed:
  133. free(sprite);
  134. sprite_alloc_failed:
  135. fclose(fd);
  136. return NULL;
  137. }
  138. /** \brief Return the number of frames in a sprite.
  139. *
  140. * \param sprite The sprite.
  141. * \return The number of frames.
  142. */
  143. int cucul_get_sprite_frames(cucul_sprite_t const *sprite)
  144. {
  145. if(sprite == NULL)
  146. return 0;
  147. return sprite->nf;
  148. }
  149. /** \brief Return the width of a sprite.
  150. *
  151. * \param sprite The sprite.
  152. * \param f The frame index.
  153. * \return The width of the given frame of the sprite.
  154. */
  155. int cucul_get_sprite_width(cucul_sprite_t const *sprite, int f)
  156. {
  157. if(sprite == NULL)
  158. return 0;
  159. if(f < 0 || f >= sprite->nf)
  160. return 0;
  161. return sprite->frames[f].w;
  162. }
  163. /** \brief Return the height of a sprite.
  164. *
  165. * \param sprite The sprite.
  166. * \param f The frame index.
  167. * \return The height of the given frame of the sprite.
  168. */
  169. int cucul_get_sprite_height(cucul_sprite_t const *sprite, int f)
  170. {
  171. if(sprite == NULL)
  172. return 0;
  173. if(f < 0 || f >= sprite->nf)
  174. return 0;
  175. return sprite->frames[f].h;
  176. }
  177. /** \brief Return the X coordinate of a sprite's handle.
  178. *
  179. * \param sprite The sprite.
  180. * \param f The frame index.
  181. * \return The X coordinate of the given frame's handle.
  182. */
  183. int cucul_get_sprite_dx(cucul_sprite_t const *sprite, int f)
  184. {
  185. if(sprite == NULL)
  186. return 0;
  187. if(f < 0 || f >= sprite->nf)
  188. return 0;
  189. return sprite->frames[f].dx;
  190. }
  191. /** \brief Return the Y coordinate of a sprite's handle.
  192. *
  193. * \param sprite The sprite.
  194. * \param f The frame index.
  195. * \return The Y coordinate of the given frame's handle.
  196. */
  197. int cucul_get_sprite_dy(cucul_sprite_t const *sprite, int f)
  198. {
  199. if(sprite == NULL)
  200. return 0;
  201. if(f < 0 || f >= sprite->nf)
  202. return 0;
  203. return sprite->frames[f].dy;
  204. }
  205. /** \brief Draw a sprite's specific frame at the given coordinates. If the
  206. * frame does not exist, nothing is displayed.
  207. *
  208. * \param qq A libcucul canvas
  209. * \param x The X coordinate.
  210. * \param y The Y coordinate.
  211. * \param sprite The sprite.
  212. * \param f The frame index.
  213. * \return void
  214. */
  215. void cucul_draw_sprite(cucul_t *qq, int x, int y, cucul_sprite_t const *sprite, int f)
  216. {
  217. int i, j;
  218. unsigned int oldfg, oldbg;
  219. struct cucul_frame *frame;
  220. if(sprite == NULL)
  221. return;
  222. if(f < 0 || f >= sprite->nf)
  223. return;
  224. frame = &sprite->frames[f];
  225. oldfg = qq->fgcolor;
  226. oldbg = qq->bgcolor;
  227. for(j = 0; j < frame->h; j++)
  228. {
  229. for(i = 0; i < frame->w; i++)
  230. {
  231. int col = frame->color[frame->w * j + i];
  232. if(col >= 0)
  233. {
  234. cucul_set_color(qq, col, CUCUL_COLOR_BLACK);
  235. cucul_putchar(qq, x + i - frame->dx, y + j - frame->dy,
  236. frame->chars[frame->w * j + i]);
  237. }
  238. }
  239. }
  240. cucul_set_color(qq, oldfg, oldbg);
  241. }
  242. /** \brief Free the memory associated with a sprite.
  243. *
  244. * \param sprite The sprite to be freed.
  245. * \return void
  246. */
  247. void cucul_free_sprite(cucul_sprite_t *sprite)
  248. {
  249. int i;
  250. if(sprite == NULL)
  251. return;
  252. for(i = sprite->nf; i--;)
  253. {
  254. struct cucul_frame *frame = &sprite->frames[i];
  255. free(frame->chars);
  256. free(frame->color);
  257. }
  258. free(sprite->frames);
  259. free(sprite);
  260. }