/*--------------------------------------------------------------------------
 * File: line.c
 * Written by: Alexander Boczar, 1997-03-29
 * Description: Line drawer for lookup color based drivers.
 *
 * Updates:
 * -- Date -- | ----- Name ----- |-- Did what....
 * 1997-04-02 | Alexander Boczar | Snabbade upp ngt med constanta varibler
 *
 -------------------------------------------------------------------------------*/

#include "system/xstdlib.h"
#include "drivers/drv8.h"
#include "draw8/draw8.h"
#include "misc/clip.h"

typedef struct
{
	float x;
	float y;
	float z;
	float l;
} COORD;

void line( BUFF *buff, const XYZ p1, const XYZ p2, BYTE col)
{
	COORD	c1,c2;
	register int x,y,z,l;
	register int xadd,yadd,zadd,ladd;
	register int offset;
  int len;
  int i;
	BYTE *vscreen = buff->image;
	BYTE *lighttab = buff->lighttab;
	BYTE *transtab = buff->transtab;
  int *zbuffer = buff->zbuffer;
	int *ytab = buff->ytab;

	c1.x = p1.x;
	c1.y = p1.y;

	c2.x = p2.x;
	c2.y = p2.y;

	i = 4;

	if( zbuffer != NULL)
		c1.z = p1.z, c2.z = p2.z;

	if( lighttab != NULL)
		c1.l = p1.l, c2.l = p2.l;

	if ( !xyclip( i, (float *)&c1, (float *)&c2, buff->minx, buff->maxx, buff->miny, buff->maxy))
		return;

	xadd = c2.x - c1.x;
	yadd = c2.y - c1.y;
  if ( abs(xadd) > abs(yadd)) len = abs(xadd);
    else len = abs( yadd);

	if( !len)
		return;

	xadd = (xadd * 65536) / len;
  yadd = (yadd * 65536) / len;

  x = c1.x * 65536;
  y = c1.y * 65536;

	if( zbuffer != NULL)
	{
		zadd = c2.z - c1.z;
  	zadd = (zadd * 65536) / len;
  	z = c1.z * 65536;
	}
	if( lighttab != NULL)
	{
		ladd = c2.l - c1.l;
  	ladd = (ladd * 65536) / len;
  	l = c1.l * 65536;
	}

	if( zbuffer != NULL)
	{
		if( lighttab != NULL)
		{
			if( transtab != NULL)
			{
				for( i=0; i<len; i++)// Z,L,T
			  {
					offset = (x >> 16) + ytab[y >> 16];
          if ( zbuffer[offset] > z)
					{
				    zbuffer[offset] = z;
				    vscreen[offset] = transtab[ (lighttab[ ((l >> 8) & ~0xff) + col] << 8) + *vscreen];
					}
				  x += xadd;
				  y += yadd;
				  z += zadd;
				  l += ladd;
				}
			}
			else
			{
				for( i=0; i<len; i++)// Z,L
			  {
					offset = (x >> 16) + ytab[y >> 16];
          if ( zbuffer[offset] > z)
					{
				    zbuffer[offset] = z;
				    vscreen[offset] = lighttab[ ((l >> 8) & ~0xff) + col];
					}
				  x += xadd;
				  y += yadd;
				  z += zadd;
				  l += ladd;
				}
			}
		}
		else
		{
			if( transtab != NULL)
			{
				col <<= 8;
				for( i=0; i<len; i++)// Z,T
			  {
					offset = (x >> 16) + ytab[y >> 16];
          if ( zbuffer[offset] > z)
					{
				    zbuffer[offset] = z;
				    vscreen[offset] = transtab[ col + *vscreen];
					}
				  x+=xadd;
				  y+=yadd;
				  z+=zadd;
				}
			}
			else
			{
				for( i=0; i<len; i++)// Z
			  {
					offset = (x >> 16) + ytab[y >> 16];
          if ( zbuffer[offset] > z)
					{
				    zbuffer[offset] = z;
				    vscreen[offset] = col;
					}
				  x+=xadd;
				  y+=yadd;
				  z+=zadd;
				}
			}
		}
	}
	else
	{
		if( lighttab != NULL)
		{
			if( transtab != NULL)
			{
				for( i=0; i<len; i++)// L,T
			  {
					offset = (x >> 16) + ytab[y >> 16];
				  vscreen[offset] = transtab[ (lighttab[ ((l >> 8) & ~0xff) + col] << 8) + *vscreen];
				  x+=xadd;
				  y+=yadd;
				  l+=ladd;
				}
			}
			else
			{
				for( i=0; i<=len; i++)// L
			  {
					offset = (x >> 16) + ytab[y >> 16];
				  vscreen[offset] = lighttab[ ((l >> 8) & ~0xff) + col];
				  x+=xadd;
				  y+=yadd;
				  l+=ladd;
				}
			}
		}
		else
		{
			if( transtab != NULL)
			{
				col <<= 8;
				for( i=0; i<len; i++)// T
			  {
					offset = (x >> 16) + ytab[y >> 16];
				  vscreen[offset] = transtab[ col + *vscreen];
				  x+=xadd;
				  y+=yadd;
				}
			}
			else
			{
				for( i=0; i<len; i++)//
			  {
					offset = (x >> 16) + ytab[y >> 16];
				  vscreen[offset] = col;
				  x+=xadd;
				  y+=yadd;
				}
			}
		}

	}
}

