#include"CSurfaceDIB.h"
#include"../CSurfaceBufferInfoTemplate.h"
#include"../../../../Auxiliary/Debug/CWarning.h"
#include"../../../../Auxiliary/Debug/CAssert.h"
#include"../../../../Auxiliary/Debug/CException.h"


namespace Maid
{

/*!
 	マスクビットの設定
 
 	@param	Header	[ o]	設定先
 	@param	Alpha	[i ]	αビット
 	@param	Red		[i ]	赤ビット
 	@param	Green	[i ]	緑ビット
 	@param	Blue	[i ]	青ビット
 */
inline void SetMask( BITMAPV4HEADER& Header, DWORD Alpha, DWORD Red, DWORD Green, DWORD Blue )
{
	Header.bV4AlphaMask = Alpha;
	Header.bV4RedMask   = Red;
	Header.bV4GreenMask = Green;
	Header.bV4BlueMask  = Blue;
}

/*!
 	@class	CSurfaceDIB CSurfaceDIB.h
 	@brief	描画平面クラス DIB Ver.
 */

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 */
CSurfaceDIB::CSurfaceDIB() : m_hDIB(NULL), m_pPlane(NULL)
{
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デストラクタ
/*!
 */
CSurfaceDIB::~CSurfaceDIB()
{
	Destory();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! サーフェスの横幅の取得
/*!
 	引数などは ISurfaceBuffer::GetSize() を参照すること
 */
SIZE2DI CSurfaceDIB::GetSize() const
{
	MAID_ASSERT( m_hDIB==NULL, "まだ作成されていません" );
	return m_Size;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! サーフェスのピクセルフォーマットの取得
/*!
 	引数などは ISurfaceBuffer::GetPixelFormat() を参照すること
 */
PIXELFORMAT CSurfaceDIB::GetPixelFormat() const
{
	MAID_ASSERT( m_hDIB==NULL, "まだ作成されていません" );
	return m_PixelFormat;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! サーフェスの作成
/*!
 	引数などは ISurfaceBuffer::CreateSurface() を参照すること
 */
void CSurfaceDIB::CreateBuffer( int Width, int Height, PIXELFORMAT Format )
{
	//	DIBの横幅は４の倍数でなければ作成できない
	const int w = (Width+3)&~3;
	BITMAPINFOHEADER dib;

	ZERO( &dib, sizeof(dib) );
	dib.biSize = sizeof(dib);
	dib.biWidth = w;
	dib.biHeight = -(int)Height;
	dib.biPlanes = 1;
	dib.biBitCount = 8*GetPixelBPP(Format)/8;


/*
	BITMAPV4HEADER Header;

	ZeroMemory(&Header, sizeof(Header));
	Header.bV4Size = sizeof(BITMAPV4HEADER);
	Header.bV4Width = w;
	Header.bV4Height = -short(Height);
	Header.bV4Planes = 1;
	Header.bV4BitCount = GetPixelBPP(eFormat);
	Header.bV4V4Compression = BI_BITFIELDS;
	Header.bV4SizeImage = 0;
	Header.bV4XPelsPerMeter = 0;
	Header.bV4YPelsPerMeter = 0;
	Header.bV4ClrUsed = 0;
	Header.bV4ClrImportant = 0;

	//	ピクセルフォーマットにあったマスクを生成する
	switch( eFormat )
	{
	case PIXELFORMAT_ARGB8888:  { SetMask( Header, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF ); }break;
	case PIXELFORMAT_XRGB8888:  { SetMask( Header, 0x00000000, 0x00FF0000, 0x0000FF00, 0x000000FF ); }break;
	case PIXELFORMAT_RGB888:	{ SetMask( Header, 0x00000000, 0x00FF0000, 0x0000FF00, 0x000000FF ); }break;
	case PIXELFORMAT_ARGB4444:	{ SetMask( Header, 0x0000F000, 0x00000F00, 0x000000F0, 0x0000000F ); }break;
	case PIXELFORMAT_ARGB1555:	{ SetMask( Header, 0x00008000, 0x00007C00, 0x000003E0, 0x0000001F ); }break;
	case PIXELFORMAT_XRGB1555:	{ SetMask( Header, 0x00000000, 0x00007C00, 0x000003E0, 0x0000001F ); }break;
	case PIXELFORMAT_RGB565:	{ SetMask( Header, 0x00000000, 0x0000F800, 0x000007E0, 0x0000001F ); }break;
		//	パレットは未サポート
	}
*/
	HDC hDC = ::CreateCompatibleDC(NULL);

	if( hDC==NULL ) { MAID_THROWEXCEPTION( MAIDTEXT("hDC==NULL") ); }
	m_hDIB = CreateDIBSection( hDC, (BITMAPINFO *)&dib, DIB_RGB_COLORS, (void **)&m_pPlane, NULL, 0 );
	::DeleteDC(hDC);
	if( m_hDIB==NULL ) { MAID_THROWEXCEPTION( MAIDTEXT("DIB確保に失敗") ); }


	m_Size = SIZE2DI(Width,Height);
	m_PixelFormat = Format;
	m_Pitch = w * GetPixelBPP(Format)/8;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! サーフェスの破棄
/*!
 	引数などは ISurfaceBuffer::Destory() を参照すること
 */
void CSurfaceDIB::Destory()
{
	::DeleteObject(m_hDIB);
	m_hDIB = NULL;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! サーフェスのロック
/*!
 	引数などは ISurfaceBuffer::Lock() を参照すること
 */
void CSurfaceDIB::Lock( SPSURFACEBUFFERINFO& info )
{
	MAID_ASSERT( m_hDIB==NULL, "まだ作成されていません" );

	info.reset( new ISurfaceBufferInfoNormal( m_pPlane, NULL, 
		m_Size.w, m_Size.h, m_PixelFormat, m_Pitch ) );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! サーフェスのアンロック
/*!
 	引数などは ISurfaceBuffer::Unlock() を参照すること
 */
void CSurfaceDIB::Unlock()
{
	//	何もしない
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! HBITMAP の取得
/*!
 	@return HBITMAP
 */
HBITMAP CSurfaceDIB::GetHBITMAP() const
{
	MAID_ASSERT( m_hDIB==NULL, "まだ作成されていません" );
	return m_hDIB;
}

}

