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

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

Large source code cleanup, getting rid of spaces, tabs, and svn keywords.

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