1 /* Ok, one other line algorithm.
2  * With subpixel and anti-alias, that's the point !
3  * Starting : Tue Sep 21 17:44:20 MET DST 1999
4  * Wed Sep 22 00:11:58 MET DST 1999 : almost done.
5  * I had some eating time and washing too, so I did not
6  * spend all this time on it. I must do a max routine
7  * (put the max value between the point and the current
8  * point). Not sure about my anti-alias stuff. Gonna watch some
9  * demos to see what it give with them.
10  * Let's go.
11  */
12 
13 #include "line.h"
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "screen.h"
20 #include "device.h"
21 #include "poly.h"
22 
23 device_line *the_lines;
24 
25 /* returns a*b/c in int 16:16 */
muldiv(int a,int b,int c)26 static inline int muldiv(int a, int b, int c)
27 {
28 #ifdef PC_ARCHI
29   register int r;
30   __asm__ volatile ("imul %2  \n"
31 		    "idiv %3  \n"
32 		    : "=a" (r)
33 		    : "a" (a), "b" (b), "c" (c)
34 		    : "eax", "ebx", "ecx", "edx"
35 		    );
36   return r;
37 #else
38   return (double)a*(double)b/(double)c;
39 #endif
40 }
41 
drawline8(device * d,line * l)42 void drawline8(device *d, line *l)
43 {
44   /* lots of goto for lisibility (if if else if if else else is impossible to debug) */
45   register int x1=l->p1.x*65536., x2=l->p2.x*65536.,
46                y1=l->p1.y*65536., y2=l->p2.y*65536., dx, dy;
47   register int xcur;
48   register int xinc;
49   register int ycur;
50   register int yinc;
51   register int i;
52   register int y1i=(y1+65535)>>16, y2i=(y2+65535)>>16;
53   register int x1i=(x1+65535)>>16, x2i=(x2+65535)>>16;
54   register unsigned char *dest;
55   register unsigned char col1=l->color;
56   register int xf;
57   register int yf;
58 
59   /* in asm, those two subs are good for us, because we can test if x1<x2 and if y1<y2 at the same time, but it's C */
60   dx=x2-x1;
61   dy=y2-y1;
62 
63   if (dx<0)
64     goto x1_sup_x2;
65   if (dx)
66     goto x1_inf_x2;
67 
68   /* here x1==x2 */
69   if (dy<0)
70     goto x1_eq_x2_and_y1_sup_y2;
71   if (dy>0)
72     goto x1_eq_x2_and_y1_inf_y2;
73   /* here x1==x2 && y1==y2 */
74   if (y1i<y2i) {
75     dest=d->buffer+y1i*SCREEN_X+(x1>>16);
76   } else {
77     dest=d->buffer+y2i*SCREEN_X+(x1>>16);
78   }
79   *dest=col1;
80   return;
81 x1_eq_x2_and_y1_sup_y2:
82   dest=d->buffer+y2i*SCREEN_X+(x1>>16);
83   for (i=y2i; i<y1i; dest+=SCREEN_X, i++) {
84     *dest=col1;
85   }
86   return;
87 x1_eq_x2_and_y1_inf_y2:
88   dest=d->buffer+y1i*SCREEN_X+(x1>>16);
89   for (i=y1i; i<y2i; dest+=SCREEN_X, i++) {
90     *dest=col1;
91   }
92   return;
93 
94 x1_inf_x2:
95   if (dy<0)
96     goto x1_inf_x2_and_y1_sup_y2;
97   if (dy>0)
98     goto x1_inf_x2_and_y1_inf_y2;
99   /* x1<x2 && y1==y2 */
100   dest=d->buffer+(y1>>16)*SCREEN_X+x1i;
101   for (i=x1i; i<x2i; dest++, i++) {
102     *dest=col1;
103   }
104   return;
105 
106 x1_inf_x2_and_y1_sup_y2:
107   /*
108                   (x2, y2)
109 
110 
111        (x1, y1)
112    */
113   /* remove those abs in the asm code */
114   if (abs(dx)>abs(dy))
115     goto x1_inf_x2_and_y1_sup_y2_dx_sup_dy;
116   if (abs(dx)<abs(dy))
117     goto x1_inf_x2_and_y1_sup_y2_dx_inf_dy;
118   /* here dx == dy */
119   dest=d->buffer+y2i*SCREEN_X+(x2>>16);
120   for (i=y2i; i<y1i; dest+=SCREEN_X-1, i++) {
121     *dest=col1;
122   }
123   return;
124 x1_inf_x2_and_y1_sup_y2_dx_sup_dy:
125   /*
126                     xxxx
127 		xxxx
128 	    xxxx
129 	xxxx
130   */
131   yinc=muldiv(dy, 65536, dx);
132   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
133   yf=ycur&65535;
134   dest=d->buffer+(ycur>>16)*SCREEN_X+x2i;
135   for (i=x2i; i>x1i; i--, dest--) {
136     *dest=col1;
137     yf-=yinc;
138     if (yf>65535) {
139       yf-=65536;
140       dest+=SCREEN_X;
141     }
142   }
143   return;
144 x1_inf_x2_and_y1_sup_y2_dx_inf_dy:
145   /*
146           x
147 	  x
148 	  x
149 	 x
150 	 x
151 	 x
152 	x
153 	x
154 	x
155   */
156   xinc=muldiv(dx, 65536, dy);
157   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
158   xf=xcur&65535;
159   dest=d->buffer+y2i*SCREEN_X+(xcur>>16);
160   for (i=y2i; i<y1i; i++, dest+=SCREEN_X) {
161     *dest=col1;
162     xf+=xinc;
163     if (xf<0) {
164       xf+=65536;
165       dest--;
166     }
167   }
168   return;
169 
170 x1_inf_x2_and_y1_inf_y2:
171   /*
172       (x1, y1)
173 
174 
175                   (x2, y2)
176   */
177   if (abs(dx)>abs(dy))
178     goto x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy;
179   if (abs(dx)<abs(dy))
180     goto x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy;
181   /* here dx == dy */
182   dest=d->buffer+y1i*SCREEN_X+(x1>>16);
183   for (i=y1i; i<y2i; dest+=SCREEN_X+1, i++) {
184     *dest=col1;
185   }
186   return;
187 
188 x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy:
189   /*
190         xxxx
191 	    xxxx
192 	        xxxx
193    */
194   yinc=muldiv(dy, 65536, dx);
195   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
196   yf=ycur&65535;
197   dest=d->buffer+(ycur>>16)*SCREEN_X+x1i;
198   for (i=x1i; i<x2i; i++, dest++) {
199     *dest=col1;
200     yf+=yinc;
201     if (yf>65535) {
202       yf-=65536;
203       dest+=SCREEN_X;
204     }
205   }
206   return;
207 x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy:
208   /*
209       x
210       x
211       x
212        x
213        x
214        x
215         x
216 	x
217 	x
218   */
219   xinc=muldiv(dx, 65536, dy);
220   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
221   xf=xcur&65535;
222   dest=d->buffer+y1i*SCREEN_X+(xcur>>16);
223   for (i=y1i; i<y2i; i++, dest+=SCREEN_X) {
224     *dest=col1;
225     xf+=xinc;
226     if (xf>65536) {
227       xf-=65536;
228       dest++;
229     }
230   }
231   return;
232 
233 x1_sup_x2:
234   if (dy<0)
235     goto x1_sup_x2_and_y1_sup_y2;
236   if (dy>0)
237     goto x1_sup_x2_and_y1_inf_y2;
238   /* x1>x2 && y1==y2 */
239   dest=d->buffer+(y2>>16)*SCREEN_X+x2i;
240   for (i=x2i; i<x1i; dest++, i++) {
241     *dest=col1;
242   }
243   return;
244 x1_sup_x2_and_y1_sup_y2:
245   /*
246        (x2, y2)
247 
248 
249                  (x1, y1)
250    */
251   if (abs(dx)>abs(dy))
252     goto x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy;
253   if (abs(dx)<abs(dy))
254     goto x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy;
255   /* here dx == dy */
256   dest=d->buffer+y2i*SCREEN_X+(x2>>16);
257   for (i=y2i; i<y1i; dest+=SCREEN_X+1, i++) {
258     *dest=col1;
259   }
260   return;
261 x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy:
262   yinc=muldiv(dy, 65536, dx);
263   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
264   yf=ycur&65535;
265   dest=d->buffer+(ycur>>16)*SCREEN_X+x2i;
266   for (i=x2i; i<x1i; i++, dest++) {
267     *dest=col1;
268     yf+=yinc;
269     if (yf>65535) {
270       yf-=65536;
271       dest+=SCREEN_X;
272     }
273   }
274   return;
275 x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy:
276   xinc=muldiv(dx, 65536, dy);
277   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
278   xf=xcur&65535;
279   dest=d->buffer+y2i*SCREEN_X+(xcur>>16);
280   for (i=y2i; i<y1i; i++, dest+=SCREEN_X) {
281     *dest=col1;
282     xf+=xinc;
283     if (xf>65536) {
284       xf-=65536;
285       dest++;
286     }
287   }
288   return;
289 
290 x1_sup_x2_and_y1_inf_y2:
291   /*
292                  (x1, y1)
293 
294 
295       (x2, y2)
296    */
297   if (abs(dx)>abs(dy))
298     goto x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy;
299   if (abs(dx)<abs(dy))
300     goto x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy;
301   /* here dx == dy */
302   dest=d->buffer+y1i*SCREEN_X+(x1>>16);
303   for (i=y1i; i<y2i; dest+=SCREEN_X-1, i++) {
304     *dest=col1;
305   }
306   return;
307 x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy:
308   yinc=muldiv(dy, 65536, dx);
309   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
310   yf=ycur&65535;
311   dest=d->buffer+(ycur>>16)*SCREEN_X+x1i;
312   for (i=x1i; i>x2i; i--, dest--) {
313     *dest=col1;
314     yf-=yinc;
315     if (yf>65535) {
316       yf-=65536;
317       dest+=SCREEN_X;
318     }
319   }
320   return;
321 x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy:
322   xinc=muldiv(dx, 65536, dy);
323   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
324   xf=xcur&65535;
325   dest=d->buffer+y1i*SCREEN_X+(xcur>>16);
326   for (i=y1i; i<y2i; i++, dest+=SCREEN_X) {
327     *dest=col1;
328     xf+=xinc;
329     if (xf<0) {
330       xf+=65536;
331       dest--;
332     }
333   }
334   return;
335 }
336 
drawline16(device * d,line * l)337 void drawline16(device *d, line *l)
338 {
339   /* lots of goto for lisibility (if if else if if else else is impossible to debug) */
340   register int x1=l->p1.x*65536., x2=l->p2.x*65536., y1=l->p1.y*65536., y2=l->p2.y*65536., dx, dy;
341   register int xcur;
342   register int xinc;
343   register int ycur;
344   register int yinc;
345   register int i;
346   register int y1i=(y1+65535)>>16, y2i=(y2+65535)>>16;
347   register int x1i=(x1+65535)>>16, x2i=(x2+65535)>>16;
348   register unsigned short *dest;
349   register unsigned short col1=l->color;
350   register int xf;
351   register int yf;
352 
353   /* in asm, those two subs are good for us, because we can test if x1<x2 and if y1<y2 at the same time, but it's C */
354   dx=x2-x1;
355   dy=y2-y1;
356 
357   if (dx<0)
358     goto x1_sup_x2;
359   if (dx)
360     goto x1_inf_x2;
361 
362   /* here x1==x2 */
363   if (dy<0)
364     goto x1_eq_x2_and_y1_sup_y2;
365   if (dy>0)
366     goto x1_eq_x2_and_y1_inf_y2;
367   /* here x1==x2 && y1==y2 */
368   if (y1i<y2i) {
369     dest=(unsigned short *)d->buffer+y1i*SCREEN_X+(x1>>16);
370   } else {
371     dest=(unsigned short *)d->buffer+y2i*SCREEN_X+(x1>>16);
372   }
373   *dest=col1;
374   return;
375 x1_eq_x2_and_y1_sup_y2:
376   dest=(unsigned short *)d->buffer+y2i*SCREEN_X+(x1>>16);
377   for (i=y2i; i<y1i; dest+=SCREEN_X, i++) {
378     *dest=col1;
379   }
380   return;
381 x1_eq_x2_and_y1_inf_y2:
382   dest=(unsigned short *)d->buffer+y1i*SCREEN_X+(x1>>16);
383   for (i=y1i; i<y2i; dest+=SCREEN_X, i++) {
384     *dest=col1;
385   }
386   return;
387 
388 x1_inf_x2:
389   if (dy<0)
390     goto x1_inf_x2_and_y1_sup_y2;
391   if (dy>0)
392     goto x1_inf_x2_and_y1_inf_y2;
393   /* x1<x2 && y1==y2 */
394   dest=(unsigned short *)d->buffer+(y1>>16)*SCREEN_X+x1i;
395   for (i=x1i; i<x2i; dest++, i++) {
396     *dest=col1;
397   }
398   return;
399 
400 x1_inf_x2_and_y1_sup_y2:
401   /*
402                   (x2, y2)
403 
404 
405        (x1, y1)
406    */
407   /* remove those abs in the asm code */
408   if (abs(dx)>abs(dy))
409     goto x1_inf_x2_and_y1_sup_y2_dx_sup_dy;
410   if (abs(dx)<abs(dy))
411     goto x1_inf_x2_and_y1_sup_y2_dx_inf_dy;
412   /* here dx == dy */
413   dest=(unsigned short *)d->buffer+y2i*SCREEN_X+(x2>>16);
414   for (i=y2i; i<y1i; dest+=SCREEN_X-1, i++) {
415     *dest=col1;
416   }
417   return;
418 x1_inf_x2_and_y1_sup_y2_dx_sup_dy:
419   /*
420                     xxxx
421 		xxxx
422 	    xxxx
423 	xxxx
424   */
425   yinc=muldiv(dy, 65536, dx);
426   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
427   yf=ycur&65535;
428   dest=(unsigned short *)d->buffer+(ycur>>16)*SCREEN_X+x2i;
429   for (i=x2i; i>x1i; i--, dest--) {
430     *dest=col1;
431     yf-=yinc;
432     if (yf>65535) {
433       yf-=65536;
434       dest+=SCREEN_X;
435     }
436   }
437   return;
438 x1_inf_x2_and_y1_sup_y2_dx_inf_dy:
439   /*
440           x
441 	  x
442 	  x
443 	 x
444 	 x
445 	 x
446 	x
447 	x
448 	x
449   */
450   xinc=muldiv(dx, 65536, dy);
451   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
452   xf=xcur&65535;
453   dest=(unsigned short *)d->buffer+y2i*SCREEN_X+(xcur>>16);
454   for (i=y2i; i<y1i; i++, dest+=SCREEN_X) {
455     *dest=col1;
456     xf+=xinc;
457     if (xf<0) {
458       xf+=65536;
459       dest--;
460     }
461   }
462   return;
463 
464 x1_inf_x2_and_y1_inf_y2:
465   /*
466       (x1, y1)
467 
468 
469                   (x2, y2)
470   */
471   if (abs(dx)>abs(dy))
472     goto x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy;
473   if (abs(dx)<abs(dy))
474     goto x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy;
475   /* here dx == dy */
476   dest=(unsigned short *)d->buffer+y1i*SCREEN_X+(x1>>16);
477   for (i=y1i; i<y2i; dest+=SCREEN_X+1, i++) {
478     *dest=col1;
479   }
480   return;
481 
482 x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy:
483   /*
484         xxxx
485 	    xxxx
486 	        xxxx
487    */
488   yinc=muldiv(dy, 65536, dx);
489   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
490   yf=ycur&65535;
491   dest=(unsigned short *)d->buffer+(ycur>>16)*SCREEN_X+x1i;
492   for (i=x1i; i<x2i; i++, dest++) {
493     *dest=col1;
494     yf+=yinc;
495     if (yf>65535) {
496       yf-=65536;
497       dest+=SCREEN_X;
498     }
499   }
500   return;
501 x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy:
502   /*
503       x
504       x
505       x
506        x
507        x
508        x
509         x
510 	x
511 	x
512   */
513   xinc=muldiv(dx, 65536, dy);
514   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
515   xf=xcur&65535;
516   dest=(unsigned short *)d->buffer+y1i*SCREEN_X+(xcur>>16);
517   for (i=y1i; i<y2i; i++, dest+=SCREEN_X) {
518     *dest=col1;
519     xf+=xinc;
520     if (xf>65536) {
521       xf-=65536;
522       dest++;
523     }
524   }
525   return;
526 
527 x1_sup_x2:
528   if (dy<0)
529     goto x1_sup_x2_and_y1_sup_y2;
530   if (dy>0)
531     goto x1_sup_x2_and_y1_inf_y2;
532   /* x1>x2 && y1==y2 */
533   dest=(unsigned short *)d->buffer+(y2>>16)*SCREEN_X+x2i;
534   for (i=x2i; i<x1i; dest++, i++) {
535     *dest=col1;
536   }
537   return;
538 x1_sup_x2_and_y1_sup_y2:
539   /*
540        (x2, y2)
541 
542 
543                  (x1, y1)
544    */
545   if (abs(dx)>abs(dy))
546     goto x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy;
547   if (abs(dx)<abs(dy))
548     goto x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy;
549   /* here dx == dy */
550   dest=(unsigned short *)d->buffer+y2i*SCREEN_X+(x2>>16);
551   for (i=y2i; i<y1i; dest+=SCREEN_X+1, i++) {
552     *dest=col1;
553   }
554   return;
555 x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy:
556   yinc=muldiv(dy, 65536, dx);
557   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
558   yf=ycur&65535;
559   dest=(unsigned short *)d->buffer+(ycur>>16)*SCREEN_X+x2i;
560   for (i=x2i; i<x1i; i++, dest++) {
561     *dest=col1;
562     yf+=yinc;
563     if (yf>65535) {
564       yf-=65536;
565       dest+=SCREEN_X;
566     }
567   }
568   return;
569 x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy:
570   xinc=muldiv(dx, 65536, dy);
571   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
572   xf=xcur&65535;
573   dest=(unsigned short *)d->buffer+y2i*SCREEN_X+(xcur>>16);
574   for (i=y2i; i<y1i; i++, dest+=SCREEN_X) {
575     *dest=col1;
576     xf+=xinc;
577     if (xf>65536) {
578       xf-=65536;
579       dest++;
580     }
581   }
582   return;
583 
584 x1_sup_x2_and_y1_inf_y2:
585   /*
586                  (x1, y1)
587 
588 
589       (x2, y2)
590    */
591   if (abs(dx)>abs(dy))
592     goto x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy;
593   if (abs(dx)<abs(dy))
594     goto x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy;
595   /* here dx == dy */
596   dest=(unsigned short *)d->buffer+y1i*SCREEN_X+(x1>>16);
597   for (i=y1i; i<y2i; dest+=SCREEN_X-1, i++) {
598     *dest=col1;
599   }
600   return;
601 x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy:
602   yinc=muldiv(dy, 65536, dx);
603   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
604   yf=ycur&65535;
605   dest=(unsigned short *)d->buffer+(ycur>>16)*SCREEN_X+x1i;
606   for (i=x1i; i>x2i; i--, dest--) {
607     *dest=col1;
608     yf-=yinc;
609     if (yf>65535) {
610       yf-=65536;
611       dest+=SCREEN_X;
612     }
613   }
614   return;
615 x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy:
616   xinc=muldiv(dx, 65536, dy);
617   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
618   xf=xcur&65535;
619   dest=(unsigned short *)d->buffer+y1i*SCREEN_X+(xcur>>16);
620   for (i=y1i; i<y2i; i++, dest+=SCREEN_X) {
621     *dest=col1;
622     xf+=xinc;
623     if (xf<0) {
624       xf+=65536;
625       dest--;
626     }
627   }
628   return;
629 }
630 
drawline24(device * d,line * l)631 void drawline24(device *d, line *l)
632 {
633   /* lots of goto for lisibility (if if else if if else else is impossible to debug) */
634   register int x1=l->p1.x*65536., x2=l->p2.x*65536., y1=l->p1.y*65536., y2=l->p2.y*65536., dx, dy;
635   register int xcur;
636   register int xinc;
637   register int ycur;
638   register int yinc;
639   register int i;
640   register int y1i=(y1+65535)>>16, y2i=(y2+65535)>>16;
641   register int x1i=(x1+65535)>>16, x2i=(x2+65535)>>16;
642   register unsigned char *dest;
643   register unsigned char col1=l->color&255;
644   register unsigned char col2=(l->color>>8)&255;
645   register unsigned char col3=l->color>>16;
646   register int xf;
647   register int yf;
648 
649   /* in asm, those two subs are good for us, because we can test if x1<x2 and if y1<y2 at the same time, but it's C */
650   dx=x2-x1;
651   dy=y2-y1;
652 
653   if (dx<0)
654     goto x1_sup_x2;
655   if (dx)
656     goto x1_inf_x2;
657 
658   /* here x1==x2 */
659   if (dy<0)
660     goto x1_eq_x2_and_y1_sup_y2;
661   if (dy>0)
662     goto x1_eq_x2_and_y1_inf_y2;
663   /* here x1==x2 && y1==y2 */
664   if (y1i<y2i) {
665     dest=d->buffer+(y1i*SCREEN_X+(x1>>16))*3;
666   } else {
667     dest=d->buffer+(y2i*SCREEN_X+(x1>>16))*3;
668   }
669   *dest=col1;
670   *(dest+1)=col2;
671   *(dest+2)=col3;
672   return;
673 x1_eq_x2_and_y1_sup_y2:
674   dest=d->buffer+(y2i*SCREEN_X+(x1>>16))*3;
675   for (i=y2i; i<y1i; dest+=SCREEN_X*3, i++) {
676     *dest=col1;
677     *(dest+1)=col2;
678     *(dest+2)=col3;
679   }
680   return;
681 x1_eq_x2_and_y1_inf_y2:
682   dest=d->buffer+(y1i*SCREEN_X+(x1>>16))*3;
683   for (i=y1i; i<y2i; dest+=SCREEN_X*3, i++) {
684     *dest=col1;
685     *(dest+1)=col2;
686     *(dest+2)=col3;
687   }
688   return;
689 
690 x1_inf_x2:
691   if (dy<0)
692     goto x1_inf_x2_and_y1_sup_y2;
693   if (dy>0)
694     goto x1_inf_x2_and_y1_inf_y2;
695   /* x1<x2 && y1==y2 */
696   dest=d->buffer+((y1>>16)*SCREEN_X+x1i)*3;
697   for (i=x1i; i<x2i; dest+=3, i++) {
698     *dest=col1;
699     *(dest+1)=col2;
700     *(dest+2)=col3;
701   }
702   return;
703 
704 x1_inf_x2_and_y1_sup_y2:
705   /*
706                   (x2, y2)
707 
708 
709        (x1, y1)
710    */
711   /* remove those abs in the asm code */
712   if (abs(dx)>abs(dy))
713     goto x1_inf_x2_and_y1_sup_y2_dx_sup_dy;
714   if (abs(dx)<abs(dy))
715     goto x1_inf_x2_and_y1_sup_y2_dx_inf_dy;
716   /* here dx == dy */
717   dest=d->buffer+(y2i*SCREEN_X+(x2>>16))*3;
718   for (i=y2i; i<y1i; dest+=(SCREEN_X-1)*3, i++) {
719     *dest=col1;
720     *(dest+1)=col2;
721     *(dest+2)=col3;
722   }
723   return;
724 x1_inf_x2_and_y1_sup_y2_dx_sup_dy:
725   /*
726                     xxxx
727 		xxxx
728 	    xxxx
729 	xxxx
730   */
731   yinc=muldiv(dy, 65536, dx);
732   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
733   yf=ycur&65535;
734   dest=d->buffer+((ycur>>16)*SCREEN_X+x2i)*3;
735   for (i=x2i; i>x1i; i--, dest-=3) {
736     *dest=col1;
737     *(dest+1)=col2;
738     *(dest+2)=col3;
739     yf-=yinc;
740     if (yf>65535) {
741       yf-=65536;
742       dest+=SCREEN_X*3;
743     }
744   }
745   return;
746 x1_inf_x2_and_y1_sup_y2_dx_inf_dy:
747   /*
748           x
749 	  x
750 	  x
751 	 x
752 	 x
753 	 x
754 	x
755 	x
756 	x
757   */
758   xinc=muldiv(dx, 65536, dy);
759   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
760   xf=xcur&65535;
761   dest=d->buffer+(y2i*SCREEN_X+(xcur>>16))*3;
762   for (i=y2i; i<y1i; i++, dest+=SCREEN_X*3) {
763     *dest=col1;
764     *(dest+1)=col2;
765     *(dest+2)=col3;
766     xf+=xinc;
767     if (xf<0) {
768       xf+=65536;
769       dest-=3;
770     }
771   }
772   return;
773 
774 x1_inf_x2_and_y1_inf_y2:
775   /*
776       (x1, y1)
777 
778 
779                   (x2, y2)
780   */
781   if (abs(dx)>abs(dy))
782     goto x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy;
783   if (abs(dx)<abs(dy))
784     goto x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy;
785   /* here dx == dy */
786   dest=d->buffer+(y1i*SCREEN_X+(x1>>16))*3;
787   for (i=y1i; i<y2i; dest+=(SCREEN_X+1)*3, i++) {
788     *dest=col1;
789     *(dest+1)=col2;
790     *(dest+2)=col3;
791   }
792   return;
793 
794 x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy:
795   /*
796         xxxx
797 	    xxxx
798 	        xxxx
799    */
800   yinc=muldiv(dy, 65536, dx);
801   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
802   yf=ycur&65535;
803   dest=d->buffer+((ycur>>16)*SCREEN_X+x1i)*3;
804   for (i=x1i; i<x2i; i++, dest+=3) {
805     *dest=col1;
806     *(dest+1)=col2;
807     *(dest+2)=col3;
808     yf+=yinc;
809     if (yf>65535) {
810       yf-=65536;
811       dest+=SCREEN_X*3;
812     }
813   }
814   return;
815 x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy:
816   /*
817       x
818       x
819       x
820        x
821        x
822        x
823         x
824 	x
825 	x
826   */
827   xinc=muldiv(dx, 65536, dy);
828   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
829   xf=xcur&65535;
830   dest=d->buffer+(y1i*SCREEN_X+(xcur>>16))*3;
831   for (i=y1i; i<y2i; i++, dest+=SCREEN_X*3) {
832     *dest=col1;
833     *(dest+1)=col2;
834     *(dest+2)=col3;
835     xf+=xinc;
836     if (xf>65536) {
837       xf-=65536;
838       dest+=3;
839     }
840   }
841   return;
842 
843 x1_sup_x2:
844   if (dy<0)
845     goto x1_sup_x2_and_y1_sup_y2;
846   if (dy>0)
847     goto x1_sup_x2_and_y1_inf_y2;
848   /* x1>x2 && y1==y2 */
849   dest=d->buffer+((y2>>16)*SCREEN_X+x2i)*3;
850   for (i=x2i; i<x1i; dest+=3, i++) {
851     *dest=col1;
852     *(dest+1)=col2;
853     *(dest+2)=col3;
854   }
855   return;
856 x1_sup_x2_and_y1_sup_y2:
857   /*
858        (x2, y2)
859 
860 
861                  (x1, y1)
862    */
863   if (abs(dx)>abs(dy))
864     goto x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy;
865   if (abs(dx)<abs(dy))
866     goto x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy;
867   /* here dx == dy */
868   dest=d->buffer+(y2i*SCREEN_X+(x2>>16))*3;
869   for (i=y2i; i<y1i; dest+=(SCREEN_X+1)*3, i++) {
870     *dest=col1;
871     *(dest+1)=col2;
872     *(dest+2)=col3;
873   }
874   return;
875 x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy:
876   yinc=muldiv(dy, 65536, dx);
877   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
878   yf=ycur&65535;
879   dest=d->buffer+((ycur>>16)*SCREEN_X+x2i)*3;
880   for (i=x2i; i<x1i; i++, dest+=3) {
881     *dest=col1;
882     *(dest+1)=col2;
883     *(dest+2)=col3;
884     yf+=yinc;
885     if (yf>65535) {
886       yf-=65536;
887       dest+=SCREEN_X*3;
888     }
889   }
890   return;
891 x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy:
892   xinc=muldiv(dx, 65536, dy);
893   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
894   xf=xcur&65535;
895   dest=d->buffer+(y2i*SCREEN_X+(xcur>>16))*3;
896   for (i=y2i; i<y1i; i++, dest+=SCREEN_X*3) {
897     *dest=col1;
898     *(dest+1)=col2;
899     *(dest+2)=col3;
900     xf+=xinc;
901     if (xf>65536) {
902       xf-=65536;
903       dest+=3;
904     }
905   }
906   return;
907 
908 x1_sup_x2_and_y1_inf_y2:
909   /*
910                  (x1, y1)
911 
912 
913       (x2, y2)
914    */
915   if (abs(dx)>abs(dy))
916     goto x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy;
917   if (abs(dx)<abs(dy))
918     goto x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy;
919   /* here dx == dy */
920   dest=d->buffer+(y1i*SCREEN_X+(x1>>16))*3;
921   for (i=y1i; i<y2i; dest+=(SCREEN_X-1)*3, i++) {
922     *dest=col1;
923     *(dest+1)=col2;
924     *(dest+2)=col3;
925   }
926   return;
927 x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy:
928   yinc=muldiv(dy, 65536, dx);
929   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
930   yf=ycur&65535;
931   dest=d->buffer+((ycur>>16)*SCREEN_X+x1i)*3;
932   for (i=x1i; i>x2i; i--, dest-=3) {
933     *dest=col1;
934     *(dest+1)=col2;
935     *(dest+2)=col3;
936     yf-=yinc;
937     if (yf>65535) {
938       yf-=65536;
939       dest+=SCREEN_X*3;
940     }
941   }
942   return;
943 x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy:
944   xinc=muldiv(dx, 65536, dy);
945   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
946   xf=xcur&65535;
947   dest=d->buffer+(y1i*SCREEN_X+(xcur>>16))*3;
948   for (i=y1i; i<y2i; i++, dest+=SCREEN_X*3) {
949     *dest=col1;
950     *(dest+1)=col2;
951     *(dest+2)=col3;
952     xf+=xinc;
953     if (xf<0) {
954       xf+=65536;
955       dest-=3;
956     }
957   }
958   return;
959 }
960 
drawline32(device * d,line * l)961 void drawline32(device *d, line *l)
962 {
963   /* lots of goto for lisibility (if if else if if else else is impossible to debug) */
964   register int x1=l->p1.x*65536.,
965                x2=l->p2.x*65536.,
966                y1=l->p1.y*65536.,
967                y2=l->p2.y*65536.;
968   register int dx, dy;
969   register int xcur;
970   register int xinc;
971   register int ycur;
972   register int yinc;
973   register int i;
974   register int y1i=(y1+65535)>>16, y2i=(y2+65535)>>16;
975   register int x1i=(x1+65535)>>16, x2i=(x2+65535)>>16;
976 /*
977   register int y1i=y1>>16, y2i=y2>>16;
978   register int x1i=x1>>16, x2i=x2>>16;
979 */
980   register unsigned int *dest;
981   register unsigned int col1=l->color;
982   register int xf;
983   register int yf;
984 
985   /* in asm, those two subs are good for us, because we can test if x1<x2 and if y1<y2 at the same time, but it's C */
986   dx=x2-x1;
987   dy=y2-y1;
988 
989   if (dx<0)
990     goto x1_sup_x2;
991   if (dx)
992     goto x1_inf_x2;
993 
994   /* here x1==x2 */
995   if (dy<0)
996     goto x1_eq_x2_and_y1_sup_y2;
997   if (dy>0)
998     goto x1_eq_x2_and_y1_inf_y2;
999   /* here x1==x2 && y1==y2 */
1000   if (y1i<y2i) {
1001     dest=(unsigned int *)d->buffer+y1i*SCREEN_X+(x1>>16);
1002   } else {
1003     dest=(unsigned int *)d->buffer+y2i*SCREEN_X+(x1>>16);
1004   }
1005   *dest=col1;
1006   return;
1007 x1_eq_x2_and_y1_sup_y2:
1008   dest=(unsigned int *)d->buffer+y2i*SCREEN_X+(x1>>16);
1009   for (i=y2i; i<y1i; dest+=SCREEN_X, i++) {
1010     *dest=col1;
1011   }
1012   return;
1013 x1_eq_x2_and_y1_inf_y2:
1014   dest=(unsigned int *)d->buffer+y1i*SCREEN_X+(x1>>16);
1015   for (i=y1i; i<y2i; dest+=SCREEN_X, i++) {
1016     *dest=col1;
1017   }
1018   return;
1019 
1020 x1_inf_x2:
1021   if (dy<0)
1022     goto x1_inf_x2_and_y1_sup_y2;
1023   if (dy>0)
1024     goto x1_inf_x2_and_y1_inf_y2;
1025   /* x1<x2 && y1==y2 */
1026   dest=(unsigned int *)d->buffer+(y1>>16)*SCREEN_X+x1i;
1027   for (i=x1i; i<x2i; dest++, i++) {
1028     *dest=col1;
1029   }
1030   return;
1031 
1032 x1_inf_x2_and_y1_sup_y2:
1033   /*
1034                   (x2, y2)
1035 
1036 
1037        (x1, y1)
1038    */
1039   /* remove those abs in the asm code */
1040   if (abs(dx)>abs(dy))
1041     goto x1_inf_x2_and_y1_sup_y2_dx_sup_dy;
1042   if (abs(dx)<abs(dy))
1043     goto x1_inf_x2_and_y1_sup_y2_dx_inf_dy;
1044   /* here dx == dy */
1045   dest=(unsigned int *)d->buffer+y2i*SCREEN_X+(x2>>16);
1046   for (i=y2i; i<y1i; dest+=SCREEN_X-1, i++) {
1047     *dest=col1;
1048   }
1049   return;
1050 x1_inf_x2_and_y1_sup_y2_dx_sup_dy:
1051   /*
1052                     xxxx
1053 		xxxx
1054 	    xxxx
1055 	xxxx
1056   */
1057   yinc=muldiv(dy, 65536, dx);
1058   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
1059   yf=ycur&65535;
1060   dest=(unsigned int *)d->buffer+(ycur>>16)*SCREEN_X+x2i;
1061   for (i=x2i; i>x1i; i--, dest--) {
1062     *dest=col1;
1063     yf-=yinc;
1064     if (yf>65535) {
1065       yf-=65536;
1066       dest+=SCREEN_X;
1067     }
1068   }
1069   return;
1070 x1_inf_x2_and_y1_sup_y2_dx_inf_dy:
1071   /*
1072           x
1073 	  x
1074 	  x
1075 	 x
1076 	 x
1077 	 x
1078 	x
1079 	x
1080 	x
1081   */
1082   xinc=muldiv(dx, 65536, dy);
1083   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
1084   xf=xcur&65535;
1085   dest=(unsigned int *)d->buffer+y2i*SCREEN_X+(xcur>>16);
1086   for (i=y2i; i<y1i; i++, dest+=SCREEN_X) {
1087     *dest=col1;
1088     xf+=xinc;
1089     if (xf<0) {
1090       xf+=65536;
1091       dest--;
1092     }
1093   }
1094   return;
1095 
1096 x1_inf_x2_and_y1_inf_y2:
1097   /*
1098       (x1, y1)
1099 
1100 
1101                   (x2, y2)
1102   */
1103   if (abs(dx)>abs(dy))
1104     goto x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy;
1105   if (abs(dx)<abs(dy))
1106     goto x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy;
1107   /* here dx == dy */
1108   dest=(unsigned int *)d->buffer+y1i*SCREEN_X+(x1>>16);
1109   for (i=y1i; i<y2i; dest+=SCREEN_X+1, i++) {
1110     *dest=col1;
1111   }
1112   return;
1113 
1114 x1_inf_x2_and_y1_inf_y2_and_dx_sup_dy:
1115   /*
1116         xxxx
1117 	    xxxx
1118 	        xxxx
1119    */
1120   yinc=muldiv(dy, 65536, dx);
1121   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
1122   yf=ycur&65535;
1123   dest=(unsigned int *)d->buffer+(ycur>>16)*SCREEN_X+x1i;
1124   for (i=x1i; i<x2i; i++, dest++) {
1125     *dest=col1;
1126     yf+=yinc;
1127     if (yf>65535) {
1128       yf-=65536;
1129       dest+=SCREEN_X;
1130     }
1131   }
1132   return;
1133 x1_inf_x2_and_y1_inf_y2_and_dx_inf_dy:
1134   /*
1135       x
1136       x
1137       x
1138        x
1139        x
1140        x
1141         x
1142 	x
1143 	x
1144   */
1145   xinc=muldiv(dx, 65536, dy);
1146   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
1147   xf=xcur&65535;
1148   dest=(unsigned int *)d->buffer+y1i*SCREEN_X+(xcur>>16);
1149   for (i=y1i; i<y2i; i++, dest+=SCREEN_X) {
1150     *dest=col1;
1151     xf+=xinc;
1152     if (xf>65536) {
1153       xf-=65536;
1154       dest++;
1155     }
1156   }
1157   return;
1158 
1159 x1_sup_x2:
1160   if (dy<0)
1161     goto x1_sup_x2_and_y1_sup_y2;
1162   if (dy>0)
1163     goto x1_sup_x2_and_y1_inf_y2;
1164   /* x1>x2 && y1==y2 */
1165   dest=(unsigned int *)d->buffer+(y2>>16)*SCREEN_X+x2i;
1166   for (i=x2i; i<x1i; dest++, i++) {
1167     *dest=col1;
1168   }
1169   return;
1170 x1_sup_x2_and_y1_sup_y2:
1171   /*
1172        (x2, y2)
1173 
1174 
1175                  (x1, y1)
1176    */
1177   if (abs(dx)>abs(dy))
1178     goto x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy;
1179   if (abs(dx)<abs(dy))
1180     goto x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy;
1181   /* here dx == dy */
1182   dest=(unsigned int *)d->buffer+y2i*SCREEN_X+(x2>>16);
1183   for (i=y2i; i<y1i; dest+=SCREEN_X+1, i++) {
1184     *dest=col1;
1185   }
1186   return;
1187 x1_sup_x2_and_y1_sup_y2_and_dx_sup_dy:
1188   yinc=muldiv(dy, 65536, dx);
1189   ycur=y2+muldiv(yinc, (x2i<<16)-x2, 65536);
1190   yf=ycur&65535;
1191   dest=(unsigned int *)d->buffer+(ycur>>16)*SCREEN_X+x2i;
1192   for (i=x2i; i<x1i; i++, dest++) {
1193     *dest=col1;
1194     yf+=yinc;
1195     if (yf>65535) {
1196       yf-=65536;
1197       dest+=SCREEN_X;
1198     }
1199   }
1200   return;
1201 x1_sup_x2_and_y1_sup_y2_and_dx_inf_dy:
1202   xinc=muldiv(dx, 65536, dy);
1203   xcur=x2+muldiv(xinc, (y2i<<16)-y2, 65536);
1204   xf=xcur&65535;
1205   dest=(unsigned int *)d->buffer+y2i*SCREEN_X+(xcur>>16);
1206   for (i=y2i; i<y1i; i++, dest+=SCREEN_X) {
1207     *dest=col1;
1208     xf+=xinc;
1209     if (xf>65536) {
1210       xf-=65536;
1211       dest++;
1212     }
1213   }
1214   return;
1215 
1216 x1_sup_x2_and_y1_inf_y2:
1217   /*
1218                  (x1, y1)
1219 
1220 
1221       (x2, y2)
1222    */
1223   if (abs(dx)>abs(dy))
1224     goto x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy;
1225   if (abs(dx)<abs(dy))
1226     goto x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy;
1227   /* here dx == dy */
1228   dest=(unsigned int *)d->buffer+y1i*SCREEN_X+(x1>>16);
1229   for (i=y1i; i<y2i; dest+=SCREEN_X-1, i++) {
1230     *dest=col1;
1231   }
1232   return;
1233 x1_sup_x2_and_y1_inf_y2_and_dx_sup_dy:
1234   yinc=muldiv(dy, 65536, dx);
1235   ycur=y1+muldiv(yinc, (x1i<<16)-x1, 65536);
1236   yf=ycur&65535;
1237   dest=(unsigned int *)d->buffer+(ycur>>16)*SCREEN_X+x1i;
1238   for (i=x1i; i>x2i; i--, dest--) {
1239     *dest=col1;
1240     yf-=yinc;
1241     if (yf>65535) {
1242       yf-=65536;
1243       dest+=SCREEN_X;
1244     }
1245   }
1246   return;
1247 x1_sup_x2_and_y1_inf_y2_and_dx_inf_dy:
1248   xinc=muldiv(dx, 65536, dy);
1249   xcur=x1+muldiv(xinc, (y1i<<16)-y1, 65536);
1250   xf=xcur&65535;
1251   dest=(unsigned int *)d->buffer+y1i*SCREEN_X+(xcur>>16);
1252   for (i=y1i; i<y2i; i++, dest+=SCREEN_X) {
1253     *dest=col1;
1254     xf+=xinc;
1255     if (xf<0) {
1256       xf+=65536;
1257       dest--;
1258     }
1259   }
1260   return;
1261 }
1262 
drawline(device * d,line * l)1263 void drawline(device *d, line *l)
1264 {
1265 #if 0
1266   void fill_left(device *, point *, point *);
1267   extern device_line *the_lines;
1268   int miny, maxy;
1269   int minx, maxx;
1270 
1271   if (l->p1.y<l->p2.y) {
1272     miny=((int)(l->p1.y*65536.)+65535)>>16;
1273     maxy=((int)(l->p2.y*65536.)+65535)>>16;
1274   } else {
1275     miny=((int)(l->p2.y*65536.)+65535)>>16;
1276     maxy=((int)(l->p1.y*65536.)+65535)>>16;
1277   }
1278 
1279   fill_left(d, &l->p1, &l->p2);
1280 
1281   minx=the_lines[miny].x_left/65536+1;
1282   maxx=the_lines[maxy-1].x_left/65536+1;
1283 
1284   if (d->depth==8) {
1285     register int i, j;
1286     register int col=l->color;
1287     register unsigned char *p=(unsigned char *)d->buffer, *q;
1288     register device_line *cur_line=&the_lines[(int)miny];
1289 
1290     p+=miny*SCREEN_X;
1291 
1292     if (minx<maxx) {
1293       for (i=miny; i<maxy-1; i++, p+=SCREEN_X, cur_line++) {
1294 	register const int xleft=(cur_line->x_left/65536)+1;
1295 	register /*const */int xright=((cur_line+1)->x_left/65536);
1296 	q=p;
1297 	q+=xleft;
1298 	if (xleft>xright)
1299 	  xright++;
1300 	for (j=xleft; j<=xright /*cur_line->x_right*/; j++, q++)
1301 	  *q=col;
1302       }
1303     } else {
1304       for (i=miny; i<maxy-1; i++, p+=SCREEN_X, cur_line++) {
1305 	register /*const */int xright=(cur_line->x_left/65536)+1;
1306 	register const int xleft=(cur_line+1)->x_left/65536;
1307 	q=p;
1308 	q+=xleft;
1309 	if (xleft>xright)
1310 	  xright++;
1311 	for (j=xleft; j<=xright /*cur_line->x_right*/; j++, q++)
1312 	  *q=col;
1313       }
1314     }
1315   } else
1316     drawline16(d, l);
1317 #endif
1318   if (d->depth==8)
1319     drawline8(d, l);
1320   else if (d->depth==16)
1321     drawline16(d, l);
1322   else if (d->depth==24)
1323     drawline24(d, l);
1324   else if (d->depth==32)
1325     drawline32(d, l);
1326 }
1327 
1328 #define LEFT	1
1329 #define RIGHT	2
1330 #define UP	4
1331 #define DOWN	8
1332 
copy_point(point * dest,point * src)1333 static inline void copy_point(point *dest, point *src)
1334 {
1335   /* this one is useless, take it away !!! */
1336   memcpy(dest, src, sizeof(point));
1337 }
1338 
do_clip_left(point * res,point * p1,point * p2)1339 static inline void do_clip_left(point *res, point *p1, point *p2)
1340 {
1341   register double factor=p2->x/(p2->x-p1->x);
1342   res->x=0;
1343   res->y=p2->y-(p2->y-p1->y)*factor;
1344 }
1345 
do_clip_right(point * res,point * p1,point * p2)1346 static inline void do_clip_right(point *res, point *p1, point *p2)
1347 {
1348   register double factor=(p2->x-SCREEN_X+2)/(p2->x-p1->x);
1349   res->x=SCREEN_X-2;
1350   res->y=p2->y-(p2->y-p1->y)*factor;
1351 }
1352 
do_clip_up(point * res,point * p1,point * p2)1353 static inline void do_clip_up(point *res, point *p1, point *p2)
1354 {
1355   register double factor=p2->y/(p2->y-p1->y);
1356   res->x=p2->x-(p2->x-p1->x)*factor;
1357   res->y=0;
1358 }
1359 
do_clip_down(point * res,point * p1,point * p2)1360 static inline void do_clip_down(point *res, point *p1, point *p2)
1361 {
1362   register double factor=(p2->y-(SCREEN_Y-2))/(p2->y-p1->y);
1363   res->x=p2->x-(p2->x-p1->x)*factor;
1364   res->y=SCREEN_Y-2;
1365 }
1366 
clip_and_draw_line(device * d,line * l)1367 void clip_and_draw_line(device *d, line *l)
1368 {
1369   register int clip=0;
1370   register double a, b;
1371   register point *pp, *pp1;
1372   point next;
1373 
1374   /* step 1 - do we clip ? */
1375   a=l->p1.x;
1376   b=l->p1.y;
1377   if (a<0)
1378     clip|=LEFT;
1379   if (a>SCREEN_X-2)
1380       clip|=RIGHT;
1381   if (b<0)
1382     clip|=UP;
1383   if (b>SCREEN_Y-2)
1384     clip|=DOWN;
1385   a=l->p2.x;
1386   b=l->p2.y;
1387   if (a<0)
1388     clip|=LEFT;
1389   if (a>SCREEN_X-2)
1390       clip|=RIGHT;
1391   if (b<0)
1392     clip|=UP;
1393   if (b>SCREEN_Y-2)
1394     clip|=DOWN;
1395 
1396   pp=&l->p1;
1397   pp1=&l->p2;
1398 
1399   /* step 2 - clip left ? */
1400   if (!(clip&LEFT))
1401     goto no_left;
1402   if (pp->x>0 && pp1->x<0) {
1403     do_clip_left(&next, pp, pp1);
1404     copy_point(pp1, &next);
1405   } else if (pp->x<0 && pp1->x>0) {
1406     do_clip_left(&next, pp, pp1);
1407     copy_point(pp, &next);
1408   }
1409 
1410 no_left:
1411   /* step 3 - right ? */
1412   if (!(clip&RIGHT))
1413     goto no_right;
1414   if (pp->x<SCREEN_X-2 && pp1->x>SCREEN_X-2) {
1415     do_clip_right(&next, pp, pp1);
1416     copy_point(pp1, &next);
1417   } else if (pp->x>SCREEN_X-2 && pp1->x<SCREEN_X-2) {
1418     do_clip_right(&next, pp, pp1);
1419     copy_point(pp, &next);
1420   }
1421 
1422 no_right:
1423   /* step 4 - up ? */
1424   if (!(clip&UP))
1425     goto no_up;
1426   if (pp->y>0 && pp1->y<0) {
1427     do_clip_up(&next, pp, pp1);
1428     copy_point(pp1, &next);
1429   } else if (pp->y<0 && pp1->y>0) {
1430     do_clip_up(&next, pp, pp1);
1431     copy_point(pp, &next);
1432   }
1433 
1434 no_up:
1435   /* step 5 - down ? */
1436   if (!(clip&DOWN))
1437     goto no_down;
1438   if (pp->y<SCREEN_Y-2 && pp1->y>SCREEN_Y-2) {
1439     do_clip_down(&next, pp, pp1);
1440     copy_point(pp1, &next);
1441   } else if (pp->y>SCREEN_Y-2 && pp1->y<SCREEN_Y-2) {
1442     do_clip_down(&next, pp, pp1);
1443     copy_point(pp, &next);
1444   }
1445 
1446 no_down:
1447   /* step 6 - draw the resulting line (clipping may have outed it all, so let's test it) */
1448   if (pp->x>=0 && pp->x<=SCREEN_X-2 && pp->y>=0 && pp->y<=SCREEN_Y-2
1449       && pp1->x>=0 && pp1->x<=SCREEN_X-2 && pp1->y>=0 && pp1->y<=SCREEN_Y-2)
1450     drawline(d, l);
1451 #if 0
1452   else
1453     fprintf(stderr, "clip=%d p1=%f %f, p2=%f %f\n", clip, pp->x, pp->y, pp1->x, pp1->y);
1454 #endif
1455 }
1456