
// draw.c
#include	"r_local.h"



image_t		*draw_chars;				// 8*8 graphic characters

//=============================================================================

/*
================
Draw_FindPic
================
*/
image_t *Draw_FindPic (const char *name, int flags)
{
	image_t	*image;
	char	fullname[MAX_QPATH];

	if (name[0] != '/' && name[0] != '\\')
	{
		Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
		image = R_FindImage (fullname, it_pic, flags);
	}
	else
		image = R_FindImage (name+1, it_pic, flags);

	return image;
}



/*
===============
Draw_InitLocal
===============
*/

void Draw_InitLocal (void)
{
	char	dk_path [1024];
	
	//	Nelno:	load Daikatana console characters
	//	draw_chars = Draw_FindPic ("conchars");
	if (!r_resourcedir || !r_resourcedir->string || r_resourcedir->string [0] == 0x00)
		draw_chars = Draw_FindPic ("dkchars", RESOURCE_EPISODE);
	else
	{
		sprintf (dk_path, "%sdkchars.pcx", r_resourcedir->string);

		draw_chars = Draw_FindPic (dk_path, RESOURCE_EPISODE);

		if (!draw_chars)
			draw_chars = Draw_FindPic ("dkchars", RESOURCE_EPISODE);
	}
}



/*
================
Draw_Char

Draws one 8*8 graphics character
It can be clipped to the top of the screen to allow the console to be
smoothly scrolled off.
================
*/
void Draw_Char (int x, int y, int num)
{
	byte			*dest;
	byte			*source;
	int				drawline;	
	int				row, col;

	num &= 255;

	if (num == 32 || num == 32+128)
		return;

	if (y <= -8)
		return;			// totally off screen

	if ( ( y + 8 ) >= vid.height )
		return;

#ifdef PARANOID
	if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
		ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y);
	if (num < 0 || num > 255)
		ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num);
#endif

	row = num>>4;
	col = num&15;
	source = draw_chars->pixels[0] + (row<<10) + (col<<3);

	if (y < 0)
	{	// clipped
		drawline = 8 + y;
		source -= 128*y;
		y = 0;
	}
	else
		drawline = 8;


	dest = vid.buffer + y*vid.rowbytes + x;

	while (drawline--)
	{
		if (source[0] != TRANSPARENT_COLOR)
			dest[0] = source[0];
		if (source[1] != TRANSPARENT_COLOR)
			dest[1] = source[1];
		if (source[2] != TRANSPARENT_COLOR)
			dest[2] = source[2];
		if (source[3] != TRANSPARENT_COLOR)
			dest[3] = source[3];
		if (source[4] != TRANSPARENT_COLOR)
			dest[4] = source[4];
		if (source[5] != TRANSPARENT_COLOR)
			dest[5] = source[5];
		if (source[6] != TRANSPARENT_COLOR)
			dest[6] = source[6];
		if (source[7] != TRANSPARENT_COLOR)
			dest[7] = source[7];
		source += 128;
		dest += vid.rowbytes;
	}
}

/*
=============
Draw_GetPicSize
=============
*/
void Draw_GetPicSize (int *w, int *h, const char *pic)
{
	image_t *gl;

	gl = Draw_FindPic (pic, RESOURCE_IGNORE);
	if (!gl)
	{
		*w = *h = -1;
		return;
	}
	*w = gl->width;
	*h = gl->height;
}

/*
=============
Draw_StretchPicImplementation
=============
*/
void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t	*pic)
{
	byte			*dest, *source;
	int				v, u, sv;
	int				height;
	int				f, fstep;
	int				skip;

	if ((x < 0) ||
		(x + w > vid.width) ||
		(y + h > vid.height))
	{
		ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
	}

	height = h;
	if (y < 0)
	{
		skip = -y;
		height += y;
		y = 0;
	}
	else
		skip = 0;

	dest = vid.buffer + y * vid.rowbytes + x;

	for (v=0 ; v<height ; v++, dest += vid.rowbytes)
	{
		sv = (skip + v)*pic->height/h;
		source = pic->pixels[0] + sv*pic->width;
		if (w == pic->width)
			memcpy (dest, source, w);
		else
		{
			f = 0;
			fstep = pic->width*0x10000/w;
			for (u=0 ; u<w ; u+=4)
			{
				dest[u] = source[f>>16];
				f += fstep;
				dest[u+1] = source[f>>16];
				f += fstep;
				dest[u+2] = source[f>>16];
				f += fstep;
				dest[u+3] = source[f>>16];
				f += fstep;
			}
		}
	}
}

