/*************************************************************************************************/
/*!
   	@file		pp_cpp_blender_overlap.h
	@author 	Fanzo
 	@date 		2008/4/20
*/
/*************************************************************************************************/
#pragma		once

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


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

namespace icubic
{
using namespace icubic;

//=================================================================================================
// overlap
//=================================================================================================
cb_inline
void pp_overlap_rgb
		(
		pp_pixel_calc		*dest , 
		pp_pixel_calc		&src
		)
{
	dest->rgb	= src.rgb;
}
cb_inline
void pp_overlap_rgba
		(
		pp_pixel_calc		*dest , 
		pp_pixel_calc		&src
		)
{
	pp_pixel_calc	d = *dest;
	dest->rgba.a	= ( uint8 )( ( uint32 )src.rgba.a + ( uint32 )d.rgba.a - ( uint32 )src.rgba.a * ( uint32 )d.rgba.a / 255 );
	dest->rgba.r	= ( uint8 )( ( uint32 )src.rgba.r + ( uint32 )d.rgba.r - ( uint32 )src.rgba.a * ( uint32 )d.rgba.r / 255 );
	dest->rgba.g	= ( uint8 )( ( uint32 )src.rgba.g + ( uint32 )d.rgba.g - ( uint32 )src.rgba.a * ( uint32 )d.rgba.g / 255 );
	dest->rgba.b	= ( uint8 )( ( uint32 )src.rgba.b + ( uint32 )d.rgba.b - ( uint32 )src.rgba.a * ( uint32 )d.rgba.b / 255 );
}
cb_inline
void pp_overlap_a
		(
		pp_pixel_calc		*dest , 
		pp_pixel_calc		&src
		)
{
	dest->a.a	= ( uint8 )( ( uint32 )src.a.a + ( uint32 )dest->a.a - ( uint32 )src.a.a * ( uint32 )dest->a.a / 255 );
}

//=================================================================================================
// blender_overlap_m
//=================================================================================================


//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_rgb_rgb
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	MemoryCopy( dest , src , sizeof( pp_rgb ) * len );
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_rgb_rgba
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgba( &srcpix , src );
		rgba_to_rgba( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_rgb( &destpix , dest );
		rgb_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgb( &destpix , destpix );
		StoreAddr_rgb( dest , destpix );
		src		= AddPixelSize_rgba( src );
		dest	= AddPixelSize_rgb( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_rgb_a
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_a( &srcpix , src );
		a_to_rgba( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_rgb( &destpix , dest );
		rgb_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgb( &destpix , destpix );
		StoreAddr_rgb( dest , destpix );
		src		= AddPixelSize_a( src );
		dest	= AddPixelSize_rgb( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_rgba_rgb
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgb( &srcpix , src );
		rgb_to_rgba( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		src		= AddPixelSize_rgb( src );
		dest	= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_rgba_rgba
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgba( &srcpix , src );
		rgba_to_rgba( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		src		= AddPixelSize_rgba( src );
		dest	= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_rgba_a
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_a( &srcpix , src );
		a_to_rgba( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		src		= AddPixelSize_a( src );
		dest	= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_a_rgb
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgb( &srcpix , src );
		rgb_to_a( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );
		
		pp_overlap_a( &destpix , srcpix );
		
		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		src		= AddPixelSize_rgb( src );
		dest	= AddPixelSize_a( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_a_rgba
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgba( &srcpix , src );
		rgba_to_a( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );
		
		pp_overlap_a( &destpix , srcpix );
		
		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		src		= AddPixelSize_rgba( src );
		dest	= AddPixelSize_a( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_a_a
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_a( &srcpix , src );
		a_to_a( &srcpix , b_color , srcpix );
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );
		
		pp_overlap_a( &destpix , srcpix );
		
		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		src		= AddPixelSize_a( src );
		dest	= AddPixelSize_a( dest );
	}
}

//=================================================================================================
// blender_overlap_m_alpha
//=================================================================================================
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_rgb_rgb
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgb( &srcpix , src );
		rgb_to_rgba( &srcpix , b_color , srcpix );
		MulAlpha_rgba( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_rgb( &destpix , dest );
		rgb_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgb( &destpix , destpix );
		StoreAddr_rgb( dest , destpix );
		src	= AddPixelSize_rgb( src );
		dest	= AddPixelSize_rgb( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_rgb_rgba
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgba( &srcpix , src );
		rgba_to_rgba( &srcpix , b_color , srcpix );
		MulAlpha_rgba( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_rgb( &destpix , dest );
		rgb_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgb( &destpix , destpix );
		StoreAddr_rgb( dest , destpix );
		src	= AddPixelSize_rgba( src );
		dest	= AddPixelSize_rgb( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_rgb_a
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_a( &srcpix , src );
		a_to_rgba( &srcpix , b_color , srcpix );
		MulAlpha_rgba( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_rgb( &destpix , dest );
		rgb_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgb( &destpix , destpix );
		StoreAddr_rgb( dest , destpix );
		src	= AddPixelSize_a( src );
		dest	= AddPixelSize_rgb( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_rgba_rgb
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgb( &srcpix , src );
		rgb_to_rgba( &srcpix , b_color , srcpix );
		MulAlpha_rgba( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		src	= AddPixelSize_rgb( src );
		dest	= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_rgba_rgba
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgba( &srcpix , src );
		rgba_to_rgba( &srcpix , b_color , srcpix );
		MulAlpha_rgba( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		src	= AddPixelSize_rgba( src );
		dest	= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_rgba_a
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_a( &srcpix , src );
		a_to_rgba( &srcpix , b_color , srcpix );
		MulAlpha_rgba( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );
		
		pp_overlap_rgba( &destpix , srcpix );
		
		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		src	= AddPixelSize_a( src );
		dest	= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_a_rgb
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgb( &srcpix , src );
		rgb_to_a( &srcpix , b_color , srcpix );
		MulAlpha_a( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );
		
		pp_overlap_a( &destpix , srcpix );
		
		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		src	= AddPixelSize_rgb( src );
		dest	= AddPixelSize_a( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_a_rgba
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_rgba( &srcpix , src );
		rgba_to_a( &srcpix , b_color , srcpix );
		MulAlpha_a( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );
		
		pp_overlap_a( &destpix , srcpix );
		
		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		src	= AddPixelSize_rgba( src );
		dest	= AddPixelSize_a( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m_alpha_a_a
		(
		void*			dest , 
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		srcpix;
		LoadAddr_a( &srcpix , src );
		a_to_a( &srcpix , b_color , srcpix );
		MulAlpha_a( &srcpix , alpha );
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );
		
		pp_overlap_a( &destpix , srcpix );
		
		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		src	= AddPixelSize_a( src );
		dest	= AddPixelSize_a( dest );
	}
}

//=================================================================================================
// blender_overlap_c
//=================================================================================================
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_c_rgb
		(
		void*			dest , 
		int32			len , 
		const pp_color&	color
		)
{
	pp_pixel_calc	c;
	color_to_rgba( &c , color );
	
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		destpix;
		LoadAddr_rgb( &destpix , dest );
		rgb_to_rgba( &destpix , destpix );

		pp_overlap_rgba( &destpix , c );

		rgba_to_rgb( &destpix , destpix );
		StoreAddr_rgb( dest , destpix );
		dest		= AddPixelSize_rgb( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_c_rgba
		(
		void*			dest , 
		int32			len , 
		const pp_color&	color
		)
{
	pp_pixel_calc	c;
	color_to_rgba( &c , color );
	
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		destpix;
		LoadAddr_rgba( &destpix , dest );
		rgba_to_rgba( &destpix , destpix );

		pp_overlap_rgba( &destpix , c );

		rgba_to_rgba( &destpix , destpix );
		StoreAddr_rgba( dest , destpix );
		dest		= AddPixelSize_rgba( dest );
	}
}
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_c_a
		(
		void*			dest , 
		int32			len , 
		const pp_color&	color
		)
{
	pp_pixel_calc	c;
	color_to_a( &c , color );
	
	int		off;
	for( off = 0 ; off < len ; off++ )
	{
		pp_pixel_calc		destpix;
		LoadAddr_a( &destpix , dest );
		a_to_a( &destpix , destpix );

		pp_overlap_a( &destpix , c );

		a_to_a( &destpix , destpix );
		StoreAddr_a( dest , destpix );
		dest		= AddPixelSize_a( dest );
	}
}

//=================================================================================================
//!	blender overlap
//!	@retval			---
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_m
		(
		pp_format		destformat , 
		void*			dest , 
		pp_format		srcformat ,
		const void*		src , 
		int32			len , 
		const pp_color&	b_color , 
		const pp_alpha&	alpha
		)
{
	typedef void (*func_m)( void* , const void* , int32 , const pp_color& );
	typedef void (*func_m_a)( void* , const void* , int32 , const pp_color& , const pp_alpha& );
	static
	func_m		funclist_m[4][4]=
	{
		{
		pp_cpp_blender_overlap_m_rgb_rgb , 
		pp_cpp_blender_overlap_m_rgb_rgba , 
		pp_cpp_blender_overlap_m_rgb_a , 
		} , 
		{
		pp_cpp_blender_overlap_m_rgba_rgb , 
		pp_cpp_blender_overlap_m_rgba_rgba , 
		pp_cpp_blender_overlap_m_rgba_a , 
		} , 
		{
		pp_cpp_blender_overlap_m_a_rgb , 
		pp_cpp_blender_overlap_m_a_rgba , 
		pp_cpp_blender_overlap_m_a_a , 
		} , 
	};
	static
	func_m_a	funclist_m_a[4][4]=
	{
		{
		pp_cpp_blender_overlap_m_alpha_rgb_rgb , 
		pp_cpp_blender_overlap_m_alpha_rgb_rgba , 
		pp_cpp_blender_overlap_m_alpha_rgb_a , 
		} , 
		{
		pp_cpp_blender_overlap_m_alpha_rgba_rgb , 
		pp_cpp_blender_overlap_m_alpha_rgba_rgba , 
		pp_cpp_blender_overlap_m_alpha_rgba_a , 
		} , 
		{
		pp_cpp_blender_overlap_m_alpha_a_rgb , 
		pp_cpp_blender_overlap_m_alpha_a_rgba , 
		pp_cpp_blender_overlap_m_alpha_a_a , 
		} , 
	};
	if( alpha.a == 256 )
		( funclist_m[ destformat ][ srcformat ] )( dest , src , len , b_color );
	else
		( funclist_m_a[ destformat ][ srcformat ] )( dest , src , len , b_color , alpha );
}
//=================================================================================================
//!	blender overlap
//!	@retval			---
//-------------------------------------------------------------------------------------------------
cb_inline
void pp_cpp_blender_overlap_c
		(
		pp_format		destformat , 
		void*			dest , 
		int32			len , 
		const pp_color&	color 
		)
{
	typedef void (*func)( void* , int32 , const pp_color& );
	static
	func	funclist[4] = 
	{
	pp_cpp_blender_overlap_c_rgb , 
	pp_cpp_blender_overlap_c_rgba , 
	pp_cpp_blender_overlap_c_a , 
	};
	( funclist[ destformat ] )( dest , len , color );
}

};	//namespace

//using namespace icubic;		

#pragma pack( pop )			//release align

