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

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