/*	
 *	clipfntx.c
 *
 *	FONTX描画ルーチン
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2009 Naoyuki Sawa
 *
 *	* Sun Jun 28 15:08:23 JST 2009 Naoyuki Sawa
 *	- 1st リリース。
 *	* Wed Jul 15 14:51:50 JST 2009 Naoyuki Sawa
 *	- frame_tableの名前を、render_font_framed_paramに変更し、clippce.cへ移しました。
 *	  clippce.cとclipfnt8.cからも使うためです。
 */
#include "clip.h"

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

//{{2009/07/15:clippce.cとclipfnt8.cからも使うため、名前をrender_font_framed_paramに変更し、clippce.cへ移しました。
//static const struct {
//	unsigned char x : 2; /* 水平オフセット */
//	unsigned char y : 2; /* 垂直オフセット */
//	unsigned char c : 4; /* カラーシフト数 */
//} frame_table[] = {
//	{ 0, 0, 8 }, { 2, 0, 8 }, { 0, 2, 8 }, { 2, 2, 8 }, /* 縁(角の部分) */
//	{ 1, 0, 4 }, { 0, 1, 4 }, { 2, 1, 4 }, { 1, 2, 4 }, /* 縁(直線部分) */
//	{ 1, 1, 0 },                                        /* 中抜き */
//};
//}}2009/07/15:clippce.cとclipfnt8.cからも使うため、名前をrender_font_framed_paramに変更し、clippce.cへ移しました。

/*---------------------------------------------------------------------------*/

unsigned short
render_fontx(RENDER* render, int x, int y, unsigned short code, const FONTX* fontx, int color)
{
	TEXTURE texture;
	TEXTURE* texture_save;
	int XSize;
	int YSize;
	int CodeType;
	int Tnum;
	int BlockStart;
	int BlockEnd;
	int i;
	const unsigned char* p;

	/* ASCIIフォント、または、漢字フォントを選択します。 */
	p = (code <= 0xFF) ? fontx->ascii : fontx->kanji;
	if(!p) {
		return 0; /* フォントが無い */
	}

	/* フォントヘッダを調べます。 */
	if(memcmp(p, "FONTX2", 6/*Identifier*/)) {
		DIE(); /* フォントが不正 */
	}
	p += 6/*Identifier*/ + 8/*FontName*/;
	XSize = *p++;
	YSize = *p++;
	CodeType = *p++;

	/* ASCIIフォントの場合… */
	if(code <= 0xFF) {
		if(CodeType != 0) {
			DIE(); /* ASCIIフォントでない */
		}
		i = code;

	/* 漢字フォントの場合… */
	} else {
		if(CodeType != 1) {
			DIE(); /* 漢字フォントでない */
		}
		/* 文字コードテーブルを調べます。 */
		Tnum = *p++;
		i = 0;
		for(;;) {
			if(!Tnum--) {
				return 0; /* フォントパターンが無い */
			}
			BlockStart = p[0] | p[1] << 8;
			BlockEnd   = p[2] | p[3] << 8;
			p += (2/*BlockStart*/ + 2/*BlockEnd*/);
			if((code >= BlockStart) && (code <= BlockEnd)) {
				i += (code - BlockStart);
				break;
			}
			i += (BlockEnd - BlockStart + 1);
		}
		p += (2/*BlockStart*/ + 2/*BlockEnd*/) * Tnum/*残り*/;
	}

	/* フォントパターンをテクスチャとして準備します。
	 * FONTXのフォントパターンは、左:MSB⇔LSB:右、8ビット単位に0パディングされ、
	 * 偶然(?)にもビット深度1のPIECE_BMPにパイナリ互換なので、そのまま使えます。
	 */
	memset(&texture, 0, sizeof texture);
	texture.header.bpp = 1;
	texture.header.w = (XSize + 7) & ~7;
	texture.header.h =  YSize;
	texture.buf = (unsigned char*)p + ((texture.header.w >> 3) * YSize) * i;

	/* フォントパターンを描きます。 */
	texture_save = render->context->texture;
	render->context->texture = &texture;
	render_object(render, x, y, 0, 0, XSize, YSize, DRW_CLR(color, COLOR_MASK));
	render->context->texture = texture_save;

	return YSize << 8 | XSize;
}

/*---------------------------------------------------------------------------*/

