File: graphics.c

package info (click to toggle)
libcaca 0.99.beta18-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 6,936 kB
  • sloc: ansic: 22,177; python: 2,316; cs: 1,213; cpp: 1,107; java: 916; objc: 836; makefile: 636; sh: 381; ruby: 193; asm: 65
file content (287 lines) | stat: -rw-r--r-- 8,000 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
 *  libcaca       Colour ASCII-Art library
 *  Copyright (c) 2002-2010 Sam Hocevar <sam@hocevar.net>
 *                All Rights Reserved
 *
 *  This library is free software. It comes without any warranty, to
 *  the extent permitted by applicable law. You can redistribute it
 *  and/or modify it under the terms of the Do What The Fuck You Want
 *  To Public License, Version 2, as published by Sam Hocevar. See
 *  http://sam.zoy.org/wtfpl/COPYING for more details.
 */

/*
 *  This file contains character and string drawing functions.
 */

#include "config.h"

#if !defined(__KERNEL__)
#   include <stdio.h>
#   include <stdlib.h>
#   include <string.h>
#endif

#include "caca.h"
#include "caca_internals.h"

/** \brief Set the display title.
 *
 *  If libcaca runs in a window, try to change its title. This works with
 *  the ncurses, S-Lang, OpenGL, X11 and Win32 drivers.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c ENOSYS Display driver does not support setting the window title.
 *
 *  \param dp The libcaca display context.
 *  \param title The desired display title.
 *  \return 0 upon success, -1 if an error occurred.
 */
int caca_set_display_title(caca_display_t *dp, char const *title)
{
    int ret = dp->drv.set_display_title(dp, title);

    if(ret)
        seterrno(ENOSYS);

    return ret;
}

/** \brief Get the display width.
 *
 *  If libcaca runs in a window, get the usable window width. This value can
 *  be used for aspect ratio calculation. If libcaca does not run in a window
 *  or if there is no way to know the font size, most drivers will assume a
 *  6x10 font is being used. Note that the units are not necessarily pixels.
 *
 *  This function never fails.
 *
 *  \param dp The libcaca display context.
 *  \return The display width.
 */
int caca_get_display_width(caca_display_t const *dp)
{
    return dp->drv.get_display_width(dp);
}

/** \brief Get the display height.
 *
 *  If libcaca runs in a window, get the usable window height. This value can
 *  be used for aspect ratio calculation. If libcaca does not run in a window
 *  or if there is no way to know the font size, assume a 6x10 font is being
 *  used. Note that the units are not necessarily pixels.
 *
 *  This function never fails.
 *
 *  \param dp The libcaca display context.
 *  \return The display height.
 */
int caca_get_display_height(caca_display_t const *dp)
{
    return dp->drv.get_display_height(dp);
}

/** \brief Set the refresh delay.
 *
 *  Set the refresh delay in microseconds. The refresh delay is used by
 *  caca_refresh_display() to achieve constant framerate. See the
 *  caca_refresh_display() documentation for more details.
 *
 *  If the argument is zero, constant framerate is disabled. This is the
 *  default behaviour.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c EINVAL Refresh delay value is invalid.
 *
 *  \param dp The libcaca display context.
 *  \param usec The refresh delay in microseconds.
 *  \return 0 upon success, -1 if an error occurred.
 */
int caca_set_display_time(caca_display_t *dp, int usec)
{
    if(usec < 0)
    {
        seterrno(EINVAL);
        return -1;
    }

    dp->delay = usec;
    return 0;
}

/** \brief Get the display's average rendering time.
 *
 *  Get the average rendering time, which is the average measured time
 *  between two caca_refresh_display() calls, in microseconds. If constant
 *  framerate was activated by calling caca_set_display_time(), the average
 *  rendering time will be close to the requested delay even if the real
 *  rendering time was shorter.
 *
 *  This function never fails.
 *
 *  \param dp The libcaca display context.
 *  \return The render time in microseconds.
 */
int caca_get_display_time(caca_display_t const *dp)
{
    return dp->rendertime;
}