/*
=============
Draw_StretchPic
=============
*/
void Draw_StretchPic (int x, int y, int w, int h, const char *name)
{
	image_t	*pic;

	pic = Draw_FindPic (name, RESOURCE_IGNORE);
	if (!pic)
	{
		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
		return;
	}
	Draw_StretchPicImplementation (x, y, w, h, pic);
}

/*
=============
Draw_StretchRaw
=============
*/
void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
{
	image_t	pic;

	pic.pixels[0] = data;
	pic.width = cols;
	pic.height = rows;
	Draw_StretchPicImplementation (x, y, w, h, &pic);
}

/*
=============
Draw_Pic
=============
*/
void Draw_Pic (int x, int y, const char *name)
{
	image_t			*pic;
	byte			*dest, *source;
	int				v, u;
	int				tbyte;
	int				height;

	pic = Draw_FindPic (name, RESOURCE_IGNORE);
	if (!pic)
	{
		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
		return;
	}

	if ((x < 0) ||
		(x + pic->width > vid.width) ||
		(y + pic->height > vid.height))
		return;	//	ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");

	height = pic->height;
	source = pic->pixels[0];
	if (y < 0)
	{
		height += y;
		source += pic->width*-y;
		y = 0;
	}

	dest = vid.buffer + y * vid.rowbytes + x;

	if (!pic->transparent)
	{
		for (v=0 ; v<height ; v++)
		{
			memcpy (dest, source, pic->width);
			dest += vid.rowbytes;
			source += pic->width;
		}
	}
	else
	{
		if (pic->width & 7)
		{	// general
			for (v=0 ; v<height ; v++)
			{
				for (u=0 ; u<pic->width ; u++)
					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
						dest[u] = tbyte;

				dest += vid.rowbytes;
				source += pic->width;
			}
		}
		else
		{	// unwound
			for (v=0 ; v<height ; v++)
			{
				for (u=0 ; u<pic->width ; u+=8)
				{
					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
						dest[u] = tbyte;
					if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
						dest[u+1] = tbyte;
					if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
						dest[u+2] = tbyte;
					if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
						dest[u+3] = tbyte;
					if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
						dest[u+4] = tbyte;
					if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
						dest[u+5] = tbyte;
					if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
						dest[u+6] = tbyte;
					if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
						dest[u+7] = tbyte;
				}
				dest += vid.rowbytes;
				source += pic->width;
			}
		}
	}
}

/*
=============
Draw_TileClear

This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void Draw_TileClear (int x, int y, int w, int h, const char *name)
{
	int			i, j;
	byte		*psrc;
	byte		*pdest;
	image_t		*pic;
	int			x2;

	if (x < 0)
	{
		w += x;
		x = 0;
	}
	if (y < 0)
	{
		h += y;
		y = 0;
	}
	if (x + w > vid.width)
		w = vid.width - x;
	if (y + h > vid.height)
		h = vid.height - y;
	if (w <= 0 || h <= 0)
		return;

	pic = Draw_FindPic (name, RESOURCE_LEVEL);
	if (!pic)
	{
		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
		return;
	}
	x2 = x + w;
	pdest = vid.buffer + y*vid.rowbytes;
	for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
	{
		psrc = pic->pixels[0] + pic->width * ((i+y)&63);
		for (j=x ; j<x2 ; j++)
			pdest[j] = psrc[j&63];
	}
}


/*
=============
Draw_Fill

Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c)
{
	byte			*dest;
	int				u, v;

	if (x+w > vid.width)
		w = vid.width - x;
	if (y+h > vid.height)
		h = vid.height - y;
	if (x < 0)
	{
		w += x;
		x = 0;
	}
	if (y < 0)
	{
		h += y;
		y = 0;
	}
	if (w < 0 || h < 0)
		return;
	dest = vid.buffer + y*vid.rowbytes + x;
	for (v=0 ; v<h ; v++, dest += vid.rowbytes)
		for (u=0 ; u<w ; u++)
			dest[u] = c;
}

//=============================================================================

/*
================
Draw_FadeScreen

================
*/
void Draw_FadeScreen (void)
{
	int			x,y;
	byte		*pbuf;
//	int			t;
	byte		pix;

/*
	for (y=0 ; y<vid.height ; y++)
	{
		pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
		t = (y & 1) << 1;

		for (x=0 ; x<vid.width ; x++)
		{
			if ((x & 3) != t)
				pbuf[x] = 0;
		}
	}
*/
	//	Q2FIXME:	needs an int * version for 16 bit modes
	for (y=0 ; y<vid.height ; y++)
	{
		pbuf = (byte *)(vid.buffer + vid.rowbytes*y);

		for (x=0 ; x<vid.width ; x++)
		{
			pix = pbuf [x];

			pbuf [x] = vid.alphamap [pix];
		}
	}

}

