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

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

Change the dirty rectangle API once again so that calling applications get
a more natural (x,y,w,h) 4-tuple to handle.

  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
4 *                All Rights Reserved
5 *
6 *  $Id: graphics.c 3494 2009-05-21 20:55:13Z 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_rect_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.