/*==============================================================================
	Copyright (C) 2008 IT Access.,Co.Ltd. All Rights Reserved.
	
	This software is the confidential and proprietary information 
	of IT Access.,Co.Ltd.
	
	Note:
		For CQ出版 Interface SH-2A board + LCD board without OS.

   Spec: SH7262 144MHz, 1MB RAM, LCD QVGA 320x240 RGB565

==============================================================================*/

/*==============================================================================
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> INCLUDE. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
==============================================================================*/
// For debug 
//#define	SH_DEBUG

#ifdef	SH_DEBUG
	#include "cpu_uart.h"
#endif


#include "GealCommon.h"
#include "GealTypes.h"
#include "GealAPI.h"
#include "GealConfigAPI.h"
#include "GealUtilAPI.h"
#include "GealFigureAPI.h"
#include "GealStringAPI.h"
#include "GealTimerAPI.h"
#include "GealTargetAPI.h"

#include "TargetTypes.h"

#if defined (TARGET_COLOR_RGB32) || defined (TARGET_COLOR_RGB24) ||		\
	defined (TARGET_COLOR_RGB16) ||	defined (TARGET_COLOR_RGB15) 

/*==============================================================================
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> CONFIGURATION. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
==============================================================================*/
/* グラフィック部1 */
//キャッシュ有効
#define RAM_PAGE3		0x1C050000	/* 大容量内蔵RAM ページ3(160KB) */
#define RAM_PAGE4		0x1C078000	/* 大容量内蔵RAM ページ4(240KB) */
#define RAM_PAGE5		0x1C0B4000	/* 大容量内蔵RAM ページ5(304KB) */

//キャッシュ無効
//#define RAM_PAGE3		0x3C050000	/* 大容量内蔵RAM ページ3(160KB) */
//#define RAM_PAGE4		0x3C078000	/* 大容量内蔵RAM ページ4(240KB) */
//#define RAM_PAGE5		0x3C0B4000	/* 大容量内蔵RAM ページ5(304KB) */


#define	_USE_FRAME_BUFFER

#ifdef	_USE_FRAME_BUFFER
	#define GRA1_VRAM_BASE        RAM_PAGE5		// Bufferあり　PAGE5→ PAGE4にRedraw
	/* フレームバッファのＸ方向ピクセル数 */
	#define FRAME_WIDTH		320
	#define GETLINE(p, y)	((TARGET_COLOR*)(((GE_UINT8*)(GRA1_VRAM_BASE)) + (FRAME_WIDTH*2) * (y)))
#else
	#define GRA1_VRAM_BASE        RAM_PAGE4	// Bufferなし 直接描画
	#define GETLINE(p, y)		((TARGET_COLOR*)(((GE_UINT8*)(GRA1_VRAM_BASE)) + (((unsigned int)(y)) <<10) ))
#endif

#define GRA1_HORIZONTAL_OFFSET		512	/* 水平改行幅 2N乗にして高速化 */


//#define GETLINE(p, y)		((TARGET_COLOR*)(((GE_UINT8*)((p)->pBits)) + (p)->dwLineByte * (y)))
#define GETADRS(p, x, y)	((GETLINE(p, y)) + (x))

#if defined (TARGET_COLOR_RGB32)

	#define SETCOLOR(bits, red, green, blue)	\
	{											\
		(bits)->b = (blue);						\
		(bits)->g = (green);					\
		(bits)->r = (red);						\
		(bits)->a = 0;							\
	}

	void SETCOLOR_BLEND(TARGET_COLOR* bits, 
						GE_UINT8      red, 
						GE_UINT8      green,
						GE_UINT8      blue,
						GE_UINT8      blend)
	{
		GE_INT32	r, g, b;

		r = ((GE_INT32)bits->r * blend + (GE_INT32)red   * (100 - blend)) / 100;
		g = ((GE_INT32)bits->g * blend + (GE_INT32)green * (100 - blend)) / 100;
		b = ((GE_INT32)bits->b * blend + (GE_INT32)blue  * (100 - blend)) / 100;

		bits->r = (GE_UINT8)r;
		bits->g = (GE_UINT8)g;
		bits->b = (GE_UINT8)b;
	}