/** \brief Flush pending changes and redraw the screen.
 *
 *  Flush all graphical operations and print them to the display device.
 *  Nothing will show on the screen until this function is called.
 *
 *  If caca_set_display_time() was called with a non-zero value,
 *  caca_refresh_display() will use that value to achieve constant
 *  framerate: if two consecutive calls to caca_refresh_display() are within
 *  a time range shorter than the value set with caca_set_display_time(),
 *  the second call will be delayed before performing the screen refresh.
 *
 *  This function never fails.
 *
 *  \param dp The libcaca display context.
 *  \return This function always returns 0.
 */
int caca_refresh_display(caca_display_t *dp)
{
#if defined PROF
    caca_timer_t proftimer = { 0, 0 };
#endif
#if !defined(_DOXYGEN_SKIP_ME)
#   define IDLE_USEC 5000
#endif
    int ticks = dp->lastticks + _caca_getticks(&dp->timer);

#if defined PROF
    _caca_getticks(&proftimer);
#endif
    dp->drv.display(dp);
#if defined PROF
    STAT_IADD(&dp->display_stat, _caca_getticks(&proftimer));
#endif

    /* Invalidate the dirty rectangle */
    caca_clear_dirty_rect_list(dp->cv);

    /* Once the display is finished, we can ack resizes */
    if(dp->resize.resized)
    {
        dp->resize.resized = 0;
        _caca_handle_resize(dp);
    }

#if defined PROF
    _caca_getticks(&proftimer);
#endif
    /* Wait until dp->delay + time of last call */
    ticks += _caca_getticks(&dp->timer);
    for(ticks += _caca_getticks(&dp->timer);
        ticks + IDLE_USEC < (int)dp->delay;
        ticks += _caca_getticks(&dp->timer))
    {
        _caca_sleep(IDLE_USEC);
    }
#if defined PROF
    STAT_IADD(&dp->wait_stat, _caca_getticks(&proftimer));
#endif

    /* Update the render time */
    dp->rendertime = ticks;

    dp->lastticks = ticks - dp->delay;

    /* If we drifted too much, it's bad, bad, bad. */
    if(dp->lastticks > (int)dp->delay)
        dp->lastticks = 0;

#if defined PROF
    _caca_dump_stats();
#endif

    return 0;
}

/** \brief Show or hide the cursor.
 *
 *  Show or hide the cursor, for devices that support such a feature.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c ENOSYS Display driver does not support showing the cursor.
 *
 *  \param dp The libcaca display context.
 *  \param flag 0 hides the cursor, 1 shows the system's default cursor
 *              (usually a white rectangle). Other values are reserved for
 *              future use.
 *  \return 0 upon success, -1 if an error occurred.
 */
int caca_set_cursor(caca_display_t *dp, int flag)
{
    if(!dp->drv.set_cursor)
    {
        seterrno(ENOSYS);
        return -1;
    }

    dp->drv.set_cursor(dp, flag);
    return 0;
}

/** \brief Show or hide the mouse pointer.
 *
 *  Show or hide the mouse pointer. This function works with the ncurses,
 *  S-Lang and X11 drivers.
 *
 *  If an error occurs, -1 is returned and \b errno is set accordingly:
 *  - \c ENOSYS Display driver does not support hiding the mouse pointer.
 *
 *  \param dp The libcaca display context.
 *  \param flag 0 hides the pointer, 1 shows the system's default pointer
 *              (usually an arrow). Other values are reserved for future use.
 *  \return 0 upon success, -1 if an error occurred.
 */
int caca_set_mouse(caca_display_t *dp, int flag)
{
    if(!dp->drv.set_mouse)
    {
        seterrno(ENOSYS);
        return -1;
    }

    dp->drv.set_mouse(dp, flag);
    return 0;
}

/*
 * XXX: following functions are local
 */

void _caca_handle_resize(caca_display_t *dp)
{
    dp->drv.handle_resize(dp);

    /* Tell libcaca we changed size */
    if(dp->resize.w != caca_get_canvas_width(dp->cv)
        || dp->resize.h != caca_get_canvas_height(dp->cv))
    {
        dp->resize.allow = 1;
        caca_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h);
        dp->resize.allow = 0;
    }
}

void _caca_set_term_title(char const *str)
{
#if defined(HAVE_GETENV)
    char *term;

    term = getenv("TERM");

    if(!term || !strcmp(term, "linux"))
        return;
#endif

    fprintf(stdout, "\033]0;%s\007", str);
    fflush(stdout);
}