#include"CFontDriverWindows.h"
#include"CFontWindows.h"
#include"CSurfaceDIB.h"
#include"../CPlaneTransiter.h"
#include"../../../../Auxiliary/Debug/CWarning.h"
#include"../../../../Auxiliary/Debug/CAssert.h"
#include"../../../../Auxiliary/Debug/CException.h"
#include"../../../../Auxiliary/CString.h"

//	めんどくさいから２種類で我慢(^^;
static const char* FONTNAME[] =
{
	"ＭＳ ゴシック",
	"ＭＳ 明朝",
};


namespace Maid
{

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォントの作成
/*!
 	引数などは IFontDriver::Create() を参照のこと
 */
SPFONT CFontDriverWindows::Create( int FontNo, int FontW, int FontH, bool IsAntialias, bool IsBold, bool IsItalic ) const
{
	const mstring name = GetFontName( FontNo );
	return Create( name, FontW, FontH, IsAntialias, IsBold, IsItalic );
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォントの作成
/*!
 	引数などは IFontDriver::Create() を参照のこと
 */
SPFONT CFontDriverWindows::Create( const mstring& FontName, int FontW, int FontH, bool IsAntialias, bool IsBold, bool IsItalic ) const
{
	boost::shared_ptr<CFontWindows> pFont( new CFontWindows );

	pFont->m_FontName	= FontName;
	pFont->m_Size		= SIZE2DI(FontW,FontH);
	pFont->m_IsAntialias= IsAntialias;
	pFont->m_IsBold		= IsBold;
	pFont->m_IsItalic	= IsItalic;

	return pFont;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォント数の取得
/*!
 	引数などは IFontDriver::GetFontNum() を参照のこと
 */
int CFontDriverWindows::GetFontNum() const
{
	return NUMELEMENTS(FONTNAME);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォント名の取得
/*!
 	引数などは IFontDriver::GetFontNum() を参照のこと
 */
mstring CFontDriverWindows::GetFontName( int FontNo ) const
{
	MAID_ASSERT( !(FontNo<NUMELEMENTS(FONTNAME)), "指定された番号のフォントは存在しません " << FontNo );
	return CString::ConvertSJIStoMAID(FONTNAME[FontNo]);
}

SPSURFACEBUFFER CFontDriverWindows::Rasterize( const SPFONT& pFont, unt32 FontCode ) const
{
	SPSURFACEBUFFERMEMORY pRet( new CSurfaceBufferMemory );

	SIZE2DI size =pFont->GetSize();

	if( !CString::IsHankaku(FontCode) ) { size.w *= 2; }

	pRet->Create( size, PIXELFORMAT_A08R08G08B08I );

	RasterizeMemory( pRet, pFont, FontCode );

	return pRet;
}

void CFontDriverWindows::RasterizeMemory( SPSURFACEBUFFERMEMORY& Dst, const SPFONT& pF, unt32 FontCode ) const
{
	int SurfaceW = pF->GetSize().w;
	int SurfaceH = pF->GetSize().h;

	if( !CString::IsHankaku(FontCode) ) { SurfaceW *= 2; }

	CSurfaceDIB tmp;
	HFONT	  hNewFont;

	if( pF->IsAntialias() )
	{
		//	フォントのアンチエイリアスをかけるために
		//	縦４倍x横４倍のサイズで作って縮小する
		tmp.CreateBuffer( SurfaceW*4, SurfaceH*4, PIXELFORMAT_A08R08G08B08I );
		hNewFont = CreateFont( pF->GetFontName(), pF->GetSize().w*4, pF->GetSize().h*4, pF->IsBold(), pF->IsItalic() );
	}else
	{
		tmp.CreateBuffer( SurfaceW, SurfaceH, PIXELFORMAT_A08R08G08B08I );
		hNewFont = CreateFont( pF->GetFontName(), pF->GetSize().w, pF->GetSize().h, pF->IsBold(), pF->IsItalic() );
	}


	const HDC	  hDC	     = ::CreateCompatibleDC(NULL);
	const HFONT   hOldFont   = (HFONT)::SelectObject( hDC, hNewFont );
	const HBITMAP hOldBitmap = (HBITMAP)::SelectObject( hDC, tmp.GetHBITMAP() );

	//	↓の設定をすることで、色のあるピクセルが 0x00000001 になる
	::SetTextColor( hDC, 0x00010000 );
	::SetBkColor  ( hDC, RGB(0,0,0) );
//	::SetBkMode   ( hDC, TRANSPARENT);
	::SetBkMode   ( hDC, OPAQUE);

	//	描画する
	{
		const MySTL::string str = CString::ConvertMAIDtoSJIS( FontCode );

		::TextOut( hDC, 0, 0, str.c_str(), (int)str.length() );
	}


	{
		SPSURFACEBUFFERINFO pSrcInfo;
		SPSURFACEBUFFERINFO pDstInfo;

		CSurfaceBufferLoacker SrcLock( tmp, pSrcInfo );
		CSurfaceBufferLoacker DstLock( *Dst, pDstInfo );

		if( pF->IsAntialias() )
		{
			for( int DstY=0; DstY<SurfaceH; ++DstY )
			{
				for( int DstX=0; DstX<SurfaceW; ++DstX )
				{
					const unt08 alpha = Antialias4X( DstX*4, DstY*4, pSrcInfo );
					pDstInfo->SetPixel(DstX,DstY,COLOR_A08R08G08B08I(alpha,0x00,0x00,0x00));
				}
			}
		}else
		{
			for( int DstY=0; DstY<SurfaceH; ++DstY )
			{
				for( int DstX=0; DstX<SurfaceW; ++DstX )
				{
					const int alpha = pSrcInfo->GetPixel(DstX,DstY);
					pDstInfo->SetPixel(DstX,DstY,COLOR_A08R08G08B08I(0xFF*alpha,0x00,0x00,0x00));
				}
			}
		}
	}

	::SelectObject( hDC, hOldBitmap );
	::SelectObject( hDC, hOldFont );
	::DeleteObject( hNewFont );
	::DeleteDC( hDC );
}


unt08 CFontDriverWindows::Antialias4X( int base_x, int base_y, SPSURFACEBUFFERINFO& pInfo )const
{
	int alpha = 0;

	for( int y=0; y<4; ++y )
	{
		for( int x=0; x<4; ++x )
		{
			alpha += pInfo->GetPixel(base_x+x,base_y+y);
		}
	}

	return 0xFF*alpha/16;
}


HFONT CFontDriverWindows::CreateFont( const mstring& FontName, int Width, int Height, bool IsBold, bool IsItalic )const
{
	const DWORD fdwItalic = IsItalic? TRUE   : FALSE;
	const int   nWeight   = IsBold?   FW_BOLD: FW_REGULAR;

	const HFONT	  hNewFont = ::CreateFont( 
			Height,			// フォントの高さ（論理単位）０ならデフォルト 
			Width,			// 幅。０なら、高さにあった幅 
			0,				// スクリーンの表示画面とＸ軸の角度の１０倍
			0,
			nWeight,		// 太さ 
			fdwItalic,		//イタリック体
			FALSE,						//アンダーライン
			FALSE,						//打ち消し線
			SHIFTJIS_CHARSET,			//文字セット
			OUT_DEFAULT_PRECIS,			//出力精度
			CLIP_DEFAULT_PRECIS,		//クリッピング精度
			PROOF_QUALITY,				//出力品質
			FIXED_PITCH | FF_MODERN,	//ピッチとファミリー
			CString::ConvertMAIDtoSJIS(FontName).c_str() );

	return hNewFont;
}


}

