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

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