source: libcaca/trunk/cucul/canvas.c @ 713

Last change on this file since 713 was 713, checked in by Sam Hocevar, 16 years ago
  • Got rid of the useless cucul_get_fg_color/cucul_get_bg_color functions.
  • Property svn:keywords set to Id
File size: 7.6 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 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the Do What The Fuck You Want To
8 *  Public License, Version 2, as published by Sam Hocevar. See
9 *  http://sam.zoy.org/wtfpl/COPYING for more details.
10 */
11
12/** \file canvas.c
13 *  \version \$Id: canvas.c 713 2006-04-01 15:25:33Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
15 *  \brief Canvas drawing
16 *
17 *  This file contains various canvas handling functions such as character
18 *  and string drawing.
19 */
20
21#include "config.h"
22
23#if !defined(__KERNEL__)
24#   include <stdio.h> /* BUFSIZ */
25#   include <string.h>
26#   include <stdlib.h>
27#   include <stdarg.h>
28#   if defined(HAVE_UNISTD_H)
29#       include <unistd.h>
30#   endif
31#   if defined(HAVE_SIGNAL_H)
32#       include <signal.h>
33#   endif
34#   if defined(HAVE_SYS_IOCTL_H)
35#       include <sys/ioctl.h>
36#   endif
37#endif
38
39#include "cucul.h"
40#include "cucul_internals.h"
41
42/** \brief Set the default colour pair.
43 *
44 *  This function sets the default colour pair. String functions such as
45 *  caca_printf() and graphical primitive functions such as caca_draw_line()
46 *  will use these colour pairs.
47 *
48 *  \param fgcolor The requested foreground colour.
49 *  \param bgcolor The requested background colour.
50 */
51void cucul_set_color(cucul_t *qq, enum cucul_color fgcolor,
52                                  enum cucul_color bgcolor)
53{
54    if(fgcolor < 0 || fgcolor > 15 || bgcolor < 0 || bgcolor > 15)
55        return;
56
57    qq->fgcolor = fgcolor;
58    qq->bgcolor = bgcolor;
59}
60
61/** \brief Print an ASCII character.
62 *
63 *  This function prints an ASCII character at the given coordinates, using
64 *  the default foreground and background values. If the coordinates are
65 *  outside the screen boundaries, nothing is printed. If the character
66 *  value is a non-printable character or is outside the ASCII range, it is
67 *  replaced with a space. To print a sequence of bytes forming an UTF-8
68 *  character, use cucul_putstr() instead.
69 *
70 *  \param x X coordinate.
71 *  \param y Y coordinate.
72 *  \param c The character to print.
73 */
74void cucul_putchar(cucul_t *qq, int x, int y, char c)
75{
76    if(x < 0 || x >= (int)qq->width ||
77       y < 0 || y >= (int)qq->height)
78        return;
79
80    if((unsigned char)c < 0x20 || (unsigned char)c > 0x7f)
81        c = 0x20;
82
83    qq->chars[x + y * qq->width] = c;
84    qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
85}
86
87/** \brief Print a string.
88 *
89 *  This function prints an UTF-8 string at the given coordinates, using the
90 *  default foreground and background values. The coordinates may be outside
91 *  the screen boundaries (eg. a negative Y coordinate) and the string will
92 *  be cropped accordingly if it is too long.
93 *
94 *  \param x X coordinate.
95 *  \param y Y coordinate.
96 *  \param s The string to print.
97 */
98void cucul_putstr(cucul_t *qq, int x, int y, char const *s)
99{
100    uint32_t *chars;
101    uint8_t *attr;
102    unsigned int len;
103
104    if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
105        return;
106
107    len = _cucul_strlen_utf8(s);
108
109    if(x < 0)
110    {
111        if(len < (unsigned int)-x)
112            return;
113        len -= -x;
114        s = _cucul_skip_utf8(s, -x);
115        x = 0;
116    }
117
118    chars = qq->chars + x + y * qq->width;
119    attr = qq->attr + x + y * qq->width;
120
121    if(x + len >= qq->width)
122        len = qq->width - x;
123
124    while(len)
125    {
126        *chars++ = _cucul_utf8_to_utf32(s);
127        *attr++ = (qq->bgcolor << 4) | qq->fgcolor;
128
129        s = _cucul_skip_utf8(s, 1);
130        len--;
131    }
132}
133
134/** \brief Format a string.
135 *
136 *  This function formats a string at the given coordinates, using the
137 *  default foreground and background values. The coordinates may be outside
138 *  the screen boundaries (eg. a negative Y coordinate) and the string will
139 *  be cropped accordingly if it is too long. The syntax of the format
140 *  string is the same as for the C printf() function.
141 *
142 *  \param x X coordinate.
143 *  \param y Y coordinate.
144 *  \param format The format string to print.
145 *  \param ... Arguments to the format string.
146 */
147void cucul_printf(cucul_t *qq, int x, int y, char const *format, ...)
148{
149    char tmp[BUFSIZ];
150    char *buf = tmp;
151    va_list args;
152
153    if(y < 0 || y >= (int)qq->height || x >= (int)qq->width)
154        return;
155
156    if(qq->width - x + 1 > BUFSIZ)
157        buf = malloc(qq->width - x + 1);
158
159    va_start(args, format);
160#if defined(HAVE_VSNPRINTF)
161    vsnprintf(buf, qq->width - x + 1, format, args);
162#else
163    vsprintf(buf, format, args);
164#endif
165    buf[qq->width - x] = '\0';
166    va_end(args);
167
168    cucul_putstr(qq, x, y, buf);
169
170    if(buf != tmp)
171        free(buf);
172}
173
174/** \brief Get the screen.
175 *
176 *  This function fills a byte array with the character values.
177 */
178void cucul_get_screen(cucul_t const *qq, char *buffer)
179{
180    unsigned int x, y;
181
182    for(y = 0; y < qq->height; y++)
183    {
184        for(x = 0; x < qq->width; x++)
185        {
186            *buffer++ = qq->attr[x + y * qq->width];
187            *buffer++ = qq->chars[x + y * qq->width] & 0x7f; /* FIXME: ASCII */
188        }
189    }
190}
191
192/** \brief Clear the screen.
193 *
194 *  This function clears the screen using a black background.
195 */
196void cucul_clear(cucul_t *qq)
197{
198    enum cucul_color oldfg = cucul_get_fg_color(qq);
199    enum cucul_color oldbg = cucul_get_bg_color(qq);
200    int y = qq->height;
201
202    cucul_set_color(qq, CUCUL_COLOR_LIGHTGRAY, CUCUL_COLOR_BLACK);
203
204    /* We could use SLsmg_cls() etc., but drawing empty lines is much faster */
205    while(y--)
206        cucul_putstr(qq, 0, y, qq->empty_line);
207
208    cucul_set_color(qq, oldfg, oldbg);
209}
210
211/** \brief Blit a canvas onto another one.
212 *
213 *  This function blits a canvas onto another one at the given coordinates.
214 *  An optional mask canvas can be used.
215 *
216 *  \param dst The destination canvas.
217 *  \param x X coordinate.
218 *  \param y Y coordinate.
219 *  \param src The source canvas.
220 *  \param mask The mask canvas.
221 */
222void cucul_blit(cucul_t *dst, int x, int y,
223                cucul_t const *src, cucul_t const *mask)
224{
225    int i, j, starti, startj, endi, endj;
226
227    if(mask && (src->width != mask->width || src->height != mask->height))
228        return;
229
230    starti = x < 0 ? -x : 0;
231    startj = y < 0 ? -y : 0;
232    endi = (x + src->width >= dst->width) ? dst->width - x : src->width;
233    endj = (y + src->height >= dst->height) ? dst->height - y : src->height;
234
235    if(starti >= endi || startj >= endj)
236        return;
237
238    for(j = startj; j < endj; j++)
239    {
240        if(mask)
241        {
242            for(i = starti; i < endi; i++)
243            {
244                if(mask->chars[j * src->width + i] == (uint32_t)' ')
245                    continue;
246
247                dst->chars[(j + y) * dst->width + (i + x)]
248                                             = src->chars[j * src->width + i];
249                dst->attr[(j + y) * dst->width + (i + x)]
250                                             = src->attr[j * src->width + i];
251            }
252        }
253        else
254        {
255            memcpy(dst->chars + (j + y) * dst->width + starti + x,
256                   src->chars + j * src->width + starti,
257                   (endi - starti) * 4);
258            memcpy(dst->attr + (j + y) * dst->width + starti + x,
259                   src->attr + j * src->width + starti,
260                   (endi - starti) * 1);
261        }
262    }
263}
264
265/*
266 * XXX: The following functions are not exported
267 */
268
269void _cucul_putchar32(cucul_t *qq, int x, int y, uint32_t c)
270{
271    if(x < 0 || x >= (int)qq->width ||
272       y < 0 || y >= (int)qq->height)
273        return;
274
275    qq->chars[x + y * qq->width] = c;
276    qq->attr[x + y * qq->width] = (qq->bgcolor << 4) | qq->fgcolor;
277}
278
Note: See TracBrowser for help on using the repository browser.