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

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