////////////////////////////////////////////////////////////
// softfont.cpp

#ifdef __WATCOMC__
#include <mem.h>
#else
#include <memory.h>
#endif
#include <stdlib.h>

#include "rasterop.h"
#include "softfont.h"
#include "util.h"


#define SWAB(w)		((w) = (((w)&0x00FF)<<8) | ((w)>>8)&0x00FF)


static void font_deletechars( FONTNODE *pf );


static FONTLIST fontlist;


FONTNODE *font_find( int id )
{
	for( FONTNODE *pf = fontlist; pf; pf = pf->next )
		if( pf->id == id )
			return pf;
	return NULL;
}

FONTNODE *font_new( int id, char *pdata, int cdata )
{
	FONTNODE *pf = font_find( id );
	if( pf )
	{
		font_deletechars( pf );
	}
	else
	{
		pf = new FONTNODE;
		if( !pf )
			return NULL;
		pf->next = fontlist;
		pf->id = id;
		memset( pf->cd, 0, sizeof(pf->cd) );
		fontlist = pf;
	}
	if( cdata >= sizeof(FONTDESC) )
	{
		memcpy( &pf->fd, pdata, sizeof(FONTDESC) );
	}
	else
	{
		memcpy( &pf->fd, pdata, cdata );
		memset( (char *)&pf->fd + cdata, 0, sizeof(FONTDESC) - cdata );
	}
	SWAB( pf->fd.fdsize );
	SWAB( pf->fd.baseline );
	SWAB( pf->fd.cellwidth );
	SWAB( pf->fd.cellheight );
	SWAB( pf->fd.symbolset );
	SWAB( pf->fd.pitch );
	SWAB( pf->fd.height );
	SWAB( pf->fd.xheight );
	SWAB( pf->fd.textheight );
	SWAB( pf->fd.textwidth );
	SWAB( pf->fd.firstcode );
	SWAB( pf->fd.lastcode );
	SWAB( pf->fd.capheight );
	swap( unsigned char, pf->fd.fontno[0], pf->fd.fontno[3] );
	swap( unsigned char, pf->fd.fontno[1], pf->fd.fontno[2] );
	SWAB( pf->fd.copyrightlen );

	return pf;
}

CHARDESC *font_newchar( int id, int charcode, char *pdata, int cdata )
{
	FONTNODE *pf = font_find( id );

	if( pf && charcode >= 0 && charcode <= 255 && cdata >= sizeof(CHARDESC) )
	{
		unsigned short w, h;

		swab( pdata + 10, (char *)&w, sizeof(unsigned short) );
		swab( pdata + 12, (char *)&h, sizeof(unsigned short) );
		if( pf->cd[charcode] )
		{
			free( pf->cd[charcode] );
			pf->cd[charcode] = NULL;
		}
		int n = sizeof(CHARDESC) + (w+7)/8 * h;
		pf->cd[charcode] = (CHARDESC *)new unsigned char[n];
		if( pf->cd[charcode] )
		{
			if( cdata >= n )
			{
				memcpy( pf->cd[charcode], pdata, n );
			}
			else
			{
				memcpy( pf->cd[charcode], pdata, cdata );
				memset( (char *)pf->cd[charcode] + cdata, 0, n - cdata );
			}
			SWAB( pf->cd[charcode]->leftoffset );
			SWAB( pf->cd[charcode]->topoffset );
			SWAB( pf->cd[charcode]->width );
			SWAB( pf->cd[charcode]->height );
			SWAB( pf->cd[charcode]->deltax );
		}
		return pf->cd[charcode];
	}
	return NULL;
}

int font_drawchar( unsigned char bits[3300][300], int x, int y, FONTNODE *pf, int charcode )
{
	if( pf && charcode >= 0 && charcode <= 255 && pf->cd[charcode] )
	{
		bit_blt( bits, x + pf->cd[charcode]->leftoffset, y - pf->cd[charcode]->topoffset,
				 (unsigned char *)(pf->cd[charcode] + 1), pf->cd[charcode]->width, pf->cd[charcode]->height );
		return pf->cd[charcode]->deltax;
	}
	return 0;
}

//////////////////////////////////////////////////////////////

void font_deletechars( FONTNODE *pf )
{
	for( int i=0; i<256; i++ )
	{
		if( pf->cd[i] )
		{
			free( pf->cd[i] );
			pf->cd[i] = NULL;
		}
	}
}