source: libcaca/trunk/caca/graphics.c @ 2821

Last change on this file since 2821 was 2821, checked in by Sam Hocevar, 11 years ago

Starting refactoring to get rid of libcucul. The initial reason for the
split is rendered moot by the plugin system: when enabled, binaries do
not link directly with libX11 or libGL. I hope this is a step towards
more consisteny and clarity.

  • Property svn:keywords set to Id
File size: 7.4 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: graphics.c 2821 2008-09-27 13:12:46Z 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 character and string drawing functions.
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 "caca.h"
28#include "caca_internals.h"
29
30/** \brief Set the display title.
31 *
32 *  If libcaca runs in a window, try to change its title. This works with
33 *  the ncurses, S-Lang, OpenGL, X11 and Win32 drivers.
34 *
35 *  If an error occurs, -1 is returned and \b errno is set accordingly:
36 *  - \c ENOSYS Display driver does not support setting the window title.
37 *
38 *  \param dp The libcaca display context.
39 *  \param title The desired display title.
40 *  \return 0 upon success, -1 if an error occurred.
41 */
42int caca_set_display_title(caca_display_t *dp, char const *title)
43{
44    int ret = dp->drv.set_display_title(dp, title);
45
46    if(ret)
47        seterrno(ENOSYS);
48
49    return ret;
50}
51
52/** \brief Get the display width.
53 *
54 *  If libcaca runs in a window, get the usable window width. This value can
55 *  be used for aspect ratio calculation. If libcaca does not run in a window
56 *  or if there is no way to know the font size, most drivers will assume a
57 *  6x10 font is being used. Note that the units are not necessarily pixels.
58 *
59 *  This function never fails.
60 *
61 *  \param dp The libcaca display context.
62 *  \return The display width.
63 */
64int caca_get_display_width(caca_display_t const *dp)
65{
66    return dp->drv.get_display_width(dp);
67}
68
69/** \brief Get the display height.
70 *
71 *  If libcaca runs in a window, get the usable window height. This value can
72 *  be used for aspect ratio calculation. If libcaca does not run in a window
73 *  or if there is no way to know the font size, assume a 6x10 font is being
74 *  used. Note that the units are not necessarily pixels.
75 *
76 *  This function never fails.
77 *
78 *  \param dp The libcaca display context.
79 *  \return The display height.
80 */
81int caca_get_display_height(caca_display_t const *dp)
82{
83    return dp->drv.get_display_height(dp);
84}
85
86/** \brief Set the refresh delay.
87 *
88 *  Set the refresh delay in microseconds. The refresh delay is used by
89 *  caca_refresh_display() to achieve constant framerate. See the
90 *  caca_refresh_display() documentation for more details.
91 *
92 *  If the argument is zero, constant framerate is disabled. This is the
93 *  default behaviour.
94 *
95 *  If an error occurs, -1 is returned and \b errno is set accordingly:
96 *  - \c EINVAL Refresh delay value is invalid.
97 *
98 *  \param dp The libcaca display context.
99 *  \param usec The refresh delay in microseconds.
100 *  \return 0 upon success, -1 if an error occurred.
101 */
102int caca_set_display_time(caca_display_t *dp, int usec)
103{
104    if(usec < 0)
105    {
106        seterrno(EINVAL);
107        return -1;
108    }
109
110    dp->delay = usec;
111    return 0;
112}
113
114/** \brief Get the display's average rendering time.
115 *
116 *  Get the average rendering time, which is the average measured time
117 *  between two caca_refresh_display() calls, in microseconds. If constant
118 *  framerate was activated by calling caca_set_display_time(), the average
119 *  rendering time will be close to the requested delay even if the real
120 *  rendering time was shorter.
121 *
122 *  This function never fails.
123 *
124 *  \param dp The libcaca display context.
125 *  \return The render time in microseconds.
126 */
127int caca_get_display_time(caca_display_t const *dp)
128{
129    return dp->rendertime;
130}
131
132/** \brief Flush pending changes and redraw the screen.
133 *
134 *  Flush all graphical operations and print them to the display device.
135 *  Nothing will show on the screen until this function is called.
136 *
137 *  If caca_set_display_time() was called with a non-zero value,
138 *  caca_refresh_display() will use that value to achieve constant
139 *  framerate: if two consecutive calls to caca_refresh_display() are within
140 *  a time range shorter than the value set with caca_set_display_time(),
141 *  the second call will be delayed before performing the screen refresh.
142 *
143 *  This function never fails.
144 *
145 *  \param dp The libcaca display context.
146 *  \return This function always returns 0.
147 */
148int caca_refresh_display(caca_display_t *dp)
149{
150#if !defined(_DOXYGEN_SKIP_ME)
151#define IDLE_USEC 5000
152#endif
153    int ticks = dp->lastticks + _caca_getticks(&dp->timer);
154
155    dp->drv.display(dp);
156
157    /* Once the display is finished, we can ack resizes */
158    if(dp->resize.resized)
159    {
160        dp->resize.resized = 0;
161        _caca_handle_resize(dp);
162    }
163
164    /* Wait until dp->delay + time of last call */
165    ticks += _caca_getticks(&dp->timer);
166    for(ticks += _caca_getticks(&dp->timer);
167        ticks + IDLE_USEC < (int)dp->delay;
168        ticks += _caca_getticks(&dp->timer))
169    {
170        _caca_sleep(IDLE_USEC);
171    }
172
173    /* Update the sliding mean of the render time */
174    dp->rendertime = (7 * dp->rendertime + ticks) / 8;
175
176    dp->lastticks = ticks - dp->delay;
177
178    /* If we drifted too much, it's bad, bad, bad. */
179    if(dp->lastticks > (int)dp->delay)
180        dp->lastticks = 0;
181
182    return 0;
183}
184
185/** \brief Show or hide the cursor.
186 *
187 *  Show or hide the cursor, for devices that support such a feature.
188 *
189 *  If an error occurs, -1 is returned and \b errno is set accordingly:
190 *  - \c ENOSYS Display driver does not support showing the cursor.
191 *
192 *  \param dp The libcaca display context.
193 *  \param flag 0 hides the cursor, 1 shows the system's default cursor
194 *              (usually a white rectangle). Other values are reserved for
195 *              future use.
196 *  \return 0 upon success, -1 if an error occurred.
197 */
198int caca_set_cursor(caca_display_t *dp, int flag)
199{
200    if(!dp->drv.set_cursor)
201    {
202        seterrno(ENOSYS);
203        return -1;
204    }
205
206    dp->drv.set_cursor(dp, flag);
207    return 0;
208}
209
210/** \brief Show or hide the mouse pointer.
211 *
212 *  Show or hide the mouse pointer. This function works with the ncurses,
213 *  S-Lang and X11 drivers.
214 *
215 *  If an error occurs, -1 is returned and \b errno is set accordingly:
216 *  - \c ENOSYS Display driver does not support hiding the mouse pointer.
217 *
218 *  \param dp The libcaca display context.
219 *  \param flag 0 hides the pointer, 1 shows the system's default pointer
220 *              (usually an arrow). Other values are reserved for future use.
221 *  \return 0 upon success, -1 if an error occurred.
222 */
223int caca_set_mouse(caca_display_t *dp, int flag)
224{
225    if(!dp->drv.set_mouse)
226    {
227        seterrno(ENOSYS);
228        return -1;
229    }
230
231    dp->drv.set_mouse(dp, flag);
232    return 0;
233}
234
235/*
236 * XXX: following functions are local
237 */
238
239void _caca_handle_resize(caca_display_t *dp)
240{
241    dp->drv.handle_resize(dp);
242
243    /* Tell libcaca we changed size */
244    if(dp->resize.w != caca_get_canvas_width(dp->cv)
245        || dp->resize.h != caca_get_canvas_height(dp->cv))
246    {
247        dp->resize.allow = 1;
248        caca_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h);
249        dp->resize.allow = 0;
250    }
251}
252
253void _caca_set_term_title(char const *str)
254{
255#if defined(HAVE_GETENV)
256    char *term;
257
258    term = getenv("TERM");
259
260    if(!term || !strcmp(term, "linux"))
261        return;
262#endif
263
264    fprintf(stdout, "\x1b]0;%s\x07", str);
265    fflush(stdout);
266}
267
Note: See TracBrowser for help on using the repository browser.