#elif defined (TARGET_COLOR_RGB24)

	#define SETCOLOR(bits, red, green, blue)	\
	{											\
		(bits)->b = (blue);						\
		(bits)->g = (green);					\
		(bits)->r = (red);						\
	}

	void SETCOLOR_BLEND(TARGET_COLOR* bits, 
						GE_UINT8      red, 
						GE_UINT8      green,
						GE_UINT8      blue,
						GE_UINT8      blend)
	{
		GE_INT32	r, g, b;

		r = ((GE_INT32)bits->r * blend + (GE_INT32)red   * (100 - blend)) / 100;
		g = ((GE_INT32)bits->g * blend + (GE_INT32)green * (100 - blend)) / 100;
		b = ((GE_INT32)bits->b * blend + (GE_INT32)blue  * (100 - blend)) / 100;

		bits->r = (GE_UINT8)r;
		bits->g = (GE_UINT8)g;
		bits->b = (GE_UINT8)b;
	}

#elif defined(TARGET_COLOR_RGB16)

	#define SETCOLOR(bits, red, green, blue) (*(bits) = (GE_UINT16)(				\
														 (((red  ) & 0xf8) << 8) |	\
														 (((green) & 0xfc) << 3) |	\
														 (((blue ) & 0xf8) >> 3)))


	void SETCOLOR_BLEND(TARGET_COLOR* bits, 
						GE_UINT8      red, 
						GE_UINT8      green,
						GE_UINT8      blue,
						GE_UINT8      blend)
	{
		GE_INT32	r, g, b;

		r = (*bits & 0xf800) >> 8;
		g = (*bits & 0x07e0) >> 3;
		b = (*bits & 0x001f) << 3;

		r = (r * blend + (GE_INT32)red   * (100 - blend)) / 100;
		g = (g * blend + (GE_INT32)green * (100 - blend)) / 100;
		b = (b * blend + (GE_INT32)blue  * (100 - blend)) / 100;

		SETCOLOR(bits, r, g, b);
	}
#elif defined(TARGET_COLOR_RGB15)

	#define SETCOLOR(bits, red, green, blue) (*(bits) = (GE_UINT16)(				\
														 (((red  ) & 0xf8) << 7) |	\
														 (((green) & 0xf8) << 2) |	\
														 (((blue ) & 0xf8) >> 3)))

	void SETCOLOR_BLEND(TARGET_COLOR* bits, 
						GE_UINT8      red, 
						GE_UINT8      green,
						GE_UINT8      blue,
						GE_UINT8      blend)
	{
		GE_INT32	r, g, b;

		r = (*bits & 0x7c00) >> 7;
		g = (*bits & 0x03e0) >> 2;
		b = (*bits & 0x001f) << 3;

		r = (r * blend + (GE_INT32)red   * (100 - blend)) / 100;
		g = (g * blend + (GE_INT32)green * (100 - blend)) / 100;
		b = (b * blend + (GE_INT32)blue  * (100 - blend)) / 100;

		SETCOLOR(bits, r, g, b);
	}
#else
	#error TARGET_COLOR_TYPE error
#endif

/*==============================================================================
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TYPE. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
==============================================================================*/

/*==============================================================================
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MEMBER. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
==============================================================================*/

/*==============================================================================
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROCEDURE. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
==============================================================================*/

/*------------------------------------------------------------------------------
	This API draws a pixel.
------------------------------------------------------------------------------*/
GE_VOID UGxDrawPixel(HTARGET  hTarget, 
					 GE_INT   x,
					 GE_INT   y,
					 GE_COLOR crColor)
{
	TARGET*			pTarget;
	TARGET_COLOR*	pBits;
	GE_UINT8		r, g, b, blend;

#ifdef	SH_DEBUG
	CPU_UartPuts("UGxDrawPixel start\n");
#endif

	if (GE_NULL ==hTarget)
		return;

	if (crColor & GE_TRANSPARENT_COLOR)
		return;

	pTarget = (TARGET*)hTarget;
	r     = GE_GetRValue(crColor);
	g     = GE_GetGValue(crColor);
	b     = GE_GetBValue(crColor);
	blend = GE_GetAValue(crColor);

	if ((x < 0 || x >= pTarget->wX) || 
		(y < 0 || y >= pTarget->wY))
		return;

	pBits = GETADRS(pTarget, x, y);
	
	if (blend == 0)
	{
		SETCOLOR(pBits, r, g, b);
	}
	else
	{
		SETCOLOR_BLEND(pBits, r, g, b, blend);
	}
#ifdef	SH_DEBUG
	CPU_UartPuts("UGxDrawPixel end\n");
#endif
}


