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

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