#pragma once

#define RGB332
#ifdef RGB332

#define C32TO8(x) (((x>>5)&0x7)|((x>>10)&0x38)|((x>>16)&0xc0))
#define C8TO32(x) (((x&0x7)<<5)|((x&0x38)<<10)|((x&0xc0)<<16))

#define GETR(x) ((x<<5)&0xe0)
#define GETG(x) ((x<<2)&0xe0)
#define GETB(x) ((x   )&0xc0)
#define MAKERGB(r, g, b) ( ((r>>5)&0x7)|((g>>2)&0x38)|((b)&0xc0) )

#else

#define C32TO8(x) (((x>>6)&0x3)|((x>>12)&0xc)|((x>>18)&0x30))

#define GETR(x) ((x<<6)&0xc0)
#define GETG(x) ((x<<4)&0xc0)
#define GETB(x) ((x<<2)&0xc0)
#define MAKERGB(r, g, b) ( ((r>>6)&0x3)|((g>>4)&0xc)|((b>>2)&0x30) )


#endif

// Font

#ifndef _DEMO

enum
{
	F_SML,
		F_MED,
		F_LRG,
		F_NUM
};


#define FONT_LO  32
#define FONT_HI  127
#define FONT_NUM (FONT_HI - FONT_LO)


struct AlexDC;

class Font
{
	int
		width,
		height,
		starts [FONT_NUM],
		twidth [FONT_NUM];
	byte
		* alexdata,
		* alexptr [FONT_NUM];
	
public:
	LUCINDA_API void	Central (AlexDC *dc, char * line, int xx, int yy, ULONG col, ULONG colon);
	LUCINDA_API void	Mess (AlexDC* dc, char * line, int l, int t, ULONG col, ULONG colon, int curpos = -1);
	LUCINDA_API void	Mess16(short *dstbuf, int dstpitch, int dstw, int dsth, int bits, char * line, int l, int t, ULONG col, ULONG colon, int curpos = -1);
	LUCINDA_API int		Length (char * line);
	LUCINDA_API int		CharW(char xch);
	LUCINDA_API int		Height () { return height; }
	LUCINDA_API void	Free ();
	LUCINDA_API void	BuildAlexData();
	LUCINDA_API void	SaveAlexData(char * pathname);
	LUCINDA_API void	LoadAlexData(char * pathname);
};


///////////////////////////////// FONTS
// Initialisation

LUCINDA_API int LoadFonts ();
LUCINDA_API void FreeFonts ();

typedef unsigned char UBYTE;
#define bound(min,x,max) ((x)<(min)?(min):(x)>(max)?(max):(x))


struct AlexDC
{
	HBITMAP hb;
	UBYTE *dst,*xdst;
	int w,h,p;


	int cx1,cy1,cx2,cy2;

	int ncx1,ncy1,ncx2,ncy2;

	void SetOrigin(int x, int y)
	{
		SetClipNC(x,y,x+cx2-cx1,y+cy2-cy1);
		dst=xdst - x - y*p;
	}

	void SetClipNC(int X1=0, int Y1=0, int X2=0, int Y2=0, int nc=0)
	{
		cx1=X1;
		cx2=X2;
		cy1=Y1;
		cy2=Y2;
	}

	void SetClip(int X1=0, int Y1=0, int X2=0, int Y2=0, int nc=0)
	{
		if (X1==0 && X2==0 && Y1==0 && Y2==0)
		{
			cx1=cy1=0;
			cx2=w;
			cy2=h;
		}
		else
		{
			cx1=bound(0,X1,w);
			cy1=bound(0,Y1,h);
			cx2=bound(cx1,X2,w);
			cy2=bound(cy1,Y2,h);
		}
		if (nc)
		{
			cx1-=ncx1;
			cy1-=ncy1;
			cx2+=ncx2;
			cy2+=ncy2;
		}		
	}	


	LUCINDA_API void CreateBMP(HDC dc);
	LUCINDA_API void KillBMP()
	{
		//delete [] left;
		//delete [] right;
		//left=NULL;
		//right=NULL;
	
	}


	LUCINDA_API void CopyBits(int x1, int y1, int x2, int y2, char *src, int scrx, int srcy, int srcw, int srch);
	