/*------------------------------------------------------------------------------
	This API draws a horizontal or vertical line.
		nType	0 : horizontal line
				1 : vertical line
------------------------------------------------------------------------------*/
GE_VOID UGxDrawLineHV(
	HTARGET					hTarget,
	GE_INT					nX,
	GE_INT					nY,
	GE_INT					nType,
	GE_INT					nLength,
	GE_COLOR				crColor
	)
{
	TARGET*			pTarget;
	TARGET_COLOR*	pBits;
	GE_UINT8		r, g, b, blend;
	GE_INT			i;
	GE_INT			length;
	GE_INT			nEnd;

#ifdef	SH_DEBUG
	CPU_UartPuts("UGxDrawLineHV start\n");
#endif
	if (GE_NULL == hTarget)
		return;

	if (crColor & GE_TRANSPARENT_COLOR)
		return;

	pTarget = (TARGET*)hTarget;
	r     = GE_GetRValue(crColor);
	g     = GE_GetGValue(crColor);
	b     = GE_GetBValue(crColor);
	blend = GE_GetAValue(crColor);

	if (nType == 0)
	{
		/* Horizontal line. */

		if (nY<0 || nY>=pTarget->wY)
			return ;

		nEnd = nX + nLength;
		if (nX > nEnd)
			GE_SWAP(nX, nEnd);
		nX = GE_MAX(nX, 0);
		nEnd = GE_MIN(nEnd, pTarget->wX);
		length = GE_MAX(nEnd - nX, 0);

		pBits = GETADRS(pTarget, nX, nY);

		if (blend == 0)
		{
			for (i=0; i<length; i++)
			{
				SETCOLOR(pBits, r, g, b);
				pBits++;
			}
		}
		else
		{
			for (i=0; i<length; i++)
			{
				SETCOLOR_BLEND(pBits, r, g, b, blend);
				pBits++;
			}
		}
	}
	else if (nType == 1)
	{
		/* Vertical line. */

		if (nX<0 || nX>=pTarget->wX)
			return;

		nEnd = nY + nLength;
		if (nY > nEnd)
			GE_SWAP(nY, nEnd);
		nY = GE_MAX(nY, 0);
		nEnd = GE_MIN(nEnd, pTarget->wY);
		length = GE_MAX(nEnd - nY, 0);

		pBits = GETADRS(pTarget, nX, nY);

		if (blend == 0)
		{
			for (i=0; i<length; i++)
			{
				pBits = GETADRS(pTarget, nX, nY+i);
				SETCOLOR(pBits, r, g, b);
			}
		}
		else
		{
			for (i=0; i<length; i++)
			{
				pBits = GETADRS(pTarget, nX, nY+i);
				SETCOLOR_BLEND(pBits, r, g, b, blend);
			}
		}
	}
}

