home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / gl / line.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-30  |  4.4 KB  |  200 lines

  1. /* Framebuffer Graphics Libary for Linux, Copyright 1993 Harm Hanemaayer */
  2. /* line.c    Line drawing */
  3.  
  4.  
  5. #include <stdlib.h>
  6. #include <vga.h>
  7. #include "inlstring.h"        /* include inline string operations */
  8.  
  9. #include "vgagl.h"
  10. #include "def.h"
  11. #include "driver.h"
  12.  
  13.  
  14. /* We use the 32-bit to 64-bit multiply and 64-bit to 32-bit divide of the */
  15. /* 386 (which gcc doesn't know well enough) to efficiently perform integer */
  16. /* scaling without having to worry about overflows. */
  17.  
  18. static inline int muldiv64( int m1, int m2, int d ) {
  19. /* int32 * int32 -> int64 / int32 -> int32 */
  20.     int result;
  21.     __asm__(
  22.         "imull %%edx\n\t"
  23.         "idivl %3\n\t"
  24.         : "=a" (result)            /* out */
  25.         : "a" (m1), "d" (m2), "g" (d)    /* in */
  26.         : "ax", "dx"            /* mod */
  27.     );
  28.     return result;
  29. }
  30.  
  31. static inline int gl_regioncode( int x, int y ) {
  32.     int dx1, dx2, dy1, dy2;
  33.     int result;
  34.     result = 0;
  35.     dy2 = __clipy2 - y;
  36.     __asm__("btl $31,%1\n\t"
  37.         "adcl $0,%0"
  38.         : "=r" ((int) result)
  39.         : "rm" ((int) dy2), "0" ((int) result)
  40.         );
  41.     result <<= 1;
  42.     dy1 = y - __clipy1;
  43.     __asm__("btl $31,%1\n\t"
  44.         "adcl $0,%0"
  45.         : "=r" ((int) result)
  46.         : "rm" ((int) dy1), "0" ((int) result)
  47.         );
  48.     result <<= 1;
  49.     dx2 = __clipx2 - x;
  50.     __asm__("btl $31,%1\n\t"
  51.         "adcl $0,%0"
  52.         : "=r" ((int) result)
  53.         : "rm" ((int) dx2), "0" ((int) result)
  54.         );
  55.     result <<= 1;
  56.     dx1 = x - __clipx1;
  57.     __asm__("btl $31,%1\n\t"
  58.         "adcl $0,%0"
  59.         : "=r" ((int) result)
  60.         : "rm" ((int) dx1), "0" ((int) result)
  61.         );
  62.     return result;
  63. }            
  64.  
  65.  
  66. /* Partly based on vgalib by Tommy Frandsen */
  67. /* This would be a lot faster if setpixel was inlined */
  68.  
  69. void gl_line( int x1, int y1, int x2, int y2, int c ) {
  70.     uchar *vp;
  71.     int dx, dy, ax, ay, sx, sy, x, y;
  72.     
  73.     if (__clip)
  74.         /* Cohen & Sutherland algorithm */
  75.         for (;;) {
  76.             int r1 = gl_regioncode(x1, y1);
  77.             int r2 = gl_regioncode(x2, y2);
  78.             if (!(r1 | r2))
  79.                 break;        /* completely inside */
  80.             if (r1 & r2)
  81.                 return;        /* completely outside */
  82.             if (r1 == 0) {
  83.                 swap(x1, x2);        /* make sure first */
  84.                 swap(y1, y2);        /* point is outside */
  85.                 r1 = r2;
  86.             }
  87.             if (r1 & 1) {        /* left */ 
  88.                 y1 += muldiv64(__clipx1 - x1, y2 - y1, x2 - x1);
  89.                 x1 = __clipx1;
  90.             }
  91.             else
  92.             if (r1 & 2) {        /* right */
  93.                 y1 += muldiv64(__clipx2 - x1, y2 - y1, x2 - x1);
  94.                 x1 = __clipx2;
  95.             }
  96.             else
  97.             if (r1 & 4) {        /* top */
  98.                 x1 += muldiv64(__clipy1 - y1, x2 - x1, y2 - y1);
  99.                 y1 = __clipy1;
  100.             }
  101.             else
  102.             if (r1 & 8) {        /* bottom */
  103.                 x1 += muldiv64(__clipy2 - y1, x2 - x1, y2 - y1);
  104.                 y1 = __clipy2;
  105.             }
  106.         }
  107.  
  108.         dx = x2 - x1;
  109.         dy = y2 - y1;
  110.         ax = abs(dx) << 1;
  111.         ay = abs(dy) << 1;
  112.         sx = (dx >= 0) ? 1 : -1;
  113.         sy = (dy >= 0) ? 1 : -1;
  114.     x = x1;
  115.     y = y1;
  116.     
  117.     if (ax > ay) {
  118.         int d = ay - (ax >> 1);
  119.         while (x != x2) {
  120.             setpixel(x, y, c);
  121.  
  122.                     if (d > 0 || d == 0 && sx == 1) {
  123.                         y += sy;
  124.                         d -= ax;
  125.                    }
  126.                     x += sx;
  127.                     d += ay; 
  128.           }
  129.         } 
  130.         else {
  131.             int sy = (dy >= 0) ? 1 : -1;
  132.         int d = ax - (ay >> 1);
  133.         while (y != y2) {
  134.             setpixel(x, y, c);
  135.  
  136.                     if (d > 0 || d == 0 && sy == 1) {
  137.                         x += sx;
  138.                         d -= ay;
  139.                     }
  140.                     y += sy;
  141.                     d += ax;
  142.             }
  143.         }
  144.         setpixel(x, y, c);
  145. }
  146.  
  147.  
  148. static void gl_setcirclepixels( int x, int y, int sx, int sy, int c ) {
  149.     if (__clip) {
  150.         int z = max(x, y);
  151.         if (sx - z < __clipx1 || sx + z  > __clipx2 
  152.         || sy - z < __clipy1 || sy + z > __clipy2) {
  153.             /* use setpixel clipping */
  154.             gl_setpixel(sx + x, sy + y, c);
  155.             gl_setpixel(sx - x, sy + y, c);
  156.             gl_setpixel(sx + x, sy - y, c);
  157.             gl_setpixel(sx - x, sy - y, c);
  158.             gl_setpixel(sx + y, sy + x, c);
  159.             gl_setpixel(sx - y, sy + x, c);
  160.             gl_setpixel(sx + y, sy - x, c);
  161.             gl_setpixel(sx - y, sy - x, c);
  162.             return;
  163.         }
  164.     }
  165.     setpixel(sx + x, sy + y, c);
  166.     setpixel(sx - x, sy + y, c);
  167.     setpixel(sx + x, sy - y, c);
  168.     setpixel(sx - x, sy - y, c);
  169.     setpixel(sx + y, sy + x, c);
  170.     setpixel(sx - y, sy + x, c);
  171.     setpixel(sx + y, sy - x, c);
  172.     setpixel(sx - y, sy - x, c);
  173. }
  174.  
  175. void gl_circle( int sx, int sy, int r, int c ) {
  176.     int x, y, d;
  177.     if (r < 1) {
  178.         gl_setpixel(sx, sy, c); 
  179.         return;
  180.     }
  181.     if (__clip)
  182.         if (sx + r < __clipx1 || sx - r > __clipx2
  183.         || sy + r < __clipy1 || sy - r > __clipy2)
  184.             return;
  185.     x = 0;
  186.     y = r;
  187.     d = 1 - r;
  188.     gl_setcirclepixels(x, y, sx, sy, c);
  189.     while (x < y) {
  190.         if (d < 0) 
  191.             d += x * 2 + 3;
  192.         else {
  193.             d += x * 2 - y * 2 + 5;
  194.             y--;
  195.         }
  196.         x++;
  197.         gl_setcirclepixels(x, y, sx, sy, c);
  198.     }
  199. }
  200.