/*****************************************************************************

  ui_font.c

*****************************************************************************/

#include "driver.h"
#include "video.h"

static UINT16 _uifonttable[65536];
static UINT32 colortable[MAX_COLORTABLE + GRADATION_LEVEL];

/* in usrintf.c */
extern struct GfxElement *uirotfont;
extern struct GfxElement *uirotfont2;

/* raw coordinates, relative to the real scrbitmap */
extern struct rectangle uirawbounds;
extern int uirawcharwidth, uirawcharheight;

/* rotated coordinates, easier to deal with */
extern struct rectangle uirotbounds;
extern int uirotwidth, uirotheight;
extern int uirotcharwidth, uirotcharheight;

/****************************************************************************/



/***************************************************************************

	Font data

***************************************************************************/

static unsigned char fontdata6x12[] =
{
#include "font\h8x12.dat"
};

static unsigned char fontdata12x12[] =
{
#include "font\z16x12.dat"
};

static struct GfxLayout fontlayout6x12 =
{
	6,12,	/* 6*12 characters */
	256,    /* 128 characters */
	1,	/* 1 bit per pixel */
	{ 0 },
	{ 0, 1, 2, 3, 4, 5, 6, 7 },	/* straightforward layout */
	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8 },
	8*12	/* every char takes 8 consecutive bytes */
};

static struct GfxLayout fontlayout12x12z =
{
	12,12,
	(0x9fff - 0x8140) + (0xfcff - 0xe040) + 1,
	1,
	{ 0 },
	{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 },
	{ 0*16,1*16,2*16,3*16,4*16,5*16,6*16,7*16,8*16,9*16,10*16,11*16 },
	16*12
};

static UINT16 uifont_buildtable(UINT16 code)
{
	UINT8 c1, c2;

	c1 = (code >> 8) & 0xff;
	c2 = code & 0xff;

	if (code >= 0x8140 && code <= 0x9ffc)
	{
		code = ((c1 - 0x81) << 8) + (c2 - 0x40);
	}
	else if (code >= 0xe040 && code <= 0xfcfc)
	{
		code = ((c1 - 0xe0 + (0xa0 - 0x81)) << 8) + (c2 - 0x40);
	}
	else
		return 0x60;

	return (code - ((code >> 8) & 0xff) * 0x40);
}


int uifont_buildfont(void)
{
	struct GfxLayout layout = fontlayout6x12;
	struct GfxLayout layout2 = fontlayout12x12z;
	UINT32 tempoffset[MAX_GFX_SIZE];
	struct GfxElement *font;
	int temp, i;

	/* free any existing fonts */
	if (Machine->uifont)
		freegfx(Machine->uifont);
	if (Machine->uifont2)
		freegfx(Machine->uifont2);
	if (uirotfont)
		freegfx(uirotfont);
	if (uirotfont2)
		freegfx(uirotfont2);

	/* first decode a straight on version for games */
	Machine->uifont = font = decodegfx(fontdata6x12, &fontlayout6x12);
	Machine->uifontwidth = layout.width;
	Machine->uifontheight = layout.height;

	Machine->uifont2 = decodegfx(fontdata12x12, &fontlayout12x12z);
	Machine->uifontwidth2 = layout2.width;
	Machine->uifontheight2 = layout2.height;

	/* apply swappage */
	if (Machine->ui_orientation & ORIENTATION_SWAP_XY)
	{
		memcpy(tempoffset, layout.xoffset, sizeof(tempoffset));
		memcpy(layout.xoffset, layout.yoffset, sizeof(layout.xoffset));
		memcpy(layout.yoffset, tempoffset, sizeof(layout.yoffset));

		temp = layout.width;
		layout.width = layout.height;
		layout.height = temp;

		memcpy(tempoffset, layout2.xoffset, sizeof(tempoffset));
		memcpy(layout2.xoffset, layout2.yoffset, sizeof(layout2.xoffset));
		memcpy(layout2.yoffset, tempoffset, sizeof(layout2.yoffset));

		temp = layout2.width;
		layout2.width = layout2.height;
		layout2.height = temp;
	}

	/* apply xflip */
	if (Machine->ui_orientation & ORIENTATION_FLIP_X)
	{
		memcpy(tempoffset, layout.xoffset, sizeof(tempoffset));
		for (i = 0; i < layout.width; i++)
			layout.xoffset[i] = tempoffset[layout.width - 1 - i];

		memcpy(tempoffset, layout2.xoffset, sizeof(tempoffset));
		for (i = 0; i < layout2.width; i++)
			layout2.xoffset[i] = tempoffset[layout2.width - 1 - i];
	}

	/* apply yflip */
	if (Machine->ui_orientation & ORIENTATION_FLIP_Y)
	{
		memcpy(tempoffset, layout.yoffset, sizeof(tempoffset));
		for (i = 0; i < layout.height; i++)
			layout.yoffset[i] = tempoffset[layout.height - 1 - i];

		memcpy(tempoffset, layout2.yoffset, sizeof(tempoffset));
		for (i = 0; i < layout2.height; i++)
			layout2.yoffset[i] = tempoffset[layout2.height - 1 - i];
	}

	/* decode rotated font */
	uirotfont = decodegfx(fontdata6x12, &layout);
	uirotfont2 = decodegfx(fontdata12x12, &layout2);

	/* set the raw and rotated character width/height */
	uirawcharwidth = layout.width;
	uirawcharheight = layout.height;
	uirotcharwidth = (Machine->ui_orientation & ORIENTATION_SWAP_XY) ? layout.height : layout.width;
	uirotcharheight = (Machine->ui_orientation & ORIENTATION_SWAP_XY) ? layout.width : layout.height;

	/* set up the bogus colortable */
	if (font)
	{
		/* colortable will be set at run time */
		font->colortable = colortable;
		font->total_colors = 2;
		uirotfont->colortable = colortable;
		uirotfont->total_colors = 2;
		uirotfont2->colortable = colortable;
		uirotfont2->total_colors = 2;
	}

	for (i = 0x4081; i < 0xfffc; i++)
		_uifonttable[i] = uifont_buildtable(i) + 256;

	return 1;
}


