source: libcaca/trunk/cucul/sprite.c @ 540

Last change on this file since 540 was 540, checked in by Sam Hocevar, 15 years ago
  • Polished the driver split a bit (still no events, except resize events), properly credited authors and documented a few things.
  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/*
2 *  libcucul      Unicode canvas library
3 *  Copyright (c) 2002-2006 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 Do What The Fuck You Want To
8 *  Public License, Version 2, as published by Sam Hocevar. See
9 *  http://sam.zoy.org/wtfpl/COPYING for more details.
10 */
11
12/** \file sprite.c
13 *  \version \$Id: sprite.c 540 2006-03-07 09:17:35Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
15 *  \brief Sprite loading and blitting
16 *
17 *  This file contains a small framework for sprite loading and blitting.
18 */
19
20#include "config.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include "cucul.h"
27#include "cucul_internals.h"
28
29#if !defined(_DOXYGEN_SKIP_ME)
30struct cucul_frame
31{
32    int w, h;
33    int dx, dy;
34    char *chars;
35    int *color;
36};
37
38struct cucul_sprite
39{
40    int nf;
41    struct cucul_frame *frames;
42};
43#endif
44
45/**
46 * \brief Allocate a sprite loaded from a file.
47 *
48 * \param file The filename.
49 * \return The sprite, or NULL if an error occured.
50 */
51struct cucul_sprite *cucul_load_sprite(cucul_t *qq, char const *file)
52{
53    char buf[BUFSIZ];
54    struct cucul_sprite *sprite;
55    FILE *fd;
56
57    fd = fopen(file, "r");
58    if(fd == NULL)
59        return NULL;
60
61    sprite = malloc(sizeof(struct cucul_sprite));
62    if(sprite == NULL)
63        goto sprite_alloc_failed;
64
65    sprite->nf = 0;
66    sprite->frames = NULL;
67
68    while(!feof(fd))
69    {
70        int x, y;
71        int w = 0, h = 0, dx = 0, dy = 0;
72        struct cucul_frame *frame;
73
74        /* Get width and height */
75        if(!fgets(buf, BUFSIZ, fd))
76            break;
77
78        sscanf(buf, "%i %i %i %i", &w, &h, &dx, &dy);
79        if(w <= 0 || h <= 0 || w > BUFSIZ / 2)
80            break;
81
82        if(sprite->nf)
83        {
84            void *tmp = realloc(sprite->frames,
85                                (sprite->nf + 1) * sizeof(struct cucul_frame));
86            if(tmp == NULL)
87                goto frame_failed;
88            sprite->frames = tmp;
89            sprite->nf++;
90        }
91        else
92        {
93            sprite->frames = malloc((sprite->nf + 1) * sizeof(struct cucul_frame));
94            if(sprite->frames == NULL)
95                goto sprite_failed;
96            sprite->nf++;
97        }
98
99        frame = &sprite->frames[sprite->nf - 1];
100
101        frame->w = w;
102        frame->h = h;
103        frame->dx = dx;
104        frame->dy = dy;
105        frame->chars = malloc(w * h * sizeof(char));
106        if(frame->chars == NULL)
107        {
108            sprite->nf--;
109            goto frame_failed;
110        }
111        frame->color = malloc(w * h * sizeof(int));
112        if(frame->color == NULL)
113        {
114            free(frame->chars);
115            sprite->nf--;
116            goto frame_failed;
117        }
118
119        for(y = 0; y < h; y++)
120        {
121            if(!fgets(buf, BUFSIZ, fd))
122                goto frame_failed;
123
124            for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
125                frame->chars[w * y + x] = buf[x];
126
127            for(; x < w; x++)
128                frame->chars[w * y + x] = ' ';
129        }
130
131        for(y = 0; y < h; y++)
132        {
133            if(!fgets(buf, BUFSIZ, fd))
134                goto frame_failed;
135
136            for(x = 0; x < w && buf[x] && buf[x] != '\r' && buf[x] != '\n'; x++)
137                frame->color[w * y + x] = buf[x] - 'a';
138
139            for(; x < w; x++)
140                frame->color[w * y + x] = ' ' - 'a';
141        }
142
143        continue;
144    }
145
146    if(sprite->nf == 0)
147        goto sprite_failed;
148
149    fclose(fd);
150    return sprite;
151
152frame_failed:
153    while(sprite->nf)
154    {
155        free(sprite->frames[sprite->nf - 1].color);
156        free(sprite->frames[sprite->nf - 1].chars);
157        sprite->nf--;
158    }
159sprite_failed:
160    free(sprite);
161sprite_alloc_failed:
162    fclose(fd);
163    return NULL;
164}
165
166/**
167 * \brief Return the number of frames in a sprite.
168 *
169 * \param sprite The sprite.
170 * \return The number of frames.
171 */
172int cucul_get_sprite_frames(cucul_t *qq, struct cucul_sprite const *sprite)
173{
174    if(sprite == NULL)
175        return 0;
176
177    return sprite->nf;
178}
179
180/**
181 * \brief Return the width of a sprite.
182 *
183 * \param sprite The sprite.
184 * \param f The frame index.
185 * \return The width of the given frame of the sprite.
186 */
187int cucul_get_sprite_width(cucul_t *qq, struct cucul_sprite const *sprite, int f)
188{
189    if(sprite == NULL)
190        return 0;
191
192    if(f < 0 || f >= sprite->nf)
193        return 0;
194
195    return sprite->frames[f].w;
196}
197
198/**
199 * \brief Return the height of a sprite.
200 *
201 * \param sprite The sprite.
202 * \param f The frame index.
203 * \return The height of the given frame of the sprite.
204 */
205int cucul_get_sprite_height(cucul_t *qq, struct cucul_sprite const *sprite, int f)
206{
207    if(sprite == NULL)
208        return 0;
209
210    if(f < 0 || f >= sprite->nf)
211        return 0;
212
213    return sprite->frames[f].h;
214}
215
216/**
217 * \brief Return the X coordinate of a sprite's handle.
218 *
219 * \param sprite The sprite.
220 * \param f The frame index.
221 * \return The X coordinate of the given frame's handle.
222 */
223int cucul_get_sprite_dx(cucul_t *qq, struct cucul_sprite const *sprite, int f)
224{
225    if(sprite == NULL)
226        return 0;
227
228    if(f < 0 || f >= sprite->nf)
229        return 0;
230
231    return sprite->frames[f].dx;
232}
233
234/**
235 * \brief Return the Y coordinate of a sprite's handle.
236 *
237 * \param sprite The sprite.
238 * \param f The frame index.
239 * \return The Y coordinate of the given frame's handle.
240 */
241int cucul_get_sprite_dy(cucul_t *qq, struct cucul_sprite const *sprite, int f)
242{
243    if(sprite == NULL)
244        return 0;
245
246    if(f < 0 || f >= sprite->nf)
247        return 0;
248
249    return sprite->frames[f].dy;
250}
251
252/**
253 * \brief Draw a sprite's specific frame at the given coordinates. If the
254 *        frame does not exist, nothing is displayed.
255 *
256 * \param x The X coordinate.
257 * \param y The Y coordinate.
258 * \param sprite The sprite.
259 * \param f The frame index.
260 * \return void
261 */
262void cucul_draw_sprite(cucul_t *qq, int x, int y, struct cucul_sprite const *sprite, int f)
263{
264    int i, j;
265    enum cucul_color oldfg, oldbg;
266    struct cucul_frame *frame;
267
268    if(sprite == NULL)
269        return;
270
271    if(f < 0 || f >= sprite->nf)
272        return;
273
274    frame = &sprite->frames[f];
275
276    oldfg = cucul_get_fg_color(qq);
277    oldbg = cucul_get_bg_color(qq);
278
279    for(j = 0; j < frame->h; j++)
280    {
281        for(i = 0; i < frame->w; i++)
282        {
283            int col = frame->color[frame->w * j + i];
284            if(col >= 0)
285            {
286                cucul_set_color(qq, col, CUCUL_COLOR_BLACK);
287                cucul_putchar(qq, x + i - frame->dx, y + j - frame->dy,
288                              frame->chars[frame->w * j + i]);
289            }
290        }
291    }
292
293    cucul_set_color(qq, oldfg, oldbg);
294}
295
296/**
297 * \brief Free the memory associated with a sprite.
298 *
299 * \param sprite The sprite to be freed.
300 * \return void
301 */
302void cucul_free_sprite(cucul_t *qq, struct cucul_sprite *sprite)
303{
304    int i;
305
306    if(sprite == NULL)
307        return;
308
309    for(i = sprite->nf; i--;)
310    {
311        struct cucul_frame *frame = &sprite->frames[i];
312        free(frame->chars);
313        free(frame->color);
314    }
315
316    free(sprite->frames);
317    free(sprite);
318}
319
Note: See TracBrowser for help on using the repository browser.