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

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