source: libcaca/trunk/cucul/frame.c @ 2305

Last change on this file since 2305 was 2305, checked in by Sam Hocevar, 12 years ago
  • Remove all unsigned ints from exported functions. Signed arithmetic is far better for error checking.
  • Property svn:keywords set to Id
File size: 7.1 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: frame.c 2305 2008-04-19 19:25:52Z sam $
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  This file contains a small framework for canvas frame management.
17 */
18
19#include "config.h"
20
21#if !defined(__KERNEL__)
22#   include <stdio.h>
23#   include <stdlib.h>
24#   include <string.h>
25#endif
26
27#include "cucul.h"
28#include "cucul_internals.h"
29
30/** \brief Get the number of frames in a canvas.
31 *
32 *  Return the current canvas' frame count.
33 *
34 *  This function never fails.
35 *
36 *  \param cv A libcucul canvas
37 *  \return The frame count
38 */
39int cucul_get_frame_count(cucul_canvas_t const *cv)
40{
41    return cv->framecount;
42}
43
44/** \brief Activate a given canvas frame.
45 *
46 *  Set the active canvas frame. All subsequent drawing operations will
47 *  be performed on that frame. The current painting context set by
48 *  cucul_set_attr() is inherited.
49 *
50 *  If the frame index is outside the canvas' frame range, nothing happens.
51 *
52 *  If an error occurs, -1 is returned and \b errno is set accordingly:
53 *  - \c EINVAL Requested frame is out of range.
54 *
55 *  \param cv A libcucul canvas
56 *  \param id The canvas frame to activate
57 *  \return 0 in case of success, -1 if an error occurred.
58 */
59int cucul_set_frame(cucul_canvas_t *cv, int id)
60{
61    if(id < 0 || id >= cv->framecount)
62    {
63        seterrno(EINVAL);
64        return -1;
65    }
66
67    _cucul_save_frame_info(cv);
68    cv->frame = id;
69    _cucul_load_frame_info(cv);
70
71    return 0;
72}
73
74/** \brief Get the current frame's name.
75 *
76 *  Return the current frame's name. The returned string is valid until
77 *  the frame is deleted or cucul_set_frame_name() is called to change
78 *  the frame name again.
79 *
80 *  This function never fails.
81 *
82 *  \param cv A libcucul canvas.
83 *  \return The current frame's name.
84 */
85char const *cucul_get_frame_name(cucul_canvas_t const *cv)
86{
87    return cv->frames[cv->frame].name;
88}
89
90/** \brief Set the current frame's name.
91 *
92 *  Set the current frame's name. Upon creation, a frame has a default name
93 *  of \c "frame#xxxxxxxx" where \c xxxxxxxx is a self-incrementing
94 *  hexadecimal number.
95 *
96 *  If an error occurs, -1 is returned and \b errno is set accordingly:
97 *  - \c ENOMEM Not enough memory to allocate new frame.
98 *
99 *  \param cv A libcucul canvas.
100 *  \param name The name to give to the current frame.
101 *  \return 0 in case of success, -1 if an error occurred.
102 */
103int cucul_set_frame_name(cucul_canvas_t *cv, char const *name)
104{
105    char *newname = strdup(name);
106
107    if(!newname)
108    {
109        seterrno(ENOMEM);
110        return -1;
111    }
112
113    free(cv->frames[cv->frame].name);
114    cv->frames[cv->frame].name = newname;
115
116    return 0;
117}
118
119/** \brief Add a frame to a canvas.
120 *
121 *  Create a new frame within the given canvas. Its contents and attributes
122 *  are copied from the currently active frame.
123 *
124 *  The frame index indicates where the frame should be inserted. Valid
125 *  values range from 0 to the current canvas frame count. If the frame
126 *  index is greater than or equals the current canvas frame count, the new
127 *  frame is appended at the end of the canvas. If the frame index is less
128 *  than zero, the new frame is inserted at index 0.
129 *
130 *  The active frame does not change, but its index may be renumbered due
131 *  to the insertion.
132 *
133 *  If an error occurs, -1 is returned and \b errno is set accordingly:
134 *  - \c ENOMEM Not enough memory to allocate new frame.
135 *
136 *  \param cv A libcucul canvas
137 *  \param id The index where to insert the new frame
138 *  \return 0 in case of success, -1 if an error occurred.
139 */
140int cucul_create_frame(cucul_canvas_t *cv, int id)
141{
142    int size = cv->width * cv->height;
143    int f;
144
145    if(id < 0)
146        id = 0;
147    else if(id > cv->framecount)
148        id = cv->framecount;
149
150    cv->framecount++;
151    cv->frames = realloc(cv->frames,
152                         sizeof(struct cucul_frame) * cv->framecount);
153
154    for(f = cv->framecount - 1; f > id; f--)
155        cv->frames[f] = cv->frames[f - 1];
156
157    if(cv->frame >= id)
158        cv->frame++;
159
160    cv->frames[id].width = cv->width;
161    cv->frames[id].height = cv->height;
162    cv->frames[id].chars = malloc(size * sizeof(uint32_t));
163    memcpy(cv->frames[id].chars, cv->chars, size * sizeof(uint32_t));
164    cv->frames[id].attrs = malloc(size * sizeof(uint32_t));
165    memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t));
166    cv->frames[id].curattr = cv->curattr;
167
168    cv->frames[id].x = cv->frames[cv->frame].x;
169    cv->frames[id].y = cv->frames[cv->frame].y;
170    cv->frames[id].handlex = cv->frames[cv->frame].handlex;
171    cv->frames[id].handley = cv->frames[cv->frame].handley;
172
173    cv->frames[id].name = strdup("frame#--------");
174    sprintf(cv->frames[id].name + 6, "%.08x", ++cv->autoinc);
175
176    return 0;
177}
178
179/** \brief Remove a frame from a canvas.
180 *
181 *  Delete a frame from a given canvas.
182 *
183 *  The frame index indicates the frame to delete. Valid values range from
184 *  0 to the current canvas frame count minus 1. If the frame index is
185 *  greater than or equals the current canvas frame count, the last frame
186 *  is deleted.
187 *
188 *  If the active frame is deleted, frame 0 becomes the new active frame.
189 *  Otherwise, the active frame does not change, but its index may be
190 *  renumbered due to the deletion.
191 *
192 *  If an error occurs, -1 is returned and \b errno is set accordingly:
193 *  - \c EINVAL Requested frame is out of range, or attempt to delete the
194 *    last frame of the canvas.
195 *
196 *  \param cv A libcucul canvas
197 *  \param id The index of the frame to delete
198 *  \return 0 in case of success, -1 if an error occurred.
199 */
200int cucul_free_frame(cucul_canvas_t *cv, int id)
201{
202    int f;
203
204    if(id < 0 || id >= cv->framecount)
205    {
206        seterrno(EINVAL);
207        return -1;
208    }
209
210    if(cv->framecount == 1)
211    {
212        seterrno(EINVAL);
213        return -1;
214    }
215
216    free(cv->frames[id].chars);
217    free(cv->frames[id].attrs);
218    free(cv->frames[id].name);
219
220    for(f = id + 1; f < cv->framecount; f++)
221        cv->frames[f - 1] = cv->frames[f];
222
223    cv->framecount--;
224    cv->frames = realloc(cv->frames,
225                         sizeof(struct cucul_frame) * cv->framecount);
226
227    if(cv->frame > id)
228        cv->frame--;
229    else if(cv->frame == id)
230    {
231        cv->frame = 0;
232        _cucul_load_frame_info(cv);
233    }
234
235    return 0;
236}
237
238/*
239 * XXX: the following functions are local.
240 */
241
242void _cucul_save_frame_info(cucul_canvas_t *cv)
243{
244    cv->frames[cv->frame].width = cv->width;
245    cv->frames[cv->frame].height = cv->height;
246
247    cv->frames[cv->frame].curattr = cv->curattr;
248}
249
250void _cucul_load_frame_info(cucul_canvas_t *cv)
251{
252    cv->width = cv->frames[cv->frame].width;
253    cv->height = cv->frames[cv->frame].height;
254
255    cv->chars = cv->frames[cv->frame].chars;
256    cv->attrs = cv->frames[cv->frame].attrs;
257
258    cv->curattr = cv->frames[cv->frame].curattr;
259}
260
Note: See TracBrowser for help on using the repository browser.