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

Last change on this file since 1362 was 1362, checked in by Sam Hocevar, 14 years ago
  • Got rid of HAVE_ERRNO_H ifdefs by defining seterrno()/geterrno() functions.
  • More debugging information in the import/export and font functions.
  • Property svn:keywords set to Id
File size: 5.7 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 1362 2006-11-12 15:26:13Z 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
30static void save_frame_info(cucul_canvas_t *);
31static void load_frame_info(cucul_canvas_t *);
32
33/** \brief Get the number of frames in a canvas.
34 *
35 *  Return 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 *  Set the active canvas frame. All subsequent drawing operations will
50 *  be performed on that frame. The current painting context set by
51 *  cucul_set_attr() 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        seterrno(EINVAL);
67        return -1;
68    }
69
70    save_frame_info(cv);
71    cv->frame = frame;
72    load_frame_info(cv);
73
74    return 0;
75}
76
77/** \brief Add a frame to a canvas.
78 *
79 *  Create a new frame within the given canvas. Its contents and attributes
80 *  are copied from the currently active frame.
81 *
82 *  The frame index indicates where the frame should be inserted. Valid
83 *  values range from 0 to the current canvas frame count. If the frame
84 *  index is greater than or equals the current canvas frame count, the new
85 *  frame is appended at the end of the canvas.
86 *
87 *  The active frame does not change, but its index may be renumbered due
88 *  to the insertion.
89 *
90 *  If an error occurs, -1 is returned and \b errno is set accordingly:
91 *  - \c ENOMEM Not enough memory to allocate new frame.
92 *
93 *  \param cv A libcucul canvas
94 *  \param id The index where to insert the new frame
95 *  \return 0 in case of success, -1 if an error occurred.
96 */
97int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int id)
98{
99    unsigned int size = cv->width * cv->height;
100    unsigned int f;
101
102    if(id > cv->framecount)
103        id = cv->framecount;
104
105    cv->framecount++;
106    cv->frames = realloc(cv->frames,
107                         sizeof(struct cucul_frame) * cv->framecount);
108
109    for(f = cv->framecount - 1; f > id; f--)
110        cv->frames[f] = cv->frames[f - 1];
111
112    if(cv->frame >= id)
113        cv->frame++;
114
115    cv->frames[id].width = cv->width;
116    cv->frames[id].height = cv->height;
117    cv->frames[id].chars = malloc(size * sizeof(uint32_t));
118    memcpy(cv->frames[id].chars, cv->chars, size * sizeof(uint32_t));
119    cv->frames[id].attrs = malloc(size * sizeof(uint32_t));
120    memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t));
121    cv->frames[id].curattr = cv->curattr;
122
123    cv->frames[id].x = cv->frames[cv->frame].x;
124    cv->frames[id].y = cv->frames[cv->frame].y;
125    cv->frames[id].handlex = cv->frames[cv->frame].handlex;
126    cv->frames[id].handley = cv->frames[cv->frame].handley;
127
128    return 0;
129}
130
131/** \brief Remove a frame from a canvas.
132 *
133 *  Delete a frame from a given canvas.
134 *
135 *  The frame index indicates the frame to delete. Valid values range from
136 *  0 to the current canvas frame count minus 1. If the frame index is
137 *  greater the or equals the current canvas frame count, the last frame
138 *  is deleted.
139 *
140 *  If the active frame is deleted, frame 0 becomes the new active frame.
141 *  Otherwise, the active frame does not change, but its index may be
142 *  renumbered due to the deletion.
143 *
144 *  If an error occurs, -1 is returned and \b errno is set accordingly:
145 *  - \c EINVAL Requested frame is out of range, or attempt to delete the
146 *    last frame of the canvas.
147 *
148 *  \param cv A libcucul canvas
149 *  \param id The index of the frame to delete
150 *  \return 0 in case of success, -1 if an error occurred.
151 */
152int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int id)
153{
154    unsigned int f;
155
156    if(id >= cv->framecount)
157    {
158        seterrno(EINVAL);
159        return -1;
160    }
161
162    if(cv->framecount == 1)
163    {
164        seterrno(EINVAL);
165        return -1;
166    }
167
168    free(cv->frames[id].chars);
169    free(cv->frames[id].attrs);
170
171    for(f = id + 1; f < cv->framecount; f++)
172        cv->frames[f - 1] = cv->frames[f];
173
174    cv->framecount--;
175    cv->frames = realloc(cv->frames,
176                         sizeof(struct cucul_frame) * cv->framecount);
177
178    if(cv->frame > id)
179        cv->frame--;
180    else if(cv->frame == id)
181    {
182        cv->frame = 0;
183        load_frame_info(cv);
184    }
185
186    return 0;
187}
188
189/*
190 * XXX: the following functions are local.
191 */
192
193static void save_frame_info(cucul_canvas_t *cv)
194{
195    cv->frames[cv->frame].width = cv->width;
196    cv->frames[cv->frame].height = cv->height;
197
198    cv->frames[cv->frame].curattr = cv->curattr;
199}
200
201static void load_frame_info(cucul_canvas_t *cv)
202{
203    cv->width = cv->frames[cv->frame].width;
204    cv->height = cv->frames[cv->frame].height;
205
206    cv->chars = cv->frames[cv->frame].chars;
207    cv->attrs = cv->frames[cv->frame].attrs;
208
209    cv->curattr = cv->frames[cv->frame].curattr;
210}
211
Note: See TracBrowser for help on using the repository browser.