/*

    line.h

    Copyright 1994, August 22 by Alec Russell, ALL rights reserved
    Permission granted to use as you wish.

    Created - 1994/8/22

    A slow hi-level line drawing func. Handy to move sprites
    along arbitrary straight line paths.

    History:
        New file

*/

#ifndef DEF_LINE
#define DEF_LINE 1

#include <g_def.h>  // BYTE etc...

enum QUAD
{
   Q_ZERO,
   Q_ONE,
   Q_TWO,
   Q_THREE,
   Q_VERT,
   Q_HORZ,
   Q_SAME
};

typedef struct
   {
   BYTE quad;
   short step;
   short x, y, x1, y1;
   short ai, bi, yi, d, dx, dy;
   }
d_line_t;

void init_dline(short x0, short y0, short x1, short y1, short step, d_line_t *dl);
short next_dline(d_line_t *dl);

#endif

/* ------------------------------ EOF -------------------------------- */



/*

    line.c

    Copyright 1994, August 22 by Alec Russell, ALL rights reserved
    Permission granted to use as you wish.

    Created - 1994/8/22

    generic line drawing, pretty slow, but good for smooth
    animation for items following arbitrary lines

    History:
        New file

*/

#include <line.h>
#include <stdlib.h>


/* ---------------------- init_dline() ------------------ August 22,1994 */
void init_dline(short x0, short y0, short x1, short y1, short step, d_line_t *dl)
{

   dl->step=step;
   dl->x=x0;
   dl->y=y0;

   dl->x1=x1;
   dl->y1=y1;

   dl->dy=abs(y1 - y0);
   dl->dx=abs(x1 - x0);

   if ( x1 == x0 && y0 == y1 )
      {
      dl->quad=Q_SAME;
      }
   else
      {
      if ( x1 == x0 )
         {
         dl->quad=Q_VERT;
         if ( y1 > y0 )
            dl->dy=1;
         else
            dl->dy=-1;
         }
      else
         {
         if ( y1 == y0 )
            {
            dl->quad=Q_HORZ;
            if ( x1 > x0 )
               dl->dy=1;
            else
               dl->dy=-1;
            }
         else
            {
            if ( x1 > x0 && dl->dy < dl->dx )
               {
pr2("quad = zero");
               dl->quad=Q_ZERO;
               dl->yi=y1 > y0 ? 1 : -1;
               dl->dx=x1 - x0;
               dl->dy=abs(y1 - y0);
               dl->d=(dl->dy<<1) - dl->dx;
               dl->ai=(dl->dy - dl->dx)<<1;
               dl->bi=dl->dy<<1;
               }
            else
               {
               if ( x1 < x0 && dl->dy < dl->dx )
                  {
                  dl->quad=Q_TWO;
pr2("quad = two");
                  dl->yi=y1 > y0 ? 1 : -1;
                  dl->dx=x0 - x1;
                  dl->dy=abs(y1 - y0);
                  dl->d=(dl->dy<<1) - dl->dx;
                  dl->ai=(dl->dy - dl->dx)<<1;
                  dl->bi=dl->dy<<1;
                  }
               else
                  {
                  if ( y1 < y0 )
                     {
pr2("quad = one");
                     dl->quad=Q_ONE;
                     dl->yi=x1 > x0 ? 1 : -1;
                     dl->dx=y0 - y1;
                     dl->dy=abs(x1 - x0);
                     dl->d=(dl->dy<<1) - dl->dx;
                     dl->ai=(dl->dy - dl->dx)<<1;
                     dl->bi=dl->dy<<1;
                     }
                  else
                     {
pr2("quad = three");
                     dl->quad=Q_THREE;
                     dl->yi=x1 > x0 ? 1 : -1;
                     dl->dx=y1 - y0;
                     dl->dy=abs(x1 - x0);
                     dl->d=(dl->dy<<1) - dl->dx;
                     dl->ai=(dl->dy - dl->dx)<<1;
                     dl->bi=dl->dy<<1;
                     }
                  }
               }
            }

         }
      }
}


/* ---------------------- next_dline() ------------------ August 22,1994 */
short next_dline(d_line_t *dl)
{
   short done=0;
   short i;

   i=dl->step;
   while ( i && !done )
      {
      switch ( dl->quad )
         {
         case Q_ZERO:
            if ( dl->d >= 0 )
               {
               dl->y+=dl->yi;
               dl->d+=dl->ai;
               }
            else
               dl->d+=dl->bi;
            dl->x++;
            break;

         case Q_ONE:
            if ( dl->d >= 0 )
               {
               dl->x+=dl->yi;
               dl->d+=dl->ai;
               }
            else
               dl->d+=dl->bi;
            dl->y--;
            break;

         case Q_TWO:
            if ( dl->d >= 0 )
               {
               dl->y+=dl->yi;
               dl->d+=dl->ai;
               }
            else
               dl->d+=dl->bi;
            dl->x--;
            break;

         case Q_THREE:
            if ( dl->d >= 0 )
               {
               dl->x+=dl->yi;
               dl->d+=dl->ai;
               }
            else
               dl->d+=dl->bi;
            dl->y++;
            break;

         case Q_VERT:
            dl->y+=dl->dy;
            break;

         case Q_HORZ:
            dl->x+=dl->dy;
            break;
         }

      if ( dl->x == dl->x1 && dl->y == dl->y1 )
         done=1;

      i--;
      }

   return done;
}

