source: libcaca/trunk/src/sprite.c @ 341

Last change on this file since 341 was 322, checked in by Sam Hocevar, 16 years ago
  • libcaca.spec debian/control: + Updated the package descriptions to include cacaball.
  • doc/cacademo.1 doc/Makefile.am: + Use the cacademo manpage as the cacaball manpage.
  • src/: + Added #ifdef _DOXYGEN_SKIP_ME here and there to prvent Doxygen from

documenting bizarre stuff.

  • Property svn:keywords set to Id
File size: 7.3 KB
Line 
1/*
2 *  libcaca       ASCII-Art library
3 *  Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2 of the License, or (at your option) any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 *  02111-1307  USA
20 */
21
22/** \file sprite.c
23 *  \version \$Id: sprite.c 322 2004-01-07 12:45:02Z sam $
24 *  \author Sam Hocevar <sam@zoy.org>
25 *  \brief Sprite loading and blitting
26 *
27 *  This file contains a small framework for sprite loading and blitting.
28 */
29
30#include "config.h"
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include "caca.h"
37#include "caca_internals.h"
38
39#if !defined(_DOXYGEN_SKIP_ME)
40struct caca_frame
41{
42    int w, h;
43    int dx, dy;
44    char *chars;
45    int *color;
46};
47
48struct caca_sprite
49{
50    int nf;
51    struct caca_frame *frames;
52};
53#endif
54
55/**
56 * \brief Allocate a sprite loaded from a file.
57 *
58 * \param file The filename.
59 * \return The sprite, or NULL if an error occured.
60 */
61struct caca_sprite *caca_load_sprite(char const *file)
62{
63    char buf[BUFSIZ];
64    struct caca_sprite *sprite;
65    FILE *fd;
66
67    fd = fopen(file, "r");
68    if(fd == NULL)
69        return NULL;
70
71    sprite = malloc(sizeof(struct caca_sprite));
72    if(sprite == NULL)
73        goto sprite_alloc_failed;
74
75    sprite->nf = 0;
76    sprite->frames = NULL;
77
78    while(!feof(fd))
79    {
80        int x, y;
81        int w = 0, h = 0, dx = 0, dy = 0;
82        struct caca_frame *frame;
83
84        /* Get width and height */
85        if(!fgets(buf, BUFSIZ, fd))
86            break;
87
88        sscanf(buf, "%i %i %i %i", &w, &h, &dx, &dy);
89        if(w <= 0 || h <= 0 || w > BUFSIZ / 2)
90            break;
91
92        if(sprite->nf)
93        {
94            void *tmp = realloc(sprite->frames,
95                                (sprite->nf + 1) * sizeof(struct caca_frame));
96            if(tmp == NULL)
97                goto frame_failed;
98            sprite->frames = tmp;
99            sprite->nf++;
100        }
101        else
102        {
103            sprite->frames = malloc((sprite->nf + 1) * sizeof(struct caca_frame));
104            if(sprite->frames == NULL)
105                goto sprite_failed;
106            sprite->nf++;
107        }
108
109        frame = &sprite->frames[sprite->nf - 1];
110
111        frame->w = w;
112        frame->h = h;
113        frame->dx = dx;
114        frame->dy = dy;
115        frame->chars = malloc(w * h * sizeof(char));
116        if(frame->chars == NULL)
117        {
118            sprite->nf--;
119            goto frame_failed;
120        }
121        frame->color = malloc(w * h * sizeof(int));
122        if(frame->color == NULL)
123        {
124            free(frame->chars);
125            sprite->nf--;
126            goto frame_failed;
127        }
128
129        for(y = 0; y < h; y++)
130        {
131            if(!fgets(buf, BUFSIZ, fd))
132                goto frame_failed;
133
134            for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
135                frame->chars[w * y + x] = buf[x];
136
137            for(; x < w; x++)
138                frame->chars[w * y + x] = ' ';
139        }
140
141        for(y = 0; y < h; y++)
142        {
143            if(!fgets(buf, BUFSIZ, fd))
144                goto frame_failed;
145
146            for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
147                frame->color[w * y + x] = buf[x] - 'a';
148
149            for(; x < w; x++)
150                frame->color[w * y + x] = ' ' - 'a';
151        }
152
153        continue;
154    }
155
156    if(sprite->nf == 0)
157        goto sprite_failed;
158
159    fclose(fd);
160    return sprite;
161
162frame_failed:
163    while(sprite->nf)
164    {
165        free(sprite->frames[sprite->nf - 1].color);
166        free(sprite->frames[sprite->nf - 1].chars);
167        sprite->nf--;
168    }
169sprite_failed:
170    free(sprite);
171sprite_alloc_failed:
172    fclose(fd);
173    return NULL;
174}
175
176/**
177 * \brief Return the number of frames in a sprite.
178 *
179 * \param sprite The sprite.
180 * \return The number of frames.
181 */
182int caca_get_sprite_frames(struct caca_sprite const *sprite)
183{
184    if(sprite == NULL)
185        return 0;
186
187    return sprite->nf;
188}
189
190/**
191 * \brief Return the width of a sprite.
192 *
193 * \param sprite The sprite.
194 * \param f The frame index.
195 * \return The width of the given frame of the sprite.
196 */
197int caca_get_sprite_width(struct caca_sprite const *sprite, int f)
198{
199    if(sprite == NULL)
200        return 0;
201
202    if(f < 0 || f >= sprite->nf)
203        return 0;
204
205    return sprite->frames[f].w;
206}
207
208/**
209 * \brief Return the height of a sprite.
210 *
211 * \param sprite The sprite.
212 * \param f The frame index.
213 * \return The height of the given frame of the sprite.
214 */
215int caca_get_sprite_height(struct caca_sprite const *sprite, int f)
216{
217    if(sprite == NULL)
218        return 0;
219
220    if(f < 0 || f >= sprite->nf)
221        return 0;
222
223    return sprite->frames[f].h;
224}
225
226/**
227 * \brief Return the X coordinate of a sprite's handle.
228 *
229 * \param sprite The sprite.
230 * \param f The frame index.
231 * \return The X coordinate of the given frame's handle.
232 */
233int caca_get_sprite_dx(struct caca_sprite const *sprite, int f)
234{
235    if(sprite == NULL)
236        return 0;
237
238    if(f < 0 || f >= sprite->nf)
239        return 0;
240
241    return sprite->frames[f].dx;
242}
243
244/**
245 * \brief Return the Y coordinate of a sprite's handle.
246 *
247 * \param sprite The sprite.
248 * \param f The frame index.
249 * \return The Y coordinate of the given frame's handle.
250 */
251int caca_get_sprite_dy(struct caca_sprite const *sprite, int f)
252{
253    if(sprite == NULL)
254        return 0;
255
256    if(f < 0 || f >= sprite->nf)
257        return 0;
258
259    return sprite->frames[f].dy;
260}
261
262/**
263 * \brief Draw a sprite's specific frame at the given coordinates. If the
264 *        frame does not exist, nothing is displayed.
265 *
266 * \param x The X coordinate.
267 * \param y The Y coordinate.
268 * \param sprite The sprite.
269 * \param f The frame index.
270 * \return void
271 */
272void caca_draw_sprite(int x, int y, struct caca_sprite const *sprite, int f)
273{
274    int i, j;
275    enum caca_color oldfg, oldbg;
276    struct caca_frame *frame;
277
278    if(sprite == NULL)
279        return;
280
281    if(f < 0 || f >= sprite->nf)
282        return;
283
284    frame = &sprite->frames[f];
285
286    oldfg = caca_get_fg_color();
287    oldbg = caca_get_bg_color();
288
289    for(j = 0; j < frame->h; j++)
290    {
291        for(i = 0; i < frame->w; i++)
292        {
293            int col = frame->color[frame->w * j + i];
294            if(col >= 0)
295            {
296                caca_set_color(col, CACA_COLOR_BLACK);
297                caca_putchar(x + i - frame->dx, y + j - frame->dy,
298                           frame->chars[frame->w * j + i]);
299            }
300        }
301    }
302
303    caca_set_color(oldfg, oldbg);
304}
305
306/**
307 * \brief Free the memory associated with a sprite.
308 *
309 * \param sprite The sprite to be freed.
310 * \return void
311 */
312void caca_free_sprite(struct caca_sprite *sprite)
313{
314    int i;
315
316    if(sprite == NULL)
317        return;
318
319    for(i = sprite->nf; i--;)
320    {
321        struct caca_frame *frame = &sprite->frames[i];
322        free(frame->chars);
323        free(frame->color);
324    }
325
326    free(sprite->frames);
327    free(sprite);
328}
329
Note: See TracBrowser for help on using the repository browser.