void uifont_freefont(void)
{
	if (Machine->uifont2)
	{
		freegfx(Machine->uifont2);
		Machine->uifont2 = 0;
	}
	if (Machine->uifont)
	{
		freegfx(Machine->uifont);
		Machine->uifont = 0;
	}
}


int uifont_decodechar(unsigned char *s, unsigned short *code)
{
	unsigned char c1 = *(unsigned char *)s;
	unsigned char c2 = *(unsigned char *)(s + 1);

	if (ISSJIS1(c1) && ISSJIS2(c2))
	{
		*code = _uifonttable[(c1 << 8) | c2];

		if (*code == 0)
			*code = _uifonttable[0x817f];

		return 2;
	}

	*code = c1;
	return 1;
}


int uifont_drawfont(struct mame_bitmap *bitmap, const char *s, int sx,
                    int sy, int color)
{
	int x, y, wrapped, next_sy, increment, uifontwidth;
	int white = 0;
	unsigned short code;
	unsigned char *c;
	struct GfxElement *uifont;
	struct rectangle bounds;

	c      = (unsigned char *)s;
	x      = sx;
	y      = sy;
	code   = 0;
	next_sy = 0;

	if (color == UI_COLOR_INVERSE)
	{
		white = Machine->uifont->colortable[FONT_COLOR_NORMAL];
		Machine->uifont->colortable[FONT_COLOR_NORMAL] = Machine->uifont->colortable[FONT_COLOR_SPECIAL];
	}

	while (*c)
	{
		wrapped = 0;

		increment = uifont_decodechar(c, &code);

		if (*c == '\n')
		{
			x = sx;
			y += uirotcharheight + 1;
			next_sy += uirotcharheight;
			c++;
			continue;
		}
		else
		{
			if (code > 0x00ff)
			{
				uifont      = uirotfont2;
				uifontwidth = uirotcharwidth * 2;
			}
			else
			{
				uifont      = uirotfont;
				uifontwidth = uirotcharwidth;
			}
		}

		if (y >= uirotheight)
			return next_sy;

		if (!wrapped)
		{
			int col = 0;

			if (code > 0x00ff)
			{
				code -= 256;
				
				if      (code == 0x0080 || code == 0x00a9)	col = BUTTON_COLOR_RED;
				else if (code == 0x0081 || code == 0x00aa)	col = BUTTON_COLOR_YELLOW;
				else if (code == 0x0082 || code == 0x00ab)	col = BUTTON_COLOR_GREEN;
				else if (code == 0x0083 || code == 0x00ac)	col = BUTTON_COLOR_BLUE;
				else if (code == 0x0086 || code == 0x00ad)	col = BUTTON_COLOR_PURPLE;
				else if (code == 0x0085 || code == 0x00ae)	col = BUTTON_COLOR_PINK;
				else if (code == 0x00af)					col = BUTTON_COLOR_AQUA;
				
				if (col)
				{
					white = Machine->uifont->colortable[FONT_COLOR_NORMAL];
					Machine->uifont->colortable[FONT_COLOR_NORMAL] = Machine->uifont->colortable[col];
				}
			}

			/* construct a rectangle in rotated coordinates, then transform it */
			bounds.min_x = x + uirotbounds.min_x + 1;
			bounds.min_y = y + uirotbounds.min_y;
			bounds.max_x = bounds.min_x + uirotcharwidth - 1;
			bounds.max_y = bounds.min_y + uirotcharheight - 1;
			ui_rot2raw_rect(&bounds);

			if (color == UI_COLOR_BOLD)
			{
				white = Machine->uifont->colortable[FONT_COLOR_NORMAL];
				Machine->uifont->colortable[FONT_COLOR_NORMAL] = Machine->uifont->colortable[FONT_COLOR_DARK];

				drawgfx(bitmap,
					uifont,
					code,
					0,
					0,
					0,
					bounds.min_x,
					bounds.min_y,
					0,
					TRANSPARENCY_FONT,
					0);

				Machine->uifont->colortable[FONT_COLOR_NORMAL] = white;
			}

			/* construct a rectangle in rotated coordinates, then transform it */
			bounds.min_x = x + uirotbounds.min_x;
			bounds.min_y = y + uirotbounds.min_y;
			bounds.max_x = bounds.min_x + uirotcharwidth - 1;
			bounds.max_y = bounds.min_y + uirotcharheight - 1;
			ui_rot2raw_rect(&bounds);

			drawgfx(bitmap,
				uifont,
				code,
				0,
				0,
				0,
				bounds.min_x,
				bounds.min_y,
				0,
				TRANSPARENCY_FONT,
				0);

			x += uifontwidth;

			while (increment)
			{
				c++;
				increment--;
			}

			if (col)
				Machine->uifont->colortable[FONT_COLOR_NORMAL] = white;
		}
	}

	if (color == UI_COLOR_INVERSE)
		Machine->uifont->colortable[FONT_COLOR_NORMAL] = white;

	return next_sy;
}