/*------------------------------------------------------------------------------
	This API draws a rectangle.
------------------------------------------------------------------------------*/
GE_VOID UGxDrawRectangle(HTARGET  hTarget,
						 GE_INT   left,
						 GE_INT   top,
						 GE_INT   right,
						 GE_INT   bottom,
						 GE_COLOR crColor,
						 GE_INT   nType)
{
	TARGET*			pTarget;
	TARGET_COLOR*	pBits;
	GE_INT			x, y;
	GE_UINT8		r, g, b, blend;

#ifdef	SH_DEBUG
	CPU_UartPuts("UGxDrawRectangle start\n");
#endif
	if (GE_NULL == hTarget)
		return;

	if (crColor & GE_TRANSPARENT_COLOR)
		return;

	if (top > bottom || left > right)
		return;

	pTarget = (TARGET*)hTarget;

	top    = GE_MINMAX(top,    0, pTarget->wY-1);
	left   = GE_MINMAX(left,   0, pTarget->wX-1);
	right  = GE_MINMAX(right,  0, pTarget->wX);
	bottom = GE_MINMAX(bottom, 0, pTarget->wY);

	r     = GE_GetRValue(crColor);
	g     = GE_GetGValue(crColor);
	b     = GE_GetBValue(crColor);
	blend = GE_GetAValue(crColor);

	if (!blend)
	{
		TARGET_COLOR color;
		SETCOLOR(&color, r, g, b);

		if (nType == 0)
		{
			/* top */
			pBits = GETADRS(pTarget, left, top);
			for (x=left; x<right; x++, pBits++) 
			{
				*pBits = color;
			}

			if (bottom > 0)
			{
				/* left,right */
				for (y=top+1; y<bottom-1; y++)
				{
					pBits = GETADRS(pTarget, left, y);
					*pBits = color;
					pBits = GETADRS(pTarget, right-1, y);
					*pBits = color;
				}

				/* bottom */
				pBits = GETADRS(pTarget, left, bottom-1);
				for (x=left; x<right; x++, pBits++) 
				{
					*pBits = color;
				}
			}
		}
		else
		{
			/* fill */
			for (y=top; y<bottom; y++)
			{
				pBits = GETADRS(pTarget, left, y);
				for (x=left; x<right; x++, pBits++) 
				{
					*pBits = color;
				}
			}
		}
	}
	else
	{
		if (nType == 0)
		{
			/* top */
			pBits = GETADRS(pTarget, left, top);
			for (x=left; x<right; x++, pBits++) 
			{
				SETCOLOR_BLEND(pBits, r, g, b, blend);
			}
			
			/* left,right */
			for (y=top+1; y<bottom-1; y++)
			{
				pBits = GETADRS(pTarget, left, y);
				SETCOLOR_BLEND(pBits, r, g, b, blend);
				pBits = GETADRS(pTarget, right-1, y);
				SETCOLOR_BLEND(pBits, r, g, b, blend);
			}

			/* bottom */
			pBits = GETADRS(pTarget, left, bottom-1);
			for (x=left; x<right; x++, pBits++) 
			{
				SETCOLOR_BLEND(pBits, r, g, b, blend);
			}
		}
		else
		{
			/* fill */
			for (y=top; y<bottom; y++)
			{
				pBits = GETADRS(pTarget, left, y);
				for (x=left; x<right; x++, pBits++) 
				{
					SETCOLOR_BLEND(pBits, r, g, b, blend);
				}
			}
		}
	}
}

