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

Last change on this file since 192 was 192, checked in by Sam Hocevar, 19 years ago
  • Changed copyleft to LGPL.
  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1/*
2 *   libcaca       ASCII-Art library
3 *   Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
4 *                 All Rights Reserved
5 *
6 *   $Id: sprite.c 192 2003-11-16 12:28:29Z sam $
7 *
8 *   This library is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU Lesser General Public
10 *   License as published by the Free Software Foundation; either
11 *   version 2 of the License, or (at your option) any later version.
12 *
13 *   This library is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *   Lesser General Public License for more details.
17 *
18 *   You should have received a copy of the GNU Lesser General Public
19 *   License along with this library; if not, write to the Free Software
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 *   02111-1307  USA
22 */
23
24#include "config.h"
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include "caca.h"
31#include "caca_internals.h"
32
33struct caca_frame
34{
35    int w, h;
36    int dx, dy;
37    char *chars;
38    int *color;
39};
40
41struct caca_sprite
42{
43    int nf;
44    struct caca_frame *frames;
45};
46
47struct caca_sprite *caca_load_sprite(const char *file)
48{
49    char buf[BUFSIZ];
50    struct caca_sprite *sprite;
51    FILE *fd;
52
53    fd = fopen(file, "r");
54    if(fd == NULL)
55        return NULL;
56
57    sprite = malloc(sizeof(struct caca_sprite));
58    if(sprite == NULL)
59        goto sprite_alloc_failed;
60
61    sprite->nf = 0;
62    sprite->frames = NULL;
63
64    while(!feof(fd))
65    {
66        int x, y;
67        int w = 0, h = 0, dx = 0, dy = 0;
68        struct caca_frame *frame;
69
70        /* Get width and height */
71        if(!fgets(buf, BUFSIZ, fd))
72            break;
73
74        sscanf(buf, "%i %i %i %i", &w, &h, &dx, &dy);
75        if(w <= 0 || h <= 0 || w > BUFSIZ / 2)
76            break;
77
78        if(sprite->nf)
79        {
80            void *tmp = realloc(sprite->frames,
81                                (sprite->nf + 1) * sizeof(struct caca_frame));
82            if(tmp == NULL)
83                goto frame_failed;
84            sprite->frames = tmp;
85            sprite->nf++;
86        }
87        else
88        {
89            sprite->frames = malloc((sprite->nf + 1) * sizeof(struct caca_frame));
90            if(sprite->frames == NULL)
91                goto sprite_failed;
92            sprite->nf++;
93        }
94
95        frame = &sprite->frames[sprite->nf - 1];
96
97        frame->w = w;
98        frame->h = h;
99        frame->dx = dx;
100        frame->dy = dy;
101        frame->chars = malloc(w * h * sizeof(char));
102        if(frame->chars == NULL)
103        {
104            sprite->nf--;
105            goto frame_failed;
106        }
107        frame->color = malloc(w * h * sizeof(int));
108        if(frame->color == NULL)
109        {
110            free(frame->chars);
111            sprite->nf--;
112            goto frame_failed;
113        }
114
115        for(y = 0; y < h; y++)
116        {
117            if(!fgets(buf, BUFSIZ, fd))
118                goto frame_failed;
119
120            for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
121                frame->chars[w * y + x] = buf[x];
122
123            for(; x < w; x++)
124                frame->chars[w * y + x] = ' ';
125        }
126
127        for(y = 0; y < h; y++)
128        {
129            if(!fgets(buf, BUFSIZ, fd))
130                goto frame_failed;
131
132            for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
133                frame->color[w * y + x] = buf[x] - 'a';
134
135            for(; x < w; x++)
136                frame->color[w * y + x] = ' ' - 'a';
137        }
138
139        continue;
140    }
141
142    if(sprite->nf == 0)
143        goto sprite_failed;
144
145    fclose(fd);
146    return sprite;
147
148frame_failed:
149    while(sprite->nf)
150    {
151        free(sprite->frames[sprite->nf - 1].color);
152        free(sprite->frames[sprite->nf - 1].chars);
153        sprite->nf--;
154    }
155sprite_failed:
156    free(sprite);
157sprite_alloc_failed:
158    fclose(fd);
159    return NULL;
160}
161
162int caca_get_sprite_frames(struct caca_sprite *sprite)
163{
164    if(sprite == NULL)
165        return 0;
166
167    return sprite->nf;
168}
169
170int caca_get_sprite_width(struct caca_sprite *sprite, int f)
171{
172    if(sprite == NULL)
173        return 0;
174
175    if(f < 0 || f >= sprite->nf)
176        return 0;
177
178    return sprite->frames[f].w;
179}
180
181int caca_get_sprite_height(struct caca_sprite *sprite, int f)
182{
183    if(sprite == NULL)
184        return 0;
185
186    if(f < 0 || f >= sprite->nf)
187        return 0;
188
189    return sprite->frames[f].h;
190}
191
192int caca_get_sprite_dx(struct caca_sprite *sprite, int f)
193{
194    if(sprite == NULL)
195        return 0;
196
197    if(f < 0 || f >= sprite->nf)
198        return 0;
199
200    return sprite->frames[f].dx;
201}
202
203int caca_get_sprite_dy(struct caca_sprite *sprite, int f)
204{
205    if(sprite == NULL)
206        return 0;
207
208    if(f < 0 || f >= sprite->nf)
209        return 0;
210
211    return sprite->frames[f].dy;
212}
213
214void caca_draw_sprite(int x, int y, struct caca_sprite *sprite, int f)
215{
216    int i, j, oldcol;
217    struct caca_frame *frame;
218
219    if(sprite == NULL)
220        return;
221
222    if(f < 0 || f >= sprite->nf)
223        return;
224
225    frame = &sprite->frames[f];
226
227    oldcol = caca_get_color();
228
229    for(j = 0; j < frame->h; j++)
230    {
231        for(i = 0; i < frame->w; i++)
232        {
233            int col = frame->color[frame->w * j + i];
234            if(col >= 0)
235            {
236                caca_set_color(col);
237                caca_putchar(x + i - frame->dx, y + j - frame->dy,
238                           frame->chars[frame->w * j + i]);
239            }
240        }
241    }
242
243    caca_set_color(oldcol);
244}
245
246void caca_free_sprite(struct caca_sprite *sprite)
247{
248    int i;
249
250    if(sprite == NULL)
251        return;
252
253    for(i = sprite->nf; i--;)
254    {
255        struct caca_frame *frame = &sprite->frames[i];
256        free(frame->chars);
257        free(frame->color);
258    }
259
260    free(sprite->frames);
261    free(sprite);
262}
263
Note: See TracBrowser for help on using the repository browser.