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

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

Change the dirty rectangle API so that it can handle several rectangles. The
inner implementation still only handles one dirty rectangle, but this way
we can prepare supporting applictions for the future.

  • Property svn:keywords set to Id
File size: 7.5 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 3470 2009-05-19 00:51:47Z 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    /* Invalidate the dirty rectangle */
158    caca_clear_dirty_rectangle_list(dp->cv);
159
160    /* Once the display is finished, we can ack resizes */
161    if(dp->resize.resized)
162    {
163        dp->resize.resized = 0;
164        _caca_handle_resize(dp);
165    }
166
167    /* Wait until dp->delay + time of last call */
168    ticks += _caca_getticks(&dp->timer);
169    for(ticks += _caca_getticks(&dp->timer);
170        ticks + IDLE_USEC < (int)dp->delay;
171        ticks += _caca_getticks(&dp->timer))
172    {
173        _caca_sleep(IDLE_USEC);
174    }
175
176    /* Update the sliding mean of the render time */
177    dp->rendertime = (7 * dp->rendertime + ticks) / 8;
178
179    dp->lastticks = ticks - dp->delay;
180
181    /* If we drifted too much, it's bad, bad, bad. */
182    if(dp->lastticks > (int)dp->delay)
183        dp->lastticks = 0;
184
185    return 0;
186}
187
188/** \brief Show or hide the cursor.
189 *
190 *  Show or hide the cursor, for devices that support such a feature.
191 *
192 *  If an error occurs, -1 is returned and \b errno is set accordingly:
193 *  - \c ENOSYS Display driver does not support showing the cursor.
194 *
195 *  \param dp The libcaca display context.
196 *  \param flag 0 hides the cursor, 1 shows the system's default cursor
197 *              (usually a white rectangle). Other values are reserved for
198 *              future use.
199 *  \return 0 upon success, -1 if an error occurred.
200 */
201int caca_set_cursor(caca_display_t *dp, int flag)
202{
203    if(!dp->drv.set_cursor)
204    {
205        seterrno(ENOSYS);
206        return -1;
207    }
208
209    dp->drv.set_cursor(dp, flag);
210    return 0;
211}
212
213/** \brief Show or hide the mouse pointer.
214 *
215 *  Show or hide the mouse pointer. This function works with the ncurses,
216 *  S-Lang and X11 drivers.
217 *
218 *  If an error occurs, -1 is returned and \b errno is set accordingly:
219 *  - \c ENOSYS Display driver does not support hiding the mouse pointer.
220 *
221 *  \param dp The libcaca display context.
222 *  \param flag 0 hides the pointer, 1 shows the system's default pointer
223 *              (usually an arrow). Other values are reserved for future use.
224 *  \return 0 upon success, -1 if an error occurred.
225 */
226int caca_set_mouse(caca_display_t *dp, int flag)
227{
228    if(!dp->drv.set_mouse)
229    {
230        seterrno(ENOSYS);
231        return -1;
232    }
233
234    dp->drv.set_mouse(dp, flag);
235    return 0;
236}
237
238/*
239 * XXX: following functions are local
240 */
241
242void _caca_handle_resize(caca_display_t *dp)
243{
244    dp->drv.handle_resize(dp);
245
246    /* Tell libcaca we changed size */
247    if(dp->resize.w != caca_get_canvas_width(dp->cv)
248        || dp->resize.h != caca_get_canvas_height(dp->cv))
249    {
250        dp->resize.allow = 1;
251        caca_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h);
252        dp->resize.allow = 0;
253    }
254}
255
256void _caca_set_term_title(char const *str)
257{
258#if defined(HAVE_GETENV)
259    char *term;
260
261    term = getenv("TERM");
262
263    if(!term || !strcmp(term, "linux"))
264        return;
265#endif
266
267    fprintf(stdout, "\033]0;%s\007", str);
268    fflush(stdout);
269}
270
Note: See TracBrowser for help on using the repository browser.