///////////////////////////////////////////////////////////////////////////////
//	Draw_AlphaStretchPicImplementation
///////////////////////////////////////////////////////////////////////////////

void Draw_AlphaStretchPicImplementation (int x, int y, int w, int h, image_t	*pic)
{
	byte			*dest, *source;
	int				v, u, sv;
	int				height;
	int				f, fstep;
	int				skip;

	if ((x < 0) ||
		(x + w > vid.width) ||
		(y + h > vid.height))
	{
		ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
	}

	height = h;
	if (y < 0)
	{
		skip = -y;
		height += y;
		y = 0;
	}
	else
		skip = 0;

	dest = vid.buffer + y * vid.rowbytes + x;

	for (v=0 ; v<height ; v++, dest += vid.rowbytes)
	{
		sv = (skip + v)*pic->height/h;
		source = pic->pixels[0] + sv*pic->width;
//		if (w == pic->width)
//			memcpy (dest, source, w);
//		else
		{
			f = 0;
			fstep = pic->width*0x10000/w;

			for (u=0 ; u<w ; u+=4)
			{
/*
				dest[u] = source[f>>16];
				f += fstep;
				dest[u+1] = source[f>>16];
				f += fstep;
				dest[u+2] = source[f>>16];
				f += fstep;
				dest[u+3] = source[f>>16];
				f += fstep;
*/
/*
				//	66% translucency
				dest [u] = vid.alphamap [dest [u] + (int) (source [f>>16] << 8)];
				f += fstep;
				dest [u+1] = vid.alphamap [dest [u+1] + (int) (source [f>>16] << 8)];
				f += fstep;
				dest [u+2] = vid.alphamap [dest [u+2] + (int) (source [f>>16] << 8)];
				f += fstep;
				dest [u+3] = vid.alphamap [dest [u+3] + (int) (source [f>>16] << 8)];
				f += fstep;
*/

				//	33% translucency
				dest [u] = vid.alphamap [(int) (dest [u] << 8) + source [f>>16]];
				f += fstep;
				dest [u+1] = vid.alphamap [(int) (dest [u+1] << 8) + source [f>>16]];
				f += fstep;
				dest [u+2] = vid.alphamap [(int) (dest [u+2] << 8) + source [f>>16]];
				f += fstep;
				dest [u+3] = vid.alphamap [(int) (dest [u+3] << 8) + source [f>>16]];
				f += fstep;

			}
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
//	Draw_AlphaStretchPic
///////////////////////////////////////////////////////////////////////////////

void Draw_AlphaStretchPic (int x, int y, int w, int h, char *name)
{
	image_t	*pic;

	pic = Draw_FindPic (name, RESOURCE_IGNORE);
	if (!pic)
	{
		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
		return;
	}
	Draw_AlphaStretchPicImplementation (x, y, w, h, pic);
}


///////////////////////////////////////////////////////////////////////////////
//	Draw_ConsolePic
//
//	finds the correct console pic based on r_resourceDir
///////////////////////////////////////////////////////////////////////////////

void Draw_ConsolePic (int x, int y, int w, int h)
{
//	char	dk_path [1024];
//	image_t	*pic;
	int		x_start, x_width;
	float	x_scale;

	//	calc where the bigger pic should start
	x_scale = (vid.width / 320.0);
	x_width = 256 * x_scale;
	x_start = vid.width - x_width;

	Draw_StretchPic (0, y, 64 * x_scale, h, "dkcon2");		
	Draw_StretchPic (x_start, y, x_width, h, "dkcon");		
/*
	//	Nelno:	load Daikatana console characters
	//	draw_chars = Draw_FindPic ("conchars");
	if (!r_resourcedir || !r_resourcedir->string || r_resourcedir->string [0] == 0x00)
		Draw_StretchPic (x, y, w, h, "dkcon");		
	else
	{
		sprintf (dk_path, "%sdkcon.pcx", r_resourcedir->string);

		pic = Draw_FindPic (dk_path, RESOURCE_GLOBAL);

		if (!pic)
		{
			pic = Draw_FindPic ("dkcon", RESOURCE_GLOBAL);

			if (!pic)
			{
				ri.Con_Printf (PRINT_ALL, "Can't find pic: pics/dkcon.pcx\n");
				return;
			}
			
			Draw_AlphaStretchPicImplementation (x, y, w, h, pic);
		}
		else
			Draw_AlphaStretchPicImplementation (x, y, w, h, pic);
	}
*/
}