/*------------------------------------------------------------------------------
	This API draws a bitmap.
------------------------------------------------------------------------------*/
GE_VOID UGxDrawBitmap(HTARGET          hTarget,
					  GE_INT           nX,
					  GE_INT           nY,
					  const GE_BITMAP* pBitmap,
					  const GE_RECT*   prcClip)
{
	TARGET*			pTarget;
	TARGET_COLOR*	pBits;
	GE_INT			k, w, h;
	GE_INT32		linebyte;
	GE_INT			top, left, right, bottom;
	GE_INT			offs_x, offs_y;
	GE_INT			x, y;

#ifdef	SH_DEBUG
	CPU_UartPuts("UGxDrawBitmap start\n");
#endif
	if ((GE_NULL == hTarget) || (GE_NULL == pBitmap))
		return;

	pTarget = (TARGET*)hTarget;

	w = pBitmap->wWidth;
	h = pBitmap->wHeight;
	linebyte = pBitmap->lwLinebyte;

	top    = GE_MINMAX(nY,   0, pTarget->wY-1);
	left   = GE_MINMAX(nX,   0, pTarget->wX-1);
	right  = GE_MINMAX(nX+w, 0, pTarget->wX);
	bottom = GE_MINMAX(nY+h, 0, pTarget->wY);

	if (prcClip)
	{
		top    = GE_MINMAX(top,    prcClip->top,  prcClip->bottom);
		left   = GE_MINMAX(left,   prcClip->left, prcClip->right);
		right  = GE_MINMAX(right,  prcClip->left, prcClip->right);
		bottom = GE_MINMAX(bottom, prcClip->top,  prcClip->bottom);
	}

	offs_x = GE_MAX(0, left - nX);
	offs_y = GE_MAX(0, top  - nY);

	if (pBitmap->cMode == eGECS_MONO)
	{
		const GE_UINT8*		sp;
		const GE_UINT8*		sline;
		const GE_COLOR*	pal = pBitmap->pPalette;

        sline  = pBitmap->pPxls;
		sline += linebyte * offs_y;

		for (y=top; y<bottom; y++)
		{
			GE_UINT8 mask;

			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x / 8;
			k     = offs_x % 8;

			mask = (GE_UINT8)(0x80 >> k);

			for (x=left; x<right; x++, pBits++) 
			{
				int dat = (*sp & mask) ? 1 : 0;

				SETCOLOR(pBits,
							GE_GetRValue(pal[dat]),
							GE_GetGValue(pal[dat]),
							GE_GetBValue(pal[dat]));

				mask >>= 1;
				if (mask == 0)
				{
					sp++;
					mask = 0x80;
				}
			}

			sline += linebyte;
		}
	}
	else if (pBitmap->cMode == eGECS_CLUT4)
	{
		const GE_UINT8*		sp;
		const GE_UINT8*		sline;
		const GE_COLOR*		pal = pBitmap->pPalette;

		sline  = pBitmap->pPxls;
		sline += linebyte * offs_y;

		for (y=top; y<bottom; y++)
		{
			GE_UINT8 mask;

			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x / 2;
			k     = (offs_x % 2) * 4;

			mask = (GE_UINT8)(0xf0 >> k);

			for (x=left; x<right; x++, pBits++) 
			{
				GE_INT   dat   = (mask == 0xf0) ? ((*sp & mask) >> 4) : (*sp & mask);
				GE_COLOR color = pal[dat];
				GE_UINT8 alpha = GE_GetAValue(color);

				if (alpha == 0)
				{
					SETCOLOR(pBits,
							 GE_GetRValue(color),
							 GE_GetGValue(color),
							 GE_GetBValue(color));
				}
				else if (alpha < 100)
				{
					SETCOLOR_BLEND(pBits,
								   GE_GetRValue(color),
								   GE_GetGValue(color),
								   GE_GetBValue(color),
								   alpha);
				}

				mask >>= 4;
				if (mask == 0)
				{
					sp++;
					mask = 0xf0;
				}
			}

			sline += linebyte;
		}
	}
	else if (pBitmap->cMode == eGECS_CLUT8) 
	{
		const GE_UINT8*		sp;
		const GE_UINT8*		sline;
		const GE_COLOR*		pal = pBitmap->pPalette;

		sline  = pBitmap->pPxls;
		sline += linebyte * offs_y;

		for (y=top; y<bottom; y++)
		{
			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x;

			for (x=left; x<right; x++, sp++, pBits++) 
			{
				GE_COLOR color = pal[*sp];
				GE_UINT8 alpha = GE_GetAValue(color);

				if (alpha == 0)
				{
					SETCOLOR(pBits,
							 GE_GetRValue(color),
							 GE_GetGValue(color),
							 GE_GetBValue(color));
				}
				else if (alpha < 100)
				{
					SETCOLOR_BLEND(pBits,
								   GE_GetRValue(color),
								   GE_GetGValue(color),
								   GE_GetBValue(color),
								   alpha);
				}
			}

			sline += linebyte;
		}
	}
	else if (pBitmap->cMode == eGECS_RGB15)
	{
		GE_UINT16*		sp;
		GE_UINT16*		sline;

		sline = (GE_UINT16*)pBitmap->pPxls;
		sline = (GE_UINT16*)((GE_UINT8*)sline + linebyte * offs_y);

		for (y=top; y<bottom; y++)
		{
			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x;

			for (x=left; x<right; x++, sp++, pBits++) 
			{
				if (!((*sp) & 0x8000))
				{
					GE_UINT8 r = (GE_UINT8)( ((*sp) & 0x7c00) >> 7 );
					GE_UINT8 g = (GE_UINT8)( ((*sp) & 0x03e0) >> 2 );
					GE_UINT8 b = (GE_UINT8)( ((*sp) & 0x001f) << 3 );
					SETCOLOR(pBits, r, g, b);
				}
			}

			sline = (GE_UINT16*)((GE_UINT8*)sline + linebyte);
		}
	}
	else if (pBitmap->cMode == eGECS_RGB16)
	{
		GE_UINT16*		sp;
		GE_UINT16*		sline;

		sline = (GE_UINT16*)pBitmap->pPxls;
		sline = (GE_UINT16*)((GE_UINT8*)sline + linebyte * offs_y);

		for (y=top; y<bottom; y++)
		{
			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x;

			for (x=left; x<right; x++, sp++, pBits++) 
			{
				GE_UINT8 r = (GE_UINT8)( ((*sp) & 0xf800) >> 8 );
				GE_UINT8 g = (GE_UINT8)( ((*sp) & 0x07e0) >> 3 );
				GE_UINT8 b = (GE_UINT8)( ((*sp) & 0x001f) << 3 );

				SETCOLOR(pBits, r, g, b);
			}

			sline = (GE_UINT16*)((GE_UINT8*)sline + linebyte);
		}
	}
	else if (pBitmap->cMode == eGECS_RGB24) 
	{

		GE_RGBT*		sp;
		GE_RGBT*		sline;

		sline  = (GE_RGBT*)pBitmap->pPxls;
		sline  = (GE_RGBT*)((GE_UINT8*)sline + linebyte * offs_y);

		for (y=top; y<bottom; y++)
		{
			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x;

			for (x=left; x<right; x++, sp++, pBits++) 
			{
				SETCOLOR(pBits, sp->r, sp->g, sp->b);
			}

			sline = (GE_RGBT*)((GE_UINT8*)sline + linebyte);
		}
	}
	else if (pBitmap->cMode == eGECS_RGB32) 
	{
		GE_RGBQ*		sp;
		GE_RGBQ*		sline;

		sline  = (GE_RGBQ*)pBitmap->pPxls;
		sline  = (GE_RGBQ*)((GE_UINT8*)sline + linebyte * offs_y);

		for (y=top; y<bottom; y++)
		{
			pBits = GETADRS(pTarget, left, y);
			sp    = sline + offs_x;

			for (x=left; x<right; x++, sp++, pBits++) 
			{
				if (sp->a == 0)
				{
					SETCOLOR(pBits, sp->r, sp->g, sp->b);
				}
				else if (sp->a < 100)
				{
					SETCOLOR_BLEND(pBits, sp->r, sp->g, sp->b, sp->a);
				}
			}

			sline = (GE_RGBQ*)((GE_UINT8*)sline + linebyte);
		}
	}
}