	LUCINDA_API void DrawHMeter(int x1, int y1, float level);
	LUCINDA_API void DrawVMeter(int x1, int y1, float level);

	int miny,maxy;
	int left[1600];
	int right[1600];
	void ResetScans()
	{
		miny=cy2;
		maxy=cy1;
	}

	LUCINDA_API void AddEdge(int x1, int y1, int x2, int y2);
	LUCINDA_API void FillScans(int c);


	void FillTri(int x1, int y1, int x2, int y2, int x3, int y3, int c, int oc=-1)
	{
		ResetScans();
		AddEdge(x1,y1,x2,y2);
		AddEdge(x2,y2,x3,y3);
		AddEdge(x3,y3,x1,y1);
		FillScans(c);
		if (oc>=0) 
		{
			Line(x1,y1,x2,y2,oc);
			Line(x2,y2,x3,y3,oc);
			Line(x3,y3,x1,y1,oc);
		}
	}

	void FillQuad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int c, int oc=-1)
	{
		ResetScans();
		AddEdge(x1,y1,x2,y2);
		AddEdge(x2,y2,x3,y3);
		AddEdge(x3,y3,x4,y4);
		AddEdge(x4,y4,x1,y1);
		FillScans(c);
		if (oc>=0) 
		{
			Line(x1,y1,x2,y2,oc);
			Line(x2,y2,x3,y3,oc);
			Line(x3,y3,x4,y4,oc);
			Line(x4,y4,x1,y1,oc);
		}
	}

	LUCINDA_API void Line(int x1, int y1, int x2, int y2, int c);
	LUCINDA_API void FatLine(int x1, int y1, int x2, int y2, int c, int oc=-1);
	void Rect(int x1, int y1, int x2, int y2, int c)
	{
		Line(x1,y1,x2+1,y1,c);
		Line(x1,y2,x2+1,y2,c);
		Line(x1,y1+1,x1,y2,c);
		Line(x2,y1+1,x2,y2,c);
	}

	void LUCINDA_API Rect3D(int x1, int y1, int x2, int y2, int c, bool down=false, bool fill=true); // takes 32 bit colours!!
	

	LUCINDA_API void Text8(char *t, int x, int y, int c, int colon);
	LUCINDA_API void Text8Side(char *t, int x, int y, int c, int colon);
	

	LUCINDA_API void Blob3(int x, int y, int c)
	{
		x--;y--;
		if (x>=cx1 && y>=cy1 && x<cx2-3 && y<cy2-3)
		{
			ULONG cc=(c)+(c<<8)+(c<<16);
			ULONG *d=(ULONG*)(dst+x+y*p);
			d[0]=(d[0]&0xff000000)|cc;
			d[p/4]=(d[p/4]&0xff000000)|cc;
			d[p/2]=(d[p/2]&0xff000000)|cc;
		}
	}
	LUCINDA_API void FillRect(int x1, int y1, int x2, int y2, int c);
	LUCINDA_API void HLine(int x1, int y1, int x2, int c);
	LUCINDA_API void VLine(int x1, int y1, int y2, int c);

	LUCINDA_API void Text(char *t, int x, int y, int c, int colon, int cen=0);
	
	AlexDC(HDC dc,int ww, int hh, int _ncx1, int _ncy1, int _ncx2, int _ncy2)
	{
		hb=NULL;
		dst=NULL;
		
		Set(dc,ww,hh,_ncx1,_ncy1,_ncx2,_ncy2);
	}

	void Set(HDC dc,int ww, int hh, int _ncx1, int _ncy1, int _ncx2, int _ncy2)
	{
		w=ww;h=hh;
		ncx1=_ncx1;ncy1=_ncy1;
		ncx2=_ncx2;ncy2=_ncy2;
		//left=right=NULL;
		ResetScans();
		SetClip();
		CreateBMP(dc);
	}

	~AlexDC()
	{
		KillBMP();
		if (hb) DeleteObject(hb);
		hb=NULL;
		dst=NULL;
		
	}

};


//////////////////////////
//	COLOR CONVERSION.	//
//////////////////////////
#define MASK_R_500	0x00007C00
#define MASK_G_050	0x000003E0
#define MASK_B_005	0x0000001F

