~ubuntu-branches/ubuntu/gutsy/libcaca/gutsy

« back to all changes in this revision

Viewing changes to cucul/frame.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hocevar (Debian packages)
  • Date: 2006-12-03 02:05:11 UTC
  • mfrom: (3.1.6 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203020511-h5nzqgf8nov7ns3z
Tags: 0.99.beta11.debian-2
Remove toilet from caca-utils now that it has entered testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 1070 2006-11-14 18:05:02Z 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
#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
 */
 
39
unsigned int cucul_get_frame_count(cucul_canvas_t *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
 */
 
59
int cucul_set_frame(cucul_canvas_t *cv, unsigned int id)
 
60
{
 
61
    if(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
 */
 
85
char const *cucul_get_frame_name(cucul_canvas_t *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
 */
 
103
int 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.
 
128
 *
 
129
 *  The active frame does not change, but its index may be renumbered due
 
130
 *  to the insertion.
 
131
 *
 
132
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 
133
 *  - \c ENOMEM Not enough memory to allocate new frame.
 
134
 *
 
135
 *  \param cv A libcucul canvas
 
136
 *  \param id The index where to insert the new frame
 
137
 *  \return 0 in case of success, -1 if an error occurred.
 
138
 */
 
139
int cucul_create_frame(cucul_canvas_t *cv, unsigned int id)
 
140
{
 
141
    unsigned int size = cv->width * cv->height;
 
142
    unsigned int f;
 
143
 
 
144
    if(id > cv->framecount)
 
145
        id = cv->framecount;
 
146
 
 
147
    cv->framecount++;
 
148
    cv->frames = realloc(cv->frames,
 
149
                         sizeof(struct cucul_frame) * cv->framecount);
 
150
 
 
151
    for(f = cv->framecount - 1; f > id; f--)
 
152
        cv->frames[f] = cv->frames[f - 1];
 
153
 
 
154
    if(cv->frame >= id)
 
155
        cv->frame++;
 
156
 
 
157
    cv->frames[id].width = cv->width;
 
158
    cv->frames[id].height = cv->height;
 
159
    cv->frames[id].chars = malloc(size * sizeof(uint32_t));
 
160
    memcpy(cv->frames[id].chars, cv->chars, size * sizeof(uint32_t));
 
161
    cv->frames[id].attrs = malloc(size * sizeof(uint32_t));
 
162
    memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t));
 
163
    cv->frames[id].curattr = cv->curattr;
 
164
 
 
165
    cv->frames[id].x = cv->frames[cv->frame].x;
 
166
    cv->frames[id].y = cv->frames[cv->frame].y;
 
167
    cv->frames[id].handlex = cv->frames[cv->frame].handlex;
 
168
    cv->frames[id].handley = cv->frames[cv->frame].handley;
 
169
 
 
170
    cv->frames[id].name = strdup("frame#--------");
 
171
    sprintf(cv->frames[id].name + 6, "%.08x", cv->autoinc++);
 
172
 
 
173
    return 0;
 
174
}
 
175
 
 
176
/** \brief Remove a frame from a canvas.
 
177
 *
 
178
 *  Delete a frame from a given canvas.
 
179
 *
 
180
 *  The frame index indicates the frame to delete. Valid values range from
 
181
 *  0 to the current canvas frame count minus 1. If the frame index is
 
182
 *  greater the or equals the current canvas frame count, the last frame
 
183
 *  is deleted.
 
184
 *
 
185
 *  If the active frame is deleted, frame 0 becomes the new active frame.
 
186
 *  Otherwise, the active frame does not change, but its index may be
 
187
 *  renumbered due to the deletion.
 
188
 *
 
189
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 
190
 *  - \c EINVAL Requested frame is out of range, or attempt to delete the
 
191
 *    last frame of the canvas.
 
192
 *
 
193
 *  \param cv A libcucul canvas
 
194
 *  \param id The index of the frame to delete
 
195
 *  \return 0 in case of success, -1 if an error occurred.
 
196
 */
 
197
int cucul_free_frame(cucul_canvas_t *cv, unsigned int id)
 
198
{
 
199
    unsigned int f;
 
200
 
 
201
    if(id >= cv->framecount)
 
202
    {
 
203
        seterrno(EINVAL);
 
204
        return -1;
 
205
    }
 
206
 
 
207
    if(cv->framecount == 1)
 
208
    {
 
209
        seterrno(EINVAL);
 
210
        return -1;
 
211
    }
 
212
 
 
213
    free(cv->frames[id].chars);
 
214
    free(cv->frames[id].attrs);
 
215
    free(cv->frames[id].name);
 
216
 
 
217
    for(f = id + 1; f < cv->framecount; f++)
 
218
        cv->frames[f - 1] = cv->frames[f];
 
219
 
 
220
    cv->framecount--;
 
221
    cv->frames = realloc(cv->frames,
 
222
                         sizeof(struct cucul_frame) * cv->framecount);
 
223
 
 
224
    if(cv->frame > id)
 
225
        cv->frame--;
 
226
    else if(cv->frame == id)
 
227
    {
 
228
        cv->frame = 0;
 
229
        _cucul_load_frame_info(cv);
 
230
    }
 
231
 
 
232
    return 0;
 
233
}
 
234
 
 
235
/*
 
236
 * XXX: the following functions are local.
 
237
 */
 
238
 
 
239
void _cucul_save_frame_info(cucul_canvas_t *cv)
 
240
{
 
241
    cv->frames[cv->frame].width = cv->width;
 
242
    cv->frames[cv->frame].height = cv->height;
 
243
 
 
244
    cv->frames[cv->frame].curattr = cv->curattr;
 
245
}
 
246
 
 
247
void _cucul_load_frame_info(cucul_canvas_t *cv)
 
248
{
 
249
    cv->width = cv->frames[cv->frame].width;
 
250
    cv->height = cv->frames[cv->frame].height;
 
251
 
 
252
    cv->chars = cv->frames[cv->frame].chars;
 
253
    cv->attrs = cv->frames[cv->frame].attrs;
 
254
 
 
255
    cv->curattr = cv->frames[cv->frame].curattr;
 
256
}
 
257