/*------------------------------------------------------------------------------
	This API draws a single font character.
------------------------------------------------------------------------------*/
GE_VOID UGxDrawFont(HTARGET        hTarget,
					GE_INT         nX,
					GE_INT         nY,
					const GE_FONT* pFont,
					GE_INT         nIndex,
					GE_INT         nOffset,
					GE_INT         nWidth,
					GE_COLOR       crColor,
					const GE_RECT* prcClip)
{
	TARGET*			pTarget;
	TARGET_COLOR*	pBits;
	const GE_UINT8*	sp;
	const GE_UINT8*	sline;
	GE_INT			w, h;
	GE_INT32		linebyte;
	GE_INT			top, left, right, bottom;
	GE_INT			offs_x, offs_y;
	GE_INT			x, y;
	GE_UINT8		r, g, b, blend;

#ifdef	SH_DEBUG
	CPU_UartPuts("UGxDrawFont start\n");
#endif

	if ((GE_NULL == hTarget) || (GE_NULL == pFont))
		return;

	if (crColor & GE_TRANSPARENT_COLOR)
		return;

	pTarget = (TARGET*)hTarget;

	r     = GE_GetRValue(crColor);
	g     = GE_GetGValue(crColor);
	b     = GE_GetBValue(crColor);
	blend = GE_GetAValue(crColor);

	w = GE_MIN(pFont->wWidth, nWidth);
	h = pFont->wHeight;

	top    = GE_MINMAX(nY,   0, pTarget->wY);
	left   = GE_MINMAX(nX,   0, pTarget->wX);
	right  = GE_MINMAX(nX+w, 0, pTarget->wX);
	bottom = GE_MINMAX(nY+h, 0, pTarget->wY);

	if (prcClip)
	{
		top    = GE_MINMAX(top,    prcClip->top,  prcClip->bottom);
		left   = GE_MINMAX(left,   prcClip->left, prcClip->right);
		right  = GE_MINMAX(right,  prcClip->left, prcClip->right);
		bottom = GE_MINMAX(bottom, prcClip->top,  prcClip->bottom);
	}

	offs_x = left - nX + nOffset;
	offs_y = top  - nY;

	if (pFont->wDepth == 1)
		linebyte = (pFont->wWidth + 7) >> 3;
	else if (pFont->wDepth == 4)
		linebyte = (pFont->wWidth + 1) >> 1;
	else 
		linebyte = (pFont->wWidth);

	sline = pFont->pBits + linebyte * pFont->wHeight * nIndex;
	sline += linebyte * offs_y;

	for (y=top; y<bottom; y++)
	{
		pBits = GETADRS(pTarget, left, y);

		if (pFont->wDepth == 1)
		{
			GE_UINT8 mask;
			GE_INT   k;

			sp    = sline + offs_x / 8;
			k     = offs_x % 8;
			mask  = 0x80 >> k;

			for (x=left; x<right; x++, pBits++) 
			{
				if (*sp & mask)
				{
					SETCOLOR_BLEND(pBits, r, g, b, blend);
				}

				mask >>= 1;
				if (mask == 0)
				{
					sp++;
					mask = 0x80;
				}
			}
		}
		else if (pFont->wDepth == 4)
		{
			GE_INT	k;
			
			sp = sline + offs_x/2;
			k  = offs_x & 0x01;

			for (x=left; x<right; x++, pBits++) 
			{
				GE_INT	val;

				if (k & 0x01)
				{
					val = (*sp++) & 0x0F;
				}
				else
					val = ((*sp) >> 4) & 0x0F;

				val = (100 - blend) * val;
				val = val / 15;
				val = 100 - val;

				SETCOLOR_BLEND(pBits, r, g, b, (GE_UINT8)val);

				k++;
			}
		}
		else if (pFont->wDepth == 8)
		{
			sp = sline + offs_x;

			for (x=left; x<right; x++, pBits++) 
			{
				GE_INT	val;

				val = *sp++;

				val = (100 - blend) * val;
				val = val / 255;
				val = 100-val;

				SETCOLOR_BLEND(pBits, r, g, b, (GE_UINT8)val);
			}
		}

		sline += linebyte;
	}
}

