added .cvsignore files
[btb/d2x.git] / 2d / line.c
1 /* $Id: line.c,v 1.4 2002-07-17 21:55:19 bradleyb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14 /*
15  * Graphical routines for drawing lines.
16  *
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <conf.h>
21 #endif
22
23 #include <stdlib.h>
24
25 #include "u_mem.h"
26
27 #include "gr.h"
28 #include "grdef.h"
29 #include "fix.h"
30
31 #include "clip.h"
32
33 #ifdef __DJGPP__
34 #include "modex.h"
35 #endif
36 #ifdef OGL
37 #include "ogl_init.h"
38 #endif
39
40
41 /*
42 Symmetric Double Step Line Algorithm
43 by Brian Wyvill
44 from "Graphics Gems", Academic Press, 1990
45 */
46
47 /* non-zero flag indicates the pixels needing EXCHG back. */
48 void plot(int x,int y,int flag)
49 {   if (flag)
50                 gr_upixel(y, x);
51         else
52                 gr_upixel(x, y);
53 }
54
55 int gr_hline(int x1, int x2, int y)
56 {   int i;
57
58         if (x1 > x2) EXCHG(x1,x2);
59         for (i=x1; i<=x2; i++ )
60                 gr_upixel( i, y );
61         return 0;
62 }
63
64 int gr_vline(int y1, int y2, int x)
65 {   int i;
66         if (y1 > y2) EXCHG(y1,y2);
67         for (i=y1; i<=y2; i++ )
68                 gr_upixel( x, i );
69         return 0;
70 }
71
72 void gr_universal_uline(int a1, int b1, int a2, int b2)
73 {
74         int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
75         int x1, y1;
76         int sign_x = 1, sign_y = 1, step, reverse, i;
77
78         if (a1==a2) {
79                 gr_vline(b1,b2,a1);
80                 return;
81         }
82
83         if (b1==b2) {
84                 gr_hline(a1,a2,b1);
85                 return;
86         }
87
88         dx = a2 - a1;
89         dy = b2 - b1;
90
91         if (dx < 0) {
92                 sign_x = -1;
93                 dx *= -1;
94         }
95         if (dy < 0) {
96                 sign_y = -1;
97                 dy *= -1;
98         }
99
100         /* decide increment sign by the slope sign */
101         if (sign_x == sign_y)
102                 step = 1;
103         else
104                 step = -1;
105
106         if (dy > dx) {          /* chooses axis of greatest movement (make * dx) */
107                 EXCHG(a1, b1);
108                 EXCHG(a2, b2);
109                 EXCHG(dx, dy);
110                 reverse = 1;
111         } else
112                 reverse = 0;
113         /* note error check for dx==0 should be included here */
114         if (a1 > a2) {          /* start from the smaller coordinate */
115                 x = a2;
116                 y = b2;
117                 x1 = a1;
118                 y1 = b1;
119         } else {
120                 x = a1;
121                 y = b1;
122                 x1 = a2;
123                 y1 = b2;
124         }
125
126
127         /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
128         /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
129         /* In fact (dx-1)/4 as 2 pixels are already plottted */
130         xend = (dx - 1) / 4;
131         pixels_left = (dx - 1) % 4;     /* number of pixels left over at the
132                                                                  * end */
133         plot(x, y, reverse);
134         plot(x1, y1, reverse);  /* plot first two points */
135         incr2 = 4 * dy - 2 * dx;
136         if (incr2 < 0) {        /* slope less than 1/2 */
137                 c = 2 * dy;
138                 incr1 = 2 * c;
139                 D = incr1 - dx;
140
141                 for (i = 0; i < xend; i++) {    /* plotting loop */
142                         ++x;
143                         --x1;
144                         if (D < 0) {
145                                         /* pattern 1 forwards */
146                                 plot(x, y, reverse);
147                                 plot(++x, y, reverse);
148                                 /* pattern 1 backwards */
149                                 plot(x1, y1, reverse);
150                                 plot(--x1, y1, reverse);
151                                 D += incr1;
152                         } else {
153                                 if (D < c) {
154                                         /* pattern 2 forwards */
155                                         plot(x, y, reverse);
156                                         plot(++x, y += step, reverse);
157                                         /* pattern 2 backwards */
158                                         plot(x1, y1, reverse);
159                                         plot(--x1, y1 -= step, reverse);
160                                 } else {
161                                         /* pattern 3 forwards */
162                                         plot(x, y += step, reverse);
163                                         plot(++x, y, reverse);
164                                         /* pattern 3 backwards */
165                                         plot(x1, y1 -= step, reverse);
166                                         plot(--x1, y1, reverse);
167                                 }
168                                 D += incr2;
169                         }
170                 }               /* end for */
171
172                 /* plot last pattern */
173                 if (pixels_left) {
174                         if (D < 0) {
175                                 plot(++x, y, reverse);  /* pattern 1 */
176                                 if (pixels_left > 1)
177                                         plot(++x, y, reverse);
178                                 if (pixels_left > 2)
179                                         plot(--x1, y1, reverse);
180                         } else {
181                                 if (D < c) {
182                                         plot(++x, y, reverse);  /* pattern 2  */
183                                         if (pixels_left > 1)
184                                                 plot(++x, y += step, reverse);
185                                         if (pixels_left > 2)
186                                                 plot(--x1, y1, reverse);
187                                 } else {
188                                   /* pattern 3 */
189                                         plot(++x, y += step, reverse);
190                                         if (pixels_left > 1)
191                                                 plot(++x, y, reverse);
192                                         if (pixels_left > 2)
193                                                 plot(--x1, y1 -= step, reverse);
194                                 }
195                         }
196                 }               /* end if pixels_left */
197         }
198         /* end slope < 1/2 */
199         else {                  /* slope greater than 1/2 */
200                 c = 2 * (dy - dx);
201                 incr1 = 2 * c;
202                 D = incr1 + dx;
203                 for (i = 0; i < xend; i++) {
204                         ++x;
205                         --x1;
206                         if (D > 0) {
207                           /* pattern 4 forwards */
208                                 plot(x, y += step, reverse);
209                                 plot(++x, y += step, reverse);
210                           /* pattern 4 backwards */
211                                 plot(x1, y1 -= step, reverse);
212                                 plot(--x1, y1 -= step, reverse);
213                                 D += incr1;
214                         } else {
215                                 if (D < c) {
216                                   /* pattern 2 forwards */
217                                         plot(x, y, reverse);
218                                         plot(++x, y += step, reverse);
219
220                                   /* pattern 2 backwards */
221                                         plot(x1, y1, reverse);
222                                         plot(--x1, y1 -= step, reverse);
223                                 } else {
224                                   /* pattern 3 forwards */
225                                         plot(x, y += step, reverse);
226                                         plot(++x, y, reverse);
227                                   /* pattern 3 backwards */
228                                         plot(x1, y1 -= step, reverse);
229                                         plot(--x1, y1, reverse);
230                                 }
231                                 D += incr2;
232                         }
233                 }               /* end for */
234                 /* plot last pattern */
235                 if (pixels_left) {
236                         if (D > 0) {
237                                 plot(++x, y += step, reverse);  /* pattern 4 */
238                                 if (pixels_left > 1)
239                                         plot(++x, y += step, reverse);
240                                 if (pixels_left > 2)
241                                         plot(--x1, y1 -= step, reverse);
242                         } else {
243                                 if (D < c) {
244                                         plot(++x, y, reverse);  /* pattern 2  */
245                                         if (pixels_left > 1)
246                                                 plot(++x, y += step, reverse);
247                                         if (pixels_left > 2)
248                                                 plot(--x1, y1, reverse);
249                                 } else {
250                                   /* pattern 3 */
251                                         plot(++x, y += step, reverse);
252                                         if (pixels_left > 1)
253                                                 plot(++x, y, reverse);
254                                         if (pixels_left > 2) {
255                                                 if (D > c) /* step 3 */
256                                                    plot(--x1, y1 -= step, reverse);
257                                                 else /* step 2 */
258                                                         plot(--x1, y1, reverse);
259                                         }
260                                 }
261                         }
262                 }
263         }
264 }
265
266
267 //unclipped version just calls clipping version for now
268 int gr_uline(fix _a1, fix _b1, fix _a2, fix _b2)
269 {
270         int a1,b1,a2,b2;
271         a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
272         switch(TYPE)
273         {
274 #ifdef OGL
275                 case BM_OGL:
276                         ogl_ulinec(a1,b1,a2,b2,COLOR);
277                         return 0;
278 #endif
279         case BM_LINEAR:
280                #ifdef NO_ASM
281                 gr_universal_uline( a1,b1,a2,b2);
282                #else
283                 gr_linear_line( a1, b1, a2, b2 );
284                #endif
285                 return 0;
286 #ifdef __DJGPP__
287         case BM_MODEX:
288                 modex_line_x1 = a1+XOFFSET;             
289                 modex_line_y1 = b1+YOFFSET;             
290                 modex_line_x2 = a2+XOFFSET;             
291                 modex_line_y2 = b2+YOFFSET;             
292                 modex_line_Color = grd_curcanv->cv_color;
293                 gr_modex_line();
294                 return 0;
295         default:
296                 gr_universal_uline( a1, b1, a2, b2 );
297                 return 0;
298 #endif
299         }
300         return 2;
301 }
302
303 // Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
304 // 2 if not drawn at all.
305
306 int gr_line(fix a1, fix b1, fix a2, fix b2)
307 {
308         int x1, y1, x2, y2;
309         int clipped=0;
310
311         x1 = i2f(MINX);
312         y1 = i2f(MINY);
313         x2 = i2f(MAXX);
314         y2 = i2f(MAXY);
315
316         CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return 2,clipped=1, FSCALE );
317
318         gr_uline( a1, b1, a2, b2 );
319
320         return clipped;
321
322 }
323
324