source: libcaca/trunk/caca/box.c @ 3585

Last change on this file since 3585 was 3585, checked in by Sam Hocevar, 10 years ago

Show how we could optimise dirty rectangle handling in a box fill. Disabled
for now because it does not work with fullwidth characters.

  • Property svn:keywords set to Id
File size: 5.9 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: box.c 3585 2009-07-26 23:25:59Z 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 box drawing functions, both filled and outline.
17 */
18
19#include "config.h"
20
21#if !defined(__KERNEL__)
22#   include <stdlib.h>
23#endif
24
25#include "caca.h"
26#include "caca_internals.h"
27
28static int draw_box(caca_canvas_t *cv, int x, int y, int w, int h,
29                    uint32_t const *chars);
30
31/** \brief Draw a box on the canvas using the given character.
32 *
33 *  This function never fails.
34 *
35 *  \param cv The handle to the libcaca canvas.
36 *  \param x X coordinate of the upper-left corner of the box.
37 *  \param y Y coordinate of the upper-left corner of the box.
38 *  \param w Width of the box.
39 *  \param h Height of the box.
40 *  \param ch UTF-32 character to be used to draw the box.
41 *  \return This function always returns 0.
42 */
43int caca_draw_box(caca_canvas_t *cv, int x, int y, int w, int h, uint32_t ch)
44{
45    int x2 = x + w - 1;
46    int y2 = y + h - 1;
47
48    caca_draw_line(cv,  x,  y,  x, y2, ch);
49    caca_draw_line(cv,  x, y2, x2, y2, ch);
50    caca_draw_line(cv, x2, y2, x2,  y, ch);
51    caca_draw_line(cv, x2,  y,  x,  y, ch);
52
53    return 0;
54}
55
56/** \brief Draw a thin box on the canvas.
57 *
58 *  This function never fails.
59 *
60 *  \param cv The handle to the libcaca canvas.
61 *  \param x X coordinate of the upper-left corner of the box.
62 *  \param y Y coordinate of the upper-left corner of the box.
63 *  \param w Width of the box.
64 *  \param h Height of the box.
65 *  \return This function always returns 0.
66 */
67int caca_draw_thin_box(caca_canvas_t *cv, int x, int y, int w, int h)
68{
69    static uint32_t const ascii_chars[] =
70    {
71        '-', '|', ',', '`', '.', '\''
72    };
73
74    return draw_box(cv, x, y, w, h, ascii_chars);
75}
76
77/** \brief Draw a box on the canvas using CP437 characters.
78 *
79 *  This function never fails.
80 *
81 *  \param cv The handle to the libcaca canvas.
82 *  \param x X coordinate of the upper-left corner of the box.
83 *  \param y Y coordinate of the upper-left corner of the box.
84 *  \param w Width of the box.
85 *  \param h Height of the box.
86 *  \return This function always returns 0.
87 */
88int caca_draw_cp437_box(caca_canvas_t *cv, int x, int y, int w, int h)
89{
90    static uint32_t const cp437_chars[] =
91    {
92        /* ─ │ ┌ └ ┐ ┘ */
93        0x2500, 0x2502, 0x250c, 0x2514, 0x2510, 0x2518
94    };
95
96    return draw_box(cv, x, y, w, h, cp437_chars);
97}
98
99/** \brief Fill a box on the canvas using the given character.
100 *
101 *  This function never fails.
102 *
103 *  \param cv The handle to the libcaca canvas.
104 *  \param x X coordinate of the upper-left corner of the box.
105 *  \param y Y coordinate of the upper-left corner of the box.
106 *  \param w Width of the box.
107 *  \param h Height of the box.
108 *  \param ch UTF-32 character to be used to draw the box.
109 *  \return This function always returns 0.
110 */
111int caca_fill_box(caca_canvas_t *cv, int x, int y, int w, int h,
112                   uint32_t ch)
113{
114    int i, j, xmax, ymax;
115
116    int x2 = x + w - 1;
117    int y2 = y + h - 1;
118
119    if(x > x2)
120    {
121        int tmp = x;
122        x = x2; x2 = tmp;
123    }
124
125    if(y > y2)
126    {
127        int tmp = y;
128        y = y2; y2 = tmp;
129    }
130
131    xmax = cv->width - 1;
132    ymax = cv->height - 1;
133
134    if(x2 < 0 || y2 < 0 || x > xmax || y > ymax)
135        return 0;
136
137    if(x < 0) x = 0;
138    if(y < 0) y = 0;
139    if(x2 > xmax) x2 = xmax;
140    if(y2 > ymax) y2 = ymax;
141
142#if 0
143    /* FIXME: this fails with fullwidth character blits. Also, the dirty
144     * rectangle handling may miss fullwidth cells. */
145    /* Optimise dirty rectangle handling, part 1 */
146    cv->dirty_disabled++;
147#endif
148
149    for(j = y; j <= y2; j++)
150        for(i = x; i <= x2; i++)
151            caca_put_char(cv, i, j, ch);
152
153#if 0
154    /* Optimise dirty rectangle handling, part 2 */
155    cv->dirty_disabled--;
156    if(!cv->dirty_disabled)
157        caca_add_dirty_rect(cv, x, y, x2 - x + 1, y2 - y + 1);
158#endif
159
160    return 0;
161}
162
163/*
164 * XXX: The following functions are local.
165 */
166
167static int draw_box(caca_canvas_t *cv, int x, int y, int w, int h,
168                    uint32_t const *chars)
169{
170    int i, j, xmax, ymax;
171
172    int x2 = x + w - 1;
173    int y2 = y + h - 1;
174
175    if(x > x2)
176    {
177        int tmp = x;
178        x = x2; x2 = tmp;
179    }
180
181    if(y > y2)
182    {
183        int tmp = y;
184        y = y2; y2 = tmp;
185    }
186
187    xmax = cv->width - 1;
188    ymax = cv->height - 1;
189
190    if(x2 < 0 || y2 < 0 || x > xmax || y > ymax)
191        return 0;
192
193    /* Draw edges */
194    if(y >= 0)
195        for(i = x < 0 ? 1 : x + 1; i < x2 && i < xmax; i++)
196            caca_put_char(cv, i, y, chars[0]);
197
198    if(y2 <= ymax)
199        for(i = x < 0 ? 1 : x + 1; i < x2 && i < xmax; i++)
200            caca_put_char(cv, i, y2, chars[0]);
201
202    if(x >= 0)
203        for(j = y < 0 ? 1 : y + 1; j < y2 && j < ymax; j++)
204            caca_put_char(cv, x, j, chars[1]);
205
206    if(x2 <= xmax)
207        for(j = y < 0 ? 1 : y + 1; j < y2 && j < ymax; j++)
208            caca_put_char(cv, x2, j, chars[1]);
209
210    /* Draw corners */
211    caca_put_char(cv, x, y, chars[2]);
212    caca_put_char(cv, x, y2, chars[3]);
213    caca_put_char(cv, x2, y, chars[4]);
214    caca_put_char(cv, x2, y2, chars[5]);
215
216    return 0;
217}
218
219/*
220 * XXX: The following functions are aliases.
221 */
222
223int cucul_draw_box(cucul_canvas_t *, int, int, int, int, uint32_t)
224         CACA_ALIAS(caca_draw_box);
225int cucul_draw_thin_box(cucul_canvas_t *, int, int, int, int)
226         CACA_ALIAS(caca_draw_thin_box);
227int cucul_draw_cp437_box(cucul_canvas_t *, int, int, int, int)
228         CACA_ALIAS(caca_draw_cp437_box);
229int cucul_fill_box(cucul_canvas_t *, int, int, int, int, uint32_t)
230         CACA_ALIAS(caca_fill_box);
231
Note: See TracBrowser for help on using the repository browser.