source: ttyvaders/trunk/libee/line.c @ 104

Last change on this file since 104 was 104, checked in by Sam Hocevar, 17 years ago
  • libee/line.c: + ee_draw_thin_line().
  • test/demo.c: + Added a thin lines demo.
  • Property svn:keywords set to Id
File size: 5.9 KB
Line 
1/*
2 *   libee         ASCII-Art library
3 *   Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
4 *                 All Rights Reserved
5 *
6 *   $Id: line.c 104 2003-11-09 19:46:14Z sam $
7 *
8 *   This program is free software; you can redistribute it and/or modify
9 *   it under the terms of the GNU General Public License as published by
10 *   the Free Software Foundation; either version 2 of the License, or
11 *   (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include "config.h"
24
25#include <inttypes.h>
26#include <stdlib.h>
27
28#include "ee.h"
29
30struct line
31{
32    int x1, y1;
33    int x2, y2;
34    char c;
35    void (*draw) (struct line*);
36};
37
38static void clip_line(struct line*);
39static uint8_t clip_bits(int, int);
40static void draw_solid_line(struct line*);
41static void draw_thin_line(struct line*);
42
43void ee_draw_line(int x1, int y1, int x2, int y2, char c)
44{
45    struct line s;
46    s.x1 = x1;
47    s.y1 = y1;
48    s.x2 = x2;
49    s.y2 = y2;
50    s.c = c;
51    s.draw = draw_solid_line;
52    clip_line(&s);
53}
54
55void ee_draw_thin_line(int x1, int y1, int x2, int y2)
56{
57    struct line s;
58    s.x1 = x1;
59    s.y1 = y1;
60    s.x2 = x2;
61    s.y2 = y2;
62    s.draw = draw_thin_line;
63    clip_line(&s);
64}
65
66static void clip_line(struct line* s)
67{
68    uint8_t bits1, bits2;
69
70    bits1 = clip_bits(s->x1, s->y1);
71    bits2 = clip_bits(s->x2, s->y2);
72
73    if(bits1 & bits2)
74        return;
75
76    if(bits1 == 0)
77    {
78        if(bits2 == 0)
79            s->draw(s);
80        else
81        {
82            int tmp;
83            tmp = s->x1; s->x1 = s->x2; s->x2 = tmp;
84            tmp = s->y1; s->y1 = s->y2; s->y2 = tmp;
85            clip_line(s);
86        }
87
88        return;
89    }
90
91    if(bits1 & (1<<0))
92    {
93        s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1);
94        s->x1 = 0;
95    }
96    else if( bits1 & (1<<1) )
97    {
98        int xmax = ee_get_width() - 1;
99        s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1);
100        s->x1 = xmax;
101    }
102    else if( bits1 & (1<<2) )
103    {
104        s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1);
105        s->y1 = 0;
106    }
107    else if( bits1 & (1<<3) )
108    {
109        int ymax = ee_get_height() - 1;
110        s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1);
111        s->y1 = ymax;
112    }
113
114    clip_line(s);
115}
116
117static uint8_t clip_bits(int x, int y)
118{
119    uint8_t b = 0;
120
121    if(x < 0)
122        b |= (1<<0);
123    else if(x >= ee_get_width())
124        b |= (1<<1);
125
126    if(y < 0)
127        b |= (1<<2);
128    else if(y >= ee_get_height())
129        b |= (1<<3);
130
131    return b;
132}
133
134static void draw_solid_line(struct line* s)
135{
136    int x1, y1, x2, y2;
137    int dx, dy;
138    int xinc, yinc;
139
140    x1 = s->x1; y1 = s->y1; x2 = s->x2; y2 = s->y2;
141
142    dx = abs(x2 - x1);
143    dy = abs(y2 - y1);
144
145    xinc = (x1 > x2) ? -1 : 1;
146    yinc = (y1 > y2) ? -1 : 1;
147
148    if(dx >= dy)
149    {
150        int dpr = dy << 1;
151        int dpru = dpr - (dx << 1);
152        int delta = dpr - dx;
153
154        for(; dx>=0; dx--)
155        {
156            ee_goto(x1, y1);
157            ee_putchar(s->c);
158            if(delta > 0)
159            {
160                x1 += xinc;
161                y1 += yinc;
162                delta += dpru;
163            }
164            else
165            {
166                x1 += xinc;
167                delta += dpr;
168            }
169        }
170    }
171    else
172    {
173        int dpr = dx << 1;
174        int dpru = dpr - (dy << 1);
175        int delta = dpr - dy;
176
177        for(; dy >= 0; dy--)
178        {
179            ee_goto(x1, y1);
180            ee_putchar(s->c);
181            if(delta > 0)
182            {
183                x1 += xinc;
184                y1 += yinc;
185                delta += dpru;
186            }
187            else
188            {
189                y1 += yinc;
190                delta += dpr;
191            }
192        }
193    }
194}
195
196static void draw_thin_line(struct line* s)
197{
198    char *charmapx, *charmapy;
199    int x1, y1, x2, y2;
200    int dx, dy;
201    int yinc;
202
203    if(s->x2 >= s->x1)
204    {
205        if(s->y1 > s->y2)
206            charmapx = ",'";
207        else
208            charmapx = "`.";
209        x1 = s->x1; y1 = s->y1; x2 = s->x2; y2 = s->y2;
210    }
211    else
212    {
213        if(s->y1 > s->y2)
214            charmapx = "`.";
215        else
216            charmapx = ",'";
217        x2 = s->x1; y2 = s->y1; x1 = s->x2; y1 = s->y2;
218    }
219
220    dx = abs(x2 - x1);
221    dy = abs(y2 - y1);
222
223    if(y1 > y2)
224    {
225        charmapy = ",'";
226        yinc = -1;
227    }
228    else
229    {
230        yinc = 1;
231        charmapy = "`.";
232    }
233
234    if(dx >= dy)
235    {
236        int dpr = dy << 1;
237        int dpru = dpr - (dx << 1);
238        int delta = dpr - dx;
239        int prev = 0;
240
241        for(; dx>=0; dx--)
242        {
243            ee_goto(x1, y1);
244            if(delta > 0)
245            {
246                ee_putchar(charmapy[1]);
247                x1++;
248                y1 += yinc;
249                delta += dpru;
250                prev = 1;
251            }
252            else
253            {
254                if(prev)
255                    ee_putchar(charmapy[0]);
256                else
257                    ee_putchar('-');
258                x1++;
259                delta += dpr;
260                prev = 0;
261            }
262        }
263    }
264    else
265    {
266        int dpr = dx << 1;
267        int dpru = dpr - (dy << 1);
268        int delta = dpr - dy;
269
270        for(; dy >= 0; dy--)
271        {
272            ee_goto(x1, y1);
273            if(delta > 0)
274            {
275                ee_putchar(charmapx[0]);
276                ee_putchar(charmapx[1]);
277                x1++;
278                y1 += yinc;
279                delta += dpru;
280            }
281            else
282            {
283                ee_putchar('|');
284                y1 += yinc;
285                delta += dpr;
286            }
287        }
288    }
289}
290
Note: See TracBrowser for help on using the repository browser.