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

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