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