unsigned int
render_stringx(RENDER* render, int x, int y, const char* str, const FONTX* fontx, int color)
{
	int h, ha, hk, wh;
	int xmin, ymin, xmax, ymax;
	unsigned char c1, c2;
	unsigned short code;
	unsigned char crlf_sel = 0; /* 改行ありの場合、CRまたはLFの先に現れた方を格納する */

	/* ASCIIフォントと漢字フォントのうち、高い方を、行の高さとします。 */
	ha = fontx->ascii ? ((const unsigned char*)fontx->ascii)[15/*YSize*/] : 0;
	hk = fontx->kanji ? ((const unsigned char*)fontx->kanji)[15/*YSize*/] : 0;
	h = (ha >= hk) ? ha : hk;

	/* 描画範囲を求めるために、まず空矩形に設定します。 */
	xmin = xmax = x;
	ymin = ymax = y;

	/* 各文字を描画します。 */
	while((c1 = *str++) != '\0') {
		/* 全角 */
		if(ismbblead(c1)) {
			if((c2 = *str++) == '\0') {
				break; /* 全角が途中で切れている */
			}
			code = c1 << 8 | c2;
		/* 半角 */
		} else {
			if((c1 == '\r') || (c1 == '\n')) {	/* CRまたはLFなら… */
				if(!crlf_sel) {			/* 先に現れた方を… */
					crlf_sel = c1;		/* 改行コードとして選択 */
				}
				if(c1 == crlf_sel) {		/* 選択したコードなら… */
					x = xmin;		/* 改行し表\示はしない */
					y += h;
				} else {			/* 選択したのと逆なら… */
					/** no job */		/* 改行も表\示もしない */
				}
				continue;
			}
			code = c1;
		}

		/* 文字を描きます。 */
		wh = render_fontx(render, x, y, code, fontx, color);
		x += (unsigned char)wh; /* 描画位置を右へ進める */

		/* 描画範囲を更新します。
		 * 実際に描いてから更新します。文字列末尾の改行は描画範囲に影響しません。
		 */
		if(x             > xmax) xmax = x            ;
		if(y + (wh >> 8) > ymax) ymax = y + (wh >> 8);
	}

	return (ymax - ymin) << 16 | (xmax - xmin);
}

/*---------------------------------------------------------------------------*/

/* 文字列展開バッファとして_def_vbuff[]を利用しています。 */
unsigned int
render_printfx(RENDER* render, int x, int y, const FONTX* fontx, int color, const char* fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vsprintf(_def_vbuff, fmt, ap);
	va_end(ap);

	return render_stringx(render, x, y, _def_vbuff, fontx, color);
}

/*---------------------------------------------------------------------------*/

unsigned short
render_fontx_framed(RENDER* render, int x, int y, unsigned short code, const FONTX* fontx, int color)
{
	int wh;
	int i;

//{{2009/07/15:frame_table→render_font_framed_paramへの名前変更に追従
//	for(i = 0; i < ARRAY_SIZE(frame_table); i++) {
//		wh = render_fontx(render,
//			x + frame_table[i].x,
//			y + frame_table[i].y,
//			code,
//			fontx,
//			(color >> frame_table[i].c) & 15);
//		if(!wh) {
//			return 0;
//		}
//	}
//↓2009/07/15:frame_table→render_font_framed_paramへの名前変更に追従
	for(i = 0; i < ARRAY_SIZE(render_font_framed_param); i++) {
		wh = render_fontx(render,
			x + render_font_framed_param[i].x,
			y + render_font_framed_param[i].y,
			code,
			fontx,
			(color >> render_font_framed_param[i].c) & 15);
		if(!wh) {
			return 0;
		}
	}
//}}2009/07/15:frame_table→render_font_framed_paramへの名前変更に追従

	return wh + 0x0202; /* 縦横2ピクセルづつ増える */
}

/*---------------------------------------------------------------------------*/

unsigned int
render_stringx_framed(RENDER* render, int x, int y, const char* str, const FONTX* fontx, int color)
{
	int wh;
	int i;

//{{2009/07/15:frame_table→render_font_framed_paramへの名前変更に追従
//	for(i = 0; i < ARRAY_SIZE(frame_table); i++) {
//		wh = render_stringx(render,
//			x + frame_table[i].x,
//			y + frame_table[i].y,
//			str,
//			fontx,
//			(color >> frame_table[i].c) & 15);
//		if(!wh) {
//			return 0;
//		}
//	}
//↓2009/07/15:frame_table→render_font_framed_paramへの名前変更に追従
	for(i = 0; i < ARRAY_SIZE(render_font_framed_param); i++) {
		wh = render_stringx(render,
			x + render_font_framed_param[i].x,
			y + render_font_framed_param[i].y,
			str,
			fontx,
			(color >> render_font_framed_param[i].c) & 15);
		if(!wh) {
			return 0;
		}
	}
//}}2009/07/15:frame_table→render_font_framed_paramへの名前変更に追従

	return wh + 0x00020002; /* 縦横2ピクセルづつ増える */
}

/*---------------------------------------------------------------------------*/

/* 文字列展開バッファとして_def_vbuff[]を利用しています。 */
unsigned int
render_printfx_framed(RENDER* render, int x, int y, const FONTX* fontx, int color, const char* fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vsprintf(_def_vbuff, fmt, ap);
	va_end(ap);

	return render_stringx_framed(render, x, y, _def_vbuff, fontx, color);
}