#define MASK_R565_500	0x0000f800
#define MASK_G565_050	0x000007E0
#define MASK_B565_005	0x0000001F

#define MASK_A_4000 0x0000F000
#define MASK_R_0400 0x00000F00
#define MASK_G_0040 0x000000F0
#define MASK_B_0004 0x0000000F

#define MASK_24B	0x00FFFFFF
#define MASK_8B		0x000000FF

#define MASK_A_32B	0xFF000000
#define MASK_R_32B	0x00FF0000
#define MASK_G_32B	0x0000FF00
#define MASK_B_32B	0x000000FF


#define GET_A_4444_TO_4000(p) ((p)&MASK_A_4000)
#define GET_R_4444_TO_0400(p) ((p)&MASK_R_0400)
#define GET_G_4444_TO_0040(p) ((p)&MASK_G_0040)
#define GET_B_4444_TO_0004(p) ((p)&MASK_B_0004)

#define GET_R_555_TO_500(p) ((p)&MASK_R_500)
#define GET_G_555_TO_050(p) ((p)&MASK_G_050)
#define GET_B_555_TO_005(p) ((p)&MASK_B_005)

#define GET_R_555_TO_5(p) (((p)           )>>10)
#define GET_G_555_TO_5(p) (((p)&MASK_G_050)>> 5)
#define GET_B_555_TO_5(p) (((p)&MASK_B_005)    )

#define GET_R_888_TO_8(p) (((p)           )>>16)
#define GET_G_888_TO_8(p) (((p)&MASK_G_32B)>> 8)
#define GET_B_888_TO_8(p) (((p)&MASK_B_32B)    )

#define GET_A_32_TO_8(p) ((p           )>>24)
#define GET_R_32_TO_8(p) ((p&MASK_R_32B)>>16)
#define GET_G_32_TO_8(p) ((p&MASK_G_32B)>> 8)
#define GET_B_32_TO_8(p) ((p&MASK_B_32B)    )

#define CONV_888_TO_555(r,g,b) (UWORD)((((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3))
#define CONV_8888_TO_4444(a,r,g,b) (UWORD)(((a>>4)<<12)|(((r)>>4)<<8)|(((g)>>4)<<4)|((b)>>4))
#define CONV_32_TO_4444(p) (CONV_8888_TO_4444(GET_A_32_TO_8(p),GET_R_32_TO_8(p),GET_G_32_TO_8(p),GET_B_32_TO_8(p)))

#define MAKE_ARGB(a,r,g,b)  ( ((a)<<24) | ((r)<<16) | ((g)<<8) | (b) )


#define INTERP(C1,C2,FRAC) \
	((((C1)&MASK_B_32B)+(((((C2)&MASK_B_32B)-((C1)&MASK_B_32B))*(FRAC))>>8))&MASK_B_32B)| \
	((((C1)&MASK_G_32B)+(((((C2)&MASK_G_32B)-((C1)&MASK_G_32B))*(FRAC))>>8))&MASK_G_32B)| \
	((((C1)&MASK_R_32B)+(((((C2)&MASK_R_32B)-((C1)&MASK_R_32B))*(FRAC))>>8))&MASK_R_32B)| \
	   (C2)&MASK_A_32B

#define INTERP_24(C1,C2,FRAC) \
	((((C1)&MASK_B_32B)+(((((C2)&MASK_B_32B)-((C1)&MASK_B_32B))*(FRAC))>>8))&MASK_B_32B)| \
	((((C1)&MASK_G_32B)+(((((C2)&MASK_G_32B)-((C1)&MASK_G_32B))*(FRAC))>>8))&MASK_G_32B)| \
	((((C1)&MASK_R_32B)+(((((C2)&MASK_R_32B)-((C1)&MASK_R_32B))*(FRAC))>>8))&MASK_R_32B)

#define INTERP_8(C1,C2,FRAC) ((((C1)&MASK_8B)+(((((C2)&MASK_8B)-((C1)&MASK_8B))*(FRAC))>>8))&MASK_8B)

#define ADD_SPECULAR_8B(COLOR,ADD_COLOR) { ULONG T = ULONG(COLOR)+ULONG(ADD_COLOR); if (T>255)COLOR=255;else COLOR=(UBYTE)T;}



#endif