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

Last change on this file since 1148 was 920, checked in by Sam Hocevar, 15 years ago
  • Completed return value and errno handling in libcucul API.
  • Property svn:keywords set to Id
File size: 5.5 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 920 2006-04-27 14:15:23Z 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 canvas frame management.
16 */
17
18#include "config.h"
19#include "common.h"
20
21#if !defined(__KERNEL__)
22#   include <stdio.h>
23#   include <stdlib.h>
24#   include <string.h>
25#   if defined(HAVE_ERRNO_H)
26#       include <errno.h>
27#   endif
28#endif
29
30#include "cucul.h"
31#include "cucul_internals.h"
32
33/** \brief Get the number of frames in a canvas.
34 *
35 *  This function returns the current canvas frame count.
36 *
37 *  This function never fails.
38 *
39 *  \param cv A libcucul canvas
40 *  \return The frame count
41 */
42unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *cv)
43{
44    return cv->framecount;
45}
46
47/** \brief Activate a given canvas frame.
48 *
49 *  This function sets the active canvas frame. All subsequent drawing
50 *  operations will be performed on that frame. The current painting
51 *  context set by cucul_set_color() or cucul_set_truecolor() is inherited.
52 *
53 *  If the frame index is outside the canvas' frame range, nothing happens.
54 *
55 *  If an error occurs, -1 is returned and \b errno is set accordingly:
56 *  - \c EINVAL Requested frame is out of range.
57 *
58 *  \param cv A libcucul canvas
59 *  \param frame The canvas frame to activate
60 *  \return 0 in case of success, -1 if an error occurred.
61 */
62int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
63{
64    if(frame >= cv->framecount)
65    {
66#if defined(HAVE_ERRNO_H)
67        errno = EINVAL;
68#endif
69        return -1;
70    }
71
72    cv->frame = frame;
73
74    cv->chars = cv->allchars[cv->frame];
75    cv->attr = cv->allattr[cv->frame];
76
77    return 0;
78}
79
80/** \brief Add a frame to a canvas.
81 *
82 *  This function creates a new frame within the given canvas. Its contents
83 *  are copied from the currently active frame.
84 *
85 *  The frame index indicates where the frame should be inserted. Valid
86 *  values range from 0 to the current canvas frame count. If the frame
87 *  index is greater the or equals the current canvas frame count, the new
88 *  frame is appended at the end of the canvas.
89 *
90 *  The active frame does not change, but its index may be renumbered due
91 *  to the insertion.
92 *
93 *  If an error occurs, -1 is returned and \b errno is set accordingly:
94 *  - \c ENOMEM Not enough memory to allocate new frame.
95 *
96 *  \param cv A libcucul canvas
97 *  \param frame The index where to insert the new frame
98 *  \return 0 in case of success, -1 if an error occurred.
99 */
100int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
101{
102    unsigned int size = cv->width * cv->height * sizeof(uint32_t);
103    unsigned int f;
104
105    if(frame > cv->framecount)
106        frame = cv->framecount;
107
108    cv->framecount++;
109    cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount);
110    cv->allattr = realloc(cv->allattr, sizeof(uint32_t *) * cv->framecount);
111
112    for(f = cv->framecount - 1; f > frame; f--)
113    {
114        cv->allchars[f] = cv->allchars[f - 1];
115        cv->allattr[f] = cv->allattr[f - 1];
116    }
117
118    cv->allchars[frame] = malloc(size);
119    memcpy(cv->allchars[frame], cv->chars, size);
120    cv->allattr[frame] = malloc(size);
121    memcpy(cv->allattr[frame], cv->attr, size);
122
123    if(cv->frame >= frame)
124        cv->frame++;
125
126    cv->chars = cv->allchars[cv->frame];
127    cv->attr = cv->allattr[cv->frame];
128
129    return 0;
130}
131
132/** \brief Remove a frame from a canvas.
133 *
134 *  This function deletes a frame from a given canvas.
135 *
136 *  It is not legal to remove the last frame from a canvas. Such a request
137 *  will be ignored by cucul_free_canvas_frame().
138 *
139 *  The frame index indicates the frame to delete. Valid values range from
140 *  0 to the current canvas frame count minus 1. If the frame index is
141 *  greater the or equals the current canvas frame count, the last frame
142 *  is deleted.
143 *
144 *  If the active frame is deleted, frame 0 becomes the new active frame.
145 *  Otherwise, the active frame does not change, but its index may be
146 *  renumbered due to the deletion.
147 *
148 *  If an error occurs, -1 is returned and \b errno is set accordingly:
149 *  - \c EINVAL Requested frame is out of range, or attempt to delete the
150 *    last frame of the canvas.
151 *
152 *  \param cv A libcucul canvas
153 *  \param frame The index of the frame to delete
154 *  \return 0 in case of success, -1 if an error occurred.
155 */
156int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame)
157{
158    unsigned int f;
159
160    if(frame >= cv->framecount)
161    {
162#if defined(HAVE_ERRNO_H)
163        errno = EINVAL;
164#endif
165        return -1;
166    }
167
168    if(cv->framecount == 1)
169    {
170#if defined(HAVE_ERRNO_H)
171        errno = EINVAL;
172#endif
173        return -1;
174    }
175
176    free(cv->allchars[frame]);
177    free(cv->allattr[frame]);
178
179    for(f = frame + 1; f < cv->framecount; f++)
180    {
181        cv->allchars[f - 1] = cv->allchars[f];
182        cv->allattr[f - 1] = cv->allattr[f];
183    }
184
185    cv->framecount--;
186    cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount);
187    cv->allattr = realloc(cv->allattr, sizeof(uint32_t *) * cv->framecount);
188
189    if(cv->frame > frame)
190        cv->frame--;
191    else if(cv->frame == frame)
192        cv->frame = 0;
193
194    cv->chars = cv->allchars[cv->frame];
195    cv->attr = cv->allattr[cv->frame];
196
197    return 0;
198}
199
Note: See TracBrowser for help on using the repository browser.