/*************************************************************************************************/
/*!
   	@file		Bitblt.h
	@author 	Fanzo
*/
/*************************************************************************************************/
#pragma		once

///////////////////////////////////////////////////////////////////////////////////////////////////
//include files


#pragma pack( push , 8 )		//set align

namespace icubic
{

///////////////////////////////////////////////////////////////////////////////////////////////////
// preprocessor deifne

///////////////////////////////////////////////////////////////////////////////////////////////////
// type define

enum BltBlendType
{
	Overlap_BltBlendType , 
	Onezero_BltBlendType , 
};
///////////////////////////////////////////////////////////////////////////////////////////////////
// classes define

//=================================================================================================
//!	color blt
//!	@retval			---
//-------------------------------------------------------------------------------------------------
cb_inline
void ColorBlt
		(
		iSurfaceDest&		dest , 
		const irect&		rect , 
		const rgba&			color , 
		BltBlendType		type
		)
{
	// clip
	irect	dr( dest->GetDestAvailableArea() );
	dr	= dr.And( rect );
	if( dr.IsExist() == false )
		return;
		
	// dest
	int			destpitchbyte;
	pixelformat	destformat		= dest->GetDestFormat();
	uint8*		destpix			= ( uint8* )dest->GetDestPixelPtr( &destpitchbyte );
	destpix += dr.ymin * destpitchbyte + dr.xmin * get_pixel_byte( destformat );
	
	// render
	int		y , len = dr.Width();
	if( type == Overlap_BltBlendType )
	{
		for( y = dr.ymin ; y < dr.ymax ; y++ )
		{
			pp_blender_overlap_c( to_pp_format( destformat ) , destpix , len , to_pp_color( color ) );
			destpix += destpitchbyte;
		}
	}
	else if( type == Onezero_BltBlendType )
	{
		for( y = dr.ymin ; y < dr.ymax ; y++ )
		{
			pp_blender_onezero_c( to_pp_format( destformat ) , destpix , len , to_pp_color( color ) );
			destpix += destpitchbyte;
		}
	}
}
//=================================================================================================
//!	surface blt
//!	@retval			---
//-------------------------------------------------------------------------------------------------
cb_inline
void SurfaceBlt
		(
		iSurfaceDest&		dest , 
		const ivector2&		pos , 
		iSurfaceSource&		src , 
		const rgba&			sc , 
		uint8				a , 	
		BltBlendType		type , 
		const irect*		clip = 0
		)
{
	// clip
	irect	dr( dest->GetDestAvailableArea() );
	dr	= dr.And( irect( pos , src->GetSourceSize() ) );
	if( clip != 0 )
		dr	= dr.And( *clip );
	if( dr.IsExist() == false )
		return;
	irect	sr( dr );
	sr = sr.Move( -pos );
		
	// dest
	int			destpitchbyte;
	pixelformat	destformat		= dest->GetDestFormat();
	uint8*		destpix			= ( uint8* )dest->GetDestPixelPtr( &destpitchbyte );
	destpix += dr.ymin * destpitchbyte + dr.xmin * get_pixel_byte( destformat );
	
	// src
	int			srcpitchbyte;
	pixelformat	srcformat		= src->GetSourceFormat();
	uint8*		srcpix			= ( uint8* )src->GetSourcePixelPtr( &srcpitchbyte );
	srcpix += sr.ymin * srcpitchbyte + sr.xmin * get_pixel_byte( srcformat );

	// render
	int		y , len = dr.Width();
	if( type == Overlap_BltBlendType )
	{
		for( y = dr.ymin ; y < dr.ymax ; y++ )
		{
			pp_blender_overlap_m( to_pp_format( destformat ) , destpix , to_pp_format( srcformat ) , srcpix , len , to_pp_color( sc ) , to_pp_alpha( a ) );
			srcpix	+= srcpitchbyte;
			destpix += destpitchbyte;
		}
	}
	else if( type == Onezero_BltBlendType )
	{
		for( y = dr.ymin ; y < dr.ymax ; y++ )
		{
			pp_blender_onezero_m( to_pp_format( destformat ) , destpix , to_pp_format( srcformat ) , srcpix , len , to_pp_color( sc ) , to_pp_alpha( a ) );
			srcpix	+= srcpitchbyte;
			destpix += destpitchbyte;
		}
	}
}
//=================================================================================================
//!	StretchSurface
//!	@retval			---
//-------------------------------------------------------------------------------------------------
cb_inline
void StretchBlt
		(
		iSurfaceDest&		dest , 
		const irect&		destrect , 
		iTexture&			src , 
		const rgba&			sc , 
		uint8				a , 	
		BltBlendType		type , 
		const irect*	 	clip = 0
		)
{
	// color
	if( ITexture::Color == src->TextureType() )
	{
		ColorBlt( dest , clip == 0 ? destrect : destrect.And( *clip ) , src->TextureColor() , type );
		return;
	}
	
	// clip
	irect	dr( dest->GetDestAvailableArea().And( destrect ) );
	if( clip != 0 )
		dr.And( *clip );
	if( dr.IsExist() == false )
		return;
		
	// uv
	float		u[2] =
	{
		( float )( dr.xmin - destrect.xmin ) / ( float )destrect.Width() , 
		( float )( dr.xmax - destrect.xmin ) / ( float )destrect.Width()
	};
	float		v[2] =
	{
		( float )( dr.ymin - destrect.ymin ) / ( float )destrect.Height() , 
		( float )( dr.ymax - destrect.ymin ) / ( float )destrect.Height()
	};
	float	dv	= ( v[1]-v[1] ) / dr.Height();
	float	sv	= v[0] + dv / 2.0f;
	
	// dest
	int			destpitchbyte;
	pixelformat	destformat		= dest->GetDestFormat();
	uint8*		destpix			= ( uint8* )dest->GetDestPixelPtr( &destpitchbyte );
	destpix += dr.ymin * destpitchbyte + dr.xmin * get_pixel_byte( destformat );
	
	// buffer
	pixelformat		srcformat = src->TextureImageFormat();
	Array<uint8>	buffer( dr.Width() * get_pixel_byte( srcformat ) );
	
	// render
	if( false == src->BeginTextureImage() )
		return;
	int		y , len = dr.Width();
	if( type == Overlap_BltBlendType )
	{
		for( y = dr.ymin ; y < dr.ymax ; y++ )
		{
			src->TextureImage( buffer.GetPtr() , len , fvector2( u[0] , sv ) , fvector2( u[1] , sv ) );
			pp_blender_overlap_m( to_pp_format( destformat ) , destpix , to_pp_format( srcformat ) , buffer.GetConstPtr() , len , to_pp_color( sc ) , to_pp_alpha( a ) );
			sv += dv;
			destpix += destpitchbyte;
		}
	}
	else if( type == Onezero_BltBlendType )
	{
		for( y = dr.ymin ; y < dr.ymax ; y++ )
		{
			src->TextureImage( buffer.GetPtr() , len , fvector2( u[0] , sv ) , fvector2( u[1] , sv ) );
			pp_blender_onezero_m( to_pp_format( destformat ) , destpix , to_pp_format( srcformat ) , buffer.GetConstPtr() , len , to_pp_color( sc ) , to_pp_alpha( a ) );
			sv += dv;
			destpix += destpitchbyte;
		}
	}
	src->EndTextureImage();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// global variable define

///////////////////////////////////////////////////////////////////////////////////////////////////
// global functions define

};	//namespace

//using namespace icubic;		

#pragma pack( pop )			//release align