/*------------------------------------------------------------------------------
	This API clears rectangle.
------------------------------------------------------------------------------*/
GE_VOID UGxClearRectangle(HTARGET hTarget,
						  GE_INT  left,
						  GE_INT  top,
						  GE_INT  right,
						  GE_INT  bottom)
{
	if (GE_NULL == hTarget)
		return;

	UGxDrawRectangle(hTarget,
					 left,
					 top,
					 right,
					 bottom,
					 0x00000000,
					 1);
}


/*******************************************************************************
	CPUメモリ → フレームメモリ 矩形転送 SH-2Aサンプル grphcon.cより
*******************************************************************************/
/* ピクセル定義 */
typedef unsigned short GCON_PIXEL;

// cpu_init.c に
extern void CPU_DMAtransfer(unsigned short *sar, unsigned short *dar, unsigned int word) ;


/*------------------------------------------------------------------------------
	This API redraws current target.
------------------------------------------------------------------------------*/
GE_VOID UGxTargetRedraw(HTARGET  hTarget,
						GE_RECT* psRect)
{
#ifdef	_USE_FRAME_BUFFER
	TARGET*			pTarget;
	GCON_PIXEL	*s, *d;
	unsigned int y ;

	if (GE_NULL == hTarget)	return;

	s = (GCON_PIXEL *)GRA1_VRAM_BASE ;
	d = (GCON_PIXEL *)RAM_PAGE4 ;
	for ( y= 0 ; y < 240 ; y++ ) {
		CPU_DMAtransfer( s, d, FRAME_WIDTH>>1 );
		s += FRAME_WIDTH ;
		d += GRA1_HORIZONTAL_OFFSET ;
	}
#endif
}

/*------------------------------------------------------------------------------
	This API gets if the color is tanslate or not.
------------------------------------------------------------------------------*/
GE_BOOL UGxIsTransColor(GE_COLOR crColor)
{
	return (crColor & 0xFF000000) ? GE_TRUE : GE_FALSE;
}

/*------------------------------------------------------------------------------
	This API gets the alpha blending value.
------------------------------------------------------------------------------*/
GE_INT UGxGetBlend(GE_COLOR crColor)
{
	GE_UINT8	cValue = GE_GetAValue(crColor) & 0x7F;

	return UGxIsTransColor(crColor) ?
		100 :
		GE_MINMAX(cValue, 0, 100);
}

#endif
