source: libcaca/trunk/caca/conic.c @ 2821

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

Starting refactoring to get rid of libcucul. The initial reason for the
split is rendered moot by the plugin system: when enabled, binaries do
not link directly with libX11 or libGL. I hope this is a step towards
more consisteny and clarity.

  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: conic.c 2821 2008-09-27 13:12:46Z 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 ellipse and circle drawing functions, both filled
17 *  and outline.
18 */
19
20#include "config.h"
21
22#if !defined(__KERNEL__)
23#   include <stdlib.h>
24#endif
25
26#include "caca.h"
27#include "caca_internals.h"
28
29static void ellipsepoints(caca_canvas_t *, int, int, int, int, uint32_t, int);
30
31/** \brief Draw a circle 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 Center X coordinate.
37 *  \param y Center Y coordinate.
38 *  \param r Circle radius.
39 *  \param ch UTF-32 character to be used to draw the circle outline.
40 *  \return This function always returns 0.
41 */
42int caca_draw_circle(caca_canvas_t *cv, int x, int y, int r, uint32_t ch)
43{
44    int test, dx, dy;
45
46    /* Optimized Bresenham. Kick ass. */
47    for(test = 0, dx = 0, dy = r ; dx <= dy ; dx++)
48    {
49        ellipsepoints(cv, x, y, dx, dy, ch, 1);
50        ellipsepoints(cv, x, y, dy, dx, ch, 1);
51
52        test += test > 0 ? dx - dy-- : dx;
53    }
54
55    return 0;
56}
57
58/** \brief Fill an ellipse on the canvas using the given character.
59 *
60 *  This function never fails.
61 *
62 *  \param cv The handle to the libcaca canvas.
63 *  \param xo Center X coordinate.
64 *  \param yo Center Y coordinate.
65 *  \param a Ellipse X radius.
66 *  \param b Ellipse Y radius.
67 *  \param ch UTF-32 character to be used to fill the ellipse.
68 *  \return This function always returns 0.
69 */
70int caca_fill_ellipse(caca_canvas_t *cv, int xo, int yo, int a, int b,
71                       uint32_t ch)
72{
73    int d2;
74    int x = 0;
75    int y = b;
76    int d1 = b*b - (a*a*b) + (a*a/4);
77
78    while(a*a*y - a*a/2 > b*b*(x+1))
79    {
80        if(d1 < 0)
81        {
82            d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
83        }
84        else
85        {
86            d1 += b*b*(2*x*1) + a*a*(-2*y+2);
87            caca_draw_line(cv, xo - x, yo - y, xo + x, yo - y, ch);
88            caca_draw_line(cv, xo - x, yo + y, xo + x, yo + y, ch);
89            y--;
90        }
91        x++;
92    }
93
94    caca_draw_line(cv, xo - x, yo - y, xo + x, yo - y, ch);
95    caca_draw_line(cv, xo - x, yo + y, xo + x, yo + y, ch);
96
97    d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
98    while(y > 0)
99    {
100        if(d2 < 0)
101        {
102            d2 += b*b*(2*x+2) + a*a*(-2*y+3);
103            x++;
104        }
105        else
106        {
107            d2 += a*a*(-2*y+3);
108        }
109
110        y--;
111        caca_draw_line(cv, xo - x, yo - y, xo + x, yo - y, ch);
112        caca_draw_line(cv, xo - x, yo + y, xo + x, yo + y, ch);
113    }
114
115    return 0;
116}
117
118/** \brief Draw an ellipse on the canvas using the given character.
119 *
120 *  This function never fails.
121 *
122 *  \param cv The handle to the libcaca canvas.
123 *  \param xo Center X coordinate.
124 *  \param yo Center Y coordinate.
125 *  \param a Ellipse X radius.
126 *  \param b Ellipse Y radius.
127 *  \param ch UTF-32 character to be used to draw the ellipse outline.
128 *  \return This function always returns 0.
129 */
130int caca_draw_ellipse(caca_canvas_t *cv, int xo, int yo, int a, int b,
131                       uint32_t ch)
132{
133    int d2;
134    int x = 0;
135    int y = b;
136    int d1 = b*b - (a*a*b) + (a*a/4);
137
138    ellipsepoints(cv, xo, yo, x, y, ch, 0);
139
140    while(a*a*y - a*a/2 > b*b*(x+1))
141    {
142        if(d1 < 0)
143        {
144            d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
145        }
146        else
147        {
148            d1 += b*b*(2*x*1) + a*a*(-2*y+2);
149            y--;
150        }
151        x++;
152        ellipsepoints(cv, xo, yo, x, y, ch, 0);
153    }
154
155    d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
156    while(y > 0)
157    {
158        if(d2 < 0)
159        {
160            d2 += b*b*(2*x+2) + a*a*(-2*y+3);
161            x++;
162        }
163        else
164        {
165            d2 += a*a*(-2*y+3);
166        }
167
168        y--;
169        ellipsepoints(cv, xo, yo, x, y, ch, 0);
170    }
171
172    return 0;
173}
174
175/** \brief Draw a thin ellipse on the canvas.
176 *
177 *  This function never fails.
178 *
179 *  \param cv The handle to the libcaca canvas.
180 *  \param xo Center X coordinate.
181 *  \param yo Center Y coordinate.
182 *  \param a Ellipse X radius.
183 *  \param b Ellipse Y radius.
184 *  \return This function always returns 0.
185 */
186int caca_draw_thin_ellipse(caca_canvas_t *cv, int xo, int yo, int a, int b)
187{
188    /* FIXME: this is not correct */
189    int d2;
190    int x = 0;
191    int y = b;
192    int d1 = b*b - (a*a*b) + (a*a/4);
193
194    ellipsepoints(cv, xo, yo, x, y, '-', 1);
195
196    while(a*a*y - a*a/2 > b*b*(x+1))
197    {
198        if(d1 < 0)
199        {
200            d1 += b*b*(2*x+1); /* XXX: "Computer Graphics" has + 3 here. */
201            ellipsepoints(cv, xo, yo, x + 1, y, '0', 1);
202        }
203        else
204        {
205            d1 += b*b*(2*x*1) + a*a*(-2*y+2);
206            y--;
207            ellipsepoints(cv, xo, yo, x + 1, y, '1', 1);
208        }
209        x++;
210       
211       
212    }
213
214    d2 = b*b*(x+0.5)*(x+0.5) + a*a*(y-1)*(y-1) - a*a*b*b;
215    while(y > 0)
216    {
217        if(d2 < 0)
218        {
219            d2 += b*b*(2*x+2) + a*a*(-2*y+3);
220            x++;
221            ellipsepoints(cv, xo, yo, x , y - 1, '2', 1);
222        }
223        else
224        {
225            d2 += a*a*(-2*y+3);
226            ellipsepoints(cv, xo, yo, x , y - 1, '3', 1);
227        }
228
229        y--;
230       
231       
232    }
233
234    return 0;
235}
236
237static void ellipsepoints(caca_canvas_t *cv, int xo, int yo, int x, int y,
238                          uint32_t ch, int thin)
239{
240    uint8_t b = 0;
241
242    if(xo + x >= 0 && xo + x < (int)cv->width)
243        b |= 0x1;
244    if(xo - x >= 0 && xo - x < (int)cv->width)
245        b |= 0x2;
246    if(yo + y >= 0 && yo + y < (int)cv->height)
247        b |= 0x4;
248    if(yo - y >= 0 && yo - y < (int)cv->height)
249        b |= 0x8;
250
251    if((b & (0x1|0x4)) == (0x1|0x4)) {
252        uint32_t c = ch;
253       
254        if(thin) {
255            switch(c) {
256            case '0':
257                c = '-';
258                break;
259            case '1':
260                c = ',';
261                break;
262            case '2':
263                c = '/';
264                break;
265            case '3':
266                c = '|';
267                break;
268            }
269
270        }
271        caca_put_char(cv, xo + x, yo + y, c);
272    }
273    if((b & (0x2|0x4)) == (0x2|0x4)) {
274        uint32_t c = ch;
275       
276        if(thin) {
277            switch(c) {
278            case '0':
279                c = '-';
280                break;
281            case '1':
282                c = '.';
283                break;
284            case '2':
285                c = '\\';
286                break;
287            case '3':
288                c = '|';
289                break;
290            }
291
292        }
293        caca_put_char(cv, xo - x, yo + y, c);
294    }
295
296
297    if((b & (0x1|0x8)) == (0x1|0x8)) {
298        uint32_t c = ch;
299       
300        if(thin) {
301            switch(c) {
302            case '0':
303                c = '-';
304                break;
305            case '1':
306                c = '`';
307                break;
308            case '2':
309                c = '\\';
310                break;
311            case '3':
312                c = '|';
313                break;
314            }
315
316        }
317        caca_put_char(cv, xo + x, yo - y, c);
318    }
319
320    if((b & (0x2|0x8)) == (0x2|0x8)) {
321        uint32_t c = ch;
322       
323        if(thin) {
324            switch(c) {
325            case '0':
326                c = '-';
327                break;
328            case '1':
329                c = '\'';
330                break;
331            case '2':
332                c = '/';
333                break;
334            case '3':
335                c = '|';
336                break;
337            }
338
339        }
340        caca_put_char(cv, xo - x, yo - y, c);
341    }
342
343       
344}
345
Note: See TracBrowser for help on using the repository browser.